From cb26b3468aea50ed6277ce88301bfb5026f158db Mon Sep 17 00:00:00 2001 From: "sachin.sp" Date: Mon, 24 Mar 2025 18:03:59 +0530 Subject: [PATCH 01/44] added technical desgin document for handle Signed-off-by: sachin.sp --- docs/HandlesUserFlow.png | Bin 0 -> 53444 bytes docs/design/handle_flow.md | 40 +++++++++++++++++++++++++++++++++++++ 2 files changed, 40 insertions(+) create mode 100644 docs/HandlesUserFlow.png create mode 100644 docs/design/handle_flow.md diff --git a/docs/HandlesUserFlow.png b/docs/HandlesUserFlow.png new file mode 100644 index 0000000000000000000000000000000000000000..f711e6d184380fd9a1f2d35040614716e639926e GIT binary patch literal 53444 zcmd432UL@3+cnDAbyOT2YzU|{2?82A2v|VrAW7(DlqS9RW>=(03mCcrfrKW#gN>5V zq(r2HH0iy!|B7v#dB69ZZ=JK&S;sYN$s~`-^W67U_O`J=TKoy*_94ENAUJ9tw~-_PzVU zi5`wAIR8cYrr5_530a!^$~puQB{I1i9DlS~Jb%B_;8_GQf?Pen>5z5HVNPyEt$(gF zBHFIb27S}wlnt?a_p4$(3tPK=OXFqsp>Os1LfN-U8A62rq#qZ4^XZ}I`c&5A<9$}W zmrgPB554u(Mq(67G|ZKHjIrdfzF&PbQk@h)4T;6REcCD&6j9#0D<_?Xl z)Md1b-gwtu4<(b$EpPKmI%xqZi%h9oNVfNa+|f@7MsmkbU{H+sT#Cc;sCQ8ZQ8Cx= zNaB~5+yWlgA1aCEuqF7aNM>RLuRM5ZDl3=fAGMWKSh>P9T-HE}?wF`AbQNbF?z5d7 z(-{_B8+0o^I>-+(NOLEjjQgGX0}T@kiW-%7ma5Uz|Lqk=(o_F-nIa-7Wu9w8wYas< zzPzQ=Zyj)Yu0~GA#$knY)C+XVOKQ>ApD{&?E)+`pcFW3(MMY}IvEyQerqWDea1P7U zf6P(yiN;2JmK` z9J>$Z@j*txjQ!MiTEkUMh{G}NJRHNjTMrpUWM$9AxO~=}BU9hB@#NISlgVVa;poKl zz2pgg@6FF$#m%*f)Hh!{COF{CHrH3ymYD7Rm93I;a^CTo)C&qxAD5;zsL6Z|7wy7;E$EdurD*KsYl(Jzhhs3ax(12^y^Bn}QnQHM_@Na~w9`f|~P_w~_Y zY-)_c)1~I2WNxp=a@#1a`qn}jyQo*RGFl_Ci#^UMG1@s_qT#mPB7#?3=epg7aI%kS znJ;8eFQRE>;pM|-S@)EQ*bkL0f0n1cINkd@uY&g=whf2V9Fn76W3y32R7i{zvBwwg zq5i)WjUj^i_cRmk>;0Ep$5SgD%~a60`*#1=+v->FTA8;h6lnJ!JO5f|ARx!Mn|e9T zjx0JP_ObD-1T|LfFwp()KJEYJ%l_ZJJ$zrmadEuu&Hddqu|r??$)>cpUBPjrDbeRJ z$7ENr`evx>+%4+e7o_W2;v+=tjn&k`YO7;CwjKKIW;4ElL)q(QQ^GKZl3`ZVz_M!TGQHbzr2=EIS^Y>x)-^s}G&SzXCaZEw2*}g&CTH?MD;&dNdYqTN4)@`!zXl+uH zEH%U(V{v4U2vLDI)SG@=i{qnZ7IbE5T{0YHEv-e1IZsAOdY2XEJP)l=wdd^J&u3g~ z<6wLS_vU)viJA*q?Y*JnnOV#{1+Ub^1Bdk!nA z+FU|&)*RkbRATTAA(TW$IWa0$qwAv}1utI5Lw?O(Jm*SRO0&g+!kXE&YeXpwb`9i= z-M)gi8lHy_MvxeSM2q_8>pOn?zqpDMi9ISQadQrJNFcyF}MzrM@tNAK6Xx}cqBS+hLf zTvzENu`-Y{Ffg%N6BQMrYQHpjzfu&xt2J%SZn)l}bzfri#i@PiUb8EC)HN{)A^7R0 ztkb)GQ7JQzPKk=~u$wJ$wJr|RZzjQRV7G7?BjvkxkpmU+MN8dlV$NkTl#EuQF_1lm_LR zONL*QShu;~!7Vq~o@$Sa;$th5EEbbF;XGX zIZeR)W3ZC8=%>?HH%knvBw8czq&cS9#SU*F<64*2S#wdWD9Xslh-8Wk4-3vYHSt{j zxAHk<{H%@H$JB~0=Osy-UiSsNny^yyRcAQozG!00gx~kgoT%T-yFu%D<1ILbTxbT$iM%yTansaAM3={ zAaA^GjW{mdSXY@Hnr1_r38K`zt9+|CQC>aQ;y4@Qc)IRx9WDlr2KPdmYP74X>tPP1 z5{Hps*UOx;zc)cK)uUMscgC3w)w-5%ScdCwtqN`5wLdH<3{guGS!qF`wDPSwUR)hk z*V8<2+3q*etdH@H@mzG(l&;&_m};nxUc;Yz>Ob*`&}`|pQs!A@G$7=@c&4?EFw*6` zwXoK+WJW=(=5BZ}cD~~1TQEV}W2wVie>1s90R{YSQbsOy7Ise*-g(AdAV?S+IQP*IRTDtsw zgG#^Rl_Akp`IO)LZmLhWnQ(5bRb9WHA0}q`Ax@HXqk2OnLoeBIw#;*Pb&jR>we*_O z(~r-&vpL6?oD`YO=<%?Z$sH<6x799W>za<~6okGNGj|?EkQIGxMj?(c=5_?s=Z0q! zaceya0#@YE5zCIeaOujJIy0<}b5|B3e{@0-HG-skuJCP$5jW>qc$&kKhLitoYxWFE zFOug?QwAX_KjZ5(i`MdYza_J%gbCu$DtjVP0veDYSuY z>3oTGXrx?%|fDXjK-lzdX0Hw&ur z$?8i=illi{0>SSOqh6lD)j99p*GtIpkQ;GsrcnvGPoA8mM2ss$i{>jtuXKHj^po?eV^ag|dV6S#?=?s&V<)^e9E(hS(_<|zbTi;hhwI1f9_8yP zj*WI8W*#j~=bc9VHmzgINBNX_*sQgzEjKGO-hSeAnweY!dujfvi2&}}vrX-}A?^uv z+YauI`Nj0ZxP3x7O~#0YYR^T@r+Ri!3>>Dq<(XtSg*KmSj`FjVgf}c%dVN{ghk^BZUo&SK_NHg@Ol=SA&Gepa&qld(CNKt?{AJr>N+goUp_cX$a5GWvdK%R+>m=2up=Qf)EcjV zV>+qxZh=v{^zw?BUW|TQI%{I_S>Bm$PPS(1o)-KbmXU-6zLLSPBC~Gdj|DYe zzZ}2RqZ}&TG}n>(IZr!pWI~q%NpE!T)aGU#_!T zwXmY0(AJM#B*278EcA(;8h3<{td$*6+VWIg_G*Au@Ci z{fIiO!&DP@ifalK+s8RXPVva~!4!3Qg>|W-%L@$0)KUhD#=I zb0W5%-{)C&Jbn7q@8P9W2ur-2yqGFfB%vN1e7M7?L&wIFWU>S*=dU-##A#@~2Tt%i zhy~7i?3inkw>Q+DeK6G)f&!efGIzB2BgURi--(#E{)3ucjQNg@^$;}J;*o(8(Tl-JUCjmP7 zDEa5GDDH&E<_fNS6@#_xKw9uT7}mWjK`L!5ag|>Y)5aW=@Cdaf%w&;+$TL>$^II+Q zxS;UW+plxd%hFW4e#Q@$AhGF!s(4BdW5tEmym-C^J3)a&lMvYq5zo~W0kclS@~5^< z#YU0c-Hr$ml;dd2$cx8J$gp#oSyGF=FfLbKId!PbgeYj)PCBF$n`fmMGV8T5iM^Y9 zqOvZgRAv{~sCV9Rq@hL#yW-))l3iIwQ`3F%DVUTYr&C4(_ek~iYyHf-Nu#5ZiCwR5 z%GZS5SUoznw)8B#vNfY8SbKdj=l%Blv;)V^7ufdOY&09m%4$QB=zczvqH7lo8N0-T z8r0H%uM?i#CkQ{qDyR2T=2%gr`S5bTFbyLz8gHVu<(s|Cg~1xFj;81m2LN=i(GpVA zy(ZsI7#8^se17y$K*c-0LuZe2(Y?@6arrQhIEgV{ZxeaXh1hf%Pm&jbpgAj4v>FgH zlVxno6mnHY<~epvURBhiiqY0?Y&8D2=Aufgs<|Hl7v+gpjcpF&aib6&pNTIz*x2~@ zZ06N$ZuAVcJ2~L>>hbt_3%aJ35{HVWD&kf~gE4)IRU1BENYN0{`C*(7Q^-Y_=?q|8 zGklJL2#T~KYUY|@78($R6-P#UADW;l ztrcc$WUpK7)GT>9G|VYMIaZP!;yqXAh)_R>^g8@9N;ZnA?-N#9!Sl+T_ zIUnCtCz2y|A{bLJa{R+yxBd|ZpCuX#wQl$(zCF{x+s4L5q@yP}5S4I*kb$OTFyk|L zyd%jy1=Ju}FhWq`MtFkDeb}l!p%c_SoKE1Pjtcpms_K)!?KN$RYY8eJNnEetbtZEs zO`dejh~OEsZzw%y{_sId$RdZ5$7R7Z6U2Y6q;8JG+u8g+Y8_0+Y%aENX*fEhizi?d zN7{DLGOb4TIXT5R9A^-;Xk_;4&oOVkt1Pi1$9!2!5or_dDKFdBFRGEFIY6S; zL`D3pVOIH*7zH&ds1Zm-Vz(#J@jmcWkDI)-VNxd^wK!R~F`oTrety`716JrF6=hf; zu^b`8jM1KTFkDqyhlCY8#pLVUvW^{Vk`3cQMZ?r<)l~$jR8~%Ib-Di;hf>sYEH-hp zWMi?TqMSp_b7OTOghM$@q0qdQhjXgC)cyXh1FH*T`L` za!tROX#O#E3(~L4!=BOgwrcYnRHRqDjXE~y8sYc7ANj_% z84gtku~a60hNU~WcQ4RW0n~=_YHg}qpQ|1Xg+F7(^LOC~w0x9D2ec;(Ski6#r-$lT zRu>t27l*sHdHymK(|y5>x=rl+IXefB&qwyGvtPWpKIOf&W)kb^H1k;+a}&_-px4Ua zn?`uL7=F{H_dbW+=f5--Ihv;lqx_HaRen05^2p;k!Ri4O1R=4`A82 zJWk@siul!yDR1u{&!yw?Lv@iy|NPToq=^kD>A5<8Z|Co;OHib8;X&xwg?@5{I9 zLg3`?ee~TmH{8(rl#g;)`QlBB181-P*RkI&gmBIO1U)08<+g`L3P!$ zB63`tw5bSm@+-SRITWM6!p_I1|LZItsgMg30JYW6H^~n-#FoQ70)cYx{(Y0W2sU3k zJG+5Iw|8=O=((XffRO1QPl!6)&Ni-VnNod{latdRv8KR+dULZHofrYNkptx_Br+iy z5lDy<0p`plKw*#_<0Tg?57%3@Vc|lqR}Mi}gy~E?>Uve?lNw zdSh)#(tgNKYcMI+>x6`d3*dFDvXvpIJvFhvA367-8f|k7SPcA8z2zy%2w|x!ZymnU zIKgwq5?G}lTt^{;jmO{(eA82JGOxI}?v>C7Y|Ssf$XYv|}`mHtb_oF-)H?@_Q~lD|HUp z|DHp^MMo)oWq%lF8*>}iE$nazUq(Es(w{U{wpN}l)_{K0>^`+Ig;$J?*PjPNlhFUYj9De$7I= z#IbrlEQQ~){r8%1ULk!}npckfei@xk!DS@0zUKnAaL=78mwVe7)er4+-bS+=V(+Hg zV@TzCBYbIG{5Z~ju-*B>hJ)sgq)1XL8|pWsXa7%LT2RE>)i1rfbLsuzKfe^*QzNjLy^|C0vE%=!&?(%L!c@|9CfL5_!FX5zs#fXW}&7Jy_A`m zSx=c~UE*0(<=ViT-OQb@Zr(4XQrGFu0X68%%uL`51jF5WAqbs2ZLiD7JTWAygL=?e zV2g}>{`_|OFb=u~mP>sSDw`1RwBN{CIyyQav3<9+$6o?#Ze23-sBm7ctJqmT&jMHY zrxDpDHdQ;Hhn>ArXFGgPtC+VT@$K8U6CL?U2?@t~iePq{s*e&usi*`-MR|Pra2n(C z`MuA_H0_26fwAencR;?drN_j^mfQAU!`Q!n@<&~SfSA{Mf!_77$+qk&OQU>CA||2! z?)KdZII^W@{^Phpv3)BjGh(8Mh)5)0uwv(_MEUS}i~Re3)z3u1QHrq0#7Y9^ETfu6#__O(A#Wn6hvt!wf>lK?Js; z-8@6K4`zAYG_Bm}>FH0OKHYrxs4ats9+t2@*E}BrAl7S@^X%C#6Zt)5C2d^K5!$(& z@qG~j=43nz3(Ix?6N%5TX`{vBJL($Fg<*2eh+c!MrEVXm#HjkS-L&*W$@22dpAH~QW^ zmftwYC|XTYR!|5Hr(=)gH$CG$dc4VOOf8{Ja$`g}i<_XIYeosz_tL}`cOA%oJf1fl z|4bs75v3@;x!iA8+0@izxH;D#nSn|QAfo}An0FRrj$d+c$T`^x%sKQR7ENg@@mBmR)(ZMSap&yfPT=h5i zkB!LI*L^gyy6iRfF%6kR+5LvSlB{M){+L*wW7>?42H7DcGYjKMN$t4$K}TXO={kFV z2Me%yE~A7b1$qb(OsSirc;Gr<3$trkQdh3ri)cNE#CAANEcLh?OgmU*7MoaR$RL}I z-0HM%kln-yn1|H@B~%8L8`0Bl(e;#{%k`S)RZbBRXe{Kmwzh~0s{(Pu{D*crSOliM z+`C-O!_lgA;bWowFnN7|6f#x1q?fi_m!p=ZCEKZL?$0EyMHlL})Zp?mb@FiT$F~oE zPt1zorBC75bNAjq>kwt?7?ZHgrE5`0WVfv*WJk1pxNl0K_&mK z@}kXykJQ$WgtXMw)luaA{IF^53d+jib{p?ZAwkSiEin25V~dCQ#}wG&rx(UrYqXGO z%R$R?TO2nfo+6z-dsgN%3N)CqqCngANb52}xkDrY=J4{ZO8eW6!fI>h7KUqaKqIcJ zC#ziEs_xki8rS>7%D3~h^Uu^tY^~3&%8P`IGV^4_uiOGytT07w2IB&U7<7& zC%3B^*)r*xSQjZ|UeVveCLfk;27wZCcLYSy9Ioakk5kMm^kagKz-`!Ehm>xr4m^D|p%Z=CW0u5G>b5|Hy#bJ+ma6e$ zUwnK#M4>Cp{)M`&?>2-=`I#U+7{=stlJ!c9B979E&wqeXjlUyJJIL67BvUz70#He+ zaVbOkV+)KhOx2g~@A8~}v%3jz$RVq?bLUQoUbRMft2@AD5+d3M`Cd7WsZEesa*LE( zYT&&`j~pMS=u?Mka(bsy7YvR6%ZR;1;37yb2STV$7tLQ;+8i}x?I ztqP3*mS&W#64gpx$cC^3sVal%hNvGO&F}F_(IYO!x5)PgX?1ao4#My(<}{u>BwsPQ z_exyvzAJr7G&J6JN*V5!d|0)0>A2-(mxZ**moHx?BqY3jd!_Ey4&FHc_>t#t-rKBT zRaR41%h2PFA0BB=O5ts)KCiVXw~?fbhkVa7Z?#%qp3$1o&_Vi1sO1r@9rr}k+(@o= zfR;mu_j;;g_Ay1hK>#JYhg4gOeh6>`0~7$Isuud2-v$4mvn)aAhA@#NcO&`Th>WBE;k|6UR35xY7uDQcD=v_R|_>P$uu3@f15)JRBOzh2|F zN_-~lG95R5XHy^sCTfz>qlXVkL1iGYB2b!XW2DVUy%V%h6UA%MYTDs^oiDEL_N0&I zhi&}?>{j&<>o%x#+QiO@Z#7Wv8Iw5cGs4O<$xV%bnbM{1=5TysVlIqy@E=esK^}=- zAFkMo+)!KcIT@aMR(>HOCfoJip+o;fZdjSOm)zWnRxb$ghMFy~Tn{ibG>j5=|5(y1 zXVnpUGjo6H@B8-oJ$%}+s#jf8Qv*9ZMJZtOWxXuRxL2@pc6oUjTJ8w1_vXrQYU;WE z>s|a~j=3ovTXai>Qt8?-H5R)aZIs&i9A=-IhabEbRcwnHtZ3UTUp!{r!6fEXtK-H7 zE&imEj!smj)JaJ%4-l^_m5r&bUbH_+;bBU6bo9pbJK9M3?H@tAU1+#=qR?|U@|42! z^Eayk7>869J4#&bYr?p%`yG4XHA9v5TaP2@qXrwVGj|o(#uxIxX5-)xy8R)}Yhx9X zTO;T8AJ*E?4t12P(RUsPqdL%An+&`fg-&ldqcuNPr@oe3Ie z$fE-cM1D3Ags3PeR92`d)Xa{ZqUopp{Bf-z;x#imZr|^}n?pN?8p-53@JIg=;a|8O zNpDjp8)x<*?(Po6hCe52=YL{dksjLZQN}RVL5Smp@CyI>1c2i-R*c`4I^9|U)}puQ z^8aj#h@nFC|AMGR$_@7X8)=6t>TPceqK%E)+*sq)FY6RG2>u0; zA3F&EYks78NY(kj0C>4~A)eW{+D%g42_Z6-z5#a1`h8l70!UY`@GWL$y~{iJf2=m_ z49&?Oz`K@}mDOXW;^y8g^7E`ua##(C=ZoU$-E`KmkB8e1Pxv>va+J$;p4~9>-C=Lxhb9BwM%vzkRE>i z{{DV`Ck4zxW3)R3XXl%h)l<|I5;gf>YEDIBJWVyTbReJyX;Qvnd(+9qHkV~9+GdUG z_ddS9yWPlos%R|z`Sa&6<;nB`qtoBtk5M!ls15>x>p~dp!EHz{l2WuN+l|v~Y|^D3 z>oZkb(~l*SS72FFj+3^32d*vhtqN@PtT=^8K}9aFY$M>~-K;Xr-Y<)YY9`tb*F(3j zfro5KQJ;cx1UrLua+>N+BP+75R9{<|zeRaMDbu8=bIXqh@v+Q-%_a3l{3Ew9(tMkw z0dSxSrS<8$#YFXt^zw{_{%4Zp*x)zNC(%AxHhovxiZa2Db!iUsea<$V+W{iecIa3i zpGxjIdgRDrhWCa%R(@2Y+-qaJEt@S6aI-k8I$sHWp21NUDtiCPDmdh5q1ftRv@ELAYeg&10rN)O16WA?&AQnft`D~N487@ zTFw91oX?KPee{U=k|vYg#6&U~%XRhYRev_oNUkRgKlu?Py~?6R zOdKF0$hDfY-muY7!Z8o2h)$$sxF_ec^=84)4$o_69`B&tFmRz$M_Xl@CR}}daP?>+ zy8g!0PF&9I##@jpLru5v3P#^HzBQE(Ya1)@uCL=H{sM}VPLs_UldhvVx-{A4KH5U4 zq=wMMr_A_FDHHphwpV|kGjKS=a2d_q(~vKOnZ_ly7%g9s2tBD3J%!VEpyTABMfu z5>VF{)k^s@%kLG~{@}fS(pLjrheN}|!*Mu5cPVF()IA_O@7>#mDjfEgDUwlEmUNv> zaJ`FX6tQDvVd;l78`{a!DR?W_Izrl$H`L{MmdusVmd33$-anX`C9S(J3Y2@S%oY>~ zdj|P9s~>7*{xU__w<< zF>xQVjJr8PcX|Ge52#pTh4JdCL)ewWQurb{Bd?u(hdTGt^eWenIFitp+PLO8o`466 zyuR=4=^x}=FyT&?`jGM=+$aLOLjU0EkJX^EfEl&1r;rp3VvcLi;~yIfDEZqhB>&HE z?mQLu)i_yl4ZrOY6*N$Nm3#KDtgOg~^N0hz(fy$h_V9e;N7DG<`g0Y61uL& z;{lZ->=pRQ2wKI)t*@^`wWxakz9mDy90H}4N5#~Tm@>4u@AIzrzc6^;@J93D9LKSb zFRnfowCXIl5q}M|ZfGhc_`7l}C|!ZoOJ{#w5R`J@W+fUJzN@~nsk2w(nyS(2{t|z4 zq|_QPuvbn_PE~}M`h00`;$`Na?BrLwqEF*$Ig&id_yms@_sn2`&Ip|#e z`N*DB*edquKVGNCM*lxA{olRx^#eD~pE~p}q)Nq3@W;jg^bqQuEs=#$3sXJbE3<<` zO{(OY8Ze!ZNFf}Q8UV(g(BCWf0X?duq$C)&+zG6Il|O?JKnSWL1GCCd#b$6sM0>uq zzQ9)ReOjweull~CCK``aKRyhwQr#~72kcEb8O5AZbqeizythi-+OkcQeS|9aWntlK z800<1g03^|J#ZizNP#F3dnV8M#xQQ}2=irmD7tkcbY+F_SV)ko~?W+9m8XQ7L?r0Z(;^g%GLkfB5hLoLeb&ZBZxDKSA4Io@U)Gd$WZ32+mNTpj^hcDfIW)Q8_p6H&YfbXJ&{X6x zfvdqEnB2acUdY2*6vf3|;tsAOZKl}VrlevDwRB&$6HrNpUf>Z0PDUj%@DnaDFm99! zsOwO2C7p0ctMZ|fzY>fnBv96m2F@&877mJz=H>+qmixIS6DCrKWBDgVKoGJb6O)o^ zR5$u<0NLXe7CL%1ogywn?F8k#{ppTp;CN4d3%d&zyUSZUy1vtb)wRGtCxDbU8&Crt z&_bh{BN(6q-zQa9%MkdeWk_XhX)1gL7LvH{T2>*IPp;DzFvp~;g=fD|YiMW)2WInW zaC5iETwM*riuA2pw?Mkc+)+QUaCpb#U)hsT1vXi{YNDLm3b3uL2#c;F%n-~WfKxg+ zQFs}uLjEN63>N%o3uK@J0c0$+Nm4gMGt1Bi5&A$4$l%fdRyIn+dj^u0ct(!voN+0B zw#_7##NO?_ya3=6WgSF6*)Myjbler4SwfqNDZpjTkiH|W293)cF@ix>aX;=+j9 z+C$sShjmjQ?yxS$430*hb;ZFlH(v3qSLE6x2d19+<4PE@q29D2^Zh#oqg;C6-Q=uR zc{M)W?k-uOlIWvgps!GWbSA|(jVu8CB}gBz!zaw)$U;68i2wGr^9mR=`cDQ1F|(Gl zIL>qDNj}mhdOf2g}l~X(w48Uv&y?XC#2?mmIW=d z{MDbJ7nC`%akH|q$+AeUPrvi!Epu64w#5vCRFbNZ`Er#uYqDgn{)C-O9YDqI> zh_JV}x4OC-n7E4f?{!LCZX8s+rwK|f2ryJJH`1y|cI(BH&dyHYpJX?n{DLf_y%qaJ z5!9t@!9g|LXz!c*s+wC7ICPjn=;4K)I=EAsf?esZ_;x5ip!vkVe5q6JHW0SM2i6?7 zZ*F!L$;U@2<`*UHrwg2CZswxT*PaP{5H>$Q4Y3^lo*FXDoN zUTmEzrq8cy4=twu2RKpzKr|6Ift0oTHj-4 zwYkIW3UDt~*cxhUTYe7VHM4ee)SqyKTWfvNxjaO2tTkh++kNWz=(h9r^+Mw_(MJYrBN+bS}5A;rICvDwj!!|s>XZqkT{UO!};Yn3%V5AM_r)OeP zO5Jv`FN*26?!LbXVJg5|-8jEtnF9R@c(FSgJ3rZY-aDl6OBn`5w@t-b8(_H0^48ZD ze~G4W2q#BsXwWZm7@6s>s{4A9>Qvwg=Qr)w@rU+1_uob0ZzJNr#A7Nxt@@{){J(n% z?(x5YAZlFoR-y%QMDMLl5X_yUov9fOjn1Bc|27Akf>_{2(zY(e1_$3tRy89kUI2y# zxYT7pTtg=kZ+h#%K`(L7)ttf{)^zhW>k7U9Ae5-#bXF70;J_-B&Qvm(Nt{022gzGt zx3UGiPF*mYd~IUH$83`Z;FH8R=9}GQEiA_Uj`Quu$SJmm*7*aVfm}O%`ZUnN8{i$P z!(KG@*2&8MDkX=#cjR76`!og&>U$Z1a!4v*H@?O2S)3%20wNDg=70b|#J-8SRZBJ7 zo76{T5>0E-M|pGtXMu4wuUHw*2cJDOIY5!=VG&5oH<*G_Rh<`dG8_WLsXmt_?Rhxs z1}Xr5m+Bjf#cm9q%keSxVpdg_Gj#0VoII zO(Fd$EiFy8i*S!pAux^0Ti^tT)^5@%K~n;M{oi=QT-_Mq*=?yPj-oQd`CU#O0In$R z*Mq%dT!(NyTboOeS(phJLjO}J=6cBNIUmHIjsPP^KOOE@8I==7QbVYvCYSs7=UqPi zhfJ_6lySqxS`s*O}C~@TKwU5$di2-4A#x+>=Sr;<=i~ zb0iDpo4$;|0sJ=wUb_WO%#l=WF(A-GkHzJKS8Rt5z`X6d58i&Hz@|vWJ{cv(brEh0qtSpWz_9RLOeJ~% z(FYw*eF%I}9-yTX1*wM}fwlx1jU&e8CHxDdL37*ykF3P%HCUU`2m+|QY!hFs**2&m zZ{<9vgouKy5khQlzx(aK3AKhzLR$3*kQ&$>(wMW?Pq!&J$#Pj~W<{MWuFcRX%mTbS zx?lb;c^R4WISJf41u6&z`CcJ4BD}U+?gR3jKV2v*O4aKeASj_z%k2yt{VxY665M^K6*P(+05;$dffh;BJ*w&%H zl4h!(11&t^+#Sr7#em!ltI&lQJh{3$P;rcTPv{=RH+UD8$cW*wy+OvPgzi}agNdHi z&`}>BAISDfx@CXL;Rl!A{OwR#YBxrZPQyMR!;8SjE5Js_Z`J}lni|~$zd<*Au<+>@ zMgZ~QCp@^nKFrBQ3RwduI1Q%&;%Ft7<3Je=zQn2t>J=K;rkyb{;gV|{zLOw_o2q!$ ze;{7wq&;}>qw@%K;B=gv@qe&oD)PE~*qJ0@fWY4Y9gv$QAl){FBJ#;-aDyOYN`bl} z#ZYlyah4IL>^nXSb0K8Bq%ZfSKXJnB+}$1x@ymPu{ADD~u*8!|q@c?s>!t|jy01@G zvNl-^xYpOlr?LO3aW(ogcz}Zsy);2kLfwQarLwBH^E;7l^Iz2UJuzHX9!&|d!EG(7 z;;6kOE#Tm95Z)0lW75m>+1p5#cvYC-PW>i38@YN+4+65=Yt7P=aAC#J#6$v!0;p5zhlh>TQZ8xGhbJ!)Mjht>2pLEQGSeANJZhHRjZgegACbf<3gw zbM<1o_aBRsIK?4yne9-kf)NHKeGi5-FuK9)#VqEekY-eihBK<^0FI%2&G#ff@%8n6 z_G}AI`sI9XXk=q!gT`%E@dp1*!~{2KP&j~$K-Y~WCO;fl`f#&U3KAiBz-jCwoCUfJ zPRu|LN4Vi)V+3adNN#L)VbsFpCHM;T{Vc}~p$$LM@P`*yn*!Rek|d$J1Nt@Po|siL z3};mhI3XZsY*+=QxQt3Q?^DCc1t@Jb5JF+xlUV#@Kn=gT!w>Gf{yY4r>dQ4NtMnbT zK0Hu1fR#6!*>+gjd-v|K`k3;>ZiKuez>pQU4ha5B z1M|xO*8=Kfgd<**s;%a27Ejv=XWcS0Bf9OqB;vJBZRfyie}yYN#Q?ww{#Dz?NSFzg16s?wz>lF*fY$DtFIgM);Tjt*&3 zf71TI?wbE(1GjQv3 zEsTqc3t&qiTiD2wy&>m)Cnu0%slUl!0q%$;kshmYE%|0RtnOn~0kw#s=Q$Gd>s`x~4+Pk-?pbq+N(0j$yhhg8|traNv57zHTTl>v-mz_0}d20{(kT%T(g zqQ4jx7&u*VRR6g=udlzqZi!1KKwEt7xX?{yNex*s7zK-abUMlI9K_u)4h`kVeG64SJv)^0zbr`v533$9YPxIZ_FDU#kRm^WT!E{}=J}Yl3Cuj@s)${5%@Oono8tpe#(rig7N*FxZ zV~|O*o&P= z(li(e9ee=2V*reSr%bOj^fma}SWMO6Hwj$wf#9(@aGZ|<s(lemIM^cK6Sw?ep9=wJ9|IpY z6}+RrBENVd6*^wIXJ+}0HWLF!_W+L%GaQ&#aeVX(8k}PPi3VjQveez~*cJ~*)M&*- z?En?G^H=6T4e-+ZYTJ(gnB$!ZVZ6pLu`k@fRklXf11iQNrPPvp{~P6so^b8 zEqD0)S=w(5(j86I*(q&`3U~=F7)Tau%M$$d1EQ#vkR^3KAp{*BMb`Eb|+dOI!Xc(Mb04>@2MLYSGX82Z+N9fLvdi%PagGKYz=AeE=%W zII}_ZrI9HeDziv9`S56Ml+RjgrqvyNF>udm`g!FxS%gg;`Xvk_P`eQH$(@Pa-4|2` zVaUMnvWY=XJsmhA%SrX{6}JFbp*jNe%@icm+|vtFF`s2WSny%JUWukCYBLfjxIbXB zj1hGtW*Yv0a4z*jpiVAFf%%;(?11Yfx{ki3UkaFPn7d(&GsM4oHC?tgIo6(=5=!+$ zJX!-V*7(#O4P9&Aun9^fP#fkIBG(^nT2XCt@`F&r)Ta90S5#C~Rc%4SYRw!82@W>Y zM)m;v4emqPDgGF$f8_{%_@xE1%Y}ns+DFc5#L;h=6a#46d+=a@pI<5<7NGD~ zOJ@Nnba^gysdi@>$uG#$25YyBn$Zp(0``i#<7q%Z7>;Tr<;Ko}Wg{-`6p16E#$+pX zu`?%(gX0AnCzsuwLkZG~#zDNvz1S=j;0$F9;q!JCD;NF=z5E|qwSgu_6Kk)O0o>D0 zn(4s(lSZA^h}!RVvZ!OEL;6=_E?>S&=!{`~@QvJyIQpkHcunH3`PU{^NRl~zyXtiH znRd*pc6)a#l-?Q`osio|353LxClHh8sOJvf>v!JSbF<>e2 zUhik7c2N*w>IAl3hqizC@ZmZj>&m^iU^t1CKTsmJHzszjrKJVD&qUXh=n^@AD2fsM zBH#`fdNU(>*OsHS`=;x?^v0EvBML%(t=BEzeZqHA;7|b}BD1iR*<<<*Xw%2!*GZ2( zPi;H#_puxV^V9F}t7SXHqXjU95U*fgY=ra%uS(6aF>vz^x!t{V&=5>7;BbUy2z6K!U@W^fJg0TO>pWX` znBMsq*+Q!9nq+KYHT4bEec^`PS@xIwg%kAK%G-b;4QL@eWV?vS3REZJG`OkY&SIcR zf{hnQc{v?%NlEYiN`E3=Vp?@^vWwxw2~p$PW2Nu$(ZI`Fwdah0!uNI9Cc-I0y$q+m zw-3K@e{*nt#O(#uO9x7nYwzp3U>YDv)Wi}y9hU${8Xg9?z*yQ2hUrt3gnN4Fk6Q5| z@$}`7Sr!(;o6yjR`MDz1*w|urw07CJ*XySEe3wlnxz)r7nyHhEPsdscgZW^@@6?kx zZE^~hFx&wEZtXkXNzWmrqk(FWf3B7qVdq|*F61|pEMJ^&C3MrQ8G$lY@9w?@Y+|MNWmwng zXTa&fsd!Q6$#Vv_3wGadC5i=o+<+v!48$a|9GG)BE}QI~DCm`1?d5nJIm&XruFGW% zj!pzMy26<6DTWMQ1E$4rvv4>j<+wm!{{8pgwR6oDfSpWn1f0Qr zLH5KtFzrU?gbgb9r@2T1L^mU&E4!L|t_K^O{3b6as)yXbuTH8!K!WO+ot=#->Cgl=W*PRBpib>1_yh8VHm<1iiFyqTJqX>Jk5a|KmTfkKn>x&OpP zmsgx9P2DoseN2X)uJ_}CDrRpqAFv1^=Uxo?r?xjFQWvGwqW1r01LX{eF~0oL~^2zJ1alJf+7&!j~%dS5MQcJAEiJUbuEoJS-iUB zo8b9)$1*)s;Y42Y;=}n za}l8UEj>tVt=1TfSj6u9yT+b6dWMKrU!J4Y6DyfT8)&ig1p#WFQbH-G!T!a&_|fbz zlQE)yf}8H};j34!_|dOd5^3N2Kl(*9gX28p*Gi9)zRApKE`EvLEL%`jk>|l?66-W* zQ}>R7jp6C%K7LX@8+>E)uNaTlL0;(UZ&2CDU5P=E&La=a)TxJeEqCqSJvNwywFB9q ze{$icl`-h<8aNpZOOn<3@Szf(s~6YCv%#KEYTO-><=C$`^7k_2e)A%ZQc|6o%p6lz zvmRIS;X*>ewY0HeSK73Fy*jb)Ay4^PZhp&)&`r`!i znEt9z)(Hd0FCQ*@w#d!7I9528EWF-MD|PLf8B>10)A_XSKUTpQfqCJElGY;%E;v6m zw9&6WgEBHPsX33JF7uMAv?;* z-pa^GsiZ>4xFjW6$z^4ajOX~!@a=a$ujl#adA*+gx^Lgh<+{$#Iga=7K91v@(e&SE z@;$PeI`_-PZg`y4=a&Sj-n;00RKxwH_nP)b*xa-Dg~{Rbvad0*%N;S+M*`injX(9u z;r&TIAHEH;6RoKYPFPnXy#>a#iZ^pFS6DmwCF$}MKgu;3OmaGxGQIM{|o4E zzN69ut6=)>MZIMvRE$Ebx6lHJq3yhm0*n5%B(#ooKLn5!g^6=uiE?k*p>5Cog4Gj%V z_WUKsBroxpov3mj&gi(CcUEfX>w$*{x!WZ6Ri5a*_UV>YP|_JI@!S!TTuO2F$DJSI z&#e16e1|Nh*Z4H&qsM?e1DwOXX}^6j29p5_%ztIDO_mW!MybvJboUbtj@t{ruJNLL zGcVWlR~6CK^Bd62H!PYYWrQ6#JJ~5d>x2&Xq^eRQF>ay%DNuNgK0{xSd>%@AkkBU@ z&wR}6n6L8P`v%>EPB)6ucM>%zPAP2DcYd6_O^-U{Y)$OVKuE=V;e@)N*TkXL@$H*z zqS}cJy(fPLrrZnvhw@I-eWS$jW1}>S6GAX1qvSrC^(8E`^!JyV>7`UTb(4h;D zVfpSSdnmarC1AWE#G&ar&QSNGX_Ed;;q&7dC;KhO8ACMU{g-sTe{eNS;DU2?8gGz^ z>rZXchg7OslaS8`jP2gWZ+Y!l7uR$mMd7$H$GuM{d{ho3&+2w@}c>0et}P zdL<<#ts=W`o+-L|4*b1u1vQQY<_~Ama%!TJ^H$g5&M(C&_xq&F-=IY@W=)b+U zZ;r+Zr4u#-cqDW!tgGc*uJoJ}&()=>wFo&ANWNni*Lb4;K#T0UJ>1-tx@4Z6usvkM zA^=UB`s9hB#dHgxx|KZI-l6Da6d_&>)ZujxkMH7JI}d(v__URKUJ-F1IVmndnlYKO3}Kw!$G9f;qwZp7FFn{Cy!_IZ z%X0>Jj?O8c?Z0c4*8^|_@teIrbVMC1yuhLV3y?igAc1iwYb^r9G-qc2D?SidL7NCt z&u#W+v(&L;w*g?$aQL64)C(}H^JKhFB`*^f^)=5bUyyH81auCSLw9zVf!qmkg&4{-OJ(2wJie3$-E4?TMnqxZ~fY#-sD)9Del4h@)*v zY|ZoA=a+{vj&9q#71jNy(fyQkgeO{mIlbbfq~O(e>zvnb_CY_ynYU7dE_BuNfq!1i z%}aZ!tz`|baL?hBf=JixDHYVxD>hDs$_X)~`r0}+adB~OZf=M>rLGv;Ph=>AR+ z=lVF4QP2hDc$0ziz}_kcC%3n^zk2g#Xnf1L!bfORN{Lg(WVO&QU3Xb@#Tu!_6qm5! zBwND&SKNI4DM~4#NXyLrhUOuG#?h5F4r=@IPo|72y9tV?!eXYANRa8^`FF z7=rFKP9jWqYyyMhpr*Fa(@%WwJZXDCr&clWOX~ab^xnOD&M1TM_ii3Jk_GP_;c^21I*5N4 zEQr#}OP=4l^_a@_Z-c|bTVXn4tJYb?uYdfw^y+9Uo167yX{ry2sj0Wgk)qDQt5Kb0 zW@VLdiF|;EDoJ^U!mAV1mW7GQH_)zmKTutwlLui)LR?^Quvb}K9QN(|_qX=-qOyZO zgniTD>4A}vII$a(b5C8_fh?jnF+P5#`C0fI_ASbl4;qfPVIgcqh6fBfnD*aVTX~^@ zPiLu8M+pMs+8)vxtm_pk1Z}^s5AkK-FKccVKX4$}r2ljNeq$=`gl#R~zHMS;BwAwV zTBONKKq&UDr^n^z=vf(OcBpcIMDf@WgOIT1v3cz-8D~4za)zC|cB!rgg<9umVZouG z$`-xpdl5}&q9R_YtgLKi#+H`zbR00`xDSdjC51DMC2d1m zrctRQn5xmyQ3N3D9!Ue>Qx^m&=Hao_>N%#${P|AY`j{XFm}i z8+${@2s5lMs&FpWnSy+SWj_ge=wtk=sHVKv8uG|$&WnOHVx)C;aOa*H@yR%SE15G5diip72 z(J?55h8EUrV92ExUH1>4T-9*(`FU0}Spuxn3m%uM3-#|?vu@oCbR=##4F=xX_svdm*)qI zaOci?EP$=0?L1W{@wqiv)U5Bdj?iAv3FX+e%LGj!U-g_k=P~XMnccg0H?D*CiLfYk zL~`q7fA^%*zw^I7o?S%J@^xFG8)MTpe2!YBJ+$o2o9jy?A!S2^nqb2Xc?}H>o zDKaFbrn*dzd@yk8pyd#^Bh&C-K!d2%KSo4EL{QBS1TefA1DR~*Z}*cRvvmdk1N|AZ z+xX?lqvl3nD}>~>1Fn*>p^l4gqR|_7zBK5fTv9kFPXf`_ z-flEtbyU_Ei(W)AzYw%WwkimlR$sM8SUH4NM}P711e@iT*-ug}F7~6KIH~kHpIq-W z*XjqH%FWG9Na#dW*AZ#~9uj-O<;$1T)6-$PYo8n(o54oKg}xl26VS7MxC>ZI z0AWsof_Z3y-+z&4nO9+bo;2)(C}u&_gKW6rLgdS|?Na3saT;XhXLFO5TwCMyKK`rB-euwYSI93~a7^Y_?x)RnpLIKR>cRM9 zrZyS^d;48$Hc0Ti@D@%s8c&>v7^|r}Qa;qn_}}(_PuY+n=f`#K_S>o|x{SsEKFtJ4 zw%PWMjsamROE1mPBQ$AGrp|5J&B}^^J&!loKbW^{;S^h}_Fnwz^YMq2kydEng6r`f z7dI1HIHhyOUGGknt`T|A+S-bqSil>Y2*H#xPj9`QzR7g`=2fF#)p!sI!^&!e<{{CT z9o$d900n65fjfIUv^Lsc&rV9yq`=|>Yb%Bwg@5u;1AaZ zm&|PMhm6RX)11H^yXQPa$+u2xV2cyk!=~Nx2%j~G*m+0qE#fwQILS}2UG*V*V6MtgYO%&E{ik>WsD4s{$wjt#x#Pe1< zuUYhNh3TD-r>N>TZcUVisABQr#jkyti_pz>TK4-Z{lzLTCNC`}K2hP*ryW%BG=ByS z%>ke5```9pP%ol|4a%QPskZ75t^tU8Q%rAU-*8ol5O=0)XT2t0W&iX3bHK@sdHMeV zoIV_wPnoBPay#+|e*J%i$kMg2Xr}l<=8c#d)n}`+tzBGQlj7Mf3q}9CT{hxa z{f*VY#B_ZKDLef$vZdE|jTh$5LqC`tGg-)-pQJ0gU;f|nJuU-iX3n#?K*RXbM!Y@to?B0=bi)iBlqn%wv=13D3 zh-+98y#)IlfMA^oo+`T_)Fm>i#vGYAQOU)i-^}la4UUb0UXPQo?fV>>l{hyVs0pyu zy=|NcK{@+&|CTvi!PdZ{rZV-FS?~{%vpFcS&ibgqUoh7W6}ZH{tBb3kQemftbkOFY z#yFxI*-JCu04*kl6CR!5OMJH9l`GZxz5tn(trTfP-7AWN@rN?+gS;ax?NC|wLLcxs zMT=*ELW(bi#9UfqDsqf!({WzbuPayv((jGihOG5Op~GOdcPtr@AGw-HvnK+wEbnk?TC+my$a}p*5>5I#LdXP zH%;s&kBY+1y*=bN@-y%$n1s%d%%u~a)V}5L#fHn#(K{?!P?in)vRa0Eg_Kl@vfqT? z`7~M{fqOy4Nd@Km7(UP;u{F5@1V%H+DJa-EIB3z#wF)nt^p)RPqy}jnwpfM`^ip*K z)dbBEY<0KLrgNQyCxQP2mtBGrLm8@G<8meU$yx~eWix*q-G9KcUjE&2Rn?cFUOU#t zh0ozTfAvx$xUO*qi*TRQOc5W9Q1h^C%uY%S4h%fDr~A*xUSx6jneE|fo6;I3asv#7 z<|1NZ&ydN6;w|&oC2M#ec!`0R;C~Dv1ALFf_POz2L7>1Qs+fjte~}+| z$eWdJyf#pCM6@R;iD+wR5LzQN1i{1E0<7pB_J~BOsirV6a!{7#ev+W>O$X_>?EYx@ z$%P4=t89zb4xbS@pw`7DG>`raRXNqHR}X4k+-n!lu+Q)q5isZEFL}5Ry?$NAPr4pE zCyv-9gPb0l9&7HjJ_S~Tr|`#>==En5JJ&2$d(O1<+Jcj>#>sbk$#Q09=5?E4`a#P{ zW%tHX>iej3vDM14z*Lh_G&9MWQMf~lXj~r(;O6E=eb+|4!3_s$9a8dG%Pl9_HlL68 z=MrBpD=qz%SxhAh=&ml)NM_f$qUli-Dv(nI!<&;8IgN_m%?s0Ks6l?GIZpvx8KtGA zt!JHeLcJvQvHd_uF;KpnZSlYug+x_(SsCG&hFb$!j*!b&O9Adj(~7%{KQt;0MLD#C ztCTKTZ4Xi$X5J(r_RVTNiPlnh%H4K3|W-|c|Scp?G8)vRuM<#cXBP)4NZ?9-+b0$Rp<^bcFeL~aMRg>6LOtNRoQ)0 zi`OKo37M|HyLjQTg&T`Xu6cQ_@?yh6RdY){V%`qjPFc;H2T$BBA`N^J4sGAg!{cip za(s18H^b^9qgw;I3p$Ir;AGg z6oS_1$k`s&bc?$3XYQ!Qs|H`$j*7SlmM=qIIQ;|!v_=os(axjUA4wrWLA2D=gWU$R zVFsG9%NDRNaYH{Jf;o&$NZ^!PbVzdk@1#<(X(FezzPy}s#|}d@iZz)}ETmGf!Xhrx zq%2;tgk2L%#Q5Z-*eC%7>o(2_KuJ3dgAzO=BO@#4VdI&Ar18j2;H!vezyE?mywk`F zK>6vZDM6`a%a=oN`xMEj$clJw!+~FTcObM(u!w5OUY7fZO|FX`SGsYCcEg62{(f<* z&w?fWNq@i|0W`6G{s7HCkkF1v{?A7Tk-3#>4q1wgpiVk+^eE~71~C3c;iUhK82?jj zE&#X-XfqIUa~sj6$(6tH;^=(B00o5w)t?_>Y;F(z+)J_l z$>*1FzH(YN+;BM@ACuF;{G?=@Eesnh`k{qj#%dFkI4zH#9+6ID%sMl=Tem}}KWg`I zgH^Xflp>X{z!ygX&X?6(?{OiKF3T_b>Nw9a-VOKlKy$51d{$RGxdvwebgw?l;t^H~ zSgZpGfkc7J&MCSs=OJjYxzE>K9YfjVIN<25lM)XpD+E(t@eyJN=nPy2U>eq_f4E`d zioBF%IZ`%zAP3dvVDX8DL>Gi{6TaHI1Y|(7b&Hmf{gj1GKK3Z(mF0Xntn~d+Q+@xT za3-c^SP+biVl#)g3me$kA@@g+sd8IZG1Jm`8&(lW)Ztb^sst2$(LW$fC)$fVJUB|A zX^-;xYthU>oaL=+;X}4b!_;B zug@1rFsB<7%>da}x0(sR4{lF;AO;@v1B5e43>xb@{6~Wm>diLoOA@1Km)h`P=Wpkn=I;@x6jhzL5lGhxsK>#ilB5&|6BAOKB*&h1kwsTfXGM#e48%K z({SnNDvl|E^B)`?_3`pTaC-)9m9(3ho`z4JK*{+wrUi5lUV<|% zC@4^sv9;yXh@wvW*pVx2D@=lr5R`&BKd1SyrV&TMCuayPpdRXPE;?s-lkDR+k3)Y5 z<{p4j;?gCGRpK~bwF@2hg;?6jq=+?{6UgEwrBrmMn_N%EzS(ik@|x^I+flpu3TsTv_g2(vm~gwemQLBvb4O#`W}@B;Tbe zBwMqy_G!H)Ih|r+VxMx)b*{4gspze&{u__=vAxPwIPBQj-k29{j|W7&QB2(yGsX#MWZ&0!9kTx6Tq=>7(g-Y6fA1yQf;HpNjeP&+2;~T$zKY6*&71RZ zkx*&o+2WTkzc_U=MognA8U0hsBH$%QleXJ%wNzmqII6P!L4qe)n<^y6>ZfXB;F~0< zIqO!Ik>Eh4CPPgsiV=k&ye#oF)|S7$5{=XqP5zYZ15fJhYsvX;@iol~lTRAR!Ro0O zynXm&oSO$Qybcj6?s}}fwTD&hPFTmvPzgun_;pYIIR4D#pq-37!$#t+!b6N4930Wk zx4`6cia-3EcVm{y713hJk`5~QRG419AG4$~Kd<}+ylve-W*CSUxVC7wJFp66skt&F zY{`L~w6?ctccjb9tm9`jQ*!G_&C`7jU%q^4HNS@84fX0n)Mn3qVt6k&-M2cQ#5nWV zpTuoWszT+uVPHBAu{?J1HDuPNrw4_F)!uP(akYQ6GutDbVqIF(0=nwLG;&$Mqk8ol zcyHcE)WJbqN^8vQ2hw&I*u|G(zpt%e>(HNJp7QU=_c+cov52M1DjhV!4U25yS3_(m zCsh5v zj4gejl|OuE@_ra|#!(=Y#JZHA-*I$IzfM3VMowp>>-8fPfx2wkZZ}_yefH*cu+mvIvNxedktJ$A?wP;c*EcR)?Bc*wo za8+Uvw|`$(RHeF?mhpMY>;o72g~UVCJI$SO{)$ z-Di$rPQj3@^uCd?yShn#iAH=)7i-KN8G-ZYxEbcp4ML%iK;Bf*R8_d}n~tgD*LLM= z53pV8ds}j`^d6~MxAmtU5yOSd$BoQMxv{a0hGfhV8qBgCtgOdsdT&lizfUp=syF%2 zY(jM3oh-R}D~B73S(?t}dT}O@WzsP*xwX7pCgXh5%SR@dZr?3&#hvD# zeaW_^7Oo7wUS6<2`y1t-ifgDpg!BS$#TtcEhYv5(ih4?TT4sDciq8yCp}eiuxkGv# zM{fG6It@^Sc4p0riV<`siU!L#brV3R9lf^Zf#Bik9thx%-!IgjuIOlME6yd(7MxKV z99ncvs6H!6Wuma9d5T*gvV(v~e$`@LlvACRwikDZQ`;t!%(A-A2&9NI3!dLL61?R> zS|ct&l}-M_9ehrvR*da^aixf11f@EGdahOzvWpF1*3_Uw@&0Ao!d|rMC&5GMD=&a6c z%v0~(@)?{Lq7kxzTA^UE&Cs1|ENC0Rq4Q>|L&sE9bHc*^#$T4RY&^= zg|ELF-HI&qGaVcp2E=kLRK<<<3SK>9|0L;L_fHT1xh6(X92K+xxBgZTP$@hl@aErqUi({mA-TA6orY$9LfKmX8&C2MM2&@SA>1~VasQH9SJPl za|Kw$a-vH0xk8u|fAA4`Y3FJFl~253T8S4aHw%s?bDBbi-vCvEQHyQ zyycC)UB`kku<7x;g!dfrKAll;;cxTd^1)GQ{E66Y=C%rDHLoC47yL9Q&I`b%hVqmsX z5>@GQlUG-h;5c^%8L88-{nziECdQ!o`l8=s@EC3Ubt*p5J?kl+t5pcj&dfaw(QAJm zMzx=^zWy_a%+R9*-adEkoR83`lj1Ur>E_O6g9XFTF7*;eDZn~bWzVQHQT4yZ8^R^> zr%Dr}es!8txNwY$BI=onfgR(r1&b)0rIoFBd!9Qi^KR=p#`U}4KLdI@kuj+3zbipV8^J1jL zofny-F#c*^{yX32RXJ!bE#x~^yxS#p1gEr`np#jC>A-xwJ~R%g8Zywfi|ODIp1DO_ zO@L>-v4dZ=wvT=C5G2yD;B@R%`o8kX@arw-hu+!{FX+I)jlD@BC^%S^kpcEuSy-aMTqhZG1agI1z*ecdM?iq^c;TD3%IK`m zaY7n9#E0is#>kKlx*qdBe^cc7=cmpgWgV7}(6%Mtc3c(PSNuy!W75K(S&(VpO?}qh zz`(%b4w{;E#N9{0?$K-ZBDL(?x&8=IX9Sdtl1aD9U0qyouS8{=t-I37gu+7IOjZxP zQ7$@fh?oWWiv4Y)LbVh;0*e+cT2K(Kd{I^9J5#PghOu`F{xoxf??w;2PSMtOm`E;> z+E450jerfPSbbi1skyt)VpB~Q5U(pmxScK32LLZ)&`aGXUcVZX*~4ZCXC6? zu}z!v{%PzK{A%o^xZV|Wy?Erv;@qku(e)tLj>+ z5Rrsi0tOI?x)mV{nOxzk*=LA&DkyFIJG$2H1oC5blRrk^gFwNWVv3`BtJbZHzw~Oq zY6seRH%jsD&W?^hI5;N{?PCX5EN_vPD*EJDFpq(v_gjcgEMEOP|H*!b2A+TX7<%Ox zI`DiCgz=8?y0m(9sxN*s{;?6~wKaqTFgIxKys0Hx=-g z6ygRik8*Z5sA`Cg2e^~I4;joFF)z^;A=h9jmGs=6{PCoDy7Cj`{GRs(t*>yXv6Z>r z*p!W|Fd5QyNq@c_YTw8XX95WnM&lI}C*t_YVdv z-l7q;iM3oU1`OXVp~WLFK70`1;=0Yuy)RjQQN~ydI80UzW@J{vYRA1RN3%XcZ^v(8 z48PxHWKMm#xkMgxn4QePmldTo*Z&q5h-+e@yI?%f zxaOb)GZEj12+dnEDV&y_+c!@ z!f)}aKWYp7*@lMEMx{Ey$bP0AL~mrtJT5-y(6_ZpzxI!2<%>v4C{~$T_IEU3Yl-$W z(FuHh2Z1Ga=+%J>jklH+oQf0fJBqdsVj3}OFws5_0=op8$at>)u(^(oj)Lv-p>)DxST2-_JwN=%g?c4jo%Fv&5_{8?*{`ddo|&DbAzjYHCEh zu`YfGz6x{U%N*W5Nj^9mdeVv642XG~TjbJ`dj#m-`WJLt7DiK{-4ZL*TJcSX)3SJS-OGR1vd}k%2(=Q-c67snnbOwmq zUHa6=KcG92T;hsfmfYZkEk3+J3e4GU1rbr?GPmG6sfd+OD=0nlbdf^Xaq05 z6a$$kgg5AsTcKfJR>f3PKyHjYOYFB4hwNzPyA>kb?yuU}(0RgwEmNh~dkLnT9P`@O zXo|*#=o9y^o@PFAaQ)mb3BE>NZ%u7&P#gsXl}f6`r^jgt2?)*bC@Ly~LWT0T9OEkW zBQLaciHlj5yPWZygFIWNl*FJ_ISgf@j!xL%k)Cb;vXq1{*RoQ|D!#p29Jw8MSL@~gk`EH2r~h4w$+T29{+72sJkhzMd$M| zG-;?{;d2o@_0j`$rSaOJ-5*y#*oIZ687!vQ`^^v#*dqt1BZ!%RMpW zvX51(o13$fHe|iuq$o!O>2CP+#^Qks_sFgwCT^Xlt1)X4u^{)zR%aRT5IG`|f3m>Ok^7l5XMnWe1$5~sqvhsdV}sjycxZ?Sz{8N@;pOQXamdmjg6o2zVJpx{ z(s=+fz@b1-lx~FBH@$FP#8Q(0T70;R(6IcNo#~%V)K32a*{<>?A^V=q-u)myP`8ui z(GO*&p`l@5XoM=p!C?%&lJf_bEdl5Qc>U@MfX2d}Fh!=*_TJ9u&%*L5%_|A0i& z=H7*0Ou6+cb#?C@Ta{`U)-sFTf4rH$V_p!gqPWGQJ}|hir{{iHm}~%4*V)g84c18* zlFSsaZTIx{HX-(|u@36&8jip!W4nOC=(IlE1W0IDeh6+s?->V2JC1()IZWll>MoB~ zRTL4m8k|5MxC%m6!4?pf2)z$Vv5x29=3WQ*^V3d6deK)%0{EUmH4BYO?QK55kf zN&(1x6T)jddX6pf-O-Ah^Imn}s+jf*Y4&FK$;vZm_{}1T53}_xZR{Ik4q2Y5p|oFg z_%>a|{9$|&J~2ory-pC~^8t81pFe+&hai)w5o62`Gopwqa#O=JAKaC*43K4ba_Keu z9`xVNyFPZAxRA`nvxp*V&VO*8wSc7=&jk)Nw#Z?ucB}?<>C4x5yaKoi%Gop4SM;-~ zpHSyDSHv8#xcr9Q@qHnTwiQ)X34V~YaVOLr4uIJyegOXC(7qn_03yR5^%|yA!b=c3 zxI-(D^VU~fEwwW2)&;rWYUWaq-WLXFp8-r&D#H4Ym_bv7*;I58q6mya9)kqesymQF zshfgBpwYu1B!kNSk!K`xZA$k>8FquWp1-kU!EfwXs_ESr%O!OgH&*^=UTaPxOVwHP zF;>%Ik+<65R8LkF(}5u#K#;z^J_5xE|3e%+Y-C&s!&|tJUD!dJU7nW_qgDO%iILN2 z4Z&+`tS)dE8yQ)=O8uF!C_d!L^`A-uDkuIAbr`ay`7U={MA zUc55}+X)2kH@9uSLOJ5$FVioDRj$&80ov#dUEF#5=*huBc)YzXr1ahhyM2UaWCE(E zK&FtS_QRg_hD6>W_v0lcg;=d#LV+J~8y=hJWX@|8A4vLtLn7rswu}pJ-?O*p+a5?F z=^bjrN~JL<;qvcb4~F&*x^;^Ld#$E|lmB2{&08!49`s-Ceo8*`7-OaSR+aX12J63n znMUB|W_}BGwEP@*dyuwVbZbCN%|Y(Y-Etx_AHTvB?2J@H1m10oa7CAjhLji2x|-?p z#(`&)mm3o<40Q8&$=?spd*=93a^jeNx|P(PZQCwI9$rRCd8=6)aJA?~OsK4j_Z`IR zo&x;R)sK-cfp0_Za`2A0h7IH+5pt#hI!(*`J97FVm7givl7kzD=BQ(yMVA_rN;GnP z7BqqJHCliiZHHXvwAHHf+Uj4xacZYfK^h&qXMYo#XMo|qNMV(?w6E5RlAw6ReMwy2 zSo6;awRz#-st*sIeW&+g`Z9>#e5PrW7Z2RSG*P3ba}2n_&P`ZT;V{*uiey zJQ36W{Nv4CIEKWG-mdpL5g0>c6_=$wwt>tYDS}^N&M)Lzr2?@Z@^7|yBl2_azI}e5 z5|-1>>Bcwe%Q$hnto%IE4I1?9&wyRW_t4mMol#ABawxOVLvPBO zP6riK^QSnSE}*2&wjHo|rW18mG4%QYu>`U3Bc2RrYjE`rZuk2!j)MX<33S~Q7Bc^< zn@(oAOkM3o%ZYhH?(J2mHbe>GwMvP&A8a`8U|c%SCZbHhUeCzDz+tEXD1jDx z>a#F3qa)V+3&00iPJxF)!WWM5h~WO2?V5`y8tz-qO#h<_U#!Nwvh`6Am`%Lj`V^pc zY2q6#pcHL=Jm6J=`Q4zqAHev~p6|MLy=(qH-iM%fk<?H&23qg5YeZHt#(NfLO*rQtqZNg&r0bj}(yOth;sr`~8Ia4*$sp%}m@Y z2=)SSL`JE8r|U0q_+1zOW%CgGR_QMdPiEBvtB>t#7E``lAW7s`j$fetW>Aum`S{d1 zH&c?o@Q+)MfzX@`Mb2Wjh4YdkXND7?fvJHXEICu3AJGU8;rl~yCJ<`o@Y3$V+Ff5!Qeq5evM#p?akbYRUgsip!PO^~1ag;h=~CsBU&{b(aS}zxS`U3wFg5K2 z!n4kQi3$zpiJTmafe9bsoPX7!enjTBtl5KKx)@qTWK}g?(Ile+&Kfp*7o(kcI$H?t z7i4MCDnNfcZ~eOrg;`i^EF9BPv$Ts!$p!M^LL?F?NY?DI`r&6$40dJ; z69VwtkjtyAz`jF4vC8KiniJSwiA*?crrVIDunWSzUJiMK$2WOwyz;6Lfi@~m6;JX?QAnY(RN&p{97eL z1Sqquv*w5qQ-1fvZCc11)cGTb?Wfk8gK-O_l30y`B84j=sG8N7Rn~S660f=rNF2g7 zy=KiC8u}`7fpl{J%)k|k>Ql0os2QUf=MZoP+q|J~nUqN~W~eN0>z>t!cqYqBSib~g z**A`cTE|dL?+na-uUO+&yODR8#L@sL`z%|%N!bKI*#I9m|C{^t2ls*f^kwGI?@#Tz zcKh}k9h|ob5?7D7xrw>HGDv3${CrG-yd%{%ExMsvM zQp{CXPY)`iA{<`av5wn(7hxX;_Z(1#o0ES@FI3Iw51iQ?WTQ~FnUJA?yhqL%(v4qH zoo9Pk9SwKYP6nF90Emn?1vvD5eh`McO~}8_!0S~tufe} z2*F%leF56LIp5F!l4)?Afn+EmBI1{hUiqOyd~#EN@%L*HR^26ZEx3Fj&4j~#tWQst z2HJ!v62BKEWGi%$_VZY9ZT8Z=G8a19$|an3gI%mBop6be2<+vc`{05 z#Y%v$x)kh91FYgF+GNsh7~-1PEN<|egUy$S=iGwjf#lAgRQD!we{q&xM-o|bgs(mq z{CCw(GZoMK@MMDD9&;Ea%WJ?;1sE1&o`Q==ZWM7!4?Ks#uc#mx_vysSZ1hIBm{59tP2f+ z5fYry4N#+}%FT-yO72lO9mYV;vzNc^dMYdIV(Z}#Te@&x4d>Nxa+(0K)P9b`6wP)T zZ&V3w9Uc4#;IWI3-bw;1kh~su6|f)+s)L@LN!fN_XlV7CHMVwkdifW2hTNiOrA>r>+UWWx6j;OvLurH39|_2ONVdTq0A|Z zZZyYf0_K@c;=E0&+P0T&!CUD8l1=m%kH1g{F@I^%68(!^JC&5Gpd#_jEO@*Ryw&iq zt+6>j64m#zvv)y{UPeW+^^IWBLyyK63yy7|C4VETcs8lE^t^;5Ct{P`1`s>MzcpZg zIri+?BPe*6nr0b9t~`or`0pn()H5Ht8S)^eLL89^z2IpPCb|@Cf^T^={^bu_s@6M_sf(}ftt=|~7e#v!;)G(g18=F!UvcbR+&1+S84JXNTJ=_a zb42E0YiSnEMJwief{W)~nMk~n;u`TH<=u4xQG71>qXB83p4|yaopjNc{3c{q5wa=$tG`URQz{Fw{LZ|E?DHcjAjmg&K}Mw+0ARqOPVfw>E1Uh#OWN<>ZfwJ zr83;yps#A;Ti?^gP6w&T>Ev7}Vmdf~vg|k_9x;2p*7RACdO=1R^;DmF`%U}Aslyr@ zlm>+c$>)vJmYq6Zcj$U{{oWC(jo_V5XlU#dUq(R=`yXXXO68L}(qV~+By@gz`un$R z`KkKE{w%oFL!ln!!uD&nh+Z^1bO@J8$ChT@+Emqkp=_^}RYgpU`zGodbT17~RH!>m ze7bt2(ev7JI3qtcO()DY3?8Ia?V%UR^Uckbs)}gZ!4la|>ZWxHaa4BDNXg;wj!+7p ze4LW9I!Ku+X>kxP96$4EhAzT$F|FO*BQ#1iLaK~pRdx08=4U#|IZ-29HtpIqBU{b6 zMsoA{olAf2uT+5|;+7}$y1#l~V8`i~#Afnig>l5;s~43*d3|=XpHm*p zx1V0`J!{wI4{A|$83WsecVXf3o>a+R*VcKfnR0OS*TmHhcNKNmA2_Su*D~-KPiWoN zDd*bwbiS7zS{aP(8z!R0`wSHO1a#6g%*S*Gn#8Ap&5BRSn;yOuQmDi($9Lm};F5HY zlkTq%k{5L1QcU76cEu?UI*8*KW9OwczS%3R>7IFVdC*w**y`kW9f1OgciymjDAOFY zInaIl%K?TB&9}_t3mpOgBK(L9{4 z7o#RN&cl=#uW6~#D4KyFy7OP$hw>_~?A>htJZODSm7o;kg6I^|J9VMv>07@2)k(EO z{T27~PPRDXZt@u4y!(T%4K&@~wdMA2jVV-d6xkzs8kb6^M~4UOd{P(cWhjGAu=#_* zmY=EK!_~PbW^aKh-bK9ow z<3Cy`(H3D2FR%S<(m&{?%a>9S(<^Ug^Jgsy0p_+fl1#U499EAITNTb2LQn1) zW|Hi$_Jmz}t5BimYjz$dN0EfcBr_2X4%`s&ibIZ%{Ao-a-|JdKLkKmsn^W7jqGvnC zqms=`8$-r8SF>lg)Af8^)$BU^0ZSsOIW3_tS<_NTw7+?luC!F9RpHVS%F$K3!}uAwgZglJL(7MQYc{{PX}ZYi{yI0lc;^1O);8zF^0WMJ ze@?Kv_Tjldlhupo7WjI;&*kw{&WKWGz0TD_1?$4@cVe zC(&1*aLYOclG*=SPo?T)y1?@0xEa>siPg@j&*Y|Mt}%(~$2(iw<)>Z4Qfq3&5afOV&?ILDg|ss{MNjwo#hfT%FNTBpb@`Z;-D!<%BO@@ zD>v+l`IIwC&wPYFWyzlA&siQGUzg%CQ8shq#(Uq+*_PqZe)Fajrl!Rj{QYScH)u45 z%DR26=8A~uYkR%6vy@Up;@LC(y1>GLuywEVpLk9ZfMmXJeCfy@UN~s3PEWg@K5c-Q zX$2?&zHho;&c6RPlPKS|s6851HSHfIZkb*<*tGOXKEJQejJCA&&qt@-&+@BvbeyAF zWkJWlfKWbDhcRSDly|C2=YG9PIW{ml`u$_p35@d7i%)m-Q&ZI@%pTa@5@J|mA*>Pn zZ0D{SugOgtH@5Wj3~P{i!(!XNc6J_}?RXxQqd(}Txm&F|^BPsZlD9Imu5Or%V1JQB zKB;%8_?g1lPZw*^PCPu^_2TI4`wWA)r(rr*HPtk=oXB;#dU|?^9`^Jai5G3tEE`Xx z+)~a?3Q96NUT|hzFYbT$9mMTTMHSOuJ(F>wMj#5u%#&A=Lc`X2P{i#7Ik7)J1ZcCtBU^b$+j_$#mcnyTL%+U zl}hEo^FR6(?iG0LW}QFQ4heMIsJT_O>GY~=Pf7|53s}u``&ItTni2OBVy>F~;MJV; zcJ-R!6Zzy~j^2@EiTG%<7e(~tZ*@D{>+%u>ua=WOb-Ed!I)41CaR2QVr{;^6$JNyZ z({5-^b2O3a7_!4^bc{sPoOQN`;;&4C z1x1#UqM31Wh(7t)Vd*tz8y&%ajJ^NlkUC@ZVhuJI*ttIkBajV|)F z%uzG$`gFy!-#Q1#Y>uUv088=wNxx58jedrXQSwKdnV{`XQ7$j3&Zb&L7Ebl@y)<|f zbGe32VekokYJEnHom>D;}aex^5{>>$}-qG1R-ti$cwU1M}VWOvPWtE$$l*Vj%X z9u)OH-)nh!4UnwZV0Oa3!lDvdKGriWo8lJKXJN5cN5MQTQ!_qU;#|%ql?sF|#l|b% zf7f1GWTo5M)y18mTnoHT-v4hOakq<-hu1H{Bcwf z^1d%R)-N`6S~MbCr%2WTn@Ea6SLy|M`K9j6{*;gE`FqnUi9wdUy?H%#jlMj$?(mn@ zJhp*aiCtJN*dyKDK~$dKv`A#-yqL9TWpkYV1q*>DZe{`kbj5!xZaWCf)~2G;60mEh zrgroOiEVcA$(d7J99Z~M&I#CuglnG_8fZ(mY%e-VsWsmBv*>_Do%FQN6Kv!mv(_9b zz3K>B>PijKjGz1|u6fgdvXoLM*w>fRG$KPagx`EHRgoN}C@D322B5fhh2036|IQsj zo2z{a#FQ-3;uS;ch%be{AFd&x&gj}`saN}j%yooQ4gQH0jpbTp7e;69gxwwITvanD z9)zCQ^U?s6<~jcZ^EPZW;b8b4Utba@bNo2CBWBOIHzvu`2b+~&o7KLqEl(M_O}`O` zJ&K>UR>OPzHfvX!H%FH!0f!ekXI#3VULI`4ciPc$z4w$;*BQWaL2KTCZ`9i57Q$Z7 zv@6s#8oT4LIq4yX)y zeX^AYo_RH{&7;0DP2ZV_=KXI?a;i`$`B8CPjqAiR;qi~scFPO4#5)fRrcl-~mr{C3 z0<8>e8FGx0P_~FRZgLyHZa_MEDg6mX*3jUsu<7tNwKbYJq>1LCHfttJWy- z%HRDVsWYjA@{wiDzlR=#zt=7q^Vf9`F&P=#;va}G<#1zoI`290BTP_ zQl&uyi~a*{=1p8K8OY5*+2K}LXdtS^xVE}l{KUwF$UgHFEm^j(@Oy(l^_~bMrij`< z)DYgBItTy$h4&hrjI=bDQH>6aqm)H`>aMKuDgdz2A>K7#ymQOURq5zT@iF)Cprn&_QS(# z(p99c@J_-tMnP&ic2%@;)6kp8F5G?_{O|1p2upQrV4&ggG>?d)z!=SSwyO88 zvtM7h7CsfdINGy`exh*vvA+JyXjGK_g9nR{4q@*w+a>{Vr$h+OCwEHN~wMx$T{1suzk0P2-~)(Uf_hUVd}gVbtiRf=gVD=a~@^? z0X%F0=krM#Q3FY8&GvS756ZHY!$P(o#E5NAUkM${Jw7M<>ef(^kot?-X&F|UGXiIa zR@=Yd1Ss6~<>{@21ZQ%5hmPonb5f>16Q6jzAYbC#-VkZ+BZRs1D`x7sMR?M$a}`%UWR4%PlTX}f91#_Btj)bC zFV<-&zAmu-qB%)RfHQMFKQ21*3*_@iskRtw7ON-cYYI<76Be>J@pmP;K$5H3Eib`R zS*Zx*VxXL-R>vjgcR13-D80ON`WmG`?zfN5Gxl8PwglbEcxP;U&gD#eS$VUf-7Br1 zUS6}L!KB(|4Q*arPB3#~9}g7`$K(Fv)1_DF1DhvDeoFLz5%0W^lJYzN-IA;!LDGXT z(@GQbv=B{KyR03n8F^$Agix#9@^yUw|NIf#nysdr#a!L`$mE)5Px~j=&R(QvjPrrb zRh8)uRkP_?`KsfeQbSYBet;u-W5N*@hoqR+m`@Hq)m+Y_ZW?hv8E%e`GldI@&VG4! zbM>ZY0>BKi+jP@&R%s-^-*N6fosOf3g5}d}a>_kg?HghK86lgqFQ$_e`Ez{>Gh%^$zm`jw57*PX>mqqrcWyK8S>vT`#nJln z{s$@gL71E#Z1IGpb~*P5MfHu6Hn*iq;qyig)cQFLj*7^h2@6 zjpU6h&kd#=$YEih{hUiO^-qGMu;-2(M5h_Le+ji=~g8sEsEVx(40 zVb3Xz{QV}r!v#{}gl6X$xAZ*k5c1p(b3|Ih20mi!5go4lCxNeuXukgrV|f3ExrNWi zp!M?i(hq_X)jKcMi)ge}35F_ZU%PTxLE#!2eN92(;MRlN3{FYe_p?~PmbCX-*I)|*DK3v-&_q2>I?fo59n>>>9=Z?PAZvM? z$huSJ&w-ODodlB?j|4rZE{}gfU-|C1ZJV^mK3aP{8WX4L&~i4hjotNL6JW0|%sWnE zQCfS+Ikmw7i0<2b*V>&M3{^;*HwT{)Y-@a|UGGMcS{sze=82k8$*Yg)tc#JPm#&;8 zyu6AyJDZfKUUX!a&O(=S%l~`Zd*zdUsP+u8adF_w@C6HldAbAZcbB+OO#B`h^(0hcgJr~$u{9(> z$iFdLjW)0hHmKph|1HzF#Cg~)!mQ)R+t2<+SVV?}nfqeJ?%>uphF8N?J*{riYqdc# z$3~YUt#iL;el~-^TfW${mU}yx+Z6n4<*;Knmapb^#4M%d?oBpxQk#WcI$AgoFs2u; z4^b7VH{HAGsgC{AQ4Ui;8jI?ApM8-BaVX^9{iDYKFdLnQ9zWRZD!mZ}H99v#_gVt}35Rq>+g9sXchCB^`;8AgU+Edt`sB*3?J` z(!wRnq`H&s6Iyt5u6~hyOk!fJwtKJVdUjvm@Y?U@VNOrEEWHfU!hG4fRDnu&{ARGF zcqGP5;w>MyBKdVrx=vOYSSV}syz38&vZth^8i`P^9Zv5I)8l(Ez|$Q`EKs(;i(e>& zwgA`I=2~lae825h)HsakfotK}~`>(}Poa(9{R&=HO>&%N2_ z;<`MH5#!e~=P@e3)&CxWlM9BI{H<-#b6QC6qXuOoUmn0 zH2x~pr@6zic|pi+Te%IibCPx>9E>6-19+tG=*4u5TRYJ7x{#+--V&`LD*4}<-0xfB zFu7;uGWSv+jJu($@&y8~JlCioz15_-okT1XTktx|<bjR!99cP-8^}73 z-WY>&t7K2KEnZckMEn^2ZNC-Zv{-j%;6_t~ffCmY0fb-o(C+w_jWLkuES%(b;vFrx zG@GEiNl01omF!})t2yGt^q-elrA7*4Fs?D+aq!Esohu=&VJF_oJI}kX)6UBeBoiyU zFIz2)JG8@y!nxL>mGTjzWl8N}i>t77RefCVmO8e~vw*e8)QLNjrrtu6%~jKnn6|RN zzAgRlVKJ2K`=Ote)ot#?!6(G@Xu_JLEn1L+_arUWv%a{Aik`yZkL-K#uLeyMjF=yI zxtQIX(^eYITHw?$aX6t;HoH89=`H4~@YEa;p!@H52qCA1AjA$SazeeyH_s2L^cWpV z-bZ8ZJ4PQeM<9{|kdL+XrHC}ypX^)w{`%7_ujP_X1tcn_enG?RfLj%gL00K)eYN$^ z!F#7!t{6Hsq=CQfKNG;E11#}pDVE>B%=W?OKT}flE*9bJ58YD{su zY6zex!>hNhod5CXq5s?GO!CZ?yFkr>-@fY`o1-k>PL23?*ZW@{1DdlPXv_G>vpvyPi=MSATHA7xRrVjiNVpwhxe>BN zm;U+a>x%kzs#WuvWyo9@8Muf*dz;e$JrrVWENJ1UVRmj!0&UTi71WT;!x4 zH?Q#XAw_xk^lT}aJZ#m$aprOsi0>C~Df+$5VEN!zn;mp~cjl6w?F8Sd_;-F3m@m(R z_fOL~!*};?J!U=Rvoy%Ds(9iEKojb`^tAOaS~VT)7eAuyBs26dIY78*K1l&tdu>(} zwdowSxH@Yy%kD68ZKdjxNaYDNlH%Qys3o+0)bp3*l{0YaCL%2c_T0Z8BhrSEOhaD) z>%*%g1GyJ?6e}||=L#%9zd#50*I?#*35Xtm)=z&7@P43YfJz$Ej~5)}6f#Bk?K4Nj z(d?WZ#R&MpLZ1sKP?S9AMA5vcrEszqfU7{RNJ&|l36=z}1kk&p)z|CW4b{hR9X>39 zn;8IgtLjgmK%3Xr0B8Hf)2Ac7T6gv?u z(oA+&OYnAcg!^G4tFN;;qF0Pyo(lMziw-?ZBd+V3noP}cy@x;yPpV}xjEfC@G`uKGo{{y-S+0>BuQ<=osL z5S`eL^RElkct7$vEQf|}N^N>bBrbLAr>9aVy(3&BHj^E8qoX@o-n6Ip){oJR!7G{E zU01WLZ#32Id9AlP=c8VRT+Np+qLR}E(d^s!vvqsHFT>Xv7Ax}kG>rk!rL(k0RUDO; z0LgpG(4b{OKm$5hcHss_15G|P zs!8D7}XRf{_$eXt912cI}$ zf7j>T5!uY}h}I-E`L}?r1T|iG%S6sC_K67d6C zuyie=*dV|cK`R(IsI0qpgA$v38R8NM>P@9%Zm2Q&vV(wKq8kBE*P$`-F~fv46l|3u zBR!y279j-A<2gq8@7_7|ZlX}u(e6cdo$FMAxX3?mz}=FR$fNP)Gz!qIOdGlmhZA)~ znpfRaTPVLBaKW>tL~i7OPxR3KqI{Qw2VR~yXRQ(xec{dBw(moAB_gFcR@r7nucHXJ zsS7+__g>*BFA>yYtpH{yEhAIdGM}*HL1O0&7~I37#>!HLsu@mlG|C0kGr;|10t{?F zf5YYBXz0wK5s+S_H3=g0fRuvs0X7@@Wc!{Y(;!z!)&sHZ&!91;zQ+!@#~^e+&@e!lbk*4qF6$y#EJDGj=7wVOpA=`XN(s`)2wghz%zg8mI{cSk6ro-)LkMoaD zqa7_4bsn;Ea$viX1rZo`7B`-mA~uq5=Se}1udgj?GK6o)n!BnFIdz(p@)2n^0v>D2 zwqH;lRfi1J4eFyJW~w-Psre;$KG(~7n8bz6B(yY*&#K9XLtiMKD&`s_%oKJqGWfN` z2+|7`l;nU)cv4uN&XgQu{38yt9sY+{W%QkiESUD{14MHzn?$;;h=N#n% z2Tn}lG3GYIarg(e@XxZ<#`)JLW^Ds$fWx8K49Ub~?;%mZUO?O`%7|5PfC>B@Y9AaWXw4OW#-`JA=n<;`;q3scg&vRSt^~dZxDD=$l>k zmKfZtJnK=RqwVGs1O?;mvYcsy1oxIVt#%SqZ;yn_7ACzD^Ntu_ggZm@g72;fDG(bqnF4XRlI6q#_g)JXJ`we-%9G@jO>xnD^W~NbrEW zVV3DSj4ZFL;%Yb3O}(itB9!EUj>u!kO8?>N>NR|Ah~XWuzUq`umbmSz>JJgpC5O_R zRu&`Z38a_I*s7k=EgHNW>c!ve;%Xok=JIKx-JwH1Ztl*mc1r}MG4*;mw`|tp{Tj6Y zlzwZxhX(z@md_~z)eDovnJ}S718$>&F>$NYm+MNU3qAtUw}vd{W{d1C+XBh&LWhk5 z&Q=$ysJ`y&Wm-c-LSgKU4-0`Ehf71AO;^kn5g2C61JbHd=4)Y;A#3qz2wCoe^kzwt*zMv{bqgSTv7 z`Zm}kB-dp9)@{kIdwIB1gF?mi^Sl+)eeB&H32i_YDIrGR@m1*(zS$G?KKCP)zeZQVXL#F2|OC4He`X%>H>Hnoim&%yNu$LGF{cx zQG9j5b9wR*(76qC)DwfYCgVNC$7P478v+5Feu zC!29GWphn6FxHbxo6ec7#4b!p&%RK=+pAKq^N9yfb!QV$Z}l=-K*%y$e%&;C{OC+n z<$<1|d?TsuXEkGH%IVfF+Y)z|~1=SLSX z;sgd}vO%uqYxs*JztT*I*2Sf+<7RdgWO?lYq3eyVS#e1ibNc_D;3(>I{?f2QV+U32Z6wsje8 z(p1)+w2zXQH1iUzUt79xaCIc(wm2bm1kWn%@~$G9T-*94-J(v!>q7&9WL)*l z5&b1HXq^f#X}j^Y>uP1TVlc_vxiqv~%(TRxfGx8?aQ0wt=oe*fmzv#aMb}l9!2O~} zW|~lp{1xUokNg>QC6eA#)Ww-rl?|^&#YIF;O1OnVjv~G=S%WxxL1If+Wh;_E#O2?v z3IKDk8^%oqHj4>Ye;VLXucBoz!ZJ<+=GQ(wHWSdTw>*y`)rNUf50yD!%u>_|VPQkW z&XJ-*_n&`Rg-4fu=&Bt$S*a{j_+$Wj8y?d219Uq9BJIyhIwL?-->+3*JuEY)om`3J z=SV6w0xCOwZdA>h3M+AOn18?!{_C1xy@@|t^=E-tXRZ0Uxh*ivc?o`1uMY$T6sk?3 z^?9d(I}DZiZiGB}rIbr@?P@oH%gG>$?MMrKVX%3ZgL4Oze=iNANQ~e8fxtZsdZsqr zw%5g9r=A4;N7twZd@aeQB|)nQMw9>6_&C?TPK!Pk z?6~d2@d+l>(%{QMlZ?quaV!o7q?%7gn*A2_D^W=OZ<3vRxFix`MAOeQ$+PQRgYHFt zW7s@?jb^~v0?k3us|?vtV7L>TRq!hRwQxndk73a zHh9xQh`Xxiy=N9qW?U7E=p6d7hD8Ls3V0wJ{9BQOZ++xOKZiMok(0S$!So4nl_X}8 z*Rk8O(KtO_-L5@XMVJUtL{Y`M&O36L)!aL*HY{O(EWxbNPO5^c9THyX&{r`y=CC?= z(YPbyoN4Gn*s9wkE!@Cmo?F1X2sHLmR(8HT{eD8o<1q-NMno5P*nY^#@@aGQspyQB zfX%ad7*^-qJH)PK-*`Jl88+LwJHvaPF1wd!t>cdLS5D>2QQ=~_YO1IrtYEmPzBeYW z4xwL}TX)wXP4^2L*xfohZ)a}b=_yVfQMz0EdPLaR?TEn^lMgVa|HfF$6?rb6BwE0n zN!E%f2D*m!dgc!y1}3m%>ZmTPU%^IHMOn_ZM%Wt?!CmtqFOmG>6F{c}cB^UO*(gG{ zsplkH2WB7Ef_t*{rxs;~>%!d|1=bf=Jx|UVgAwrW?;jWS$+}8G3KmW?4vG~oZu8_y z@i{{hHswx&@D3hrhxA0hL16WU(_V41&FF!Yah8mrYA zPERlvK)y!UfDxidXK+BIU`dM@;g;!YPXEfIqRSg|NL~Zl`f0er4Kub9_i}xIecb%F zqc{FF_<`__Lu=MUTa3S4`{M;;o(#P=8$DQ?zYeWbo-nf}l+Ose;re@;qnhyGN*)!x zz>m5>S@||^Awo=n^c=aW^7K04rL&^{3vl}x#SdoCVO^bJ;LvChqR)T8{c>S`zV{F{ zvF@rCbA1EL|KthjMm0lOm{HZh;*&%F?eSak2h+s0mv1;fDZrNtT)bE}PR3&RW%{Tv z1HymQqAgvq>~(4;#W37o9xe%>=a@{~{VB>8CTE%6*4EZ#^0PdlDWdlL+Dt?QE9-sd zLtRxrk=QKAgk)UDGMorN^y!fPd8{j5;VR{BU7cSs48Z4ZkyzWEjOCAR)gjFo4Y~>f zU;JLyBO>BR#x){BTH14}>+w*a2M{cACGL3puC4pDQ(lu>Al~vUvmvgEY;n}dBKA4P zFZ+*X|1LQw&BY)r6f3 zNZ3dDC*4<%&0g{9KWwLNCKMROvN_;C<@9ml1l)6pL&r5qekCFQW0GFq`a*kedNOgW z?Ja63(C84aSeO6*f3@uIf7dZU+``Fu{kNHh0P|kG8OZ+AzP_jaQ$?i+Nr;JgfAb^0 z%r2)*T|Kf0j}Lb|a0SXge81;nKkUnXwAH zj?0c!_T~~EitPz2!={VlYpqTnlVxP$O8jZm%cAxsuN<)_zJlOVu{l+2mQ#ah^U=>8 z%2&6%wr>IJBBdajSK2F0N)8Vj38{9L2Qz|>Rrg@lvNnoBV&&>;hW6Y@nhkM>TAVl? z)S>_>9DIDar_|LOIR4IaBclB@-`%!7D^?~ZicpQBkxnCD=R5XW^g9o4c0xPZ4s9Wo zhTAOb{Dd;b{)`_#PDcgDv8t+JkTH>htG6c*EIFrVGk*Vmq-XB)m4N|VW8>SIG{+61 zjbQLfEt&=bDi%;B0{fjE+($&Qw0z)~=!GBQ+9+Wz=_Mjl)R4#vB20L;?>?ruCH$;2 zH}XK*5zhp+faoO;69mY@vI2W)%-{byTxFgPtiIDy=kI;L(tpaq+@|_C^Z1qXXHKIo zzxwiX<0_B%{;rD#Z_r9u)|eY0|3lgI|MYP7K`}b`3&?e z?SZ#wYcj^s9%Nhh?jZAspP}fV?s0QNER^LxHt^4NmTymSTM$Xhk<9O@DQR8HQoQN+ EUjdA7w*UYD literal 0 HcmV?d00001 diff --git a/docs/design/handle_flow.md b/docs/design/handle_flow.md new file mode 100644 index 000000000..a86099c72 --- /dev/null +++ b/docs/design/handle_flow.md @@ -0,0 +1,40 @@ +# Handles Feature +The Handles Feature is designed to streamline citizen registration and authentication. During registration, specific attributes such as email, phone number, or national ID—can be designated as a handle. This handle serves as a unique identifier that can later be used for authentication for various services. Handles can also be used to update data in case of data discrepancies. By allowing flexible and secure identification, the feature enhances the accuracy and integrity of citizen records while simplifying user interactions with government systems. + +# Configuration Guide + +It is important to acknowledge that all properties listed in this guide are automatically synchronized with the Android Registration Client. These properties are sourced from the `registration-default.properties` file. + +## Configuration Steps + +### 1. Update the Handle Fields in `registration-default.properties` + +In the `registration-default.properties` file, update the following property to specify the field values on which you want to enable the handle. Ensure that these field values match the field values in the IDSchema. + +```properties +mosip.registration.default-selected-handle-fields=email,phone +``` + +### 2. Update the Regex for Handle Validation in `id-authentication-default.properties` +In the `id-authentication-default.properties` file, update the Regex to validate handles with the provided key as the postfix: + +```properties +mosip.ida.handle-types.regex={ '@email' : '.*@email$', '@phonenumber' : '.*@phonenumber$' } +``` + +### 3. Map Postfix Values in `id-repository-default.properties` +In the `id-repository-default.properties` file, map the postfix values with the corresponding field values: + +```properties +mosip.identity.fieldid.handle-postfix.mapping={'email':'@email', 'phone':'@phonenumber'} +``` + +#### Configuration files + +* `application-default.properties` +* `registration-default.properties` + +## Sequence Diagram +The following sequence diagram illustrates the registration process, including the use of the Handles Feature: + +![HandlesUserFlow.png](../HandlesUserFlow.png) From 5b4b2ecb1501c185ddff37641685edc2ad733ad9 Mon Sep 17 00:00:00 2001 From: "sachin.sp" Date: Tue, 25 Mar 2025 10:21:12 +0530 Subject: [PATCH 02/44] Updated README.md file Signed-off-by: sachin.sp --- README.md | 158 ++++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 112 insertions(+), 46 deletions(-) diff --git a/README.md b/README.md index 0948e4a37..f6477204f 100644 --- a/README.md +++ b/README.md @@ -1,47 +1,113 @@ # android-registration-client -Reference Android Registration Client Software - WIP - -# Use of Java Packages: - 1. Added all the java packages in android directory of the project: - 2. Add implementation in settings.gradle file of the project: - Eg: include(:) - 3. Set the server base url in android/build.gradle file. - 4. Add implementation for packages in android/app/build.gradle files inside dependency block as: - implementation project(:) - -# Creation of Services in the project's java package. - 1. Added all the required functions by creating individual services for each functionality. - 2. Using AppComponent interface which inherits Dagger for dependecny injection. - 3. Dependency injection performed in MainActivity.java file by calling inject() method. - -# Creation of MethodChannels in dart classes. - 1. Create MethodChannel with a constant string name in a dart class and try to invoke a method - provided by this channel. - 2. This invoke method will take the function name and arguments which will be sent to native side - for getting a response. - 3. The function name in invoke method and on native side should be the same as: - methodChannel.invokeMethod("fetchDetails"); - 4. On native side, in MainActivity file, inside MethodChennel() use a switch case to check for method name - call.method argument which checks "fetchDetails" case. On matching, it implements "fetchDetails" method. - case "fetchDetails: - Service().fetchDetails(result); - break; - -# Fetch Machine Details - 1. Method channel on Credential Page invokes "getMachineDetails" method and gets a response from - native side as a string. - 2. Then this string can be decoded into a Map and the details can be displayed - on a page. - 3. It also contains functionality to copy the details and save a file containing details in internal storage. - -# Perform Online Login - 1. First create a machine with given machine details in admin portal. - 2. Try to login by providing correct userId and password. - 3. After pressing login button, "login" method will be invoked from method channel. - 3. If user is able to login with given credentials, perform master data sync by pressing the sync data button. - 4. After that based on the roles of the user which is logged in, he will be prompted to a either home page or onboarding page. - -# Performing Offline Login - 1. After performing online login and master data sync, a hashed value of the password will be saved in the db. - 2. So if the user provides offline login, then the hashed value for password will be checked and matched with the entered password value. - 3. If the value matches, then the user is able to perform offline login, else screen will display required error messages. + +The Android Registration Client is a tablet application that serves as a portable version of the existing desktop Registration Client. It has been developed to support accessibility on all Android devices. The creation of the Android Registration Client was driven by the need to meet the mobility requirements of countries adopting MOSIP. + +# Developer Guide + +The documentation here will guide you through the pre-requisites and the other necessary details required for Android Registration Client developer setup. + +The android-registration-client repository contains the Android Registration Client software for MOSIP. The feature-flutter branch focuses on integrating Flutter into the client. + +## Setup + +To set up the Android Registration Client with Flutter and Android Studio, follow the steps below: + +#### Prerequisites + +* Flutter SDK (3.10.4): Install Flutter by following the official [Flutter installation guide](https://flutter.dev/docs/get-started/install). +* Android Studio (or Any IDE of your choice): Download and install Android Studio from the official [Android Studio website](https://developer.android.com/studio). + +#### Step 1: Clone the Repository + +The `develop` branch of android-reg-client is currently being actively developed. If you wish to access this branch, you can clone the repository by executing the following command in your terminal. Alternatively, you can download one of the releases available in the repository's release section. + +``` +git clone -b feature-flutter https://github.com/mosip/android-registration-client.git +``` + +**Active Branches**: + +* [release-0.11.x](https://github.com/mosip/android-registration-client/tree/release-0.11.x)(developer release branch) +* [develop](https://github.com/mosip/android-registration-client/tree/develop)(active development branch) + +#### Step 2: Set up Flutter in Android Studio + +1. To begin, launch Android Studio. +2. Next, select **Open an existing Android Studio project** and navigate to the cloned repository. +3. Open the `android-registration-client` directory as a project in Android Studio. +4. In order to integrate Flutter with Android Studio, install the Flutter plugin by accessing `File > Settings > Plugins` and searching for **Flutter**. Proceed to click on **Install** to install the plugin. +5. To ensure proper functionality, configure the Flutter SDK path by navigating to `File > Settings > Languages & Frameworks > Flutter` and specifying the Flutter SDK path as the location where you have installed Flutter. +6. Finally, save the changes by clicking on the "Apply" button. + +**Customizing the Registration Client** + +* Styling of the application can be configured by modifying these files `lib/utils/app_style.dart, lib/utils/app_config.dart` +* Application language bundles can be added to this path `lib/l10n` After adding the bundle run the below command to generate Localization data (Required for the first time). + +``` +flutter gen-l10n +``` + +* The label and application logo can be changed here android/app/src/main/AndroidManifest.xml + +#### Step 3: Build and Run the Application + +* The `pigeon.sh` file consists of the necessary commands for downloading dependencies and generating Flutter - Android native communication code. Please execute the `pigeon.sh` file or execute the commands within the file separately. +* Ensure you have connected an Android device or initiated an Android emulator. +* Open the terminal within Android Studio or use an external terminal. +* Navigate to the `android-registration-client` directory. +* Run the following command to build and execute the application: + +``` +flutter run +``` + +#### Step 4: Build, debug, and release APK + +Execute the commands below to debug and release the APK + +``` +// Debug APK +flutter build apk --debug + +// Release APK +flutter build apk --release +``` + +### Set up Mock MDS for Biometric Scan + +The Mock MDS tool can be utilized to simulate the functionalities of biometric devices. The Mock MDS application is compliant with CTK standards and can serve as a substitute for Android SBI modules during testing and validation. + +1. Install the Mock MDS application. +2. Access the **Settings** menu. +3. Under Device Configuration, choose **Registration** from the dropdown menu. +4. In P12 Configuration: + * Enter the necessary credentials for the Device Key and upload the Device P12 file. + * Enter the required credentials for the FTM Key and upload the FTM P12 file. + * Complete all fields in MOSIP IDA Configuration. +5. In Modality Configuration, specify the quality score for Face, Finger, and Iris scans(these values can also be adjusted during testing). +6. Click on the **Save** button. +7. Go back to the Home Page and select `LOAD AND VALIDATE CERTIFICATES`. + +A toast message will be displayed indicating the success of the validation process. + +**Note**: To view the released version of the Mock SBI APK, click [here](https://github.com/mosip/android-camera-mds/releases/tag/vDP1). + +To download the Mock SBI APK, click on `camera-mds.zip`. + +### Contributions + +If you would like to contribute to the Android Registration Client, please follow the guidelines outlined [here](https://docs.mosip.io/1.2.0/community/code-contributions). + +### License + +The Android Registration Client is licensed under the [MIT License](https://github.com/mosip/android-registration-client/blob/develop/LICENSE). + +### Support + +If you encounter any issues or have any questions, please open an issue on the [GitHub repository](https://github.com/mosip/android-registration-client/issues). + +### Sources + +* [Flutter- Get started: Install](https://flutter.dev/docs/get-started/install) +* [Android Studio- Download](https://developer.android.com/studio) From 3dba72ff0882a68f68ae725f46ce12d96f068d83 Mon Sep 17 00:00:00 2001 From: "sachin.sp" Date: Fri, 18 Jul 2025 08:06:00 +0530 Subject: [PATCH 03/44] multiple click continue button navigate to diff screen Signed-off-by: sachin.sp --- android/build.gradle | 2 +- lib/ui/process_ui/lost_process.dart | 173 +++++----- lib/ui/process_ui/new_process.dart | 158 ++++++---- lib/ui/process_ui/update_process.dart | 433 ++++++++++++++------------ 4 files changed, 414 insertions(+), 352 deletions(-) diff --git a/android/build.gradle b/android/build.gradle index 5e1ffbad1..cb3cd355e 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -58,7 +58,7 @@ ext { clientmanagerLibVersionCode = 1 clientmanagerLibVersionName = "\"1.0.0\"" - serverBaseURL = "\"https://api-internal.qa-base.mosip.net\"" + serverBaseURL = "\"https://api-internal.qa-core.mosip.net\"" serverHealthCheckPath = "\"/v1/syncdata/actuator/health\"" serverActuatorInfoPath = "\"/v1/syncdata/actuator/info\"" debugPassword = "\"APTyKejHxACQyKBSRciR\"" diff --git a/lib/ui/process_ui/lost_process.dart b/lib/ui/process_ui/lost_process.dart index deb493f8e..fd794c88d 100644 --- a/lib/ui/process_ui/lost_process.dart +++ b/lib/ui/process_ui/lost_process.dart @@ -54,6 +54,7 @@ class _LostProcessState extends State late ConnectivityProvider connectivityProvider; late AppLocalizations appLocalizations = AppLocalizations.of(context)!; bool isPortrait = true; + bool _isLostUinContinue = false; List postRegistrationTabs = [ 'Preview', @@ -365,7 +366,7 @@ class _LostProcessState extends State if (globalProvider.newProcessTabIndex < size) { Screen screen = newProcess.screens!.elementAt(currentIndex)!; for (int i = 0; i < screen.fields!.length; i++) { - if (screen.fields!.elementAt(i)!.id == "dateOfBirth") { + if (screen.fields!.elementAt(i)!.controlType == "ageDate") { if (globalProvider.checkAgeGroupChange == "") { globalProvider.checkAgeGroupChange = globalProvider.ageGroup; } else { @@ -386,7 +387,7 @@ class _LostProcessState extends State .toString(), ), ); - if (process.id == "NEW" || process.id == "UPDATE" || process.id == "LOST") { + if (process.id == "LOST") { screens = process.screens!; } } @@ -578,65 +579,85 @@ class _LostProcessState extends State return isValid; } + const debounceDuration = Duration(milliseconds: 500); + DateTime? lastClickTime; + continueButtonTap(int size, newProcess) async { - if (globalProvider.newProcessTabIndex < size) { - ageDateChangeValidation(globalProvider.newProcessTabIndex); - bool customValidator = - await customValidation(globalProvider.newProcessTabIndex); - if (customValidator) { - if (globalProvider.formKey.currentState!.validate()) { - if (globalProvider.newProcessTabIndex == - newProcess.screens!.length - 1) { - templateTitleMap = { - 'demographicInfo': appLocalizations.demographic_information, - 'documents': appLocalizations.documents, - 'bioMetrics': appLocalizations.biometrics, - }; - registrationTaskProvider.setPreviewTemplate(""); - registrationTaskProvider.setAcknowledgementTemplate(""); - await registrationTaskProvider.getPreviewTemplate( - true, templateTitleMap!); - await registrationTaskProvider.getAcknowledgementTemplate( - false, templateTitleMap!); - } + final now = DateTime.now(); + if (lastClickTime != null && + now.difference(lastClickTime!) < debounceDuration) { + return; + } + lastClickTime = now; + + setState(() { + _isLostUinContinue = true; + }); + + try { + if (globalProvider.newProcessTabIndex < size) { + ageDateChangeValidation(globalProvider.newProcessTabIndex); + bool customValidator = + await customValidation(globalProvider.newProcessTabIndex); + if (customValidator) { + if (globalProvider.formKey.currentState!.validate()) { + if (globalProvider.newProcessTabIndex == + newProcess.screens!.length - 1) { + templateTitleMap = { + 'demographicInfo': appLocalizations.demographic_information, + 'documents': appLocalizations.documents, + 'bioMetrics': appLocalizations.biometrics, + }; + registrationTaskProvider.setPreviewTemplate(""); + registrationTaskProvider.setAcknowledgementTemplate(""); + await registrationTaskProvider.getPreviewTemplate( + true, templateTitleMap!); + await registrationTaskProvider.getAcknowledgementTemplate( + false, templateTitleMap!); + } - globalProvider.newProcessTabIndex = - globalProvider.newProcessTabIndex + 1; + globalProvider.newProcessTabIndex = + globalProvider.newProcessTabIndex + 1; + } } - } - _nextButtonClickedAudit(); - } else { - if (globalProvider.newProcessTabIndex == size + 1) { - bool isPacketAuthenticated = await _authenticatePacket(context); - if (!isPacketAuthenticated) { - return; + _nextButtonClickedAudit(); + } else { + if (globalProvider.newProcessTabIndex == size + 1) { + bool isPacketAuthenticated = await _authenticatePacket(context); + if (!isPacketAuthenticated) { + return; + } + RegistrationSubmitResponse registrationSubmitResponse = + await registrationTaskProvider.submitRegistrationDto(username); + if (registrationSubmitResponse.errorCode!.isNotEmpty) { + _showInSnackBar(registrationSubmitResponse.errorCode!); + return; + } + globalProvider.setRegId(registrationSubmitResponse.rId); + + // Updating key to packetId after success creation of packet + registrationTaskProvider + .updateTemplateStorageKey(registrationSubmitResponse.rId); + registrationTaskProvider.deleteDefaultTemplateStored(); + + setState(() { + username = ''; + password = ''; + }); } - RegistrationSubmitResponse registrationSubmitResponse = - await registrationTaskProvider.submitRegistrationDto(username); - if (registrationSubmitResponse.errorCode!.isNotEmpty) { - _showInSnackBar(registrationSubmitResponse.errorCode!); + if (globalProvider.newProcessTabIndex == size + 2) { + _resetValuesOnRegistrationComplete(); return; } - globalProvider.setRegId(registrationSubmitResponse.rId); - - // Updating key to packetId after success creation of packet - registrationTaskProvider - .updateTemplateStorageKey(registrationSubmitResponse.rId); - registrationTaskProvider.deleteDefaultTemplateStored(); - - setState(() { - username = ''; - password = ''; - }); - } - if (globalProvider.newProcessTabIndex == size + 2) { - _resetValuesOnRegistrationComplete(); - return; + globalProvider.newProcessTabIndex = + globalProvider.newProcessTabIndex + 1; } - globalProvider.newProcessTabIndex = - globalProvider.newProcessTabIndex + 1; + } finally { + setState(() { + _isLostUinContinue = false; + }); } } @@ -675,31 +696,37 @@ class _LostProcessState extends State ? Row( children: [ Expanded( - child: OutlinedButton( - child: SizedBox( - height: - isPortrait && !isMobileSize ? 68.h : 52.h, - child: Center( - child: Text( - appLocalizations.go_back, - style: TextStyle( - fontSize: isPortrait && !isMobileSize - ? 22 - : 14, + child: OutlinedButton( + child: SizedBox( + height: + isPortrait && !isMobileSize ? 68.h : 52.h, + child: Center( + child: Text( + appLocalizations.go_back, + style: TextStyle( + fontSize: isPortrait && !isMobileSize + ? 22 + : 14, + ), ), ), ), - ), - onPressed: () { - Navigator.of(context).pop(); - }, - ) + onPressed: () { + Navigator.of(context).pop(); + }, + ) ), SizedBox( width: 10.w, ), Expanded( child: ElevatedButton( + onPressed: _isLostUinContinue ? null : () async { + registrationTaskProvider.addConsentField("Y"); + await DemographicsApi() + .addDemographicField("consent", "true"); + continueButtonTap(size, newProcess); + }, child: SizedBox( height: isPortrait && !isMobileSize ? 68.h : 52.h, child: Center( @@ -712,12 +739,6 @@ class _LostProcessState extends State ), ), ), - onPressed: () async { - registrationTaskProvider.addConsentField("Y"); - await DemographicsApi() - .addDemographicField("consent", "true"); - continueButtonTap(size, newProcess); - }, ), ), ], @@ -775,8 +796,8 @@ class _LostProcessState extends State backgroundColor: MaterialStateProperty.all( continueButton ? solidPrimary : Colors.grey), ), - onPressed: () { - continueButtonTap(size, newProcess); + onPressed: _isLostUinContinue ? null : () async { + await continueButtonTap(size, newProcess); }, child: Text( context.read().newProcessTabIndex <= diff --git a/lib/ui/process_ui/new_process.dart b/lib/ui/process_ui/new_process.dart index dea2fadf9..bcd1c1296 100644 --- a/lib/ui/process_ui/new_process.dart +++ b/lib/ui/process_ui/new_process.dart @@ -58,6 +58,7 @@ class _NewProcessState extends State with WidgetsBindingObserver { late AppLocalizations appLocalizations = AppLocalizations.of(context)!; bool isPortrait = true; ScrollController scrollController = ScrollController(); + bool _isContinueProcessing = false; List postRegistrationTabs = [ 'Preview', @@ -306,7 +307,7 @@ class _NewProcessState extends State with WidgetsBindingObserver { if (globalProvider.newProcessTabIndex < size) { Screen screen = newProcess.screens!.elementAt(currentIndex)!; for (int i = 0; i < screen.fields!.length; i++) { - if (screen.fields!.elementAt(i)!.id == "dateOfBirth") { + if (screen.fields!.elementAt(i)!.controlType == "ageDate") { if (globalProvider.checkAgeGroupChange == "") { globalProvider.checkAgeGroupChange = globalProvider.ageGroup; } else { @@ -628,53 +629,62 @@ class _NewProcessState extends State with WidgetsBindingObserver { // height: isPortrait ? 94.h : 84.h, child: globalProvider.newProcessTabIndex == 0 ? Row( - children: [ - Expanded( - child: OutlinedButton( - child: SizedBox( - height: isPortrait && !isMobileSize ? 68.h : 52.h, - child: Center( - child: Text( - appLocalizations.go_back, - style: TextStyle( - fontSize: - isPortrait && !isMobileSize ? 22 : 14, - ), - ), - ), + children: [ + Expanded( + child: OutlinedButton( + child: SizedBox( + height: isPortrait && !isMobileSize ? 68.h : 52.h, + child: Center( + child: Text( + appLocalizations.go_back, + style: TextStyle( + fontSize: + isPortrait && !isMobileSize ? 22 : 14, ), - onPressed: () { - Navigator.of(context).pop(); - }, ), ), - SizedBox( - width: 10.w, - ), - Expanded( - child: ElevatedButton( - child: SizedBox( - height: isPortrait && !isMobileSize ? 68.h : 52.h, - child: Center( - child: Text( - appLocalizations.informed, - style: TextStyle( - fontSize: - isPortrait && !isMobileSize ? 22 : 14, - ), - ), - ), + ), + onPressed: () { + Navigator.of(context).pop(); + }, + ), + ), + SizedBox( + width: 10.w, + ), + Expanded( + child: ElevatedButton( + onPressed: _isContinueProcessing ? null : () async { + setState(() { + _isContinueProcessing = true; + }); + try { + registrationTaskProvider.addConsentField("Y"); + await DemographicsApi() + .addDemographicField("consent", "true"); + continueButtonTap(size, newProcess); + } finally { + setState(() { + _isContinueProcessing = false; + }); + } + }, + child: SizedBox( + height: isPortrait && !isMobileSize ? 68.h : 52.h, + child: Center( + child: Text( + appLocalizations.informed, + style: TextStyle( + fontSize: + isPortrait && !isMobileSize ? 22 : 14, ), - onPressed: () async { - registrationTaskProvider.addConsentField("Y"); - await DemographicsApi() - .addDemographicField("consent", "true"); - continueButtonTap(size, newProcess); - }, ), ), - ], - ) + ), + ), + ), + ], + ) : Row( mainAxisAlignment: MainAxisAlignment.start, children: [ @@ -716,34 +726,44 @@ class _NewProcessState extends State with WidgetsBindingObserver { child: Text(appLocalizations.upload_packet), ) : const SizedBox.shrink(),*/ - const Expanded( - child: SizedBox(), - ), - ElevatedButton( - style: ButtonStyle( - maximumSize: MaterialStateProperty.all( - const Size(209, 52)), - minimumSize: MaterialStateProperty.all( - const Size(209, 52)), - backgroundColor: MaterialStateProperty.all( - (continueButton && context.read().newProcessTabIndex <= - size) ? solidPrimary : authButton ? solidPrimary: Colors.grey), - ), - onPressed: () { - continueButtonTap(size, newProcess); - }, - child: Text( - context.read().newProcessTabIndex <= - size - ? appLocalizations.continue_text - : globalProvider.newProcessTabIndex == size + 1 - ? appLocalizations.authenticate - : appLocalizations.go_to_home, - style: const TextStyle(color: appWhite), - ), - ), - ], + const Expanded( + child: SizedBox(), + ), + ElevatedButton( + style: ButtonStyle( + maximumSize: MaterialStateProperty.all( + const Size(209, 52)), + minimumSize: MaterialStateProperty.all( + const Size(209, 52)), + backgroundColor: MaterialStateProperty.all( + (continueButton && context.read().newProcessTabIndex <= + size) ? solidPrimary : authButton ? solidPrimary: Colors.grey), ), + onPressed: _isContinueProcessing ? null : () async { + if (_isContinueProcessing) return; + setState(() { + _isContinueProcessing = true; + }); + try { + await continueButtonTap(size, newProcess); + } finally { + setState(() { + _isContinueProcessing = false; + }); + } + }, + child: Text( + context.read().newProcessTabIndex <= + size + ? appLocalizations.continue_text + : globalProvider.newProcessTabIndex == size + 1 + ? appLocalizations.authenticate + : appLocalizations.go_to_home, + style: const TextStyle(color: appWhite), + ), + ), + ], + ), ), body: SingleChildScrollView( controller: scrollController, diff --git a/lib/ui/process_ui/update_process.dart b/lib/ui/process_ui/update_process.dart index 2312656d0..bb61c0a01 100644 --- a/lib/ui/process_ui/update_process.dart +++ b/lib/ui/process_ui/update_process.dart @@ -58,6 +58,7 @@ class _UpdateProcessState extends State late AppLocalizations appLocalizations = AppLocalizations.of(context)!; bool isPortrait = true; bool fieldSelectionCompleted = false; + bool _isContinueProcessing = false; List postRegistrationTabs = [ 'Preview', @@ -362,7 +363,7 @@ class _UpdateProcessState extends State if (globalProvider.newProcessTabIndex < size) { Screen screen = newProcess.screens!.elementAt(currentIndex)!; for (int i = 0; i < screen.fields!.length; i++) { - if (screen.fields!.elementAt(i)!.id == "dateOfBirth") { + if (screen.fields!.elementAt(i)!.controlType == "ageDate") { if (globalProvider.checkAgeGroupChange == "") { globalProvider.checkAgeGroupChange = globalProvider.ageGroup; } else { @@ -458,83 +459,103 @@ class _UpdateProcessState extends State return true; } + const debounceDuration = Duration(milliseconds: 500); + DateTime? lastClickTime; + continueButtonTap(int size, newProcess) async { - if (globalProvider.newProcessTabIndex == 0 && !fieldSelectionCompleted) { - if (globalProvider.selectedUpdateFields.isEmpty || - globalProvider.updateFieldKey.currentState == null || - !globalProvider.updateFieldKey.currentState!.validate()) { - return; - } - } - if (!fieldSelectionCompleted) { - globalProvider.clearMap(); - globalProvider.clearScannedPages(); - globalProvider.clearExceptions(); - await registrationTaskProvider.changeUpdatableFieldGroups(); - globalProvider.ageGroup = ""; - await BiometricsApi().clearBiometricAndDocumentHashmap(); - setState(() { - fieldSelectionCompleted = true; - }); + final now = DateTime.now(); + if (lastClickTime != null && + now.difference(lastClickTime!) < debounceDuration) { return; } - if (globalProvider.newProcessTabIndex < size) { - ageDateChangeValidation(globalProvider.newProcessTabIndex); - bool customValidator = - await customValidation(globalProvider.newProcessTabIndex); - if (customValidator) { - if (globalProvider.formKey.currentState!.validate()) { - if (globalProvider.newProcessTabIndex == - newProcess.screens!.length - 1) { - templateTitleMap = { - 'demographicInfo': appLocalizations.demographic_information, - 'documents': appLocalizations.documents, - 'bioMetrics': appLocalizations.biometrics, - }; - registrationTaskProvider.setPreviewTemplate(""); - registrationTaskProvider.setAcknowledgementTemplate(""); - await registrationTaskProvider.getPreviewTemplate( - true, templateTitleMap!); - await registrationTaskProvider.getAcknowledgementTemplate( - false, templateTitleMap!); - } + lastClickTime = now; - globalProvider.newProcessTabIndex = - globalProvider.newProcessTabIndex + 1; - } - } + setState(() { + _isContinueProcessing = true; + }); - _nextButtonClickedAudit(); - } else { - if (globalProvider.newProcessTabIndex == size + 1) { - bool isPacketAuthenticated = await _authenticatePacket(context); - if (!isPacketAuthenticated) { - return; - } - RegistrationSubmitResponse registrationSubmitResponse = - await registrationTaskProvider.submitRegistrationDto(username); - if (registrationSubmitResponse.errorCode!.isNotEmpty) { - _showInSnackBar(registrationSubmitResponse.errorCode!); + try { + if (globalProvider.newProcessTabIndex == 0 && !fieldSelectionCompleted) { + if (globalProvider.selectedUpdateFields.isEmpty || + globalProvider.updateFieldKey.currentState == null || + !globalProvider.updateFieldKey.currentState!.validate()) { return; } - globalProvider.setRegId(registrationSubmitResponse.rId); - - // Updating key to packetId after success creation of packet - registrationTaskProvider - .updateTemplateStorageKey(registrationSubmitResponse.rId); - registrationTaskProvider.deleteDefaultTemplateStored(); - + } + if (!fieldSelectionCompleted) { + globalProvider.clearMap(); + globalProvider.clearScannedPages(); + globalProvider.clearExceptions(); + await registrationTaskProvider.changeUpdatableFieldGroups(); + globalProvider.ageGroup = ""; + await BiometricsApi().clearBiometricAndDocumentHashmap(); setState(() { - username = ''; - password = ''; + fieldSelectionCompleted = true; }); - } - if (globalProvider.newProcessTabIndex == size + 2) { - _resetValuesOnRegistrationComplete(); return; } - globalProvider.newProcessTabIndex = - globalProvider.newProcessTabIndex + 1; + if (globalProvider.newProcessTabIndex < size) { + ageDateChangeValidation(globalProvider.newProcessTabIndex); + bool customValidator = + await customValidation(globalProvider.newProcessTabIndex); + if (customValidator) { + if (globalProvider.formKey.currentState!.validate()) { + if (globalProvider.newProcessTabIndex == + newProcess.screens!.length - 1) { + templateTitleMap = { + 'demographicInfo': appLocalizations.demographic_information, + 'documents': appLocalizations.documents, + 'bioMetrics': appLocalizations.biometrics, + }; + registrationTaskProvider.setPreviewTemplate(""); + registrationTaskProvider.setAcknowledgementTemplate(""); + await registrationTaskProvider.getPreviewTemplate( + true, templateTitleMap!); + await registrationTaskProvider.getAcknowledgementTemplate( + false, templateTitleMap!); + } + + globalProvider.newProcessTabIndex = + globalProvider.newProcessTabIndex + 1; + } + } + + _nextButtonClickedAudit(); + } else { + if (globalProvider.newProcessTabIndex == size + 1) { + bool isPacketAuthenticated = await _authenticatePacket(context); + if (!isPacketAuthenticated) { + return; + } + RegistrationSubmitResponse registrationSubmitResponse = + await registrationTaskProvider.submitRegistrationDto(username); + if (registrationSubmitResponse.errorCode!.isNotEmpty) { + _showInSnackBar(registrationSubmitResponse.errorCode!); + return; + } + globalProvider.setRegId(registrationSubmitResponse.rId); + + // Updating key to packetId after success creation of packet + registrationTaskProvider + .updateTemplateStorageKey(registrationSubmitResponse.rId); + registrationTaskProvider.deleteDefaultTemplateStored(); + + setState(() { + username = ''; + password = ''; + }); + } + if (globalProvider.newProcessTabIndex == size + 2) { + _resetValuesOnRegistrationComplete(); + return; + } + globalProvider.newProcessTabIndex = + globalProvider.newProcessTabIndex + 1; + } + } finally { + setState(() { + _isContinueProcessing = false; + }); } } @@ -580,153 +601,153 @@ class _UpdateProcessState extends State // height: isPortrait ? 94.h : 84.h, child: context.watch().newProcessTabIndex == 0 ? Row( - children: [ - Expanded( - child: fieldSelectionCompleted - ? OutlinedButton( - child: SizedBox( - height: - isPortrait && !isMobileSize ? 68.h : 52.h, - child: Center( - child: Text( - appLocalizations.go_back, - style: TextStyle( - fontSize: isPortrait && !isMobileSize - ? 22 - : 14, - ), - ), - ), - ), - onPressed: () { - if (!fieldSelectionCompleted) { - Navigator.of(context).pop(); - } else { - setState(() { - fieldSelectionCompleted = false; - }); - } - }, - ) - : const SizedBox(), - ), - SizedBox( - width: 10.w, - ), - Expanded( - child: ElevatedButton( - style: ButtonStyle( - maximumSize: MaterialStateProperty.all( - const Size(209, 52)), - minimumSize: MaterialStateProperty.all( - const Size(209, 52)), - backgroundColor: MaterialStateProperty.all( - !fieldSelectionCompleted - ? (context - .watch() - .selectedUpdateFields - .isNotEmpty && - continueButton) - ? solidPrimary - : Colors.grey - : solidPrimary), - ), - child: SizedBox( - height: isPortrait && !isMobileSize ? 68.h : 52.h, - child: Center( - child: Text( - fieldSelectionCompleted - ? appLocalizations.informed - : appLocalizations.continue_text, - style: TextStyle( - fontSize: - isPortrait && !isMobileSize ? 22 : 14, - ), - ), - ), + children: [ + Expanded( + child: fieldSelectionCompleted + ? OutlinedButton( + child: SizedBox( + height: + isPortrait && !isMobileSize ? 68.h : 52.h, + child: Center( + child: Text( + appLocalizations.go_back, + style: TextStyle( + fontSize: isPortrait && !isMobileSize + ? 22 + : 14, ), - onPressed: () async { - if (fieldSelectionCompleted) { - registrationTaskProvider.addConsentField("Y"); - await DemographicsApi().addDemographicField( - "UIN", globalProvider.updateUINNumber); - await DemographicsApi() - .addDemographicField("consent", "true"); - } - continueButtonTap(size, newProcess); - }, ), ), - ], + ), + onPressed: () { + if (!fieldSelectionCompleted) { + Navigator.of(context).pop(); + } else { + setState(() { + fieldSelectionCompleted = false; + }); + } + }, ) - : Row( - mainAxisAlignment: MainAxisAlignment.start, - children: [ - // globalProvider.newProcessTabIndex == size + 2 - // ? ElevatedButton( - // onPressed: () async { - // await connectivityProvider - // .checkNetworkConnection(); - // bool isConnected = - // connectivityProvider.isConnected; - // if (!isConnected) { - // _showInSnackBar( - // appLocalizations.network_error); - // return; - // } - // globalProvider.syncPacket(globalProvider.regId); - // }, - // child: Text(appLocalizations.sync_packet), - // ) - // : const SizedBox.shrink(), - // SizedBox( - // width: 10.w, - // ), - // globalProvider.newProcessTabIndex == size + 2 - // ? ElevatedButton( - // onPressed: () async { - // await connectivityProvider - // .checkNetworkConnection(); - // bool isConnected = - // connectivityProvider.isConnected; - // if (!isConnected) { - // _showInSnackBar( - // appLocalizations.network_error); - // return; - // } - // globalProvider - // .uploadPacket(globalProvider.regId); - // }, - // child: Text(appLocalizations.upload_packet), - // ) - // : const SizedBox.shrink(), - const Expanded( - child: SizedBox(), - ), - ElevatedButton( - style: ButtonStyle( - maximumSize: MaterialStateProperty.all( - const Size(209, 52)), - minimumSize: MaterialStateProperty.all( - const Size(209, 52)), - backgroundColor: MaterialStateProperty.all( - continueButton ? solidPrimary : Colors.grey), - ), - onPressed: () { - continueButtonTap(size, newProcess); - }, + : const SizedBox(), + ), + SizedBox( + width: 10.w, + ), + Expanded( + child: ElevatedButton( + style: ButtonStyle( + maximumSize: MaterialStateProperty.all( + const Size(209, 52)), + minimumSize: MaterialStateProperty.all( + const Size(209, 52)), + backgroundColor: MaterialStateProperty.all( + !fieldSelectionCompleted + ? (context + .watch() + .selectedUpdateFields + .isNotEmpty && + continueButton) + ? solidPrimary + : Colors.grey + : solidPrimary), + ), + onPressed: _isContinueProcessing ? null : () async { + if (fieldSelectionCompleted) { + registrationTaskProvider.addConsentField("Y"); + await DemographicsApi().addDemographicField( + "UIN", globalProvider.updateUINNumber); + await DemographicsApi() + .addDemographicField("consent", "true"); + } + continueButtonTap(size, newProcess); + }, + child: SizedBox( + height: isPortrait && !isMobileSize ? 68.h : 52.h, + child: Center( child: Text( - context.read().newProcessTabIndex <= - size - ? appLocalizations.continue_text - : globalProvider.newProcessTabIndex == size + 1 - ? appLocalizations.authenticate - : appLocalizations.go_to_home, - style: const TextStyle(color: appWhite), + fieldSelectionCompleted + ? appLocalizations.informed + : appLocalizations.continue_text, + style: TextStyle( + fontSize: + isPortrait && !isMobileSize ? 22 : 14, + ), ), ), - ], + ), ), + ), + ], + ) + : Row( + mainAxisAlignment: MainAxisAlignment.start, + children: [ + // globalProvider.newProcessTabIndex == size + 2 + // ? ElevatedButton( + // onPressed: () async { + // await connectivityProvider + // .checkNetworkConnection(); + // bool isConnected = + // connectivityProvider.isConnected; + // if (!isConnected) { + // _showInSnackBar( + // appLocalizations.network_error); + // return; + // } + // globalProvider.syncPacket(globalProvider.regId); + // }, + // child: Text(appLocalizations.sync_packet), + // ) + // : const SizedBox.shrink(), + // SizedBox( + // width: 10.w, + // ), + // globalProvider.newProcessTabIndex == size + 2 + // ? ElevatedButton( + // onPressed: () async { + // await connectivityProvider + // .checkNetworkConnection(); + // bool isConnected = + // connectivityProvider.isConnected; + // if (!isConnected) { + // _showInSnackBar( + // appLocalizations.network_error); + // return; + // } + // globalProvider + // .uploadPacket(globalProvider.regId); + // }, + // child: Text(appLocalizations.upload_packet), + // ) + // : const SizedBox.shrink(), + const Expanded( + child: SizedBox(), + ), + ElevatedButton( + style: ButtonStyle( + maximumSize: MaterialStateProperty.all( + const Size(209, 52)), + minimumSize: MaterialStateProperty.all( + const Size(209, 52)), + backgroundColor: MaterialStateProperty.all( + continueButton ? solidPrimary : Colors.grey), + ), + onPressed: _isContinueProcessing ? null : () async { + await continueButtonTap(size, newProcess); + }, + child: Text( + context.read().newProcessTabIndex <= + size + ? appLocalizations.continue_text + : globalProvider.newProcessTabIndex == size + 1 + ? appLocalizations.authenticate + : appLocalizations.go_to_home, + style: const TextStyle(color: appWhite), + ), + ), + ], + ), ), body: SingleChildScrollView( child: AnnotatedRegion( From ed96db46b667d32a2256c441e25fc516a56822d9 Mon Sep 17 00:00:00 2001 From: jayesh12234 <111957576+jayesh12234@users.noreply.github.com> Date: Fri, 18 Jul 2025 17:28:35 +0530 Subject: [PATCH 04/44] RCF-1176 (#547) Signed-off-by: jayesh12234 <111957576+jayesh12234@users.noreply.github.com> --- ui-test/pom.xml | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/ui-test/pom.xml b/ui-test/pom.xml index dc38bc51d..f96f9ea01 100644 --- a/ui-test/pom.xml +++ b/ui-test/pom.xml @@ -122,12 +122,6 @@ extentreports 5.1.0 - - junit - junit - 4.13.2 - test - io.rest-assured rest-assured @@ -143,11 +137,6 @@ slf4j-log4j12 1.6.2 - - javax.ws.rs - javax.ws.rs-api - 2.1.1 - org.yaml snakeyaml From 3056af1bb0913be9b48b14dce8bccba17e1a6065 Mon Sep 17 00:00:00 2001 From: Famuda1234 <144789326+Famuda1234@users.noreply.github.com> Date: Sun, 17 Aug 2025 15:14:21 +0530 Subject: [PATCH 05/44] Updated UI automation testscripts (#563) Signed-off-by: G Famuda Mubashira --- ui-test/pom.xml | 1 - .../regclient/BaseTest/AndroidBaseTest.java | 1 + .../NewRegistrationAdult.java | 13 ++++++++- .../NewRegistrationMinorException.java | 4 +-- .../androidTestCases/UpdateMyUinMinor.java | 2 +- .../regclient/androidTestCases/logintest.java | 8 +++--- .../main/java/regclient/page/BasePage.java | 28 +++++++++++++++++-- .../main/java/regclient/page/CameraPage.java | 20 ++++++------- .../java/regclient/page/PendingApproval.java | 6 ++++ .../pages/arabic/PendingApprovalArabic.java | 15 ++++++++++ .../english/AuthenticationPageEnglish.java | 4 +++ .../DemographicDetailsPageEnglish.java | 1 + .../pages/english/LoginPageEnglish.java | 3 +- .../pages/english/PendingApprovalEnglish.java | 20 +++++++++++-- .../pages/french/PendingApprovalFrench.java | 15 ++++++++++ .../pages/hindi/PendingApprovalHindi.java | 15 ++++++++++ .../pages/kannada/PendingApprovalKannada.java | 14 ++++++++++ .../pages/tamil/PendingApprovalTamil.java | 12 ++++++++ .../main/resources/DesiredCapabilities.json | 4 +-- ui-test/src/main/resources/config.properties | 2 +- 20 files changed, 160 insertions(+), 28 deletions(-) diff --git a/ui-test/pom.xml b/ui-test/pom.xml index f96f9ea01..52debc1c9 100644 --- a/ui-test/pom.xml +++ b/ui-test/pom.xml @@ -25,7 +25,6 @@ ${maven.compiler.target} - org.apache.maven.plugins maven-jar-plugin diff --git a/ui-test/src/main/java/regclient/BaseTest/AndroidBaseTest.java b/ui-test/src/main/java/regclient/BaseTest/AndroidBaseTest.java index 51272ff11..604337fa4 100644 --- a/ui-test/src/main/java/regclient/BaseTest/AndroidBaseTest.java +++ b/ui-test/src/main/java/regclient/BaseTest/AndroidBaseTest.java @@ -11,6 +11,7 @@ public class AndroidBaseTest extends BaseTest { @BeforeMethod(alwaysRun = true) public void setup() { try { + DriverManager.startAppiumServer(); this.driver = DriverManager.getDriver(); } catch (Exception e) { throw new RuntimeException(); diff --git a/ui-test/src/main/java/regclient/androidTestCases/NewRegistrationAdult.java b/ui-test/src/main/java/regclient/androidTestCases/NewRegistrationAdult.java index ee6b10092..59cb84514 100644 --- a/ui-test/src/main/java/regclient/androidTestCases/NewRegistrationAdult.java +++ b/ui-test/src/main/java/regclient/androidTestCases/NewRegistrationAdult.java @@ -539,7 +539,15 @@ else if(TestDataReader.readData("language").equalsIgnoreCase("ara")){ pendingApproval.clickOnSubmitButton(); assertTrue(pendingApproval.isSupervisorAuthenticationTitleDisplayed(), "Verify if Supervisor Authentication page displayed"); + + pendingApproval.clickOnSubmitButton(); + assertTrue(pendingApproval.isInvalidemptyUsernameSumbitButtonEnbled(), "Verify if error empty username submit button enabled"); + + pendingApproval.enterUserName(KeycloakUserManager.moduleSpecificUser+"123"); + + assertTrue(pendingApproval.isInvalidUsernameMessageDisplayed(), "Verify if invalid username messgae is displayed"); pendingApproval.enterUserName(KeycloakUserManager.moduleSpecificUser); + pendingApproval.enterPassword(ConfigManager.getIAMUsersPassword()); pendingApproval.clickOnSubmitButton(); pendingApproval.clickOnBackButton(); @@ -610,7 +618,7 @@ else if(TestDataReader.readData("language").equalsIgnoreCase("ara")){ assertTrue(loginPage.isLoginPageLoaded(),"verify if login page is displayeded in Selected language"); } - @Test + public void newRegistrationAdultUploadMultipleDoccuments(){ FetchUiSpec.getUiSpec("newProcess"); FetchUiSpec.getBiometricDetails("individualBiometrics"); @@ -1131,6 +1139,9 @@ else if(TestDataReader.readData("language").equalsIgnoreCase("ara")){ authenticationPage=new AuthenticationPageArabic(driver); } assertTrue(authenticationPage.isAuthenticationPageDisplayed(),"Verify if authentication details page is displayed"); + authenticationPage.clickOnAuthenticatenButton(); + assertTrue(authenticationPage.isAuthenticationPageDisplayed(),"Username/password required error should be displayed"); + authenticationPage.clickOnAuthenticatenButton(); authenticationPage.enterUserName(KeycloakUserManager.moduleSpecificUser); authenticationPage.enterPassword(ConfigManager.getIAMUsersPassword()); authenticationPage.clickOnAuthenticatenButton(); diff --git a/ui-test/src/main/java/regclient/androidTestCases/NewRegistrationMinorException.java b/ui-test/src/main/java/regclient/androidTestCases/NewRegistrationMinorException.java index b3c7d08bc..26b90e4e6 100644 --- a/ui-test/src/main/java/regclient/androidTestCases/NewRegistrationMinorException.java +++ b/ui-test/src/main/java/regclient/androidTestCases/NewRegistrationMinorException.java @@ -359,7 +359,7 @@ else if(TestDataReader.readData("language").equalsIgnoreCase("ara")){ applicantBiometricsPage.clickOnMarkExceptionButton(); assertTrue(applicantBiometricsPage.isExceptionTypeTitleDisplyed(),"Verify if applicant biometric mark exception is displayed"); - applicantBiometricsPage.clickOnZoomButton(); + applicantBiometricsPage.clickOnZoomButton(); assertTrue(applicantBiometricsPage.isRightHandScanTitleDisplyed(),"Verify if applicant right hand scan is displayed"); applicantBiometricsPage.markFourFingureExceptionThenRemoveOne(); @@ -382,7 +382,7 @@ else if(TestDataReader.readData("language").equalsIgnoreCase("ara")){ applicantBiometricsPage.clickOnMarkExceptionButton(); assertTrue(applicantBiometricsPage.isExceptionTypeTitleDisplyed(),"Verify if applicant biometric mark exception is displayed"); - applicantBiometricsPage.clickOnZoomButton(); + applicantBiometricsPage.clickOnZoomButton(); assertTrue(applicantBiometricsPage.isLeftHandScanTitleDisplyed(),"Verify if applicant right hand scan is displayed"); applicantBiometricsPage.markOneFingureException(); diff --git a/ui-test/src/main/java/regclient/androidTestCases/UpdateMyUinMinor.java b/ui-test/src/main/java/regclient/androidTestCases/UpdateMyUinMinor.java index af11816bb..68cd2d60a 100644 --- a/ui-test/src/main/java/regclient/androidTestCases/UpdateMyUinMinor.java +++ b/ui-test/src/main/java/regclient/androidTestCases/UpdateMyUinMinor.java @@ -342,7 +342,7 @@ else if(TestDataReader.readData("language").equalsIgnoreCase("tam")){ else if(TestDataReader.readData("language").equalsIgnoreCase("ara")){ biometricDetailsPage=new BiometricDetailsPageArabic(driver); } - assertTrue(biometricDetailsPage.isBiometricDetailsPageDisplayed(),"Verify if biometric details page is displayed"); + assertTrue(biometricDetailsPage.isBiometricDetailsPageDisplayed(),"Verify if biometric details page is displayed"); if(TestDataReader.readData("language").equalsIgnoreCase("eng")) { applicantBiometricsPage=new ApplicantBiometricsPageEnglish(driver); } diff --git a/ui-test/src/main/java/regclient/androidTestCases/logintest.java b/ui-test/src/main/java/regclient/androidTestCases/logintest.java index b94abdcdc..ae97160c4 100644 --- a/ui-test/src/main/java/regclient/androidTestCases/logintest.java +++ b/ui-test/src/main/java/regclient/androidTestCases/logintest.java @@ -119,7 +119,7 @@ else if(TestDataReader.readData("language").equalsIgnoreCase("ara")){ //assertFalse(loginPage.isLoginButtonEnabled(),"verify if the login button is disable without entering password"); assertTrue(loginPage.isBackButtonDisplayed(), "Verify if back button is displayed"); - assertTrue(loginPage.isForgetOptionDisplayed(), "Verify if forget password option is displayed"); + //assertTrue(loginPage.isForgetOptionDisplayed(), "Verify if forget password option is displayed"); assertTrue(loginPage.isPasswordHeaderDisplayed(), "Verify if the password input box header displayed"); @@ -341,7 +341,7 @@ else if(TestDataReader.readData("language").equalsIgnoreCase("ara")){ supervisorBiometricVerificationpage.markOneEyeException(); supervisorBiometricVerificationpage.clickOnExceptionTypeTemporaryButton(); - assertTrue(supervisorBiometricVerificationpage.isCommentHeaderDisplyed(),"Verify if Comments header is displayed"); + assertTrue(supervisorBiometricVerificationpage.isCommentHeaderDisplyed(),"Verify if Comments header is displayed"); supervisorBiometricVerificationpage.clickOnIrisScanTitle(); supervisorBiometricVerificationpage.clickOnScanButton(); @@ -560,9 +560,9 @@ else if(TestDataReader.readData("language").equalsIgnoreCase("ara")){ assertTrue(UpdateOperatorBiometricspage.isExceptionTypeTitleDisplyed(),"Verify if mark exception is displayed"); UpdateOperatorBiometricspage.markOneEyeException(); - UpdateOperatorBiometricspage.clickOnExceptionTypeTemporaryButton(); + UpdateOperatorBiometricspage.clickOnExceptionTypeTemporaryButton(); - assertTrue(UpdateOperatorBiometricspage.isCommentHeaderDisplyed(),"Verify if Comments header is displayed"); + assertTrue(UpdateOperatorBiometricspage.isCommentHeaderDisplyed(),"Verify if Comments header is displayed"); UpdateOperatorBiometricspage.clickOnIrisScanTitle(); UpdateOperatorBiometricspage.clickOnScanButton(); diff --git a/ui-test/src/main/java/regclient/page/BasePage.java b/ui-test/src/main/java/regclient/page/BasePage.java index c8be843b1..f36da2d48 100644 --- a/ui-test/src/main/java/regclient/page/BasePage.java +++ b/ui-test/src/main/java/regclient/page/BasePage.java @@ -96,7 +96,7 @@ protected void clickAndsendKeysToTextBox(WebElement element, String text) { ((HidesKeyboard) driver).hideKeyboard(); } - protected void sendKeysToTextBox(WebElement element, String text) { + protected void clickAndsendKeysToTextBox2(WebElement element, String text) { this.waitForElementToBeVisible(element); element.click(); waitTime(1); @@ -106,6 +106,16 @@ protected void sendKeysToTextBox(WebElement element, String text) { waitTime(1); driver.navigate().back(); } + + protected void sendKeysToTextBox(WebElement element, String text) { + this.waitForElementToBeVisible(element); + waitTime(1); + element.clear(); + waitTime(1); + element.sendKeys(text); + waitTime(1); + driver.navigate().back(); + } protected String getTextFromLocator(WebElement element) { this.waitForElementToBeVisible(element); @@ -354,8 +364,8 @@ public static String generateData(String validator) { case "^(?=.{2,50}$).*": return generateStringOfLength(2, 30); - case "^[0-9]{6}[/][0-9]{2}[/][0-9]{1}$": - return generateSixDigitNumber() + "/" + generateTwoDigitNumber() + "/" + generateOneDigitNumber(); + case "^([0-9]{10})$": + return generateTenDigitNumber(); case "^(1869|18[7-9][0-9]|19[0-9][0-9]|20[0-9][0-9])/([0][1-9]|1[0-2])/([0][1-9]|[1-2][0-9]|3[01])$": return generateDateInRange(); @@ -371,6 +381,9 @@ public static String generateData(String validator) { case "^[A-Za-z0-9_\\-]+(\\.[A-Za-z0-9_]+)*@[A-Za-z0-9_-]+(\\.[A-Za-z0-9_]+)*(\\.[a-zA-Z]{2,})$": return generateEmail(); + + case "^([0-9]{10,30})$": + return generateTenDigitNumber(); default: return "abcd"; @@ -411,6 +424,15 @@ private static String generateDateInRange() { private static String generateNineDigitNumber() { return String.format("%09d", random.nextInt(1000000000)); } + + + private static final Random randomten = new Random(); + + private static String generateTenDigitNumber() { + long number = 1000000000L + (long)(randomten.nextDouble() * 9000000000L); + return String.valueOf(number); + } + private static String generateEmail() { String[] domains = {"example.com", "test.com", "email.com"}; diff --git a/ui-test/src/main/java/regclient/page/CameraPage.java b/ui-test/src/main/java/regclient/page/CameraPage.java index 04007c873..88755d7b8 100644 --- a/ui-test/src/main/java/regclient/page/CameraPage.java +++ b/ui-test/src/main/java/regclient/page/CameraPage.java @@ -10,7 +10,8 @@ public class CameraPage extends BasePage{ - @AndroidFindBy(xpath = "//android.widget.TextView[@text=\"OK\"]") + @AndroidFindBy(xpath = "//android.widget.TextView[@text=\"OK\"]") + private WebElement okButton; public CameraPage(AppiumDriver driver) { @@ -18,18 +19,17 @@ public CameraPage(AppiumDriver driver) { } public void clickOkButton() { -// if(isElementDisplayed(okButton)) -// clickOnElement(okButton); -// else { - waitTime(7); - clickAtCoordinates(633,2042); -// } + if(isElementDisplayed(okButton)) + clickOnElement(okButton); + else { + waitTime(7); + clickAtCoordinates(401,1123); + } } public void clickimage() { - waitTime(2); - isElementDisplayed(driver.findElement(By.id(TestDataReader.readData("id")))); - clickOnElement(driver.findElement(By.id(TestDataReader.readData("id")))); + waitTime(7); + clickAtCoordinates(401,1123); } diff --git a/ui-test/src/main/java/regclient/page/PendingApproval.java b/ui-test/src/main/java/regclient/page/PendingApproval.java index b75355816..bc5e76bb7 100644 --- a/ui-test/src/main/java/regclient/page/PendingApproval.java +++ b/ui-test/src/main/java/regclient/page/PendingApproval.java @@ -47,5 +47,11 @@ public PendingApproval(AppiumDriver driver) { public abstract boolean isRejectPacketTitleDisplayed(); public abstract boolean isSubmitButtonEnabled(); + + public abstract boolean isInvalidUsernameMessageDisplayed(); + + public abstract boolean isInvalidemptyUsernameSumbitButtonEnbled(); + + } diff --git a/ui-test/src/main/java/regclient/pages/arabic/PendingApprovalArabic.java b/ui-test/src/main/java/regclient/pages/arabic/PendingApprovalArabic.java index 42c76cb22..7b1cb4aa5 100644 --- a/ui-test/src/main/java/regclient/pages/arabic/PendingApprovalArabic.java +++ b/ui-test/src/main/java/regclient/pages/arabic/PendingApprovalArabic.java @@ -29,6 +29,12 @@ public class PendingApprovalArabic extends PendingApproval{ @AndroidFindBy(accessibility = "يُقدِّم") private WebElement submitButton; + + @AndroidFindBy(accessibility = "اسم المستخدم غير صالح!") + private WebElement invalidUsernameMessage; + + @AndroidFindBy(accessibility = "SUBMIT") + private WebElement invalidUsernameMessageForempty; @AndroidFindBy(accessibility = "مصادقة المشرف") private WebElement supervisorAuthenticationTitle; @@ -116,6 +122,11 @@ public boolean isRejectButtonDisplayed() { return isElementDisplayed(rejectButton); } + public boolean isInvalidUsernameMessageDisplayed() { + return isElementDisplayed(invalidUsernameMessage); + } + + public boolean isPageAttributesDisplayed() { return isElementDisplayed(pageAttributes); } @@ -157,5 +168,9 @@ public void selectRejectionReasonDropdown() { public boolean isSubmitButtonEnabled() { return isElementEnabled(submitButton); } + + public boolean isInvalidemptyUsernameSumbitButtonEnbled() { + return isElementEnabled(invalidUsernameMessageForempty); + } } diff --git a/ui-test/src/main/java/regclient/pages/english/AuthenticationPageEnglish.java b/ui-test/src/main/java/regclient/pages/english/AuthenticationPageEnglish.java index 2fc296d05..f76be7dcf 100644 --- a/ui-test/src/main/java/regclient/pages/english/AuthenticationPageEnglish.java +++ b/ui-test/src/main/java/regclient/pages/english/AuthenticationPageEnglish.java @@ -37,6 +37,10 @@ public boolean isAuthenticationPageDisplayed() { return isElementDisplayed(authenticationPageTitle); } + + + + public AcknowledgementPage clickOnAuthenticatenButton() { clickOnElement(authenticateButton); return new AcknowledgementPageEnglish(driver); diff --git a/ui-test/src/main/java/regclient/pages/english/DemographicDetailsPageEnglish.java b/ui-test/src/main/java/regclient/pages/english/DemographicDetailsPageEnglish.java index a9e27b4a1..dcf0d3df1 100644 --- a/ui-test/src/main/java/regclient/pages/english/DemographicDetailsPageEnglish.java +++ b/ui-test/src/main/java/regclient/pages/english/DemographicDetailsPageEnglish.java @@ -69,6 +69,7 @@ public DocumentUploadPage clickOnContinueButton() { public boolean isContinueButtonEnable() { return isElementEnabled(continueButton); + } diff --git a/ui-test/src/main/java/regclient/pages/english/LoginPageEnglish.java b/ui-test/src/main/java/regclient/pages/english/LoginPageEnglish.java index 7c6ab24c2..aa9fd84cc 100644 --- a/ui-test/src/main/java/regclient/pages/english/LoginPageEnglish.java +++ b/ui-test/src/main/java/regclient/pages/english/LoginPageEnglish.java @@ -31,6 +31,7 @@ public LoginPageEnglish(AppiumDriver driver) { @AndroidFindBy(xpath = "//android.widget.EditText") private WebElement passwordTextBox; + @AndroidFindBy(accessibility = "LOGIN") private WebElement loginButton; @@ -68,7 +69,7 @@ public LoginPageEnglish(AppiumDriver driver) { @AndroidFindBy(accessibility = "BACK") private WebElement backButton; - @AndroidFindBy(accessibility = "Forgot Password?") + @AndroidFindBy(accessibility = "FORGOT PASSWORD?") private WebElement forgetPasswordButton; @AndroidFindBy(accessibility = "User not found!") diff --git a/ui-test/src/main/java/regclient/pages/english/PendingApprovalEnglish.java b/ui-test/src/main/java/regclient/pages/english/PendingApprovalEnglish.java index 01cdc99cc..f2cce4bd6 100644 --- a/ui-test/src/main/java/regclient/pages/english/PendingApprovalEnglish.java +++ b/ui-test/src/main/java/regclient/pages/english/PendingApprovalEnglish.java @@ -32,6 +32,14 @@ public class PendingApprovalEnglish extends PendingApproval{ @AndroidFindBy(accessibility = "SUBMIT") private WebElement submitButton; + + @AndroidFindBy(accessibility = "Username invalid!") + private WebElement invalidUsernameMessage; + + + @AndroidFindBy(accessibility = "SUBMIT") + private WebElement invalidUsernameMessageForempty; + @AndroidFindBy(accessibility = "Supervisor's Authentication") private WebElement supervisorAuthenticationTitle; @@ -95,13 +103,21 @@ public void clickOnSubmitButton() { public boolean isSupervisorAuthenticationTitleDisplayed() { return isElementDisplayed(supervisorAuthenticationTitle); } + + public boolean isInvalidUsernameMessageDisplayed() { + return isElementDisplayed(invalidUsernameMessage); + } + + public boolean isInvalidemptyUsernameSumbitButtonEnbled() { + return isElementEnabled(invalidUsernameMessageForempty); + } public void enterUserName(String username) { - sendKeysToTextBox(userNameTextBox,username); + clickAndsendKeysToTextBox2(userNameTextBox,username); } public void enterPassword(String password) { - sendKeysToTextBox(passwordTextBox,password); + clickAndsendKeysToTextBox2(passwordTextBox,password); } public void clickOnBackButton() { diff --git a/ui-test/src/main/java/regclient/pages/french/PendingApprovalFrench.java b/ui-test/src/main/java/regclient/pages/french/PendingApprovalFrench.java index f747da797..3ca8b313f 100644 --- a/ui-test/src/main/java/regclient/pages/french/PendingApprovalFrench.java +++ b/ui-test/src/main/java/regclient/pages/french/PendingApprovalFrench.java @@ -62,7 +62,14 @@ public class PendingApprovalFrench extends PendingApproval{ @AndroidFindBy(accessibility = "Please select a value") private WebElement rejectReasonDropdown; + + @AndroidFindBy(accessibility = "اسم المستخدم غير صالح!") + private WebElement invalidUsernameMessage; + @AndroidFindBy(accessibility = "SUBMIT") + private WebElement invalidUsernameMessageForempty; + + public PendingApprovalFrench(AppiumDriver driver) { super(driver); } @@ -132,6 +139,10 @@ public void enterAID(String AID) { clickAndsendKeysToTextBox(applicationIdTextbox,AID); } + public boolean isInvalidUsernameMessageDisplayed() { + return isElementDisplayed(invalidUsernameMessage); + } + public void clickOnRejectButton() { clickOnElement(rejectButton); } @@ -157,5 +168,9 @@ public void selectRejectionReasonDropdown() { public boolean isSubmitButtonEnabled() { return isElementEnabled(submitButton); } + + public boolean isInvalidemptyUsernameSumbitButtonEnbled() { + return isElementEnabled(invalidUsernameMessageForempty); + } } diff --git a/ui-test/src/main/java/regclient/pages/hindi/PendingApprovalHindi.java b/ui-test/src/main/java/regclient/pages/hindi/PendingApprovalHindi.java index 1eed65cbe..5570bc5e2 100644 --- a/ui-test/src/main/java/regclient/pages/hindi/PendingApprovalHindi.java +++ b/ui-test/src/main/java/regclient/pages/hindi/PendingApprovalHindi.java @@ -23,6 +23,9 @@ public class PendingApprovalHindi extends PendingApproval{ @AndroidFindBy(accessibility = "स्क्रिम") private WebElement backGroundScreen; + + @AndroidFindBy(accessibility = "उपयोगकर्ता नाम अमान्य!") + private WebElement invalidUsernameMessage; @AndroidFindBy(uiAutomator = "UiSelector().className(\"android.widget.CheckBox\").instance(0)") private WebElement searchCheckBoxButton; @@ -63,6 +66,10 @@ public class PendingApprovalHindi extends PendingApproval{ @AndroidFindBy(accessibility = "Please select a value") private WebElement rejectReasonDropdown; + + @AndroidFindBy(accessibility = "SUBMIT") + private WebElement invalidUsernameMessageForempty; + public PendingApprovalHindi(AppiumDriver driver) { super(driver); } @@ -112,6 +119,14 @@ public boolean isApprovalButtonDisplayed() { return isElementDisplayed(approveButton); } + public boolean isInvalidUsernameMessageDisplayed() { + return isElementDisplayed(invalidUsernameMessage); + } + + public boolean isInvalidemptyUsernameSumbitButtonEnbled() { + return isElementEnabled(invalidUsernameMessageForempty); + } + public boolean isRejectButtonDisplayed() { return isElementDisplayed(rejectButton); } diff --git a/ui-test/src/main/java/regclient/pages/kannada/PendingApprovalKannada.java b/ui-test/src/main/java/regclient/pages/kannada/PendingApprovalKannada.java index 18df5507c..1e5427e60 100644 --- a/ui-test/src/main/java/regclient/pages/kannada/PendingApprovalKannada.java +++ b/ui-test/src/main/java/regclient/pages/kannada/PendingApprovalKannada.java @@ -23,6 +23,8 @@ public class PendingApprovalKannada extends PendingApproval{ @AndroidFindBy(accessibility = "ಸ್ಕ್ರಿಮ್") private WebElement backGroundScreen; + @AndroidFindBy(accessibility = "ಬಳಕೆದಾರ ಹೆಸರು ಅಮಾನ್ಯ!") + private WebElement invalidUsernameMessage; @AndroidFindBy(uiAutomator = "UiSelector().className(\"android.widget.CheckBox\").instance(0)") private WebElement searchCheckBoxButton; @@ -63,6 +65,9 @@ public class PendingApprovalKannada extends PendingApproval{ @AndroidFindBy(accessibility = "Please select a value") private WebElement rejectReasonDropdown; + @AndroidFindBy(accessibility = "SUBMIT") + private WebElement invalidUsernameMessageForempty; + public PendingApprovalKannada(AppiumDriver driver) { super(driver); } @@ -116,6 +121,7 @@ public boolean isRejectButtonDisplayed() { return isElementDisplayed(rejectButton); } + public boolean isPageAttributesDisplayed() { return isElementDisplayed(pageAttributes); } @@ -135,11 +141,15 @@ public void enterAID(String AID) { public void clickOnRejectButton() { clickOnElement(rejectButton); } + public boolean isInvalidUsernameMessageDisplayed() { + return isElementDisplayed(invalidUsernameMessage); + } public boolean isRejectPacketTitleDisplayed() { return isElementDisplayed(rejectPacketTitle); } + public void selectRejectionReasonDropdown() { boolean isdisplayed =isElementDisplayed(rejectReasonDropdown); assertTrue(isdisplayed,"Verify if "+rejectReasonDropdown+" header is displayed"); @@ -157,4 +167,8 @@ public void selectRejectionReasonDropdown() { public boolean isSubmitButtonEnabled() { return isElementEnabled(submitButton); } + + public boolean isInvalidemptyUsernameSumbitButtonEnbled() { + return isElementEnabled(invalidUsernameMessageForempty); + } } diff --git a/ui-test/src/main/java/regclient/pages/tamil/PendingApprovalTamil.java b/ui-test/src/main/java/regclient/pages/tamil/PendingApprovalTamil.java index e5136a7a3..f1f7db29e 100644 --- a/ui-test/src/main/java/regclient/pages/tamil/PendingApprovalTamil.java +++ b/ui-test/src/main/java/regclient/pages/tamil/PendingApprovalTamil.java @@ -20,6 +20,8 @@ public class PendingApprovalTamil extends PendingApproval{ @AndroidFindBy(accessibility = "ஒப்புதல்") private WebElement approveButton; + @AndroidFindBy(accessibility = "பயனர்பெயர் செல்லாது!") + private WebElement invalidUsernameMessage; @AndroidFindBy(accessibility = "ஸ்க்ரிம்") private WebElement backGroundScreen; @@ -63,6 +65,9 @@ public class PendingApprovalTamil extends PendingApproval{ @AndroidFindBy(accessibility = "Please select a value") private WebElement rejectReasonDropdown; + @AndroidFindBy(accessibility = "SUBMIT") + private WebElement invalidUsernameMessageForempty; + public PendingApprovalTamil(AppiumDriver driver) { super(driver); } @@ -70,6 +75,9 @@ public PendingApprovalTamil(AppiumDriver driver) { public boolean isPendingApprovalTitleDisplayed() { return isElementDisplayed(pendingApprovalTitle); } + public boolean isInvalidUsernameMessageDisplayed() { + return isElementDisplayed(invalidUsernameMessage); + } @SuppressWarnings("deprecation") public void clickOnAID(String AID) { @@ -157,5 +165,9 @@ public void selectRejectionReasonDropdown() { public boolean isSubmitButtonEnabled() { return isElementEnabled(submitButton); } + + public boolean isInvalidemptyUsernameSumbitButtonEnbled() { + return isElementEnabled(invalidUsernameMessageForempty); + } } diff --git a/ui-test/src/main/resources/DesiredCapabilities.json b/ui-test/src/main/resources/DesiredCapabilities.json index 59d1b2fdc..64e978cf8 100644 --- a/ui-test/src/main/resources/DesiredCapabilities.json +++ b/ui-test/src/main/resources/DesiredCapabilities.json @@ -2,9 +2,9 @@ { "name": "androidDevice", "caps": { - "appium:udid": "ZD222L7BGN", + "appium:udid": "HA1TB4W4", "appium:automationName": "UiAutomator2", - "appium:app": "D:/app-release.apk", + "appium:app": "E:\app-release.apk", "platformName": "android", "appium:appPackage": "io.mosip.registration_client", "appium:appActivity": "io.mosip.registration_client.MainActivity", diff --git a/ui-test/src/main/resources/config.properties b/ui-test/src/main/resources/config.properties index 959f514f7..38f26270a 100644 --- a/ui-test/src/main/resources/config.properties +++ b/ui-test/src/main/resources/config.properties @@ -1,5 +1,5 @@ ipAddress=127.0.0.1 nodePath=C:/Program Files/nodejs/node -appiumServerExecutable=C:/Users/jayesh.kharode/AppData/Roaming/npm/node_modules/appium/build/lib/main.js +appiumServerExecutable=C:/Users/famuda.m/AppData/Roaming/npm/node_modules/appium/build/lib/main.js appiumLogFilePath=report/appiumLogs.txt startAppiumServer=true \ No newline at end of file From 80a4e368b4c81ad12ab9820571e4229fae3db369 Mon Sep 17 00:00:00 2001 From: Rakshithasai123 Date: Fri, 22 Aug 2025 17:15:32 +0530 Subject: [PATCH 06/44] removed hardcoded label (#551) Signed-off-by: Rakshithasai123 --- lib/ui/process_ui/widgets/pre_reg_data_control.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/ui/process_ui/widgets/pre_reg_data_control.dart b/lib/ui/process_ui/widgets/pre_reg_data_control.dart index 1d23d6419..cdc1bd95f 100644 --- a/lib/ui/process_ui/widgets/pre_reg_data_control.dart +++ b/lib/ui/process_ui/widgets/pre_reg_data_control.dart @@ -241,7 +241,7 @@ class _PreRegDataControlState extends State { const BorderSide(color: appGreyShade, width: 1), ), contentPadding: const EdgeInsets.symmetric(horizontal: 16,vertical: 14), - hintText: "Enter Application ID", + hintText: AppLocalizations.of(context)!.enter_application_id, hintStyle: const TextStyle(color: appBlackShade3, fontSize: 14), ), From 7579e319c38fcf97cb9efe02437ad3bcf61277fc Mon Sep 17 00:00:00 2001 From: Madhuravas reddy Date: Sat, 23 Aug 2025 21:14:15 +0530 Subject: [PATCH 07/44] RCF-1167 Removed download json btn for machine details (#546) * RCF-1167 Removed download json btn for machine details Signed-off-by: Madhuravas reddy * changed height of the card Signed-off-by: Madhuravas reddy * Commented the download btn code as it is not using Signed-off-by: Madhuravas reddy --------- Signed-off-by: Madhuravas reddy --- lib/ui/machine_keys.dart | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/lib/ui/machine_keys.dart b/lib/ui/machine_keys.dart index e87d2dc7d..9344f4953 100644 --- a/lib/ui/machine_keys.dart +++ b/lib/ui/machine_keys.dart @@ -108,15 +108,15 @@ class _MachineKeysState extends State { SizedBox( height: 20.h, ), - _downloadButton( - title: appLocalizations.download_json, - onTap: () { - FileStorage.writeCounter(machineDetails, "machine_details.txt") - .then((value) { - showInSnackBar(appLocalizations.download_message); - }); - }, - ), + // _downloadButton( + // title: appLocalizations.download_json, + // onTap: () { + // FileStorage.writeCounter(machineDetails, "machine_details.txt") + // .then((value) { + // showInSnackBar(appLocalizations.download_message); + // }); + // }, + // ), // SizedBox( // height: 20.h, // ), From f9071d5eed11c37312093b165ffb4428957c5e98 Mon Sep 17 00:00:00 2001 From: Rakshithasai123 Date: Mon, 25 Aug 2025 22:32:18 +0530 Subject: [PATCH 08/44] Rcf 1135 (#555) * fixed aligment of arabic button Signed-off-by: Rakshithasai123 * fixed the button alignment Signed-off-by: Rakshithasai123 * fixed button alignment Signed-off-by: Rakshithasai123 --------- Signed-off-by: Rakshithasai123 --- lib/ui/widgets/language_component.dart | 28 +++++++++++++++----------- 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/lib/ui/widgets/language_component.dart b/lib/ui/widgets/language_component.dart index 40dcb9cc5..d5cad29ca 100644 --- a/lib/ui/widgets/language_component.dart +++ b/lib/ui/widgets/language_component.dart @@ -39,8 +39,9 @@ class _LanguageComponentState extends State { widget.onTap(); } }, + child: Container( - padding: EdgeInsets.only( + padding: EdgeInsets.only( left: 25.w, right: 25.w, top: widget.isMobile && !isMobileSize ? 15.h : 9.h, @@ -76,17 +77,20 @@ class _LanguageComponentState extends State { SizedBox( width: widget.isFreezed || widget.isSelected ? 15.02 : 0, ), - Text( - widget.title, - style: TextStyle( - fontSize: widget.isMobile && !isMobileSize ? 24 : 16, - color: widget.isDisabled - ? appBlackShade3 - : widget.isFreezed - ? appGreyShade - : widget.isSelected - ? appWhite - : appBlackShade1, + Directionality( + textDirection: TextDirection.ltr, + child: Text( + widget.title, + style: TextStyle( + fontSize: widget.isMobile && !isMobileSize ? 24 : 16, + color: widget.isDisabled + ? appBlackShade3 + : widget.isFreezed + ? appGreyShade + : widget.isSelected + ? appWhite + : appBlackShade1, + ), ), ), ], From d19529a3bed7b19d70e5dfe7484d4311b32930f4 Mon Sep 17 00:00:00 2001 From: Rakshithasai123 Date: Mon, 25 Aug 2025 22:33:16 +0530 Subject: [PATCH 09/44] fixed the overflow text (#558) Signed-off-by: Rakshithasai123 --- .../biometric_capture_scan_block_portrait.dart | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/lib/ui/process_ui/widgets_mobile/biometric_capture_scan_block_portrait.dart b/lib/ui/process_ui/widgets_mobile/biometric_capture_scan_block_portrait.dart index 827a17500..a1e90e64c 100644 --- a/lib/ui/process_ui/widgets_mobile/biometric_capture_scan_block_portrait.dart +++ b/lib/ui/process_ui/widgets_mobile/biometric_capture_scan_block_portrait.dart @@ -2998,8 +2998,12 @@ class _BiometricCaptureScanBlockPortraitState child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ + Expanded( + child: (widget.field.inputRequired!) ? RichText( + overflow: TextOverflow.ellipsis, + maxLines: 2, text: TextSpan( text: context .read() @@ -3011,7 +3015,8 @@ class _BiometricCaptureScanBlockPortraitState fontSize: (isMobileSize) ? 14.h : 24.h, color: blackShade1, fontWeight: semiBold, - overflow: TextOverflow.ellipsis), + // overflow: TextOverflow.ellipsis + ), children: const [ TextSpan( text: " *", @@ -3024,6 +3029,8 @@ class _BiometricCaptureScanBlockPortraitState context .read() .chooseLanguage(widget.field.label!), + overflow: TextOverflow.ellipsis, + maxLines: 2, style: Theme.of(context) .textTheme .titleLarge @@ -3031,8 +3038,10 @@ class _BiometricCaptureScanBlockPortraitState fontSize: (isMobileSize) ? 14.h : 24.h, color: blackShade1, fontWeight: semiBold, - overflow: TextOverflow.ellipsis), + // overflow: TextOverflow.ellipsis + ), ), + ), Padding( padding: const EdgeInsets.only(right: 30), child: InkWell( From cb95c1907b972640545e9e78536b13891d2b4818 Mon Sep 17 00:00:00 2001 From: Rakshithasai123 Date: Mon, 25 Aug 2025 22:33:51 +0530 Subject: [PATCH 10/44] fixed date picker (#553) Signed-off-by: Rakshithasai123 --- lib/ui/process_ui/widgets/custom_cupertino_picker.dart | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/lib/ui/process_ui/widgets/custom_cupertino_picker.dart b/lib/ui/process_ui/widgets/custom_cupertino_picker.dart index 47d1f8dad..137e16c7b 100644 --- a/lib/ui/process_ui/widgets/custom_cupertino_picker.dart +++ b/lib/ui/process_ui/widgets/custom_cupertino_picker.dart @@ -135,11 +135,7 @@ class _CustomCupertinoDatePickerState extends State { } void _scrollList(FixedExtentScrollController controller, int index) { - controller.animateToItem( - index, - curve: Curves.easeIn, - duration: const Duration(milliseconds: 300), - ); + controller.jumpToItem(index); } @override From f2b3202ea9b101c7a8d7a3ca6b89a30e832ddc72 Mon Sep 17 00:00:00 2001 From: Rakshithasai123 Date: Thu, 28 Aug 2025 11:14:51 +0530 Subject: [PATCH 11/44] RCF-887 While Onboarding/Updating operator details, Supervisor's Biometrics Onboarding/Update displayed on the page (#567) * While Onboarding/Updating operator details, Supervisor's Biometrics Onboarding/Update displayed on the page Signed-off-by: Rakshithasai123 * fixed the onboarding,pending application and manage application pages button issueWhile Onboarding/Updating operator details, Supervisor's Biometrics Onboarding/Update displayed on the pages Signed-off-by: Rakshithasai123 --------- Signed-off-by: Rakshithasai123 --- assets/l10n/app_ar.arb | 1 + assets/l10n/app_en.arb | 1 + assets/l10n/app_fr.arb | 1 + assets/l10n/app_hi.arb | 1 + assets/l10n/app_kn.arb | 1 + assets/l10n/app_ta.arb | 1 + .../operator_biometrics_capture_view.dart | 121 ++++++++++-------- 7 files changed, 75 insertions(+), 52 deletions(-) diff --git a/assets/l10n/app_ar.arb b/assets/l10n/app_ar.arb index 83fc9b4e3..467f3eee1 100644 --- a/assets/l10n/app_ar.arb +++ b/assets/l10n/app_ar.arb @@ -179,6 +179,7 @@ "system_storage_usage": "استخدام تخزين النظام", "download_pre_registration_data": "تنزيل بيانات التسجيل المسبق", "update_operator_biomterics": "تحديث القياسات الحيوية للمشغل", + "onboard_operator_biomterics": "تسجيل القياسات الحيوية للمشغل", "appliction_upload": "تحميل التطبيق", "check_updates": "تفقد التحديث", "center_remap_sync": "مركز إعادة رسم خريطة المزامنة.", diff --git a/assets/l10n/app_en.arb b/assets/l10n/app_en.arb index 8c64c08e3..0071d8c3a 100644 --- a/assets/l10n/app_en.arb +++ b/assets/l10n/app_en.arb @@ -180,6 +180,7 @@ "system_storage_usage": "System Storage Usage", "download_pre_registration_data": "Download Pre-Registration Data", "update_operator_biomterics": "Update Operator Biometrics", + "onboard_operator_biomterics":"Onboard Operator Biometrics", "appliction_upload": "Application Upload", "check_updates": "Check Updates", "center_remap_sync": "Center Remap Sync.", diff --git a/assets/l10n/app_fr.arb b/assets/l10n/app_fr.arb index b00454270..2c4a7cd0c 100644 --- a/assets/l10n/app_fr.arb +++ b/assets/l10n/app_fr.arb @@ -254,6 +254,7 @@ "packets_created": "Paquets créés", "packets_synced": "Paquets synchronisés", "packets_uploaded": "Paquets téléchargés", + "onboard_operator_biomterics": "Enrôler les données biométriques de l'opérateur", "users": "Utilisatrices", "user_id": "ID de l'utilisateur", "user_name": "Nom d'utilisateur", diff --git a/assets/l10n/app_hi.arb b/assets/l10n/app_hi.arb index eaf5db9b1..cd7e6df6b 100644 --- a/assets/l10n/app_hi.arb +++ b/assets/l10n/app_hi.arb @@ -236,6 +236,7 @@ "is_not_allowed": "अनुमति नहीं है", "capture": "कब्जा", "attempts_left": "प्रयास बाकी हैं", + "onboard_operator_biomterics": "ऑपरेटर बायोमेट्रिक्स ऑनबोर्ड करें", "left_hand": "बाएं हाथ", "left": "बाएं", "right": "दाएं", diff --git a/assets/l10n/app_kn.arb b/assets/l10n/app_kn.arb index f82673aa0..fbb56952c 100644 --- a/assets/l10n/app_kn.arb +++ b/assets/l10n/app_kn.arb @@ -266,6 +266,7 @@ "sync_alert_text": "ಸಿಂಕ್ ಮಾಡಿ", "onboarded_successfully": "ನೀವು ಯಶಸ್ವಿಯಾಗಿ ಆನ್‌ಬೋರ್ಡ್ ಮಾಡಿರುವಿರಿ.", "operator_biometric_updated_successfully": "ಆಪರೇಟರ್ ಬಯೋಮೆಟ್ರಿಕ್ಸ್ ಅನ್ನು ಯಶಸ್ವಿಯಾಗಿ ನವೀಕರಿಸಲಾಗಿದೆ.", + "onboard_operator_biomterics": "ಆಪರೇಟರ್ ಬಯೋಮೆಟ್ರಿಕ್ಸ್ ನೋಂದಣಿ", "home": "ಮನೆ", "verify_and_save": "ಪರಿಶೀಲಿಸಿ ಮತ್ತು ಉಳಿಸಿ", "supervisors_biometric_onboard": "ನಿರೀಕ್ಷಕರ ಬಯೋಮೆಟ್ರಿಕ್ ಔನ್‌ಬೋರ್ಡಿಂಗ್", diff --git a/assets/l10n/app_ta.arb b/assets/l10n/app_ta.arb index fc6093885..a225d9696 100644 --- a/assets/l10n/app_ta.arb +++ b/assets/l10n/app_ta.arb @@ -41,6 +41,7 @@ "cred_expired": "நற்சான்றிதழ்கள் காணப்படவில்லை அல்லது காலாவதியாகவில்லை. ஆன்லைன் உள்நுழைவை முயற்சிக்கவும்!", "not_initialized": "இயந்திரத்தை துவக்க முடியவில்லை!", "invalid_user": "பயனர்பெயர் செல்லாது!", + "onboard_operator_biomterics": "ஆபரேட்டர் பயோமெட்ரிக் பதிவுசெய்தல்", "machine_inactive": "இயந்திரம் செயலில் இல்லை!", "center_inactive": "மையம் செயல்படவில்லை!", "sync_completed_succesfully": "ஒத்திசைவு வெற்றிகரமாக நிறைவடைந்தது", diff --git a/lib/ui/onboard/widgets/operator_biometrics_capture_view.dart b/lib/ui/onboard/widgets/operator_biometrics_capture_view.dart index d6123916f..b14526942 100644 --- a/lib/ui/onboard/widgets/operator_biometrics_capture_view.dart +++ b/lib/ui/onboard/widgets/operator_biometrics_capture_view.dart @@ -12,6 +12,8 @@ import 'package:registration_client/utils/app_config.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:responsive_grid_list/responsive_grid_list.dart'; +import '../../../provider/auth_provider.dart'; + class OperatorBiometricsCaptureView extends StatefulWidget { const OperatorBiometricsCaptureView({super.key}); @@ -51,9 +53,9 @@ class _OperatorBiometricsCaptureState context, MaterialPageRoute( builder: (context) => ChangeNotifierProvider.value( - value: providerCopy, - child: OperatorBiometricCaptureScanBlockView(), - ))).then((value) { + value: providerCopy, + child: OperatorBiometricCaptureScanBlockView(), + ))).then((value) { setState(() {}); }); }, @@ -68,15 +70,15 @@ class _OperatorBiometricsCaptureState border: Border.all( color: (biometricAttributeData.isScanned == true) ? (biometricAttributeData.exceptions.contains(true)) - ? secondaryColors.elementAt(16) - : secondaryColors.elementAt(11) + ? secondaryColors.elementAt(16) + : secondaryColors.elementAt(11) : (context - .watch< - BiometricCaptureControlProvider>() - .biometricAttribute == - biometricAttributeData.title) - ? secondaryColors.elementAt(12) - : secondaryColors.elementAt(14)), + .watch< + BiometricCaptureControlProvider>() + .biometricAttribute == + biometricAttributeData.title) + ? secondaryColors.elementAt(12) + : secondaryColors.elementAt(14)), borderRadius: BorderRadius.circular(10)), child: Column( mainAxisAlignment: MainAxisAlignment.center, @@ -109,11 +111,11 @@ class _OperatorBiometricsCaptureState right: 15, child: (biometricAttributeData.exceptions.contains(true)) ? Image.asset( - "assets/images/Group 57548@2x.png", - ) + "assets/images/Group 57548@2x.png", + ) : Image.asset( - "assets/images/Group 57745@2x.png", - )), + "assets/images/Group 57745@2x.png", + )), if (!biometricAttributeData.exceptions.contains(false)) Positioned( top: 15, @@ -130,9 +132,9 @@ class _OperatorBiometricsCaptureState horizontal: 10, vertical: 7), decoration: BoxDecoration( color: (biometricAttributeData.qualityPercentage - .toInt() < - int.parse(biometricAttributeData - .thresholdPercentage)) + .toInt() < + int.parse(biometricAttributeData + .thresholdPercentage)) ? secondaryColors.elementAt(26) : secondaryColors.elementAt(11), borderRadius: BorderRadius.circular(50)), @@ -148,9 +150,25 @@ class _OperatorBiometricsCaptureState ), )); } - @override Widget build(BuildContext context) { + globalProvider = context.watch(); + biometricCaptureControlProvider = context.watch(); + final authProvider = context.watch(); + final appLocalizations = AppLocalizations.of(context)!; + + String getBiometricTitle() { + if (authProvider.isOperator) { + return globalProvider.onboardingProcessName == "Onboarding" + ? appLocalizations.onboard_operator_biomterics + : appLocalizations.update_operator_biomterics; + } + + return globalProvider.onboardingProcessName == "Onboarding" + ? appLocalizations.supervisors_biometric_onboard + : appLocalizations.supervisors_biometric_update; + } + return SafeArea( child: Scaffold( backgroundColor: secondaryColors.elementAt(10), @@ -177,7 +195,7 @@ class _OperatorBiometricsCaptureState .contains("rightMiddle")&& globalProvider.operatorOnboardingAttributes .contains("rightIndex")) - ? ((biometricCaptureControlProvider.rightHand.isScanned || + ? ((biometricCaptureControlProvider.rightHand.isScanned || !biometricCaptureControlProvider.rightHand.exceptions .contains(false)) && (biometricCaptureControlProvider.rightHand.qualityPercentage >= int.parse(biometricCaptureControlProvider @@ -192,26 +210,26 @@ class _OperatorBiometricsCaptureState .contains("leftMiddle")&& globalProvider.operatorOnboardingAttributes .contains("leftIndex")) - ? ((biometricCaptureControlProvider.leftHand.isScanned || + ? ((biometricCaptureControlProvider.leftHand.isScanned || !biometricCaptureControlProvider.leftHand.exceptions .contains(false)) && - (biometricCaptureControlProvider.leftHand.qualityPercentage >= int.parse(biometricCaptureControlProvider.leftHand.thresholdPercentage) || - !biometricCaptureControlProvider.leftHand.exceptions - .contains(false))) : true) && + (biometricCaptureControlProvider.leftHand.qualityPercentage >= int.parse(biometricCaptureControlProvider.leftHand.thresholdPercentage) || + !biometricCaptureControlProvider.leftHand.exceptions + .contains(false))) : true) && ((globalProvider.operatorOnboardingAttributes .contains("leftThumb") && globalProvider.operatorOnboardingAttributes .contains("rightThumb")) - ? ((biometricCaptureControlProvider.thumbs.isScanned || + ? ((biometricCaptureControlProvider.thumbs.isScanned || !biometricCaptureControlProvider.thumbs.exceptions .contains(false)) && - (biometricCaptureControlProvider.thumbs.qualityPercentage >= + (biometricCaptureControlProvider.thumbs.qualityPercentage >= int.parse(biometricCaptureControlProvider.thumbs.thresholdPercentage) || - !biometricCaptureControlProvider.thumbs.exceptions.contains(false))) : true) && + !biometricCaptureControlProvider.thumbs.exceptions.contains(false))) : true) && ((globalProvider.operatorOnboardingAttributes .contains("face")) - ? ((biometricCaptureControlProvider.face.qualityPercentage >= int.parse(biometricCaptureControlProvider.face.thresholdPercentage)) && - biometricCaptureControlProvider.face.isScanned) : true)) { + ? ((biometricCaptureControlProvider.face.qualityPercentage >= int.parse(biometricCaptureControlProvider.face.thresholdPercentage)) && + biometricCaptureControlProvider.face.isScanned) : true)) { setState(() { isSavingBiometrics = true; }); @@ -251,12 +269,12 @@ class _OperatorBiometricsCaptureState "assets/svg/success_message_icon.svg"), Text( (context - .read() - .onboardingProcessName == - "Onboarding") + .read() + .onboardingProcessName == + "Onboarding") ? appLocalizations.onboarded_successfully : appLocalizations - .operator_biometric_updated_successfully, + .operator_biometric_updated_successfully, textAlign: TextAlign.center, style: TextStyle( fontSize: 28, @@ -295,15 +313,15 @@ class _OperatorBiometricsCaptureState }, child: isSavingBiometrics ? CircularProgressIndicator( - color: appWhite, - ) + color: appWhite, + ) : Text( - appLocalizations.verify_and_save, - style: Theme.of(context) - .textTheme - .bodyLarge - ?.copyWith(fontSize: 26.h, color: pureWhite), - ), + appLocalizations.verify_and_save, + style: Theme.of(context) + .textTheme + .bodyLarge + ?.copyWith(fontSize: 26.h, color: pureWhite), + ), style: OutlinedButton.styleFrom( backgroundColor: ( ((globalProvider.operatorOnboardingAttributes @@ -377,14 +395,13 @@ class _OperatorBiometricsCaptureState mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text( - globalProvider.onboardingProcessName == "Onboarding" - ? appLocalizations.supervisors_biometric_onboard - : appLocalizations.supervisors_biometric_update, + getBiometricTitle(), // Call the function here style: Theme.of(context).textTheme.titleLarge?.copyWith( - fontSize: (isMobileSize) ? 16.w : 24.w, - color: blackShade1, - fontWeight: semiBold, - overflow: TextOverflow.ellipsis), + fontSize: (isMobileSize) ? 16.w : 24.w, + color: blackShade1, + fontWeight: semiBold, + overflow: TextOverflow.ellipsis, + ), ), // SizedBox( // height: (isMobileSize)?20.h:52.h, @@ -428,13 +445,13 @@ class _OperatorBiometricsCaptureState maxItemsPerRow: (isMobileSize) ? 1 : 2, children: [ if (globalProvider.operatorOnboardingAttributes - .contains("leftEye") && + .contains("leftEye") && globalProvider.operatorOnboardingAttributes .contains("rightEye")) _getBiometricCaptureSelectionBlockMobile( biometricCaptureControlProvider.iris), if (globalProvider.operatorOnboardingAttributes - .contains("rightLittle") && + .contains("rightLittle") && globalProvider.operatorOnboardingAttributes .contains("rightRing") && globalProvider.operatorOnboardingAttributes @@ -444,7 +461,7 @@ class _OperatorBiometricsCaptureState _getBiometricCaptureSelectionBlockMobile( biometricCaptureControlProvider.rightHand), if (globalProvider.operatorOnboardingAttributes - .contains("leftLittle") && + .contains("leftLittle") && globalProvider.operatorOnboardingAttributes .contains("leftRing") && globalProvider.operatorOnboardingAttributes @@ -454,7 +471,7 @@ class _OperatorBiometricsCaptureState _getBiometricCaptureSelectionBlockMobile( biometricCaptureControlProvider.leftHand), if (globalProvider.operatorOnboardingAttributes - .contains("rightThumb") && + .contains("rightThumb") && globalProvider.operatorOnboardingAttributes .contains("leftThumb")) _getBiometricCaptureSelectionBlockMobile( From bfddf89f82f4f1cbe81ebca0f02f648716a7e236 Mon Sep 17 00:00:00 2001 From: Rakshithasai123 Date: Thu, 28 Aug 2025 11:39:25 +0530 Subject: [PATCH 12/44] pending approval dropdown, app upload, expand buttons, onboarding packet overflow (#566) Signed-off-by: Rakshithasai123 --- .../widget/template_bottom_sheet.dart | 294 +++++++++--------- lib/ui/dashboard/user_dashboard.dart | 25 +- lib/ui/export_packet/export_packet_ui.dart | 38 ++- 3 files changed, 190 insertions(+), 167 deletions(-) diff --git a/lib/ui/approve_packet/widget/template_bottom_sheet.dart b/lib/ui/approve_packet/widget/template_bottom_sheet.dart index 0781b09aa..bf01a854d 100644 --- a/lib/ui/approve_packet/widget/template_bottom_sheet.dart +++ b/lib/ui/approve_packet/widget/template_bottom_sheet.dart @@ -1,6 +1,7 @@ import 'dart:developer'; import 'package:flutter/material.dart'; +import 'package:flutter_screenutil/flutter_screenutil.dart'; import 'package:flutter_secure_storage/flutter_secure_storage.dart'; import 'package:provider/provider.dart'; import 'package:registration_client/utils/app_config.dart'; @@ -79,30 +80,34 @@ class TemplateBottomSheet { const SizedBox( height: 18, ), - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, + Column( children: [ - Card( - margin: const EdgeInsets.only(left: 24), - elevation: 0, - shape: CircleBorder( - side: BorderSide( - color: (currentInd > 1) ? solidPrimary : Colors.grey, - )), - child: IconButton( - icon: Icon( - Icons.arrow_back, - color: (currentInd > 1) ? solidPrimary : Colors.grey, - ), - onPressed: (currentInd > 1) - ? () { + Padding( + padding: const EdgeInsets.symmetric(horizontal: 24, vertical: 8), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + // Back Arrow + Card( + elevation: 0, + shape: CircleBorder( + side: BorderSide( + color: (currentInd > 1) ? solidPrimary : Colors.grey, + ), + ), + child: IconButton( + icon: Icon( + Icons.arrow_back, + color: (currentInd > 1) ? solidPrimary : Colors.grey, + ), + onPressed: (currentInd > 1) + ? () { context .read() .setCurrentInd(currentInd - 1); Registration reg = context - .read() - .matchingPackets[(currentInd - 1) - 1] - ['packet'] as Registration; + .read().matchingPackets[(currentInd - 1) - 1]['packet'] as Registration; log(reg.packetId); loadHtmlData( context @@ -110,145 +115,134 @@ class TemplateBottomSheet { .webViewPlusController, reg.packetId); } - : () { + : () { log("Out of range"); }, - ), - ), - Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - ElevatedButton.icon( - style: ElevatedButton.styleFrom( - disabledForegroundColor: Colors.white, - disabledBackgroundColor: Colors.grey.withOpacity(0.5), - padding: const EdgeInsets.symmetric( - vertical: 12, horizontal: 18), - ), - icon: const Icon( - Icons.check_outlined, - color: Colors.white, + ), ), - onPressed: reviewStatus == ReviewStatus.APPROVED.name - ? null - : () { + // Buttons Column + Column( + children: [ + // APPROVE BUTTON + SizedBox( + width: 190.sp, + child: ElevatedButton.icon( + style: ElevatedButton.styleFrom( + backgroundColor: solidPrimary, + padding: const EdgeInsets.symmetric(vertical: 14, horizontal: 18), + ), + icon: const Icon(Icons.check_outlined, color: Colors.white), + label: Text( + AppLocalizations.of(context)!.approve, + style: const TextStyle(fontWeight: FontWeight.bold), + ), + onPressed: reviewStatus == ReviewStatus.APPROVED.name + ? null + : () { + context + .read() + .approvePacket(regCurrent.packetId); + if (currentInd < + context.read().matchingPackets.length) { context .read() - .approvePacket(regCurrent.packetId); - log(currentInd.toString()); - if (currentInd < + .setCurrentInd(currentInd + 1); + Registration reg = context + .read() + .matchingPackets[(currentInd + 1) - 1]['packet'] as Registration; + loadHtmlData( + context.read().webViewPlusController, + reg.packetId); + } + }, + ), + ), + const SizedBox(height: 12), + + // REJECT BUTTON + SizedBox( + width: 190.sp, + child: OutlinedButton.icon( + icon: const Icon(Icons.close), + label: Text( + AppLocalizations.of(context)!.reject, + style: const TextStyle(fontWeight: FontWeight.bold), + ), + style: OutlinedButton.styleFrom( + foregroundColor: Colors.red, + padding: const EdgeInsets.symmetric(vertical: 14, horizontal: 18), + side: const BorderSide(color: Colors.red, width: 2), + ), + onPressed: reviewStatus == ReviewStatus.REJECTED.name + ? null + : () { + showDialog( + context: context, + builder: (BuildContext context) { + return dialogBox(() { context .read() - .matchingPackets - .length) { - context - .read() - .setCurrentInd(currentInd + 1); - Registration reg = context - .read() - .matchingPackets[(currentInd + 1) - 1] - ['packet'] as Registration; - log(reg.packetId); - loadHtmlData( + .rejectPacket(regCurrent.packetId); + if (currentInd < + context.read().matchingPackets.length) { context .read() - .webViewPlusController, - reg.packetId); - } - }, - label: Text(AppLocalizations.of(context)!.approve), - ), - const SizedBox( - width: 16, - ), - OutlinedButton.icon( - icon: const Icon(Icons.close), - onPressed: reviewStatus == ReviewStatus.REJECTED.name - ? null - : () { - showDialog( - context: context, - builder: (BuildContext context) { - return dialogBox(() { - context - .read() - .rejectPacket(regCurrent.packetId); - if (currentInd < - context - .read() - .matchingPackets - .length) { + .setCurrentInd(currentInd + 1); + Registration reg = context + .read() + .matchingPackets[(currentInd + 1) - 1]['packet'] + as Registration; + loadHtmlData( context .read() - .setCurrentInd(currentInd + 1); - - Registration reg = context - .read() - .matchingPackets[(currentInd + - 1) - - 1]['packet'] as Registration; - log(reg.packetId); - loadHtmlData( - context - .read< - ApprovePacketsProvider>() - .webViewPlusController, - reg.packetId); - } - Navigator.of(context).pop(); - }, context); - }); - }, - style: OutlinedButton.styleFrom( - disabledForegroundColor: Colors.white, - disabledBackgroundColor: Colors.grey.withOpacity(0.5), - foregroundColor: Colors.red, - padding: const EdgeInsets.symmetric( - vertical: 12, horizontal: 18), - side: BorderSide( - color: reviewStatus == ReviewStatus.REJECTED.name - ? Colors.transparent - : Colors.red, - width: 2), - ), - label: Text( - AppLocalizations.of(context)!.reject, - style: const TextStyle(fontWeight: FontWeight.bold), + .webViewPlusController, + reg.packetId); + } + Navigator.of(context).pop(); + }, context); + }, + ); + }, + ), ), - ), - const SizedBox( - width: 16, - ), - Card( - margin: const EdgeInsets.only(right: 24), - elevation: 0, - shape: CircleBorder( - side: BorderSide( - color: reviewStatus == ReviewStatus.NOACTIONTAKEN.name - ? Colors.grey - : solidPrimary, - )), - child: IconButton( - onPressed: - reviewStatus == ReviewStatus.NOACTIONTAKEN.name + const SizedBox(height: 12), + // RESET BUTTON + MouseRegion( + cursor: SystemMouseCursors.click, + child: SizedBox( + width: 190.sp, + child: OutlinedButton( + style: OutlinedButton.styleFrom( + backgroundColor: Colors.white, + padding: const EdgeInsets.symmetric(vertical: 14, horizontal: 18), + side: BorderSide(color: Colors.transparent, width: 2), + ).copyWith( + side: MaterialStateProperty.resolveWith((states) { + if (states.contains(MaterialState.hovered)) { + return BorderSide(color: solidPrimary, width: 2); + } + return BorderSide(color: Colors.transparent, width: 2); + }), + ), + onPressed: reviewStatus == ReviewStatus.NOACTIONTAKEN.name ? null : () { - context - .read() - .clearReview(regCurrent.packetId); - }, - icon: Icon( - Icons.refresh_outlined, - color: - reviewStatus == ReviewStatus.NOACTIONTAKEN.name - ? Colors.grey - : solidPrimary, - size: 28, + context.read().clearReview(regCurrent.packetId); + }, + child: Text( + 'RESET', + style: TextStyle( + fontWeight: FontWeight.bold, + color: solidPrimary, + ), + ), + ), ), ), - ) - ], - ), + + ], + ), + Card( margin: const EdgeInsets.only(right: 24), elevation: 0, @@ -296,16 +290,18 @@ class TemplateBottomSheet { } : () { log("Out of range"); - }, + }, ), ), - ], - ), - const SizedBox( - height: 18, - ), - ], + ], + ), ), + const SizedBox( + height: 18), + ], + ), + ], + ), ); }, ); diff --git a/lib/ui/dashboard/user_dashboard.dart b/lib/ui/dashboard/user_dashboard.dart index 5194ece89..e20aed8e6 100644 --- a/lib/ui/dashboard/user_dashboard.dart +++ b/lib/ui/dashboard/user_dashboard.dart @@ -209,11 +209,26 @@ class _UserDashBoardState extends State { ) ], ), - const SizedBox(height: 10), - Text(appLocalizations.packets_uploaded, - style: TextStyle( - fontSize: isMobileSize ? 15 : 20, - fontWeight: FontWeight.bold)), + Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + const SizedBox(height: 12), // pushes text slightly downward + Padding( + padding: const EdgeInsets.symmetric(horizontal: 4.0), + child: FittedBox( + fit: BoxFit.scaleDown, + child: Text( + appLocalizations.packets_uploaded, + textAlign: TextAlign.center, + style: TextStyle( + fontSize: isMobileSize ? 15 : 20, + fontWeight: FontWeight.bold, + ), + ), + ), + ), + ], + ) ], ), ); diff --git a/lib/ui/export_packet/export_packet_ui.dart b/lib/ui/export_packet/export_packet_ui.dart index f1156fea3..87db5c3a3 100644 --- a/lib/ui/export_packet/export_packet_ui.dart +++ b/lib/ui/export_packet/export_packet_ui.dart @@ -56,24 +56,36 @@ class ExportPacketsPage extends StatelessWidget { const SizedBox( height: 4, ), - const Row( + Column( children: [ - Flexible( - flex: 2, - child: SearchBoxExport(), - ), - SizedBox(width: 10), - Flexible( - flex: 1, - child: UploadButton(), + const Row( + children: [ + Expanded( + child: SearchBoxExport(), + ), + ], ), - SizedBox(width: 10), // Add spacing between buttons - Flexible( - flex: 1, - child: ExportButton(), + const SizedBox(height: 10), + Row( + children: [ + Expanded( + child: SizedBox( + height: 48, + child: UploadButton(), + ), + ), + const SizedBox(width: 10), + Expanded( + child: SizedBox( + height: 48, + child: ExportButton(), + ), + ), + ], ), ], ), + const SizedBox( height: 24, ), From f4da6a11b8f154088fb97051f7ea0a7ddef7132d Mon Sep 17 00:00:00 2001 From: Rakshithasai123 Date: Thu, 28 Aug 2025 16:15:08 +0530 Subject: [PATCH 13/44] RCF-471 RCF-472 Android Reg Client in Landscape mode Tablet and phone (#565) * Android Reg Client in Landscape mode Tablet and phone Signed-off-by: Rakshithasai123 * Fixed on reviewed comments Signed-off-by: Rakshithasai123 --------- Signed-off-by: Rakshithasai123 --- .../widget/template_bottom_sheet.dart | 561 ++-- lib/ui/dashboard/user_dashboard.dart | 92 +- lib/ui/export_packet/export_packet_ui.dart | 74 +- .../onboard/portrait/registration_tasks.dart | 69 +- ...tor_biometric_capture_scan_block_view.dart | 42 +- .../acknowledgement_page.dart | 7 +- .../process_ui/widgets/dropdown_control.dart | 9 +- .../widgets/pre_reg_data_control.dart | 53 +- .../biometric_capture_control_portrait.dart | 8 +- ...biometric_capture_scan_block_portrait.dart | 2623 +++++++++-------- lib/ui/widgets/language_component.dart | 25 +- pubspec.lock | 726 +++-- 12 files changed, 2257 insertions(+), 2032 deletions(-) diff --git a/lib/ui/approve_packet/widget/template_bottom_sheet.dart b/lib/ui/approve_packet/widget/template_bottom_sheet.dart index bf01a854d..73cb706c9 100644 --- a/lib/ui/approve_packet/widget/template_bottom_sheet.dart +++ b/lib/ui/approve_packet/widget/template_bottom_sheet.dart @@ -80,109 +80,69 @@ class TemplateBottomSheet { const SizedBox( height: 18, ), + isMobileSize? Column( - children: [ - Padding( - padding: const EdgeInsets.symmetric(horizontal: 24, vertical: 8), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - // Back Arrow - Card( - elevation: 0, - shape: CircleBorder( - side: BorderSide( - color: (currentInd > 1) ? solidPrimary : Colors.grey, - ), - ), - child: IconButton( - icon: Icon( - Icons.arrow_back, - color: (currentInd > 1) ? solidPrimary : Colors.grey, - ), - onPressed: (currentInd > 1) - ? () { - context - .read() - .setCurrentInd(currentInd - 1); - Registration reg = context - .read().matchingPackets[(currentInd - 1) - 1]['packet'] as Registration; - log(reg.packetId); - loadHtmlData( - context - .read() - .webViewPlusController, - reg.packetId); - } - : () { - log("Out of range"); - }, - ), - ), - // Buttons Column - Column( - children: [ - // APPROVE BUTTON - SizedBox( - width: 190.sp, - child: ElevatedButton.icon( - style: ElevatedButton.styleFrom( - backgroundColor: solidPrimary, - padding: const EdgeInsets.symmetric(vertical: 14, horizontal: 18), - ), - icon: const Icon(Icons.check_outlined, color: Colors.white), - label: Text( - AppLocalizations.of(context)!.approve, - style: const TextStyle(fontWeight: FontWeight.bold), + children: [ + Padding( + padding: const EdgeInsets.symmetric(horizontal: 24, vertical: 8), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + // Back Arrow + Card( + elevation: 0, + shape: CircleBorder( + side: BorderSide( + color: (currentInd > 1) ? solidPrimary : Colors.grey, + ), ), - onPressed: reviewStatus == ReviewStatus.APPROVED.name - ? null - : () { - context - .read() - .approvePacket(regCurrent.packetId); - if (currentInd < - context.read().matchingPackets.length) { + child: IconButton( + icon: Icon( + Icons.arrow_back, + color: (currentInd > 1) ? solidPrimary : Colors.grey, + ), + onPressed: (currentInd > 1) + ? () { context .read() - .setCurrentInd(currentInd + 1); + .setCurrentInd(currentInd - 1); Registration reg = context - .read() - .matchingPackets[(currentInd + 1) - 1]['packet'] as Registration; + .read().matchingPackets[(currentInd - 1) - 1]['packet'] as Registration; + log(reg.packetId); loadHtmlData( - context.read().webViewPlusController, + context + .read() + .webViewPlusController, reg.packetId); } - }, - ), - ), - const SizedBox(height: 12), - - // REJECT BUTTON - SizedBox( - width: 190.sp, - child: OutlinedButton.icon( - icon: const Icon(Icons.close), - label: Text( - AppLocalizations.of(context)!.reject, - style: const TextStyle(fontWeight: FontWeight.bold), - ), - style: OutlinedButton.styleFrom( - foregroundColor: Colors.red, - padding: const EdgeInsets.symmetric(vertical: 14, horizontal: 18), - side: const BorderSide(color: Colors.red, width: 2), + : () { + log("Out of range"); + }, ), - onPressed: reviewStatus == ReviewStatus.REJECTED.name - ? null - : () { - showDialog( - context: context, - builder: (BuildContext context) { - return dialogBox(() { + ), + // Buttons Column + Column( + children: [ + // APPROVE BUTTON + SizedBox( + width: 190.sp, + child: ElevatedButton.icon( + style: ElevatedButton.styleFrom( + backgroundColor: solidPrimary, + padding: const EdgeInsets.symmetric(vertical: 14, horizontal: 18), + ), + icon: const Icon(Icons.check_outlined, color: Colors.white), + label: Text( + AppLocalizations.of(context)!.approve, + style: const TextStyle(fontWeight: FontWeight.bold), + ), + onPressed: reviewStatus == ReviewStatus.APPROVED.name + ? null + : () { context .read() - .rejectPacket(regCurrent.packetId); + .approvePacket(regCurrent.packetId); if (currentInd < context.read().matchingPackets.length) { context @@ -190,118 +150,381 @@ class TemplateBottomSheet { .setCurrentInd(currentInd + 1); Registration reg = context .read() - .matchingPackets[(currentInd + 1) - 1]['packet'] - as Registration; + .matchingPackets[(currentInd + 1) - 1]['packet'] as Registration; loadHtmlData( - context - .read() - .webViewPlusController, + context.read().webViewPlusController, reg.packetId); } - Navigator.of(context).pop(); - }, context); - }, - ); - }, + }, + ), + ), + const SizedBox(height: 12), + + // REJECT BUTTON + SizedBox( + width: 190.sp, + child: OutlinedButton.icon( + icon: const Icon(Icons.close), + label: Text( + AppLocalizations.of(context)!.reject, + style: const TextStyle(fontWeight: FontWeight.bold), + ), + style: OutlinedButton.styleFrom( + foregroundColor: Colors.red, + padding: const EdgeInsets.symmetric(vertical: 14, horizontal: 18), + side: const BorderSide(color: Colors.red, width: 2), + ), + onPressed: reviewStatus == ReviewStatus.REJECTED.name + ? null + : () { + showDialog( + context: context, + builder: (BuildContext context) { + return dialogBox(() { + context + .read() + .rejectPacket(regCurrent.packetId); + if (currentInd < + context.read().matchingPackets.length) { + context + .read() + .setCurrentInd(currentInd + 1); + Registration reg = context + .read() + .matchingPackets[(currentInd + 1) - 1]['packet'] + as Registration; + loadHtmlData( + context + .read() + .webViewPlusController, + reg.packetId); + } + Navigator.of(context).pop(); + }, context); + }, + ); + }, + ), + ), + const SizedBox(height: 12), + // RESET BUTTON + MouseRegion( + cursor: SystemMouseCursors.click, + child: SizedBox( + width: 190.sp, + child: OutlinedButton( + style: OutlinedButton.styleFrom( + backgroundColor: Colors.white, + padding: const EdgeInsets.symmetric(vertical: 14, horizontal: 18), + side: BorderSide(color: Colors.transparent, width: 2), + ).copyWith( + side: MaterialStateProperty.resolveWith((states) { + if (states.contains(MaterialState.hovered)) { + return BorderSide(color: solidPrimary, width: 2); + } + return BorderSide(color: Colors.transparent, width: 2); + }), + ), + onPressed: reviewStatus == ReviewStatus.NOACTIONTAKEN.name + ? null + : () { + context.read().clearReview(regCurrent.packetId); + }, + child: Text( + 'RESET', + style: TextStyle( + fontWeight: FontWeight.bold, + color: solidPrimary, + ), + ), + ), + ), + ), + + ], ), - ), - const SizedBox(height: 12), - // RESET BUTTON - MouseRegion( - cursor: SystemMouseCursors.click, - child: SizedBox( - width: 190.sp, - child: OutlinedButton( - style: OutlinedButton.styleFrom( - backgroundColor: Colors.white, - padding: const EdgeInsets.symmetric(vertical: 14, horizontal: 18), - side: BorderSide(color: Colors.transparent, width: 2), - ).copyWith( - side: MaterialStateProperty.resolveWith((states) { - if (states.contains(MaterialState.hovered)) { - return BorderSide(color: solidPrimary, width: 2); - } - return BorderSide(color: Colors.transparent, width: 2); - }), + + Card( + margin: const EdgeInsets.only(right: 24), + elevation: 0, + shape: CircleBorder( + side: BorderSide( + color: (currentInd < + context + .read() + .matchingPackets + .length) + ? solidPrimary + : Colors.grey, + )), + child: IconButton( + icon: Icon( + Icons.arrow_forward, + color: (currentInd < + context + .read() + .matchingPackets + .length) + ? solidPrimary + : Colors.grey, + size: 24, ), - onPressed: reviewStatus == ReviewStatus.NOACTIONTAKEN.name - ? null + onPressed: currentInd < + context + .read() + .matchingPackets + .length + ? () { + context + .read() + .setCurrentInd(currentInd + 1); + Registration reg = context + .read() + .matchingPackets[(currentInd + 1) - 1] + ['packet'] as Registration; + log(reg.packetId); + loadHtmlData( + context + .read() + .webViewPlusController, + reg.packetId); + } : () { - context.read().clearReview(regCurrent.packetId); + log("Out of range"); }, - child: Text( - 'RESET', - style: TextStyle( - fontWeight: FontWeight.bold, - color: solidPrimary, - ), - ), ), ), - ), - - ], + ], + ), + ), + ] + ) + :Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Card( + margin: const EdgeInsets.only(left: 24), + elevation: 0, + shape: CircleBorder( + side: BorderSide( + color: (currentInd > 1) ? solidPrimary : Colors.grey, + )), + child: IconButton( + icon: Icon( + Icons.arrow_back, + color: (currentInd > 1) ? solidPrimary : Colors.grey, + ), + onPressed: (currentInd > 1) + ? () { + context + .read() + .setCurrentInd(currentInd - 1); + Registration reg = context + .read() + .matchingPackets[(currentInd - 1) - 1] + ['packet'] as Registration; + log(reg.packetId); + loadHtmlData( + context + .read() + .webViewPlusController, + reg.packetId); + } + : () { + log("Out of range"); + }, ), + ), + Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + ElevatedButton.icon( + style: ElevatedButton.styleFrom( + disabledForegroundColor: Colors.white, + disabledBackgroundColor: Colors.grey.withOpacity(0.5), + padding: const EdgeInsets.symmetric( + vertical: 12, horizontal: 18), + ), + icon: const Icon( + Icons.check_outlined, + color: Colors.white, + ), + onPressed: reviewStatus == ReviewStatus.APPROVED.name + ? null + : () { + context + .read() + .approvePacket(regCurrent.packetId); + log(currentInd.toString()); + if (currentInd < + context + .read() + .matchingPackets + .length) { + context + .read() + .setCurrentInd(currentInd + 1); + Registration reg = context + .read() + .matchingPackets[(currentInd + 1) - 1] + ['packet'] as Registration; + log(reg.packetId); + loadHtmlData( + context + .read() + .webViewPlusController, + reg.packetId); + } + }, + label: Text(AppLocalizations.of(context)!.approve), + ), + const SizedBox( + width: 16, + ), + OutlinedButton.icon( + icon: const Icon(Icons.close), + onPressed: reviewStatus == ReviewStatus.REJECTED.name + ? null + : () { + showDialog( + context: context, + builder: (BuildContext context) { + return dialogBox(() { + context + .read() + .rejectPacket(regCurrent.packetId); + if (currentInd < + context + .read() + .matchingPackets + .length) { + context + .read() + .setCurrentInd(currentInd + 1); + Registration reg = context + .read() + .matchingPackets[(currentInd + + 1) - + 1]['packet'] as Registration; + log(reg.packetId); + loadHtmlData( + context + .read< + ApprovePacketsProvider>() + .webViewPlusController, + reg.packetId); + } + Navigator.of(context).pop(); + }, context); + }); + }, + style: OutlinedButton.styleFrom( + disabledForegroundColor: Colors.white, + disabledBackgroundColor: Colors.grey.withOpacity(0.5), + foregroundColor: Colors.red, + padding: const EdgeInsets.symmetric( + vertical: 12, horizontal: 18), + side: BorderSide( + color: reviewStatus == ReviewStatus.REJECTED.name + ? Colors.transparent + : Colors.red, + width: 2), + ), + label: Text( + AppLocalizations.of(context)!.reject, + style: const TextStyle(fontWeight: FontWeight.bold), + ), + ), + const SizedBox( + width: 16, + ), + Card( + margin: const EdgeInsets.only(right: 24), + elevation: 0, + shape: CircleBorder( + side: BorderSide( + color: reviewStatus == ReviewStatus.NOACTIONTAKEN.name + ? Colors.grey + : solidPrimary, + )), + child: IconButton( + onPressed: + reviewStatus == ReviewStatus.NOACTIONTAKEN.name + ? null + : () { + context + .read() + .clearReview(regCurrent.packetId); + }, + icon: Icon( + Icons.refresh_outlined, + color: + reviewStatus == ReviewStatus.NOACTIONTAKEN.name + ? Colors.grey + : solidPrimary, + size: 28, + ), + ), + ) + ], + ), Card( margin: const EdgeInsets.only(right: 24), elevation: 0, shape: CircleBorder( side: BorderSide( - color: (currentInd < + color: (currentInd < context .read() .matchingPackets .length) - ? solidPrimary - : Colors.grey, - )), + ? solidPrimary + : Colors.grey, + )), child: IconButton( icon: Icon( Icons.arrow_forward, color: (currentInd < - context - .read() - .matchingPackets - .length) + context + .read() + .matchingPackets + .length) ? solidPrimary : Colors.grey, size: 24, ), onPressed: currentInd < - context - .read() - .matchingPackets - .length + context + .read() + .matchingPackets + .length ? () { - context - .read() - .setCurrentInd(currentInd + 1); - Registration reg = context - .read() - .matchingPackets[(currentInd + 1) - 1] - ['packet'] as Registration; - log(reg.packetId); - loadHtmlData( - context - .read() - .webViewPlusController, - reg.packetId); - } + context + .read() + .setCurrentInd(currentInd + 1); + Registration reg = context + .read() + .matchingPackets[(currentInd + 1) - 1] + ['packet'] as Registration; + log(reg.packetId); + loadHtmlData( + context + .read() + .webViewPlusController, + reg.packetId); + } : () { - log("Out of range"); + log("Out of range"); }, ), ), - ], - ), - ), + ], + ), const SizedBox( - height: 18), - ], - ), - ], - ), + height: 18), + ], + ), ); }, ); diff --git a/lib/ui/dashboard/user_dashboard.dart b/lib/ui/dashboard/user_dashboard.dart index e20aed8e6..1641f1dae 100644 --- a/lib/ui/dashboard/user_dashboard.dart +++ b/lib/ui/dashboard/user_dashboard.dart @@ -314,52 +314,56 @@ class _UserDashBoardState extends State { margin: isMobileSize ? const EdgeInsets.only(left: 10, right: 10, bottom: 10) : const EdgeInsets.only( - left: 40, right: 40, bottom: 20), + left: 40, right: 40, bottom: 20), child: SizedBox( width: MediaQuery.of(context).size.width, child: snapshot.hasData - ? DataTable( - dividerThickness: 2, - headingRowHeight: 60, - columns: [ - DataColumn( - label: Text(appLocalizations.user_id, - style: TextStyle( - fontWeight: FontWeight.bold, - fontSize: isMobileSize ? 12 : 20, - color: appBlackShade2))), - DataColumn( - label: Text(appLocalizations.user_name, - style: TextStyle( - fontWeight: FontWeight.bold, - fontSize: isMobileSize ? 12 : 20, - color: appBlackShade2))), - DataColumn( - label: Text(appLocalizations.status, - style: TextStyle( - fontWeight: FontWeight.bold, - fontSize: isMobileSize ? 12 : 20, - color: appBlackShade2))), - ], - rows: snapshot.data! - .map((data) => DataRow(cells: [ - DataCell(Text(data!.userId.toString(), - style: TextStyle( - fontSize: - isMobileSize ? 10 : 17, - color: appBlackShade1, - fontWeight: FontWeight.w500))), - DataCell(Text(data.userName.toString(), - style: TextStyle( - fontSize: - isMobileSize ? 10 : 17, - color: appBlackShade2, - fontWeight: FontWeight.w500))), - DataCell(statusWidget(data.userStatus, - data.userIsOnboarded)) - ])) - .toList()) - : const SizedBox.shrink(), + ? FittedBox( + fit: BoxFit.scaleDown, // Shrinks table to fit in screen + alignment: Alignment.topLeft, + child:DataTable( + dividerThickness: 2, + headingRowHeight: 60, + columns: [ + DataColumn( + label: Text(appLocalizations.user_id, + style: TextStyle( + fontWeight: FontWeight.bold, + fontSize: isMobileSize ? 12 : 20, + color: appBlackShade2))), + DataColumn( + label: Text(appLocalizations.user_name, + style: TextStyle( + fontWeight: FontWeight.bold, + fontSize: isMobileSize ? 12 : 20, + color: appBlackShade2))), + DataColumn( + label: Text(appLocalizations.status, + style: TextStyle( + fontWeight: FontWeight.bold, + fontSize: isMobileSize ? 12 : 20, + color: appBlackShade2))), + ], + rows: snapshot.data! + .map((data) => DataRow(cells: [ + DataCell(Text(data!.userId.toString(), + style: TextStyle( + fontSize: + isMobileSize ? 10 : 17, + color: appBlackShade1, + fontWeight: FontWeight.w500))), + DataCell(Text(data.userName.toString(), + style: TextStyle( + fontSize: + isMobileSize ? 10 : 17, + color: appBlackShade2, + fontWeight: FontWeight.w500))), + DataCell(statusWidget(data.userStatus, + data.userIsOnboarded)) + ])) + .toList()) + ) + : const SizedBox.shrink(), ), ); }) @@ -439,4 +443,4 @@ class _UserDashBoardState extends State { ], ); } -} +} \ No newline at end of file diff --git a/lib/ui/export_packet/export_packet_ui.dart b/lib/ui/export_packet/export_packet_ui.dart index 87db5c3a3..bb9f925e5 100644 --- a/lib/ui/export_packet/export_packet_ui.dart +++ b/lib/ui/export_packet/export_packet_ui.dart @@ -56,7 +56,7 @@ class ExportPacketsPage extends StatelessWidget { const SizedBox( height: 4, ), - Column( + isMobileSize?Column( children: [ const Row( children: [ @@ -84,6 +84,24 @@ class ExportPacketsPage extends StatelessWidget { ], ), ], + ) + :const Row( + children: [ + Flexible( + flex: 2, + child: SearchBoxExport(), + ), + SizedBox(width: 10), + Flexible( + flex: 1, + child: UploadButton(), + ), + SizedBox(width: 10), // Add spacing between buttons + Flexible( + flex: 1, + child: ExportButton(), + ), + ], ), const SizedBox( @@ -105,35 +123,35 @@ class ExportPacketsPage extends StatelessWidget { mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ context - .watch() - .countSelected > - 0 + .watch() + .countSelected > + 0 ? Text( - AppLocalizations.of(context)! - .total_selected_application( - context - .watch() - .countSelected, - context - .watch() - .matchingPackets - .length), - style: Theme.of(context) - .textTheme - .titleLarge - ?.copyWith(fontSize: 20), - ) + AppLocalizations.of(context)! + .total_selected_application( + context + .watch() + .countSelected, + context + .watch() + .matchingPackets + .length), + style: Theme.of(context) + .textTheme + .titleLarge + ?.copyWith(fontSize: 20), + ) : Text( - AppLocalizations.of(context)! - .number_of_application(context - .watch() - .matchingPackets - .length), - style: Theme.of(context) - .textTheme - .titleLarge - ?.copyWith(fontSize: 20), - ), + AppLocalizations.of(context)! + .number_of_application(context + .watch() + .matchingPackets + .length), + style: Theme.of(context) + .textTheme + .titleLarge + ?.copyWith(fontSize: 20), + ), const SizedBox( width: 50, ), diff --git a/lib/ui/onboard/portrait/registration_tasks.dart b/lib/ui/onboard/portrait/registration_tasks.dart index df8ae9aec..686c0aa28 100644 --- a/lib/ui/onboard/portrait/registration_tasks.dart +++ b/lib/ui/onboard/portrait/registration_tasks.dart @@ -45,30 +45,32 @@ class _RegistrationTasksState extends State { @override Widget build(BuildContext context) { isPortrait = MediaQuery.of(context).orientation == Orientation.portrait; - return Column( - children: [ - SizedBox( - height: 26.h, - ), - isMobileSize - ? Padding( - padding: EdgeInsets.symmetric(horizontal: 16.w), - child: HomePageCard( - index: 0, - icon: SvgPicture.asset( - syncDataIcon, - ), - title: AppLocalizations.of(context)!.synchronize_data, - ontap: () => widget.syncData(context), - subtitle: null, - ), - ) - : _getSyncDataProvider(), - SizedBox( - height: 16.h, - ), - _getTasks(), - ], + return SingleChildScrollView( + child: Column( + children: [ + SizedBox( + height: 26.h, + ), + isMobileSize + ? Padding( + padding: EdgeInsets.symmetric(horizontal: 16.w), + child: HomePageCard( + index: 0, + icon: SvgPicture.asset( + syncDataIcon, + ), + title: AppLocalizations.of(context)!.synchronize_data, + ontap: () => widget.syncData(context), + subtitle: null, + ), + ) + : _getSyncDataProvider(), + SizedBox( + height: 16.h, + ), + _getTasks(), + ], + ), ); } @@ -141,11 +143,11 @@ class _RegistrationTasksState extends State { Text( context.watch().lastSuccessfulSyncTime != "" ? DateFormat("EEEE d MMMM, hh:mma") - .format(DateTime.parse(context - .watch() - .lastSuccessfulSyncTime) - .toLocal()) - .toString() + .format(DateTime.parse(context + .watch() + .lastSuccessfulSyncTime) + .toLocal()) + .toString() : "Last Sync time not found", style: const TextStyle( fontSize: 18, @@ -163,8 +165,9 @@ class _RegistrationTasksState extends State { padding: EdgeInsets.symmetric(horizontal: 20.w), child: GridView.builder( itemCount: - context.watch().listOfProcesses.length, + context.watch().listOfProcesses.length, shrinkWrap: true, + physics: NeverScrollableScrollPhysics(), gridDelegate: SliverGridDelegateWithFixedCrossAxisCount( crossAxisCount: (isPortrait) ? 2 : 4, mainAxisSpacing: (isPortrait) ? 8.h : 1.h, @@ -226,8 +229,8 @@ class _RegistrationTasksState extends State { ), Text( process.label![context - .read() - .selectedLanguage] ?? + .read() + .selectedLanguage] ?? process.label!["eng"] ?? process.label!.values.first, style: TextStyle( @@ -243,4 +246,4 @@ class _RegistrationTasksState extends State { }), ); } -} +} \ No newline at end of file diff --git a/lib/ui/onboard/widgets/operator_biometric_capture_scan_block_view.dart b/lib/ui/onboard/widgets/operator_biometric_capture_scan_block_view.dart index 28030db1a..def9f5812 100644 --- a/lib/ui/onboard/widgets/operator_biometric_capture_scan_block_view.dart +++ b/lib/ui/onboard/widgets/operator_biometric_capture_scan_block_view.dart @@ -101,14 +101,17 @@ class _OperatorBiometricCaptureScanBlockViewState ), Row( children: [ - const Spacer(), + //const Spacer(), const SizedBox( width: 28, ), Text( "${biometricAttributeData.title.replaceAll(" ", "")} ${AppLocalizations.of(context)!.capture}", + textAlign: TextAlign.start, + overflow: TextOverflow.visible, + maxLines: 1, style: Theme.of(context).textTheme.bodyLarge?.copyWith( - fontSize: 28, fontWeight: bold, color: blackShade1), + fontSize: 22, fontWeight: bold, color: blackShade1), ), const Spacer(), IconButton( @@ -131,34 +134,39 @@ class _OperatorBiometricCaptureScanBlockViewState Row( mainAxisAlignment: MainAxisAlignment.center, children: [ - (biometricAttributeData.title == "Iris" && - biometricAttributeData.exceptions.contains(true)) - ? ((biometricAttributeData.exceptions.first == true) - ? SvgPicture.asset( + if (biometricAttributeData.title == "Iris" && + biometricAttributeData.exceptions.contains(true) && + biometricAttributeData.exceptions.first == true) + Expanded( + child:SvgPicture.asset( "assets/svg/Left Eye Exception.svg", height: (isMobileSize) ? 130.h : 260.h, - ) - : const SizedBox()) - : const SizedBox(), + fit: BoxFit.contain, + ), + ), + ...temp.map( - (e) => Image.memory( + (e) =>Expanded( + child: Image.memory( e!, height: (isMobileSize) ? 130.h : 260.h, + fit: BoxFit.contain, + ), ), ), - (biometricAttributeData.title == "Iris" && - biometricAttributeData.exceptions.contains(true)) - ? ((biometricAttributeData.exceptions.first == true) - ? const SizedBox() - : Transform.flip( + if (biometricAttributeData.title == "Iris" && + biometricAttributeData.exceptions.contains(true) && + biometricAttributeData.exceptions.first != true) + Expanded( + child: Transform.flip( flipX: true, child: SvgPicture.asset( "assets/svg/Left Eye Exception.svg", height: (isMobileSize) ? 130.h : 260.h, + fit: BoxFit.contain, ), )) - : const SizedBox(), - ], + ], ), // Divider( // height: 82, diff --git a/lib/ui/post_registration/acknowledgement_page.dart b/lib/ui/post_registration/acknowledgement_page.dart index bbe73b103..f9ccba188 100644 --- a/lib/ui/post_registration/acknowledgement_page.dart +++ b/lib/ui/post_registration/acknowledgement_page.dart @@ -69,7 +69,8 @@ class _AcknowledgementPageState extends State { Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ - Text( + Expanded( + child:Text( AppLocalizations.of(context)!.registration_acknowledgement, style: const TextStyle( fontSize: 20, @@ -77,6 +78,8 @@ class _AcknowledgementPageState extends State { color: appBlackShade1, ), ), + ), + SizedBox(width: 10.w), InkWell( onTap: () { _printAcknowledgementAudit(); @@ -84,7 +87,7 @@ class _AcknowledgementPageState extends State { }, child: Container( height: 42.h, - width: 170.w, + padding: EdgeInsets.symmetric(horizontal: 12.w), decoration: BoxDecoration( color: appSolidPrimary, border: Border.all( diff --git a/lib/ui/process_ui/widgets/dropdown_control.dart b/lib/ui/process_ui/widgets/dropdown_control.dart index 2b0095306..fdcdcab81 100644 --- a/lib/ui/process_ui/widgets/dropdown_control.dart +++ b/lib/ui/process_ui/widgets/dropdown_control.dart @@ -249,6 +249,7 @@ class _CustomDropDownState extends State { height: 10, ), DropdownButtonFormField( + isExpanded: true, icon: const Icon(null), decoration: InputDecoration( contentPadding: @@ -270,8 +271,14 @@ class _CustomDropDownState extends State { items: list .map((option) => DropdownMenuItem( value: option, + child: Flexible( child: - Text(option!.concatenatedName ?? option.name), + Text(option!.concatenatedName ?? option.name, + overflow: TextOverflow.ellipsis, + maxLines: 1, + softWrap: false, + ), + ), )) .toList(), autovalidateMode: AutovalidateMode.onUserInteraction, diff --git a/lib/ui/process_ui/widgets/pre_reg_data_control.dart b/lib/ui/process_ui/widgets/pre_reg_data_control.dart index cdc1bd95f..a6a9d1b4b 100644 --- a/lib/ui/process_ui/widgets/pre_reg_data_control.dart +++ b/lib/ui/process_ui/widgets/pre_reg_data_control.dart @@ -247,20 +247,16 @@ class _PreRegDataControlState extends State { ), ), ), - Expanded( - flex: 3, - child: Padding( - padding: EdgeInsets.symmetric(horizontal: 20.w), - child: OutlinedButton( - style: OutlinedButton.styleFrom( - fixedSize: const Size(100, 50), - elevation: 0, - backgroundColor: Colors.white, - side: BorderSide(width: 1.0, color: solidPrimary), - shape: const RoundedRectangleBorder( - borderRadius: BorderRadius.all(Radius.circular(2)), - ), - ), + SizedBox(width: 8.w), + OutlinedButton( + style: OutlinedButton.styleFrom( + padding: EdgeInsets.symmetric(horizontal: 12.w, vertical: 14.h), + backgroundColor: Colors.white, + side: BorderSide(width: 1.0, color: solidPrimary), + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(2), + ), + ), onPressed: () async { widget.onFetched(); if(preRegIdController.text.isEmpty){ @@ -300,20 +296,17 @@ class _PreRegDataControlState extends State { style: TextStyle(fontSize: isPortrait && !isMobileSize ? 22 : 14, color: solidPrimary,fontWeight: FontWeight.bold), ), ), - ), - ), - Expanded( - flex: 1, - child: OutlinedButton( - style: OutlinedButton.styleFrom( - fixedSize: const Size(50, 50), - elevation: 0, - backgroundColor: Colors.white, - side: BorderSide(width: 1.0, color: solidPrimary), - shape: const RoundedRectangleBorder( - borderRadius: BorderRadius.all(Radius.circular(2)), - ), - ), + + SizedBox(width: 8.w), + OutlinedButton( + style: OutlinedButton.styleFrom( + minimumSize: Size(50.w, 50.h), + backgroundColor: Colors.white, + side: BorderSide(width: 1.0, color: solidPrimary), + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(2), + ), + ), onPressed: () async { widget.onFetched(); var data = await Navigator.push( @@ -353,8 +346,8 @@ class _PreRegDataControlState extends State { }, child: Icon(Icons.crop_free,size: 32.6,color: solidPrimary), ), - ), - const Spacer(), + + //const Spacer(), ], ) ], diff --git a/lib/ui/process_ui/widgets_mobile/biometric_capture_control_portrait.dart b/lib/ui/process_ui/widgets_mobile/biometric_capture_control_portrait.dart index 262c37738..414467e08 100644 --- a/lib/ui/process_ui/widgets_mobile/biometric_capture_control_portrait.dart +++ b/lib/ui/process_ui/widgets_mobile/biometric_capture_control_portrait.dart @@ -110,6 +110,10 @@ class _BiometricCaptureControlPortraitState fontWeight: semiBold, color: blackShade1, ), + textAlign: TextAlign.center, + maxLines: 2, + overflow: TextOverflow.ellipsis, + softWrap: true, ) ], ), @@ -179,7 +183,8 @@ class _BiometricCaptureControlPortraitState child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ - (widget.field.inputRequired!) + Expanded( + child:(widget.field.inputRequired!) ? RichText( text: TextSpan( text: context @@ -225,6 +230,7 @@ class _BiometricCaptureControlPortraitState // SizedBox( // height: (isMobileSize)?20.h:52.h, // ), + ), ], ), ), diff --git a/lib/ui/process_ui/widgets_mobile/biometric_capture_scan_block_portrait.dart b/lib/ui/process_ui/widgets_mobile/biometric_capture_scan_block_portrait.dart index a1e90e64c..f6c8e7649 100644 --- a/lib/ui/process_ui/widgets_mobile/biometric_capture_scan_block_portrait.dart +++ b/lib/ui/process_ui/widgets_mobile/biometric_capture_scan_block_portrait.dart @@ -96,22 +96,29 @@ class _BiometricCaptureScanBlockPortraitState height: (isMobileSize) ? 410.h : 610.h, width: 760.w, child: Column( + mainAxisSize: MainAxisSize.min, children: [ const SizedBox( height: 26, ), Row( children: [ - const Spacer(), + // const Spacer(), const SizedBox( width: 28, ), - Text( - "${biometricAttributeData.title.replaceAll(" ", "")} ${AppLocalizations.of(context)!.capture}", - style: Theme.of(context).textTheme.bodyLarge?.copyWith( - fontSize: 28, fontWeight: bold, color: blackShade1), + Expanded( + child:Text( + "${biometricAttributeData.title.replaceAll(" ", "")} ${AppLocalizations.of(context)!.capture}", + style: Theme.of(context).textTheme.bodyLarge?.copyWith( + fontSize: 28, fontWeight: bold, color: blackShade1), + maxLines: 2, + overflow: TextOverflow.visible, + softWrap: true, + + ), ), - const Spacer(), + // const Spacer(), IconButton( onPressed: () { Navigator.pop(context); @@ -129,60 +136,72 @@ class _BiometricCaptureScanBlockPortraitState thickness: 1, color: secondaryColors.elementAt(22), ), - Row( - mainAxisAlignment: (biometricAttributeData.title == "Iris") - ? MainAxisAlignment.spaceEvenly - : MainAxisAlignment.center, - children: [ - (biometricAttributeData.title == "Iris" && - biometricAttributeData.exceptions.contains(true)) - ? ((biometricAttributeData.exceptions.first == true) - ? SvgPicture.asset( - "assets/svg/Left Eye Exception.svg", - height: (isMobileSize) ? 130.h : 260.h, - ) - : const SizedBox()) - : const SizedBox(), - ...temp.map( - (e) => Image.memory( - e!, - height: (isMobileSize) ? 130.h : 260.h, + Expanded( + child: Row( + mainAxisAlignment: (biometricAttributeData.title == "Iris") + ? MainAxisAlignment.spaceEvenly + : MainAxisAlignment.center, + children: [ + // Left eye exception (if any) + if (biometricAttributeData.title == "Iris" && + biometricAttributeData.exceptions.contains(true) && + biometricAttributeData.exceptions.first == true) + SvgPicture.asset( + "assets/svg/Left Eye Exception.svg", + height: (isMobileSize) ? 130.h : 260.h, + ), + ...temp.map( + (e) => Flexible( + child: Container( + constraints: BoxConstraints( + maxHeight: (isMobileSize) ? 150.h : 280.h, + maxWidth: (isMobileSize) ? 150.w : 280.w, + ), + child: Image.memory( + e!, + fit: BoxFit.contain, + ), + ), + ), ), - ), - (biometricAttributeData.title == "Iris" && - biometricAttributeData.exceptions.contains(true)) - ? ((biometricAttributeData.exceptions.first == true) - ? const SizedBox() - : Transform.flip( - flipX: true, - child: SvgPicture.asset( - "assets/svg/Left Eye Exception.svg", - height: (isMobileSize) ? 130.h : 260.h, - ), - )) - : const SizedBox(), - ], + + if (biometricAttributeData.title == "Iris" && + biometricAttributeData.exceptions.contains(true) && + biometricAttributeData.exceptions.first != true) + Transform.flip( + flipX: true, + child: SvgPicture.asset( + "assets/svg/Left Eye Exception.svg", + height: (isMobileSize) ? 130.h : 260.h, + ), + ), + ], + ), ), Divider( height: 82, thickness: 1, color: secondaryColors.elementAt(22), ), - Container( - height: 96, - decoration: BoxDecoration( - color: secondaryColors.elementAt(23), - borderRadius: BorderRadius.circular(6)), - child: Center( - child: Text( - "${biometricAttributeData.noOfCapturesAllowed - currentAttemptNo} ${AppLocalizations.of(context)!.attempts_left}", - style: TextStyle( - fontSize: 25, - fontWeight: semiBold, - color: secondaryColors.elementAt(24)), + Row( + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + //const Spacer(), + const SizedBox(width: 28), + Expanded( + child: Text( + "${biometricAttributeData.noOfCapturesAllowed - currentAttemptNo} ${AppLocalizations.of(context)!.attempts_left}", + style: TextStyle( + fontSize: 25, + fontWeight: semiBold, + color: secondaryColors.elementAt(24)), + overflow: TextOverflow.visible, + maxLines:2, + ), ), - ), - ) + ], + ), + ], ), ), @@ -237,16 +256,16 @@ class _BiometricCaptureScanBlockPortraitState if (context.read().fieldInputValue.containsKey(key)) { if (context.read().getElementPosition( - context.read().fieldInputValue[key], - data.title) == + context.read().fieldInputValue[key], + data.title) == -1) { context.read().fieldInputValue[key].add(data); } else { context.read().fieldInputValue[key].removeAt(context .read() .getElementPosition( - context.read().fieldInputValue[key], - data.title)); + context.read().fieldInputValue[key], + data.title)); context.read().fieldInputValue[key].add(data); } } else { @@ -267,70 +286,70 @@ class _BiometricCaptureScanBlockPortraitState width: (isPortrait) ? double.infinity : 760.w, child: (biometricAttributeData.isScanned == false) ? Directionality( - textDirection: TextDirection.ltr, - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceEvenly, - children: [ - ...biometricAttributeData.listofImages - .map((e) => SvgPicture.asset( - "$e", - height: (isMobileSize) - ? biometricAttributeData.imageHeightMobile.h - : biometricAttributeData - .imageHeightTablet.h, - fit: BoxFit.fitHeight, - )) - ], - ), - ) + textDirection: TextDirection.ltr, + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + children: [ + ...biometricAttributeData.listofImages + .map((e) => SvgPicture.asset( + "$e", + height: (isMobileSize) + ? biometricAttributeData.imageHeightMobile.h + : biometricAttributeData + .imageHeightTablet.h, + fit: BoxFit.fitHeight, + )) + ], + ), + ) : Directionality( - textDirection: TextDirection.ltr, - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceEvenly, - children: [ - (biometricAttributeData.title == "Iris" && - biometricAttributeData.exceptions.contains(true)) - ? ((biometricAttributeData.exceptions.first == true) - ? Row( - children: [ - SizedBox( - width: 115.h, - ), - SvgPicture.asset( - "assets/svg/Left Eye Exception.svg", - height: (isMobileSize) ? 70.h : 130.h, - ), - ], - ) - : const SizedBox()) - : const SizedBox(), - ...biometricAttributeData.listofImages - .map((e) => Image.memory( - e, - height: (isMobileSize) ? 70.h : 130.h, - )), - (biometricAttributeData.title == "Iris" && - biometricAttributeData.exceptions.contains(true)) - ? ((biometricAttributeData.exceptions.first == true) - ? const SizedBox() - : Row( - children: [ - Transform.flip( - flipX: true, - child: SvgPicture.asset( - "assets/svg/Left Eye Exception.svg", - height: (isMobileSize) ? 70.h : 130.h, - ), - ), - SizedBox( - width: 115.h, - ) - ], - )) - : const SizedBox(), - ], - ), - ), + textDirection: TextDirection.ltr, + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + children: [ + (biometricAttributeData.title == "Iris" && + biometricAttributeData.exceptions.contains(true)) + ? ((biometricAttributeData.exceptions.first == true) + ? Row( + children: [ + SizedBox( + width: 115.h, + ), + SvgPicture.asset( + "assets/svg/Left Eye Exception.svg", + height: (isMobileSize) ? 70.h : 130.h, + ), + ], + ) + : const SizedBox()) + : const SizedBox(), + ...biometricAttributeData.listofImages + .map((e) => Image.memory( + e, + height: (isMobileSize) ? 70.h : 130.h, + )), + (biometricAttributeData.title == "Iris" && + biometricAttributeData.exceptions.contains(true)) + ? ((biometricAttributeData.exceptions.first == true) + ? const SizedBox() + : Row( + children: [ + Transform.flip( + flipX: true, + child: SvgPicture.asset( + "assets/svg/Left Eye Exception.svg", + height: (isMobileSize) ? 70.h : 130.h, + ), + ), + SizedBox( + width: 115.h, + ) + ], + )) + : const SizedBox(), + ], + ), + ), ), const SizedBox( height: 30, @@ -357,10 +376,10 @@ class _BiometricCaptureScanBlockPortraitState Text( "${AppLocalizations.of(context)!.threshold} ${biometricAttributeData.thresholdPercentage}%", style: Theme.of(context).textTheme.bodyLarge?.copyWith( - fontSize: 23, - fontWeight: regular, - color: secondaryColors.elementAt(1), - ), + fontSize: 23, + fontWeight: regular, + color: secondaryColors.elementAt(1), + ), ), SizedBox( height: 21.h, @@ -374,11 +393,11 @@ class _BiometricCaptureScanBlockPortraitState percent: biometricAttributeData.qualityPercentage / 100, backgroundColor: Colors.grey, progressColor: - (biometricAttributeData.qualityPercentage.toInt() < - int.parse( - biometricAttributeData.thresholdPercentage)) - ? secondaryColors.elementAt(26) - : secondaryColors.elementAt(11), + (biometricAttributeData.qualityPercentage.toInt() < + int.parse( + biometricAttributeData.thresholdPercentage)) + ? secondaryColors.elementAt(26) + : secondaryColors.elementAt(11), ), SizedBox( width: (isMobileSize) ? 20.w : 43.w, @@ -386,10 +405,10 @@ class _BiometricCaptureScanBlockPortraitState Text( "${biometricAttributeData.qualityPercentage.toInt()}%", style: Theme.of(context).textTheme.bodyLarge?.copyWith( - fontSize: 23, - fontWeight: semiBold, - color: secondaryColors.elementAt(1), - ), + fontSize: 23, + fontWeight: semiBold, + color: secondaryColors.elementAt(1), + ), ), ], ), @@ -429,8 +448,8 @@ class _BiometricCaptureScanBlockPortraitState mainAxisAlignment: MainAxisAlignment.center, children: [ for (int i = 1; - i <= biometricAttributeData.noOfCapturesAllowed; - i++) + i <= biometricAttributeData.noOfCapturesAllowed; + i++) Padding( padding: const EdgeInsets.only(right: 16.3), child: InkWell( @@ -438,17 +457,17 @@ class _BiometricCaptureScanBlockPortraitState if (biometricAttributeData.attemptNo >= i) { await BiometricsApi() .getBiometrics( - widget.field.id!, - biometricAttributeData.title - .replaceAll(" ", ""), - i) + widget.field.id!, + biometricAttributeData.title + .replaceAll(" ", ""), + i) .then((value) { biometricAttributeData.listOfBiometricsDto .clear(); for (var e in value) { biometricAttributeData.listOfBiometricsDto .add(BiometricsDto.fromJson( - json.decode(e!))); + json.decode(e!))); } }); @@ -456,16 +475,16 @@ class _BiometricCaptureScanBlockPortraitState biometricAttributeData.qualityPercentage = context .read< - BiometricCaptureControlProvider>() + BiometricCaptureControlProvider>() .avgScore(biometricAttributeData - .listOfBiometricsDto); + .listOfBiometricsDto); }); await BiometricsApi() .extractImageValuesByAttempt( - widget.field.id!, - biometricAttributeData.title - .replaceAll(" ", ""), - i) + widget.field.id!, + biometricAttributeData.title + .replaceAll(" ", ""), + i) .then((value) { biometricAttributeData.listofImages = value; }); @@ -492,13 +511,13 @@ class _BiometricCaptureScanBlockPortraitState .textTheme .bodyLarge ?.copyWith( - fontSize: 21, - color: - (biometricAttributeData.attemptNo < - i) - ? secondaryColors.elementAt(19) - : pureWhite, - fontWeight: semiBold), + fontSize: 21, + color: + (biometricAttributeData.attemptNo < + i) + ? secondaryColors.elementAt(19) + : pureWhite, + fontWeight: semiBold), ), ), ), @@ -526,11 +545,11 @@ class _BiometricCaptureScanBlockPortraitState biometricAttributeData.title.replaceAll(" ", "")); await BiometricsApi() .getBestBiometrics(widget.field.id!, - biometricAttributeData.title.replaceAll(" ", "")) + biometricAttributeData.title.replaceAll(" ", "")) .then((value) {}); await BiometricsApi() .extractImageValues(widget.field.id!, - biometricAttributeData.title.replaceAll(" ", "")) + biometricAttributeData.title.replaceAll(" ", "")) .then((value) { tempImageList = value; }); @@ -540,10 +559,10 @@ class _BiometricCaptureScanBlockPortraitState biometricAttributeData.title.replaceAll(" ", "")); biometricAttributeData.attemptNo = await BiometricsApi() .getBioAttempt(widget.field.id!, - biometricAttributeData.title.replaceAll(" ", "")); + biometricAttributeData.title.replaceAll(" ", "")); await BiometricsApi() .getBestBiometrics(widget.field.id!, - biometricAttributeData.title.replaceAll(" ", "")) + biometricAttributeData.title.replaceAll(" ", "")) .then((value) async { for (var e in value) { biometricAttributeData.listOfBiometricsDto.add( @@ -558,7 +577,7 @@ class _BiometricCaptureScanBlockPortraitState .avgScore(biometricAttributeData.listOfBiometricsDto); await BiometricsApi() .extractImageValues(widget.field.id!, - biometricAttributeData.title.replaceAll(" ", "")) + biometricAttributeData.title.replaceAll(" ", "")) .then((value) { biometricAttributeData.listofImages = value; }); @@ -587,9 +606,9 @@ class _BiometricCaptureScanBlockPortraitState : const EdgeInsets.symmetric(horizontal: 46, vertical: 34), backgroundColor: (biometricAttributeData.exceptions.contains(false) ? biometricAttributeData.attemptNo < - biometricAttributeData.noOfCapturesAllowed - ? solidPrimary - : appGreyShade + biometricAttributeData.noOfCapturesAllowed + ? solidPrimary + : appGreyShade : secondaryColors.elementAt(22)), shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(5), @@ -606,14 +625,14 @@ class _BiometricCaptureScanBlockPortraitState resetAfterException(String key, BiometricAttributeData data) { if (context.read().fieldInputValue.containsKey(key)) { if (context.read().getElementPosition( - context.read().fieldInputValue[key], - data.title) != + context.read().fieldInputValue[key], + data.title) != -1) { context.read().fieldInputValue[key].removeAt(context .read() .getElementPosition( - context.read().fieldInputValue[key], - data.title)); + context.read().fieldInputValue[key], + data.title)); } } } @@ -814,7 +833,7 @@ class _BiometricCaptureScanBlockPortraitState decoration: BoxDecoration( color: pureWhite, border: - Border.all(color: secondaryColors.elementAt(14), width: 1), + Border.all(color: secondaryColors.elementAt(14), width: 1), ), height: 353, width: (isPortrait) ? double.infinity : 760.w, @@ -825,215 +844,215 @@ class _BiometricCaptureScanBlockPortraitState height: 40, ), (biometricAttributeData.title != "Face" && - biometricAttributeData.title != "Exception") + biometricAttributeData.title != "Exception") ? Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Center( - child: Container( - decoration: BoxDecoration( - color: pureWhite, - border: Border.all( - color: secondaryColors.elementAt(14), width: 1), - ), - height: 134, - width: (isPortrait) ? double.infinity : 714.w, - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Text( - AppLocalizations.of(context)!.exceptions, - style: Theme.of(context) - .textTheme - .bodyLarge - ?.copyWith( - fontSize: 24, - color: blackShade1, - fontWeight: semiBold), - ), - const SizedBox( - height: 20, - ), - Padding( - padding: const EdgeInsets.only(right: 16.3), - child: Container( - padding: const EdgeInsets.symmetric( - vertical: 7.3, - horizontal: 30, - ), - decoration: BoxDecoration( - borderRadius: BorderRadius.circular(20), - border: Border.all( - color: secondaryColors.elementAt(17), - ), - color: secondaryColors.elementAt(18), - ), - child: Text( - noOfTrue(biometricAttributeData.exceptions) - .toString(), - style: Theme.of(context) - .textTheme - .bodyLarge - ?.copyWith( - fontSize: 21, - color: secondaryColors.elementAt(19), - fontWeight: semiBold), - ), - ), + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Center( + child: Container( + decoration: BoxDecoration( + color: pureWhite, + border: Border.all( + color: secondaryColors.elementAt(14), width: 1), + ), + height: 134, + width: (isPortrait) ? double.infinity : 714.w, + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Text( + AppLocalizations.of(context)!.exceptions, + style: Theme.of(context) + .textTheme + .bodyLarge + ?.copyWith( + fontSize: 24, + color: blackShade1, + fontWeight: semiBold), + ), + const SizedBox( + height: 20, + ), + Padding( + padding: const EdgeInsets.only(right: 16.3), + child: Container( + padding: const EdgeInsets.symmetric( + vertical: 7.3, + horizontal: 30, + ), + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(20), + border: Border.all( + color: secondaryColors.elementAt(17), ), - ], + color: secondaryColors.elementAt(18), + ), + child: Text( + noOfTrue(biometricAttributeData.exceptions) + .toString(), + style: Theme.of(context) + .textTheme + .bodyLarge + ?.copyWith( + fontSize: 21, + color: secondaryColors.elementAt(19), + fontWeight: semiBold), + ), ), ), - ), - const SizedBox( - height: 40, - ), - // Text( - // AppLocalizations.of(context)!.exception_type, - // style: TextStyle( - // fontSize: 25, fontWeight: semiBold, color: blackShade1), - // ), - // const SizedBox( - // height: 18, - // ), - // Row( - // children: [ - // Expanded( - // child: OutlinedButton( - // onPressed: () { - // if (biometricAttributeData.exceptions - // .contains(true)) { - // biometricAttributeData.exceptionType = - // "Permanent"; - // } - // }, - // style: ButtonStyle( - // backgroundColor: MaterialStateProperty.all( - // (biometricAttributeData.exceptionType == - // "Permanent") - // ? secondaryColors.elementAt(12) - // : pureWhite), - // shape: MaterialStateProperty.all( - // RoundedRectangleBorder( - // borderRadius: BorderRadius.circular(36), - // ), - // ), - // side: MaterialStateProperty.all( - // BorderSide( - // color: secondaryColors.elementAt(12))), - // padding: - // MaterialStateProperty.all( - // EdgeInsets.symmetric( - // horizontal: (isMobileSize) ? 10.w : 109.w, - // vertical: (isMobileSize) ? 10.h : 20.h), - // ), - // ), - // child: Text( - // AppLocalizations.of(context)!.permanent, - // style: TextStyle( - // fontSize: (isMobileSize) ? 16.h : 24.h, - // fontWeight: FontWeight.w400, - // color: (biometricAttributeData.exceptionType == - // "Permanent") - // ? pureWhite - // : blackShade1), - // ), - // ), - // ), - // const SizedBox( - // width: 30, - // ), - // Expanded( - // child: OutlinedButton( - // onPressed: () { - // if (biometricAttributeData.exceptions - // .contains(true)) { - // biometricAttributeData.exceptionType = - // "Temporary"; - // } - // }, - // style: ButtonStyle( - // backgroundColor: MaterialStateProperty.all( - // (biometricAttributeData.exceptionType == - // "Temporary") - // ? secondaryColors.elementAt(12) - // : pureWhite), - // shape: MaterialStateProperty.all( - // RoundedRectangleBorder( - // borderRadius: BorderRadius.circular(36), - // ), - // ), - // side: MaterialStateProperty.all( - // BorderSide( - // color: secondaryColors.elementAt(12))), - // padding: - // MaterialStateProperty.all( - // EdgeInsets.symmetric( - // horizontal: (isMobileSize) ? 10.w : 109.w, - // vertical: (isMobileSize) ? 10.h : 20.h), - // ), - // ), - // child: Text( - // AppLocalizations.of(context)!.temporary, - // style: TextStyle( - // fontSize: (isMobileSize) ? 16.h : 24.h, - // fontWeight: FontWeight.w400, - // color: (biometricAttributeData.exceptionType == - // "Temporary") - // ? pureWhite - // : blackShade1), - // ), - // ), - // ), - // ], - // ), - // const SizedBox( - // height: 40, - // ), - // Text( - // AppLocalizations.of(context)!.comments, - // style: TextStyle( - // fontSize: 25, fontWeight: semiBold, color: blackShade1), - // ), - // const SizedBox( - // height: 20, - // ), - // TextField( - // enabled: false, - // maxLines: 10, - // decoration: InputDecoration( - // fillColor: pureWhite, - // hintText: AppLocalizations.of(context)! - // .add_comments_for_marking_the_exception, - // hintStyle: TextStyle( - // fontSize: 28, - // fontWeight: regular, - // color: secondaryColors.elementAt(1)), - // border: OutlineInputBorder( - // borderRadius: BorderRadius.circular(6), - // borderSide: BorderSide( - // color: secondaryColors.elementAt(12), - // ), - // ), - // ), - // ), - ], - ) - : Container( - height: 96, - decoration: BoxDecoration( - color: secondaryColors.elementAt(23), - borderRadius: BorderRadius.circular(6)), - child: Center( - child: Text( - "${AppLocalizations.of(context)!.marking_exceptions_on} ${biometricAttributeData.viewTitle} ${AppLocalizations.of(context)!.is_not_allowed}", - style: TextStyle( - fontSize: 25, - fontWeight: semiBold, - color: secondaryColors.elementAt(24)), - ), + ], ), ), + ), + const SizedBox( + height: 40, + ), + // Text( + // AppLocalizations.of(context)!.exception_type, + // style: TextStyle( + // fontSize: 25, fontWeight: semiBold, color: blackShade1), + // ), + // const SizedBox( + // height: 18, + // ), + // Row( + // children: [ + // Expanded( + // child: OutlinedButton( + // onPressed: () { + // if (biometricAttributeData.exceptions + // .contains(true)) { + // biometricAttributeData.exceptionType = + // "Permanent"; + // } + // }, + // style: ButtonStyle( + // backgroundColor: MaterialStateProperty.all( + // (biometricAttributeData.exceptionType == + // "Permanent") + // ? secondaryColors.elementAt(12) + // : pureWhite), + // shape: MaterialStateProperty.all( + // RoundedRectangleBorder( + // borderRadius: BorderRadius.circular(36), + // ), + // ), + // side: MaterialStateProperty.all( + // BorderSide( + // color: secondaryColors.elementAt(12))), + // padding: + // MaterialStateProperty.all( + // EdgeInsets.symmetric( + // horizontal: (isMobileSize) ? 10.w : 109.w, + // vertical: (isMobileSize) ? 10.h : 20.h), + // ), + // ), + // child: Text( + // AppLocalizations.of(context)!.permanent, + // style: TextStyle( + // fontSize: (isMobileSize) ? 16.h : 24.h, + // fontWeight: FontWeight.w400, + // color: (biometricAttributeData.exceptionType == + // "Permanent") + // ? pureWhite + // : blackShade1), + // ), + // ), + // ), + // const SizedBox( + // width: 30, + // ), + // Expanded( + // child: OutlinedButton( + // onPressed: () { + // if (biometricAttributeData.exceptions + // .contains(true)) { + // biometricAttributeData.exceptionType = + // "Temporary"; + // } + // }, + // style: ButtonStyle( + // backgroundColor: MaterialStateProperty.all( + // (biometricAttributeData.exceptionType == + // "Temporary") + // ? secondaryColors.elementAt(12) + // : pureWhite), + // shape: MaterialStateProperty.all( + // RoundedRectangleBorder( + // borderRadius: BorderRadius.circular(36), + // ), + // ), + // side: MaterialStateProperty.all( + // BorderSide( + // color: secondaryColors.elementAt(12))), + // padding: + // MaterialStateProperty.all( + // EdgeInsets.symmetric( + // horizontal: (isMobileSize) ? 10.w : 109.w, + // vertical: (isMobileSize) ? 10.h : 20.h), + // ), + // ), + // child: Text( + // AppLocalizations.of(context)!.temporary, + // style: TextStyle( + // fontSize: (isMobileSize) ? 16.h : 24.h, + // fontWeight: FontWeight.w400, + // color: (biometricAttributeData.exceptionType == + // "Temporary") + // ? pureWhite + // : blackShade1), + // ), + // ), + // ), + // ], + // ), + // const SizedBox( + // height: 40, + // ), + // Text( + // AppLocalizations.of(context)!.comments, + // style: TextStyle( + // fontSize: 25, fontWeight: semiBold, color: blackShade1), + // ), + // const SizedBox( + // height: 20, + // ), + // TextField( + // enabled: false, + // maxLines: 10, + // decoration: InputDecoration( + // fillColor: pureWhite, + // hintText: AppLocalizations.of(context)! + // .add_comments_for_marking_the_exception, + // hintStyle: TextStyle( + // fontSize: 28, + // fontWeight: regular, + // color: secondaryColors.elementAt(1)), + // border: OutlineInputBorder( + // borderRadius: BorderRadius.circular(6), + // borderSide: BorderSide( + // color: secondaryColors.elementAt(12), + // ), + // ), + // ), + // ), + ], + ) + : Container( + height: 96, + decoration: BoxDecoration( + color: secondaryColors.elementAt(23), + borderRadius: BorderRadius.circular(6)), + child: Center( + child: Text( + "${AppLocalizations.of(context)!.marking_exceptions_on} ${biometricAttributeData.viewTitle} ${AppLocalizations.of(context)!.is_not_allowed}", + style: TextStyle( + fontSize: 25, + fontWeight: semiBold, + color: secondaryColors.elementAt(24)), + ), + ), + ), SizedBox( height: 20.h, ), @@ -1048,7 +1067,7 @@ class _BiometricCaptureScanBlockPortraitState child: Directionality( textDirection: TextDirection.ltr, child: - Row(mainAxisAlignment: MainAxisAlignment.spaceEvenly, children: [ + Row(mainAxisAlignment: MainAxisAlignment.spaceEvenly, children: [ Stack( children: [ SizedBox( @@ -1098,13 +1117,13 @@ class _BiometricCaptureScanBlockPortraitState biometricAttributeData.thresholdPercentage = "0"; } biometricAttributeData.exceptions[0] = - !(biometricAttributeData.exceptions[0]); + !(biometricAttributeData.exceptions[0]); if (biometricAttributeData.exceptions .contains(true)) { if (biometricAttributeData.exceptionType.isEmpty) { biometricAttributeData.exceptionType = - "Permanent"; + "Permanent"; } } if (!biometricAttributeData.exceptions @@ -1175,13 +1194,13 @@ class _BiometricCaptureScanBlockPortraitState biometricAttributeData.thresholdPercentage = "0"; } biometricAttributeData.exceptions[1] = - !(biometricAttributeData.exceptions[1]); + !(biometricAttributeData.exceptions[1]); if (biometricAttributeData.exceptions .contains(true)) { if (biometricAttributeData.exceptionType.isEmpty) { biometricAttributeData.exceptionType = - "Permanent"; + "Permanent"; } } if (!biometricAttributeData.exceptions @@ -1231,7 +1250,7 @@ class _BiometricCaptureScanBlockPortraitState child: InkWell( onTap: () async { if (!(biometricAttributeData.exceptions - .elementAt(0)) == + .elementAt(0)) == true) { await BiometricsApi().addBioException( widget.field.id!, "RightHand", "rightIndex"); @@ -1260,14 +1279,14 @@ class _BiometricCaptureScanBlockPortraitState biometricAttributeData.thresholdPercentage = "0"; } biometricAttributeData.exceptions[0] = - !(biometricAttributeData.exceptions[0]); + !(biometricAttributeData.exceptions[0]); if (biometricAttributeData.exceptions .contains(true)) { if (biometricAttributeData .exceptionType.isEmpty) { biometricAttributeData.exceptionType = - "Permanent"; + "Permanent"; } } if (!biometricAttributeData.exceptions @@ -1282,9 +1301,9 @@ class _BiometricCaptureScanBlockPortraitState "assets/svg/RH_1.svg", height: 165, color: - (biometricAttributeData.exceptions[0] == true) - ? secondaryColors.elementAt(25) - : Colors.transparent, + (biometricAttributeData.exceptions[0] == true) + ? secondaryColors.elementAt(25) + : Colors.transparent, ), )), Positioned( @@ -1293,7 +1312,7 @@ class _BiometricCaptureScanBlockPortraitState child: InkWell( onTap: () async { if (!(biometricAttributeData.exceptions - .elementAt(1)) == + .elementAt(1)) == true) { await BiometricsApi().addBioException( widget.field.id!, "RightHand", "rightMiddle"); @@ -1322,14 +1341,14 @@ class _BiometricCaptureScanBlockPortraitState biometricAttributeData.thresholdPercentage = "0"; } biometricAttributeData.exceptions[1] = - !(biometricAttributeData.exceptions[1]); + !(biometricAttributeData.exceptions[1]); if (biometricAttributeData.exceptions .contains(true)) { if (biometricAttributeData .exceptionType.isEmpty) { biometricAttributeData.exceptionType = - "Permanent"; + "Permanent"; } } if (!biometricAttributeData.exceptions @@ -1344,9 +1363,9 @@ class _BiometricCaptureScanBlockPortraitState "assets/svg/RH_2.svg", height: 205, color: - (biometricAttributeData.exceptions[1] == true) - ? secondaryColors.elementAt(25) - : Colors.transparent, + (biometricAttributeData.exceptions[1] == true) + ? secondaryColors.elementAt(25) + : Colors.transparent, ), )), Positioned( @@ -1355,7 +1374,7 @@ class _BiometricCaptureScanBlockPortraitState child: InkWell( onTap: () async { if (!(biometricAttributeData.exceptions - .elementAt(2)) == + .elementAt(2)) == true) { await BiometricsApi().addBioException( widget.field.id!, "RightHand", "rightRing"); @@ -1384,14 +1403,14 @@ class _BiometricCaptureScanBlockPortraitState biometricAttributeData.thresholdPercentage = "0"; } biometricAttributeData.exceptions[2] = - !(biometricAttributeData.exceptions[2]); + !(biometricAttributeData.exceptions[2]); if (biometricAttributeData.exceptions .contains(true)) { if (biometricAttributeData .exceptionType.isEmpty) { biometricAttributeData.exceptionType = - "Permanent"; + "Permanent"; } } if (!biometricAttributeData.exceptions @@ -1406,9 +1425,9 @@ class _BiometricCaptureScanBlockPortraitState "assets/svg/RH_3.svg", height: 165, color: - (biometricAttributeData.exceptions[2] == true) - ? secondaryColors.elementAt(25) - : const Color.fromARGB(0, 221, 210, 210), + (biometricAttributeData.exceptions[2] == true) + ? secondaryColors.elementAt(25) + : const Color.fromARGB(0, 221, 210, 210), ), )), Positioned( @@ -1417,7 +1436,7 @@ class _BiometricCaptureScanBlockPortraitState child: InkWell( onTap: () async { if (!(biometricAttributeData.exceptions - .elementAt(3)) == + .elementAt(3)) == true) { await BiometricsApi().addBioException( widget.field.id!, "RightHand", "rightLittle"); @@ -1446,14 +1465,14 @@ class _BiometricCaptureScanBlockPortraitState biometricAttributeData.thresholdPercentage = "0"; } biometricAttributeData.exceptions[3] = - !(biometricAttributeData.exceptions[3]); + !(biometricAttributeData.exceptions[3]); if (biometricAttributeData.exceptions .contains(true)) { if (biometricAttributeData .exceptionType.isEmpty) { biometricAttributeData.exceptionType = - "Permanent"; + "Permanent"; } } if (!biometricAttributeData.exceptions @@ -1468,9 +1487,9 @@ class _BiometricCaptureScanBlockPortraitState "assets/svg/RH_4.svg", height: 100, color: - (biometricAttributeData.exceptions[3] == true) - ? secondaryColors.elementAt(25) - : Colors.transparent, + (biometricAttributeData.exceptions[3] == true) + ? secondaryColors.elementAt(25) + : Colors.transparent, ), )), ], @@ -1487,422 +1506,422 @@ class _BiometricCaptureScanBlockPortraitState context: context, barrierDismissible: true, builder: (BuildContext context) => StatefulBuilder( - builder: (context, StateSetter setStateAlert) { - return Center( - child: AlertDialog( - insetPadding: EdgeInsets.symmetric( - vertical: (isMobileSize) ? 10 : 24, - horizontal: (isMobileSize) ? 10 : 40), - content: Container( - height: (isMobileSize) ? 500 : 720, - width: (isMobileSize) ? 404 : 760, - decoration: BoxDecoration( - borderRadius: BorderRadius.circular(12)), - child: SingleChildScrollView( - child: Column( - children: [ - Row( - children: [ - const SizedBox( - width: 50, - ), - const Spacer(), - Text( - "${biometricAttributeData.viewTitle} ${AppLocalizations.of(context)!.scan}", - style: TextStyle( - fontSize: (isMobileSize) ? 20.h : 28.h, - fontWeight: bold, - color: blackShade1, - overflow: TextOverflow.ellipsis), - ), - const Spacer(), - IconButton( - onPressed: () { - setState(() { - - }); - Navigator.pop(context); - }, - icon: Icon( - Icons.close, - color: blackShade1, - weight: 25, - size: 28, - )), - ], - ), - Divider( - height: 30, - thickness: 1, - color: secondaryColors.elementAt(22), - ), - Stack( - children: [ - SizedBox( - height: (isMobileSize) ? 339 : 639, - width: (isMobileSize) ? 339 : 639, - child: SvgPicture.asset( - "assets/svg/Right Hand.svg", - fit: BoxFit.fitHeight, + builder: (context, StateSetter setStateAlert) { + return Center( + child: AlertDialog( + insetPadding: EdgeInsets.symmetric( + vertical: (isMobileSize) ? 10 : 24, + horizontal: (isMobileSize) ? 10 : 40), + content: Container( + height: (isMobileSize) ? 500 : 720, + width: (isMobileSize) ? 404 : 760, + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(12)), + child: SingleChildScrollView( + child: Column( + children: [ + Row( + children: [ + const SizedBox( + width: 50, ), - ), - Positioned( - top: (isMobileSize) ? 109 : 205, - left: (isMobileSize) ? 72 : 140, - child: InkWell( - onTap: () async { - if (!(biometricAttributeData - .exceptions - .elementAt(0)) == - true) { - await BiometricsApi() - .addBioException( - widget.field.id!, - "RightHand", - "rightIndex"); - resetAfterException( - widget.field.id!, - biometricAttributeData); - biometricAttributeData.isScanned = - false; - biometricAttributeData.attemptNo = - 0; - biometricAttributeData - .listofImages = [ - "assets/svg/Right Hand.svg" - ]; - biometricAttributeData - .listOfBiometricsDto = []; - biometricAttributeData - .qualityPercentage = 0; - biometricAttributeData - .thresholdPercentage = "0"; - } else { - await BiometricsApi() - .removeBioException( - widget.field.id!, - "RightHand", - "rightIndex"); - resetAfterException( - widget.field.id!, - biometricAttributeData); - biometricAttributeData.isScanned = - false; - biometricAttributeData.attemptNo = - 0; - biometricAttributeData - .listofImages = [ - "assets/svg/Right Hand.svg" - ]; - biometricAttributeData - .listOfBiometricsDto = []; - biometricAttributeData - .qualityPercentage = 0; - biometricAttributeData - .thresholdPercentage = "0"; - } - biometricAttributeData.exceptions[0] = - !(biometricAttributeData - .exceptions[0]); + const Spacer(), + Text( + "${biometricAttributeData.viewTitle} ${AppLocalizations.of(context)!.scan}", + style: TextStyle( + fontSize: (isMobileSize) ? 20.h : 28.h, + fontWeight: bold, + color: blackShade1, + overflow: TextOverflow.ellipsis), + ), + const Spacer(), + IconButton( + onPressed: () { + setState(() { - if (biometricAttributeData.exceptions - .contains(true)) { - if (biometricAttributeData - .exceptionType.isEmpty) { - biometricAttributeData - .exceptionType = "Permanent"; - } - } - if (!biometricAttributeData.exceptions - .contains(true)) { - biometricAttributeData - .exceptionType = ""; - } - updateExceptionList("Right Hand"); - proofOfExceptionList("Right Hand"); - setState(() {}); - setStateAlert(() {}); + }); + Navigator.pop(context); }, - child: SvgPicture.asset( - "assets/svg/RH_1.svg", - height: (isMobileSize) ? 204 : 385, - color: (biometricAttributeData - .exceptions[0] == - true) - ? secondaryColors.elementAt(25) - : Colors.transparent, - ), - )), - Positioned( - top: (isMobileSize) ? 66 : 125, - left: (isMobileSize) ? 127 : 245, - child: InkWell( - onTap: () async { - if (!(biometricAttributeData - .exceptions - .elementAt(1)) == - true) { - await BiometricsApi() - .addBioException( - widget.field.id!, - "RightHand", - "rightMiddle"); - resetAfterException( - widget.field.id!, - biometricAttributeData); - biometricAttributeData.isScanned = - false; - biometricAttributeData.attemptNo = - 0; - biometricAttributeData - .listofImages = [ - "assets/svg/Right Hand.svg" - ]; - biometricAttributeData - .listOfBiometricsDto = []; - biometricAttributeData - .qualityPercentage = 0; - biometricAttributeData - .thresholdPercentage = "0"; - } else { - await BiometricsApi() - .removeBioException( - widget.field.id!, - "RightHand", - "rightMiddle"); - resetAfterException( - widget.field.id!, - biometricAttributeData); - biometricAttributeData.isScanned = - false; - biometricAttributeData.attemptNo = - 0; - biometricAttributeData - .listofImages = [ - "assets/svg/Right Hand.svg" - ]; - biometricAttributeData - .listOfBiometricsDto = []; - biometricAttributeData - .qualityPercentage = 0; - biometricAttributeData - .thresholdPercentage = "0"; - } - biometricAttributeData.exceptions[1] = - !(biometricAttributeData - .exceptions[1]); - - if (biometricAttributeData.exceptions - .contains(true)) { - if (biometricAttributeData - .exceptionType.isEmpty) { + icon: Icon( + Icons.close, + color: blackShade1, + weight: 25, + size: 28, + )), + ], + ), + Divider( + height: 30, + thickness: 1, + color: secondaryColors.elementAt(22), + ), + Stack( + children: [ + SizedBox( + height: (isMobileSize) ? 339 : 639, + width: (isMobileSize) ? 339 : 639, + child: SvgPicture.asset( + "assets/svg/Right Hand.svg", + fit: BoxFit.fitHeight, + ), + ), + Positioned( + top: (isMobileSize) ? 109 : 205, + left: (isMobileSize) ? 72 : 140, + child: InkWell( + onTap: () async { + if (!(biometricAttributeData + .exceptions + .elementAt(0)) == + true) { + await BiometricsApi() + .addBioException( + widget.field.id!, + "RightHand", + "rightIndex"); + resetAfterException( + widget.field.id!, + biometricAttributeData); + biometricAttributeData.isScanned = + false; + biometricAttributeData.attemptNo = + 0; biometricAttributeData - .exceptionType = "Permanent"; - } - } - if (!biometricAttributeData.exceptions - .contains(true)) { - biometricAttributeData - .exceptionType = ""; - } - updateExceptionList("Right Hand"); - proofOfExceptionList("Right Hand"); - setState(() {}); - setStateAlert(() {}); - }, - child: SvgPicture.asset( - "assets/svg/RH_2.svg", - height: (isMobileSize) ? 247 : 465, - color: (biometricAttributeData - .exceptions[1] == - true) - ? secondaryColors.elementAt(25) - : Colors.transparent, - ), - )), - Positioned( - top: (isMobileSize) ? 114 : 215, - right: (isMobileSize) ? 104 : 203, - child: InkWell( - onTap: () async { - if (!(biometricAttributeData - .exceptions - .elementAt(2)) == - true) { - await BiometricsApi() - .addBioException( - widget.field.id!, - "RightHand", - "rightRing"); - resetAfterException( - widget.field.id!, - biometricAttributeData); - biometricAttributeData.isScanned = - false; - biometricAttributeData.attemptNo = - 0; - biometricAttributeData - .listofImages = [ - "assets/svg/Right Hand.svg" - ]; - biometricAttributeData - .listOfBiometricsDto = []; - biometricAttributeData - .qualityPercentage = 0; - biometricAttributeData - .thresholdPercentage = "0"; - } else { - await BiometricsApi() - .removeBioException( - widget.field.id!, - "RightHand", - "rightRing"); - resetAfterException( - widget.field.id!, - biometricAttributeData); - biometricAttributeData.isScanned = - false; - biometricAttributeData.attemptNo = - 0; - biometricAttributeData - .listofImages = [ - "assets/svg/Right Hand.svg" - ]; - biometricAttributeData - .listOfBiometricsDto = []; - biometricAttributeData - .qualityPercentage = 0; - biometricAttributeData - .thresholdPercentage = "0"; - } - biometricAttributeData.exceptions[2] = - !(biometricAttributeData - .exceptions[2]); + .listofImages = [ + "assets/svg/Right Hand.svg" + ]; + biometricAttributeData + .listOfBiometricsDto = []; + biometricAttributeData + .qualityPercentage = 0; + biometricAttributeData + .thresholdPercentage = "0"; + } else { + await BiometricsApi() + .removeBioException( + widget.field.id!, + "RightHand", + "rightIndex"); + resetAfterException( + widget.field.id!, + biometricAttributeData); + biometricAttributeData.isScanned = + false; + biometricAttributeData.attemptNo = + 0; + biometricAttributeData + .listofImages = [ + "assets/svg/Right Hand.svg" + ]; + biometricAttributeData + .listOfBiometricsDto = []; + biometricAttributeData + .qualityPercentage = 0; + biometricAttributeData + .thresholdPercentage = "0"; + } + biometricAttributeData.exceptions[0] = + !(biometricAttributeData + .exceptions[0]); - if (biometricAttributeData.exceptions - .contains(true)) { - if (biometricAttributeData - .exceptionType.isEmpty) { + if (biometricAttributeData.exceptions + .contains(true)) { + if (biometricAttributeData + .exceptionType.isEmpty) { + biometricAttributeData + .exceptionType = "Permanent"; + } + } + if (!biometricAttributeData.exceptions + .contains(true)) { biometricAttributeData - .exceptionType = "Permanent"; + .exceptionType = ""; } - } - if (!biometricAttributeData.exceptions - .contains(true)) { - biometricAttributeData - .exceptionType = ""; - } - updateExceptionList("Right Hand"); - proofOfExceptionList("Right Hand"); - setState(() {}); - setStateAlert(() {}); - }, - child: SvgPicture.asset( - "assets/svg/RH_3.svg", - height: (isMobileSize) ? 204 : 385, - color: (biometricAttributeData - .exceptions[2] == - true) - ? secondaryColors.elementAt(25) - : Colors.transparent, - ), - )), - Positioned( - top: (isMobileSize) ? 189 : 357, - right: (isMobileSize) ? 56 : 110, - child: InkWell( - onTap: () async { - if (!(biometricAttributeData - .exceptions - .elementAt(3)) == - true) { - await BiometricsApi() - .addBioException( - widget.field.id!, - "RightHand", - "rightLittle"); - resetAfterException( - widget.field.id!, - biometricAttributeData); - biometricAttributeData.isScanned = - false; - biometricAttributeData.attemptNo = - 0; - biometricAttributeData - .listofImages = [ - "assets/svg/Right Hand.svg" - ]; - biometricAttributeData - .listOfBiometricsDto = []; - biometricAttributeData - .qualityPercentage = 0; - biometricAttributeData - .thresholdPercentage = "0"; - } else { - await BiometricsApi() - .removeBioException( - widget.field.id!, - "RightHand", - "rightLittle"); - resetAfterException( - widget.field.id!, - biometricAttributeData); - biometricAttributeData.isScanned = - false; - biometricAttributeData.attemptNo = - 0; - biometricAttributeData - .listofImages = [ - "assets/svg/Right Hand.svg" - ]; - biometricAttributeData - .listOfBiometricsDto = []; - biometricAttributeData - .qualityPercentage = 0; - biometricAttributeData - .thresholdPercentage = "0"; - } - biometricAttributeData.exceptions[3] = - !(biometricAttributeData - .exceptions[3]); + updateExceptionList("Right Hand"); + proofOfExceptionList("Right Hand"); + setState(() {}); + setStateAlert(() {}); + }, + child: SvgPicture.asset( + "assets/svg/RH_1.svg", + height: (isMobileSize) ? 204 : 385, + color: (biometricAttributeData + .exceptions[0] == + true) + ? secondaryColors.elementAt(25) + : Colors.transparent, + ), + )), + Positioned( + top: (isMobileSize) ? 66 : 125, + left: (isMobileSize) ? 127 : 245, + child: InkWell( + onTap: () async { + if (!(biometricAttributeData + .exceptions + .elementAt(1)) == + true) { + await BiometricsApi() + .addBioException( + widget.field.id!, + "RightHand", + "rightMiddle"); + resetAfterException( + widget.field.id!, + biometricAttributeData); + biometricAttributeData.isScanned = + false; + biometricAttributeData.attemptNo = + 0; + biometricAttributeData + .listofImages = [ + "assets/svg/Right Hand.svg" + ]; + biometricAttributeData + .listOfBiometricsDto = []; + biometricAttributeData + .qualityPercentage = 0; + biometricAttributeData + .thresholdPercentage = "0"; + } else { + await BiometricsApi() + .removeBioException( + widget.field.id!, + "RightHand", + "rightMiddle"); + resetAfterException( + widget.field.id!, + biometricAttributeData); + biometricAttributeData.isScanned = + false; + biometricAttributeData.attemptNo = + 0; + biometricAttributeData + .listofImages = [ + "assets/svg/Right Hand.svg" + ]; + biometricAttributeData + .listOfBiometricsDto = []; + biometricAttributeData + .qualityPercentage = 0; + biometricAttributeData + .thresholdPercentage = "0"; + } + biometricAttributeData.exceptions[1] = + !(biometricAttributeData + .exceptions[1]); - if (biometricAttributeData.exceptions - .contains(true)) { - if (biometricAttributeData - .exceptionType.isEmpty) { + if (biometricAttributeData.exceptions + .contains(true)) { + if (biometricAttributeData + .exceptionType.isEmpty) { + biometricAttributeData + .exceptionType = "Permanent"; + } + } + if (!biometricAttributeData.exceptions + .contains(true)) { biometricAttributeData - .exceptionType = "Permanent"; + .exceptionType = ""; } - } - if (!biometricAttributeData.exceptions - .contains(true)) { - biometricAttributeData - .exceptionType = ""; - } - updateExceptionList("Right Hand"); - proofOfExceptionList("Right Hand"); - setState(() {}); - setStateAlert(() {}); - }, - child: SvgPicture.asset( - "assets/svg/RH_4.svg", - height: (isMobileSize) ? 132 : 250, - color: (biometricAttributeData - .exceptions[3] == - true) - ? secondaryColors.elementAt(25) - : Colors.transparent, - ), - )), - ], - ), - ], + updateExceptionList("Right Hand"); + proofOfExceptionList("Right Hand"); + setState(() {}); + setStateAlert(() {}); + }, + child: SvgPicture.asset( + "assets/svg/RH_2.svg", + height: (isMobileSize) ? 247 : 465, + color: (biometricAttributeData + .exceptions[1] == + true) + ? secondaryColors.elementAt(25) + : Colors.transparent, + ), + )), + Positioned( + top: (isMobileSize) ? 114 : 215, + right: (isMobileSize) ? 104 : 203, + child: InkWell( + onTap: () async { + if (!(biometricAttributeData + .exceptions + .elementAt(2)) == + true) { + await BiometricsApi() + .addBioException( + widget.field.id!, + "RightHand", + "rightRing"); + resetAfterException( + widget.field.id!, + biometricAttributeData); + biometricAttributeData.isScanned = + false; + biometricAttributeData.attemptNo = + 0; + biometricAttributeData + .listofImages = [ + "assets/svg/Right Hand.svg" + ]; + biometricAttributeData + .listOfBiometricsDto = []; + biometricAttributeData + .qualityPercentage = 0; + biometricAttributeData + .thresholdPercentage = "0"; + } else { + await BiometricsApi() + .removeBioException( + widget.field.id!, + "RightHand", + "rightRing"); + resetAfterException( + widget.field.id!, + biometricAttributeData); + biometricAttributeData.isScanned = + false; + biometricAttributeData.attemptNo = + 0; + biometricAttributeData + .listofImages = [ + "assets/svg/Right Hand.svg" + ]; + biometricAttributeData + .listOfBiometricsDto = []; + biometricAttributeData + .qualityPercentage = 0; + biometricAttributeData + .thresholdPercentage = "0"; + } + biometricAttributeData.exceptions[2] = + !(biometricAttributeData + .exceptions[2]); + + if (biometricAttributeData.exceptions + .contains(true)) { + if (biometricAttributeData + .exceptionType.isEmpty) { + biometricAttributeData + .exceptionType = "Permanent"; + } + } + if (!biometricAttributeData.exceptions + .contains(true)) { + biometricAttributeData + .exceptionType = ""; + } + updateExceptionList("Right Hand"); + proofOfExceptionList("Right Hand"); + setState(() {}); + setStateAlert(() {}); + }, + child: SvgPicture.asset( + "assets/svg/RH_3.svg", + height: (isMobileSize) ? 204 : 385, + color: (biometricAttributeData + .exceptions[2] == + true) + ? secondaryColors.elementAt(25) + : Colors.transparent, + ), + )), + Positioned( + top: (isMobileSize) ? 189 : 357, + right: (isMobileSize) ? 56 : 110, + child: InkWell( + onTap: () async { + if (!(biometricAttributeData + .exceptions + .elementAt(3)) == + true) { + await BiometricsApi() + .addBioException( + widget.field.id!, + "RightHand", + "rightLittle"); + resetAfterException( + widget.field.id!, + biometricAttributeData); + biometricAttributeData.isScanned = + false; + biometricAttributeData.attemptNo = + 0; + biometricAttributeData + .listofImages = [ + "assets/svg/Right Hand.svg" + ]; + biometricAttributeData + .listOfBiometricsDto = []; + biometricAttributeData + .qualityPercentage = 0; + biometricAttributeData + .thresholdPercentage = "0"; + } else { + await BiometricsApi() + .removeBioException( + widget.field.id!, + "RightHand", + "rightLittle"); + resetAfterException( + widget.field.id!, + biometricAttributeData); + biometricAttributeData.isScanned = + false; + biometricAttributeData.attemptNo = + 0; + biometricAttributeData + .listofImages = [ + "assets/svg/Right Hand.svg" + ]; + biometricAttributeData + .listOfBiometricsDto = []; + biometricAttributeData + .qualityPercentage = 0; + biometricAttributeData + .thresholdPercentage = "0"; + } + biometricAttributeData.exceptions[3] = + !(biometricAttributeData + .exceptions[3]); + + if (biometricAttributeData.exceptions + .contains(true)) { + if (biometricAttributeData + .exceptionType.isEmpty) { + biometricAttributeData + .exceptionType = "Permanent"; + } + } + if (!biometricAttributeData.exceptions + .contains(true)) { + biometricAttributeData + .exceptionType = ""; + } + updateExceptionList("Right Hand"); + proofOfExceptionList("Right Hand"); + setState(() {}); + setStateAlert(() {}); + }, + child: SvgPicture.asset( + "assets/svg/RH_4.svg", + height: (isMobileSize) ? 132 : 250, + color: (biometricAttributeData + .exceptions[3] == + true) + ? secondaryColors.elementAt(25) + : Colors.transparent, + ), + )), + ], + ), + ], + ), ), ), ), - ), - ); - } + ); + } ), ); }, @@ -1947,7 +1966,7 @@ class _BiometricCaptureScanBlockPortraitState child: InkWell( onTap: () async { if (!(biometricAttributeData.exceptions - .elementAt(3)) == + .elementAt(3)) == true) { await BiometricsApi().addBioException( widget.field.id!, "LeftHand", "leftLittle"); @@ -1976,14 +1995,14 @@ class _BiometricCaptureScanBlockPortraitState biometricAttributeData.thresholdPercentage = "0"; } biometricAttributeData.exceptions[3] = - !(biometricAttributeData.exceptions[3]); + !(biometricAttributeData.exceptions[3]); if (biometricAttributeData.exceptions .contains(true)) { if (biometricAttributeData .exceptionType.isEmpty) { biometricAttributeData.exceptionType = - "Permanent"; + "Permanent"; } } if (!biometricAttributeData.exceptions @@ -1998,9 +2017,9 @@ class _BiometricCaptureScanBlockPortraitState "assets/svg/LH_1.svg", height: 100, color: - (biometricAttributeData.exceptions[3] == true) - ? secondaryColors.elementAt(25) - : Colors.transparent, + (biometricAttributeData.exceptions[3] == true) + ? secondaryColors.elementAt(25) + : Colors.transparent, ), )), Positioned( @@ -2009,7 +2028,7 @@ class _BiometricCaptureScanBlockPortraitState child: InkWell( onTap: () async { if (!(biometricAttributeData.exceptions - .elementAt(2)) == + .elementAt(2)) == true) { await BiometricsApi().addBioException( widget.field.id!, "LeftHand", "leftRing"); @@ -2038,14 +2057,14 @@ class _BiometricCaptureScanBlockPortraitState biometricAttributeData.thresholdPercentage = "0"; } biometricAttributeData.exceptions[2] = - !(biometricAttributeData.exceptions[2]); + !(biometricAttributeData.exceptions[2]); if (biometricAttributeData.exceptions .contains(true)) { if (biometricAttributeData .exceptionType.isEmpty) { biometricAttributeData.exceptionType = - "Permanent"; + "Permanent"; } } if (!biometricAttributeData.exceptions @@ -2060,9 +2079,9 @@ class _BiometricCaptureScanBlockPortraitState "assets/svg/LH_2.svg", height: 165, color: - (biometricAttributeData.exceptions[2] == true) - ? secondaryColors.elementAt(25) - : Colors.transparent, + (biometricAttributeData.exceptions[2] == true) + ? secondaryColors.elementAt(25) + : Colors.transparent, ), )), Positioned( @@ -2071,7 +2090,7 @@ class _BiometricCaptureScanBlockPortraitState child: InkWell( onTap: () async { if (!(biometricAttributeData.exceptions - .elementAt(1)) == + .elementAt(1)) == true) { await BiometricsApi().addBioException( widget.field.id!, "LeftHand", "leftMiddle"); @@ -2100,14 +2119,14 @@ class _BiometricCaptureScanBlockPortraitState biometricAttributeData.thresholdPercentage = "0"; } biometricAttributeData.exceptions[1] = - !(biometricAttributeData.exceptions[1]); + !(biometricAttributeData.exceptions[1]); if (biometricAttributeData.exceptions .contains(true)) { if (biometricAttributeData .exceptionType.isEmpty) { biometricAttributeData.exceptionType = - "Permanent"; + "Permanent"; } } if (!biometricAttributeData.exceptions @@ -2122,9 +2141,9 @@ class _BiometricCaptureScanBlockPortraitState "assets/svg/LH_3.svg", height: 205, color: - (biometricAttributeData.exceptions[1] == true) - ? secondaryColors.elementAt(25) - : Colors.transparent, + (biometricAttributeData.exceptions[1] == true) + ? secondaryColors.elementAt(25) + : Colors.transparent, ), )), Positioned( @@ -2133,7 +2152,7 @@ class _BiometricCaptureScanBlockPortraitState child: InkWell( onTap: () async { if (!(biometricAttributeData.exceptions - .elementAt(0)) == + .elementAt(0)) == true) { await BiometricsApi().addBioException( widget.field.id!, "LeftHand", "leftIndex"); @@ -2162,14 +2181,14 @@ class _BiometricCaptureScanBlockPortraitState biometricAttributeData.thresholdPercentage = "0"; } biometricAttributeData.exceptions[0] = - !(biometricAttributeData.exceptions[0]); + !(biometricAttributeData.exceptions[0]); if (biometricAttributeData.exceptions .contains(true)) { if (biometricAttributeData .exceptionType.isEmpty) { biometricAttributeData.exceptionType = - "Permanent"; + "Permanent"; } } if (!biometricAttributeData.exceptions @@ -2184,9 +2203,9 @@ class _BiometricCaptureScanBlockPortraitState "assets/svg/LH_4.svg", height: 165, color: - (biometricAttributeData.exceptions[0] == true) - ? secondaryColors.elementAt(25) - : Colors.transparent, + (biometricAttributeData.exceptions[0] == true) + ? secondaryColors.elementAt(25) + : Colors.transparent, ), )), ], @@ -2203,434 +2222,434 @@ class _BiometricCaptureScanBlockPortraitState context: context, builder: (context) => StatefulBuilder( builder: (context, StateSetter setStateAlert) { - return AlertDialog( - content: Container( - height: (isMobileSize) ? 500 : 720, - width: (isMobileSize) ? 404 : 760, - decoration: BoxDecoration( - borderRadius: BorderRadius.circular(12)), - child: SingleChildScrollView( - child: Column( - children: [ - Row( - children: [ - const SizedBox( - width: 50, - ), - const Spacer(), - Text( - "${biometricAttributeData.viewTitle} ${AppLocalizations.of(context)!.scan}", - style: TextStyle( - fontSize: - (isMobileSize) ? 20.h : 28.h, - fontWeight: bold, - color: blackShade1, - overflow: TextOverflow.ellipsis), - ), - const Spacer(), - IconButton( - onPressed: () { - setState(() { - - }); - Navigator.pop(context); - }, - icon: Icon( - Icons.close, - color: blackShade1, - weight: 25, - size: 28, - )), - ], - ), - Divider( - height: 30, - thickness: 1, - color: secondaryColors.elementAt(22), - ), - Stack( - children: [ - SizedBox( - height: (isMobileSize) ? 339 : 639, - width: (isMobileSize) ? 339 : 639, - child: SvgPicture.asset( - "assets/svg/Left Hand.svg", - fit: BoxFit.fitHeight, + return AlertDialog( + content: Container( + height: (isMobileSize) ? 500 : 720, + width: (isMobileSize) ? 404 : 760, + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(12)), + child: SingleChildScrollView( + child: Column( + children: [ + Row( + children: [ + const SizedBox( + width: 50, ), - ), - Positioned( - top: (isMobileSize) ? 189 : 357, - left: (isMobileSize) ? 52 : 110, - child: InkWell( - onTap: () async { - if (!(biometricAttributeData - .exceptions - .elementAt(3)) == - true) { - await BiometricsApi() - .addBioException( - widget.field.id!, - "LeftHand", - "leftLittle"); - resetAfterException( - widget.field.id!, - biometricAttributeData); - biometricAttributeData.isScanned = - false; - biometricAttributeData.attemptNo = - 0; - biometricAttributeData - .listofImages = [ - "assets/svg/Left Hand.svg" - ]; - biometricAttributeData - .listOfBiometricsDto = []; - biometricAttributeData - .qualityPercentage = 0; - biometricAttributeData - .thresholdPercentage = "0"; - } else { - await BiometricsApi() - .removeBioException( - widget.field.id!, - "LeftHand", - "leftLittle"); - resetAfterException( - widget.field.id!, - biometricAttributeData); - biometricAttributeData.isScanned = - false; - biometricAttributeData.attemptNo = - 0; - biometricAttributeData - .listofImages = [ - "assets/svg/Left Hand.svg" - ]; - biometricAttributeData - .listOfBiometricsDto = []; - biometricAttributeData - .qualityPercentage = 0; - biometricAttributeData - .thresholdPercentage = "0"; - } - biometricAttributeData - .exceptions[3] = - !(biometricAttributeData - .exceptions[3]); + const Spacer(), + Text( + "${biometricAttributeData.viewTitle} ${AppLocalizations.of(context)!.scan}", + style: TextStyle( + fontSize: + (isMobileSize) ? 20.h : 28.h, + fontWeight: bold, + color: blackShade1, + overflow: TextOverflow.ellipsis), + ), + const Spacer(), + IconButton( + onPressed: () { + setState(() { - if (biometricAttributeData - .exceptions - .contains(true)) { - if (biometricAttributeData - .exceptionType.isEmpty) { - biometricAttributeData - .exceptionType = - "Permanent"; - } - } - if (!biometricAttributeData - .exceptions - .contains(true)) { - biometricAttributeData - .exceptionType = ""; - } - updateExceptionList("Left Hand"); - proofOfExceptionList("Left Hand"); - setState(() {}); - setStateAlert(() {}); + }); + Navigator.pop(context); }, - child: SvgPicture.asset( - "assets/svg/LH_1.svg", - height: - (isMobileSize) ? 132.h : 250.h, - color: (biometricAttributeData - .exceptions[3] == - true) - ? secondaryColors.elementAt(25) - : Colors.transparent, - ), - )), - Positioned( - top: (isMobileSize) ? 114 : 215, - left: (isMobileSize) ? 110 : 203, - child: InkWell( - onTap: () async { - if (!(biometricAttributeData - .exceptions - .elementAt(2)) == - true) { - await BiometricsApi() - .addBioException( - widget.field.id!, - "LeftHand", - "leftRing"); - resetAfterException( - widget.field.id!, - biometricAttributeData); - biometricAttributeData.isScanned = - false; - biometricAttributeData.attemptNo = - 0; - biometricAttributeData - .listofImages = [ - "assets/svg/Left Hand.svg" - ]; - biometricAttributeData - .listOfBiometricsDto = []; - biometricAttributeData - .qualityPercentage = 0; - biometricAttributeData - .thresholdPercentage = "0"; - } else { - await BiometricsApi() - .removeBioException( - widget.field.id!, - "LeftHand", - "leftRing"); - resetAfterException( - widget.field.id!, - biometricAttributeData); - biometricAttributeData.isScanned = - false; - biometricAttributeData.attemptNo = - 0; - biometricAttributeData - .listofImages = [ - "assets/svg/Left Hand.svg" - ]; - biometricAttributeData - .listOfBiometricsDto = []; - biometricAttributeData - .qualityPercentage = 0; + icon: Icon( + Icons.close, + color: blackShade1, + weight: 25, + size: 28, + )), + ], + ), + Divider( + height: 30, + thickness: 1, + color: secondaryColors.elementAt(22), + ), + Stack( + children: [ + SizedBox( + height: (isMobileSize) ? 339 : 639, + width: (isMobileSize) ? 339 : 639, + child: SvgPicture.asset( + "assets/svg/Left Hand.svg", + fit: BoxFit.fitHeight, + ), + ), + Positioned( + top: (isMobileSize) ? 189 : 357, + left: (isMobileSize) ? 52 : 110, + child: InkWell( + onTap: () async { + if (!(biometricAttributeData + .exceptions + .elementAt(3)) == + true) { + await BiometricsApi() + .addBioException( + widget.field.id!, + "LeftHand", + "leftLittle"); + resetAfterException( + widget.field.id!, + biometricAttributeData); + biometricAttributeData.isScanned = + false; + biometricAttributeData.attemptNo = + 0; + biometricAttributeData + .listofImages = [ + "assets/svg/Left Hand.svg" + ]; + biometricAttributeData + .listOfBiometricsDto = []; + biometricAttributeData + .qualityPercentage = 0; + biometricAttributeData + .thresholdPercentage = "0"; + } else { + await BiometricsApi() + .removeBioException( + widget.field.id!, + "LeftHand", + "leftLittle"); + resetAfterException( + widget.field.id!, + biometricAttributeData); + biometricAttributeData.isScanned = + false; + biometricAttributeData.attemptNo = + 0; + biometricAttributeData + .listofImages = [ + "assets/svg/Left Hand.svg" + ]; + biometricAttributeData + .listOfBiometricsDto = []; + biometricAttributeData + .qualityPercentage = 0; + biometricAttributeData + .thresholdPercentage = "0"; + } biometricAttributeData - .thresholdPercentage = "0"; - } - biometricAttributeData - .exceptions[2] = - !(biometricAttributeData - .exceptions[2]); + .exceptions[3] = + !(biometricAttributeData + .exceptions[3]); - if (biometricAttributeData - .exceptions - .contains(true)) { if (biometricAttributeData - .exceptionType.isEmpty) { + .exceptions + .contains(true)) { + if (biometricAttributeData + .exceptionType.isEmpty) { + biometricAttributeData + .exceptionType = + "Permanent"; + } + } + if (!biometricAttributeData + .exceptions + .contains(true)) { biometricAttributeData - .exceptionType = - "Permanent"; + .exceptionType = ""; + } + updateExceptionList("Left Hand"); + proofOfExceptionList("Left Hand"); + setState(() {}); + setStateAlert(() {}); + }, + child: SvgPicture.asset( + "assets/svg/LH_1.svg", + height: + (isMobileSize) ? 132.h : 250.h, + color: (biometricAttributeData + .exceptions[3] == + true) + ? secondaryColors.elementAt(25) + : Colors.transparent, + ), + )), + Positioned( + top: (isMobileSize) ? 114 : 215, + left: (isMobileSize) ? 110 : 203, + child: InkWell( + onTap: () async { + if (!(biometricAttributeData + .exceptions + .elementAt(2)) == + true) { + await BiometricsApi() + .addBioException( + widget.field.id!, + "LeftHand", + "leftRing"); + resetAfterException( + widget.field.id!, + biometricAttributeData); + biometricAttributeData.isScanned = + false; + biometricAttributeData.attemptNo = + 0; + biometricAttributeData + .listofImages = [ + "assets/svg/Left Hand.svg" + ]; + biometricAttributeData + .listOfBiometricsDto = []; + biometricAttributeData + .qualityPercentage = 0; + biometricAttributeData + .thresholdPercentage = "0"; + } else { + await BiometricsApi() + .removeBioException( + widget.field.id!, + "LeftHand", + "leftRing"); + resetAfterException( + widget.field.id!, + biometricAttributeData); + biometricAttributeData.isScanned = + false; + biometricAttributeData.attemptNo = + 0; + biometricAttributeData + .listofImages = [ + "assets/svg/Left Hand.svg" + ]; + biometricAttributeData + .listOfBiometricsDto = []; + biometricAttributeData + .qualityPercentage = 0; + biometricAttributeData + .thresholdPercentage = "0"; } - } - if (!biometricAttributeData - .exceptions - .contains(true)) { - biometricAttributeData - .exceptionType = ""; - } - updateExceptionList("Left Hand"); - proofOfExceptionList("Left Hand"); - setState(() {}); - setStateAlert(() {}); - }, - child: SvgPicture.asset( - "assets/svg/LH_2.svg", - height: (isMobileSize) ? 204 : 385, - color: (biometricAttributeData - .exceptions[2] == - true) - ? secondaryColors.elementAt(25) - : Colors.transparent, - ), - )), - Positioned( - top: (isMobileSize) ? 66 : 125, - right: (isMobileSize) ? 130 : 245, - child: InkWell( - onTap: () async { - if (!(biometricAttributeData - .exceptions - .elementAt(1)) == - true) { - await BiometricsApi() - .addBioException( - widget.field.id!, - "LeftHand", - "leftMiddle"); - resetAfterException( - widget.field.id!, - biometricAttributeData); - biometricAttributeData.isScanned = - false; - biometricAttributeData.attemptNo = - 0; - biometricAttributeData - .listofImages = [ - "assets/svg/Left Hand.svg" - ]; - biometricAttributeData - .listOfBiometricsDto = []; - biometricAttributeData - .qualityPercentage = 0; - biometricAttributeData - .thresholdPercentage = "0"; - } else { - await BiometricsApi() - .removeBioException( - widget.field.id!, - "LeftHand", - "leftMiddle"); - resetAfterException( - widget.field.id!, - biometricAttributeData); - biometricAttributeData.isScanned = - false; - biometricAttributeData.attemptNo = - 0; - biometricAttributeData - .listofImages = [ - "assets/svg/Left Hand.svg" - ]; - biometricAttributeData - .listOfBiometricsDto = []; - biometricAttributeData - .qualityPercentage = 0; biometricAttributeData - .thresholdPercentage = "0"; - } - biometricAttributeData - .exceptions[1] = - !(biometricAttributeData - .exceptions[1]); + .exceptions[2] = + !(biometricAttributeData + .exceptions[2]); - if (biometricAttributeData - .exceptions - .contains(true)) { if (biometricAttributeData - .exceptionType.isEmpty) { + .exceptions + .contains(true)) { + if (biometricAttributeData + .exceptionType.isEmpty) { + biometricAttributeData + .exceptionType = + "Permanent"; + } + } + if (!biometricAttributeData + .exceptions + .contains(true)) { biometricAttributeData - .exceptionType = - "Permanent"; + .exceptionType = ""; + } + updateExceptionList("Left Hand"); + proofOfExceptionList("Left Hand"); + setState(() {}); + setStateAlert(() {}); + }, + child: SvgPicture.asset( + "assets/svg/LH_2.svg", + height: (isMobileSize) ? 204 : 385, + color: (biometricAttributeData + .exceptions[2] == + true) + ? secondaryColors.elementAt(25) + : Colors.transparent, + ), + )), + Positioned( + top: (isMobileSize) ? 66 : 125, + right: (isMobileSize) ? 130 : 245, + child: InkWell( + onTap: () async { + if (!(biometricAttributeData + .exceptions + .elementAt(1)) == + true) { + await BiometricsApi() + .addBioException( + widget.field.id!, + "LeftHand", + "leftMiddle"); + resetAfterException( + widget.field.id!, + biometricAttributeData); + biometricAttributeData.isScanned = + false; + biometricAttributeData.attemptNo = + 0; + biometricAttributeData + .listofImages = [ + "assets/svg/Left Hand.svg" + ]; + biometricAttributeData + .listOfBiometricsDto = []; + biometricAttributeData + .qualityPercentage = 0; + biometricAttributeData + .thresholdPercentage = "0"; + } else { + await BiometricsApi() + .removeBioException( + widget.field.id!, + "LeftHand", + "leftMiddle"); + resetAfterException( + widget.field.id!, + biometricAttributeData); + biometricAttributeData.isScanned = + false; + biometricAttributeData.attemptNo = + 0; + biometricAttributeData + .listofImages = [ + "assets/svg/Left Hand.svg" + ]; + biometricAttributeData + .listOfBiometricsDto = []; + biometricAttributeData + .qualityPercentage = 0; + biometricAttributeData + .thresholdPercentage = "0"; } - } - if (!biometricAttributeData - .exceptions - .contains(true)) { - biometricAttributeData - .exceptionType = ""; - } - updateExceptionList("Left Hand"); - proofOfExceptionList("Left Hand"); - setState(() {}); - setStateAlert(() {}); - }, - child: SvgPicture.asset( - "assets/svg/LH_3.svg", - height: (isMobileSize) ? 247 : 465, - color: (biometricAttributeData - .exceptions[1] == - true) - ? secondaryColors.elementAt(25) - : Colors.transparent, - ), - )), - Positioned( - top: (isMobileSize) ? 109 : 205, - right: (isMobileSize) ? 73 : 140, - child: InkWell( - onTap: () async { - if (!(biometricAttributeData - .exceptions - .elementAt(0)) == - true) { - await BiometricsApi() - .addBioException( - widget.field.id!, - "LeftHand", - "leftIndex"); - resetAfterException( - widget.field.id!, - biometricAttributeData); - biometricAttributeData.isScanned = - false; - biometricAttributeData.attemptNo = - 0; - biometricAttributeData - .listofImages = [ - "assets/svg/Left Hand.svg" - ]; - biometricAttributeData - .listOfBiometricsDto = []; - biometricAttributeData - .qualityPercentage = 0; - biometricAttributeData - .thresholdPercentage = "0"; - } else { - await BiometricsApi() - .removeBioException( - widget.field.id!, - "LeftHand", - "leftIndex"); - resetAfterException( - widget.field.id!, - biometricAttributeData); - biometricAttributeData.isScanned = - false; - biometricAttributeData.attemptNo = - 0; - biometricAttributeData - .listofImages = [ - "assets/svg/Left Hand.svg" - ]; - biometricAttributeData - .listOfBiometricsDto = []; - biometricAttributeData - .qualityPercentage = 0; biometricAttributeData - .thresholdPercentage = "0"; - } - biometricAttributeData - .exceptions[0] = - !(biometricAttributeData - .exceptions[0]); + .exceptions[1] = + !(biometricAttributeData + .exceptions[1]); - if (biometricAttributeData - .exceptions - .contains(true)) { if (biometricAttributeData - .exceptionType.isEmpty) { + .exceptions + .contains(true)) { + if (biometricAttributeData + .exceptionType.isEmpty) { + biometricAttributeData + .exceptionType = + "Permanent"; + } + } + if (!biometricAttributeData + .exceptions + .contains(true)) { biometricAttributeData - .exceptionType = - "Permanent"; + .exceptionType = ""; + } + updateExceptionList("Left Hand"); + proofOfExceptionList("Left Hand"); + setState(() {}); + setStateAlert(() {}); + }, + child: SvgPicture.asset( + "assets/svg/LH_3.svg", + height: (isMobileSize) ? 247 : 465, + color: (biometricAttributeData + .exceptions[1] == + true) + ? secondaryColors.elementAt(25) + : Colors.transparent, + ), + )), + Positioned( + top: (isMobileSize) ? 109 : 205, + right: (isMobileSize) ? 73 : 140, + child: InkWell( + onTap: () async { + if (!(biometricAttributeData + .exceptions + .elementAt(0)) == + true) { + await BiometricsApi() + .addBioException( + widget.field.id!, + "LeftHand", + "leftIndex"); + resetAfterException( + widget.field.id!, + biometricAttributeData); + biometricAttributeData.isScanned = + false; + biometricAttributeData.attemptNo = + 0; + biometricAttributeData + .listofImages = [ + "assets/svg/Left Hand.svg" + ]; + biometricAttributeData + .listOfBiometricsDto = []; + biometricAttributeData + .qualityPercentage = 0; + biometricAttributeData + .thresholdPercentage = "0"; + } else { + await BiometricsApi() + .removeBioException( + widget.field.id!, + "LeftHand", + "leftIndex"); + resetAfterException( + widget.field.id!, + biometricAttributeData); + biometricAttributeData.isScanned = + false; + biometricAttributeData.attemptNo = + 0; + biometricAttributeData + .listofImages = [ + "assets/svg/Left Hand.svg" + ]; + biometricAttributeData + .listOfBiometricsDto = []; + biometricAttributeData + .qualityPercentage = 0; + biometricAttributeData + .thresholdPercentage = "0"; } - } - if (!biometricAttributeData - .exceptions - .contains(true)) { biometricAttributeData - .exceptionType = ""; - } - updateExceptionList("Left Hand"); - proofOfExceptionList("Left Hand"); - setState(() {}); - setStateAlert(() {}); - }, - child: SvgPicture.asset( - "assets/svg/LH_4.svg", - height: (isMobileSize) ? 204 : 385, - color: (biometricAttributeData - .exceptions[0] == - true) - ? secondaryColors.elementAt(25) - : Colors.transparent, - ), - )), - ], - ), - ], + .exceptions[0] = + !(biometricAttributeData + .exceptions[0]); + + if (biometricAttributeData + .exceptions + .contains(true)) { + if (biometricAttributeData + .exceptionType.isEmpty) { + biometricAttributeData + .exceptionType = + "Permanent"; + } + } + if (!biometricAttributeData + .exceptions + .contains(true)) { + biometricAttributeData + .exceptionType = ""; + } + updateExceptionList("Left Hand"); + proofOfExceptionList("Left Hand"); + setState(() {}); + setStateAlert(() {}); + }, + child: SvgPicture.asset( + "assets/svg/LH_4.svg", + height: (isMobileSize) ? 204 : 385, + color: (biometricAttributeData + .exceptions[0] == + true) + ? secondaryColors.elementAt(25) + : Colors.transparent, + ), + )), + ], + ), + ], + ), ), ), - ), - ); - } + ); + } ), ); }, @@ -2698,7 +2717,7 @@ class _BiometricCaptureScanBlockPortraitState biometricAttributeData.thresholdPercentage = "0"; } biometricAttributeData.exceptions[0] = - !(biometricAttributeData.exceptions[0]); + !(biometricAttributeData.exceptions[0]); if (biometricAttributeData.exceptions.contains(true)) { if (biometricAttributeData.exceptionType.isEmpty) { @@ -2754,7 +2773,7 @@ class _BiometricCaptureScanBlockPortraitState biometricAttributeData.thresholdPercentage = "0"; } biometricAttributeData.exceptions[1] = - !(biometricAttributeData.exceptions[1]); + !(biometricAttributeData.exceptions[1]); if (biometricAttributeData.exceptions.contains(true)) { if (biometricAttributeData.exceptionType.isEmpty) { @@ -2945,22 +2964,22 @@ class _BiometricCaptureScanBlockPortraitState ElevatedButton( style: ButtonStyle( maximumSize: - MaterialStateProperty.all(const Size(200, 68)), + MaterialStateProperty.all(const Size(200, 68)), minimumSize: - MaterialStateProperty.all(const Size(200, 68)), + MaterialStateProperty.all(const Size(200, 68)), ), onPressed: () { List bioAttributes = (widget - .field.conditionalBioAttributes!.first!.ageGroup! - .compareTo( - context.read().ageGroup) == - 0) + .field.conditionalBioAttributes!.first!.ageGroup! + .compareTo( + context.read().ageGroup) == + 0) ? _returnBiometricList( - widget.field.conditionalBioAttributes!.first! - .bioAttributes!, - widget.field.id!) + widget.field.conditionalBioAttributes!.first! + .bioAttributes!, + widget.field.id!) : _returnBiometricList( - widget.field.bioAttributes!, widget.field.id!); + widget.field.bioAttributes!, widget.field.id!); var nextElement = _getNextElement( bioAttributes, @@ -2998,13 +3017,13 @@ class _BiometricCaptureScanBlockPortraitState child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ - Expanded( - child: - (widget.field.inputRequired!) - ? RichText( - overflow: TextOverflow.ellipsis, - maxLines: 2, - text: TextSpan( + Expanded( + child: + (widget.field.inputRequired!) + ? RichText( + overflow: TextOverflow.ellipsis, + maxLines: 2, + text: TextSpan( text: context .read() .chooseLanguage(widget.field.label!), @@ -3012,11 +3031,11 @@ class _BiometricCaptureScanBlockPortraitState .textTheme .titleLarge ?.copyWith( - fontSize: (isMobileSize) ? 14.h : 24.h, - color: blackShade1, - fontWeight: semiBold, - // overflow: TextOverflow.ellipsis - ), + fontSize: (isMobileSize) ? 14.h : 24.h, + color: blackShade1, + fontWeight: semiBold, + //overflow: TextOverflow.ellipsis + ), children: const [ TextSpan( text: " *", @@ -3025,22 +3044,22 @@ class _BiometricCaptureScanBlockPortraitState ) ], )) - : Text( - context - .read() - .chooseLanguage(widget.field.label!), - overflow: TextOverflow.ellipsis, - maxLines: 2, - style: Theme.of(context) - .textTheme - .titleLarge - ?.copyWith( - fontSize: (isMobileSize) ? 14.h : 24.h, - color: blackShade1, - fontWeight: semiBold, - // overflow: TextOverflow.ellipsis - ), - ), + : Text( + context + .read() + .chooseLanguage(widget.field.label!), + overflow: TextOverflow.ellipsis, + maxLines: 2, + style: Theme.of(context) + .textTheme + .titleLarge + ?.copyWith( + fontSize: (isMobileSize) ? 14.h : 24.h, + color: blackShade1, + fontWeight: semiBold, + // overflow: TextOverflow.ellipsis, + ), + ), ), Padding( padding: const EdgeInsets.only(right: 30), @@ -3083,33 +3102,37 @@ class _BiometricCaptureScanBlockPortraitState child: Container( decoration: BoxDecoration( color: (context - .read() - .biometricCaptureScanBlockTabIndex == - 1) + .read() + .biometricCaptureScanBlockTabIndex == + 1) ? solidPrimary : pureWhite, border: (context - .read() - .biometricCaptureScanBlockTabIndex == - 1) + .read() + .biometricCaptureScanBlockTabIndex == + 1) ? const Border() : Border( - bottom: BorderSide( - color: solidPrimary, width: 3), - ), + bottom: BorderSide( + color: solidPrimary, width: 3), + ), ), height: 84, child: Center( child: Text( "${biometricAttributeData.viewTitle} ${AppLocalizations.of(context)!.scan}", + maxLines: 2, + overflow: TextOverflow.ellipsis, + softWrap: true, + textAlign: TextAlign.center, style: TextStyle( fontSize: (isMobileSize) ? 18 : 24, fontWeight: semiBold, color: (context - .read< - BiometricCaptureControlProvider>() - .biometricCaptureScanBlockTabIndex == - 1) + .read< + BiometricCaptureControlProvider>() + .biometricCaptureScanBlockTabIndex == + 1) ? pureWhite : blackShade1), ), @@ -3128,20 +3151,20 @@ class _BiometricCaptureScanBlockPortraitState child: Container( decoration: BoxDecoration( color: (context - .read() - .biometricCaptureScanBlockTabIndex == - 2) + .read() + .biometricCaptureScanBlockTabIndex == + 2) ? solidPrimary : pureWhite, border: (context - .read() - .biometricCaptureScanBlockTabIndex == - 2) + .read() + .biometricCaptureScanBlockTabIndex == + 2) ? const Border() : Border( - bottom: BorderSide( - color: solidPrimary, width: 3), - ), + bottom: BorderSide( + color: solidPrimary, width: 3), + ), ), height: 84, child: Center( @@ -3151,10 +3174,10 @@ class _BiometricCaptureScanBlockPortraitState fontSize: (isMobileSize) ? 18 : 24, fontWeight: semiBold, color: (context - .read< - BiometricCaptureControlProvider>() - .biometricCaptureScanBlockTabIndex == - 2) + .read< + BiometricCaptureControlProvider>() + .biometricCaptureScanBlockTabIndex == + 2) ? pureWhite : blackShade1), ), @@ -3168,9 +3191,9 @@ class _BiometricCaptureScanBlockPortraitState height: 40, ), (context - .read() - .biometricCaptureScanBlockTabIndex == - 1) + .read() + .biometricCaptureScanBlockTabIndex == + 1) ? _scanBlock() : _exceptionBlock() ], diff --git a/lib/ui/widgets/language_component.dart b/lib/ui/widgets/language_component.dart index d5cad29ca..53d9a9822 100644 --- a/lib/ui/widgets/language_component.dart +++ b/lib/ui/widgets/language_component.dart @@ -41,7 +41,8 @@ class _LanguageComponentState extends State { }, child: Container( - padding: EdgeInsets.only( + height: 60.h, + padding: EdgeInsets.only( left: 25.w, right: 25.w, top: widget.isMobile && !isMobileSize ? 15.h : 9.h, @@ -51,15 +52,15 @@ class _LanguageComponentState extends State { color: widget.isFreezed ? appButtonBorderText : widget.isSelected - ? appButtonBorderText - : Colors.transparent, + ? appButtonBorderText + : Colors.transparent, border: Border.all( width: 1, color: widget.isDisabled ? appBlackShade3 : widget.isSelected - ? appButtonBorderText - : languageSelectedColor, + ? appButtonBorderText + : languageSelectedColor, ), borderRadius: const BorderRadius.all( Radius.circular(36), @@ -70,9 +71,9 @@ class _LanguageComponentState extends State { children: [ widget.isFreezed || widget.isSelected ? Icon( - Icons.check, - color: widget.isFreezed ? appGreyShade : appWhite, - ) + Icons.check, + color: widget.isFreezed ? appGreyShade : appWhite, + ) : const SizedBox(), SizedBox( width: widget.isFreezed || widget.isSelected ? 15.02 : 0, @@ -86,10 +87,10 @@ class _LanguageComponentState extends State { color: widget.isDisabled ? appBlackShade3 : widget.isFreezed - ? appGreyShade - : widget.isSelected - ? appWhite - : appBlackShade1, + ? appGreyShade + : widget.isSelected + ? appWhite + : appBlackShade1, ), ), ), diff --git a/pubspec.lock b/pubspec.lock index 06ec3955a..a012c5009 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -6,7 +6,7 @@ packages: description: name: _fe_analyzer_shared sha256: ae92f5d747aee634b87f89d9946000c2de774be1d6ac3e58268224348cd0101a - url: "https://infyartifactory.jfrog.io/artifactory/api/pub/pub.dev-remote/" + url: "https://pub.dev" source: hosted version: "61.0.0" analyzer: @@ -14,31 +14,23 @@ packages: description: name: analyzer sha256: ea3d8652bda62982addfd92fdc2d0214e5f82e43325104990d4f4c4a2a313562 - url: "https://infyartifactory.jfrog.io/artifactory/api/pub/pub.dev-remote/" + url: "https://pub.dev" source: hosted version: "5.13.0" - android_alarm_manager_plus: - dependency: "direct main" - description: - name: android_alarm_manager_plus - sha256: "84720c8ad2758aabfbeafd24a8c355d8c8dd3aa52b01eaf3bb827c7210f61a91" - url: "https://infyartifactory.jfrog.io/artifactory/api/pub/pub.dev-remote/" - source: hosted - version: "3.0.4" archive: dependency: transitive description: name: archive - sha256: cb6a278ef2dbb298455e1a713bda08524a175630ec643a242c399c932a0a1f7d - url: "https://infyartifactory.jfrog.io/artifactory/api/pub/pub.dev-remote/" + sha256: "2fde1607386ab523f7a36bb3e7edb43bd58e6edaf2ffb29d8a6d578b297fdbbd" + url: "https://pub.dev" source: hosted - version: "3.6.1" + version: "4.0.7" args: dependency: transitive description: name: args sha256: "7cf60b9f0cc88203c5a190b4cd62a99feea42759a7fa695010eb5de1c0b2252a" - url: "https://infyartifactory.jfrog.io/artifactory/api/pub/pub.dev-remote/" + url: "https://pub.dev" source: hosted version: "2.5.0" async: @@ -46,31 +38,31 @@ packages: description: name: async sha256: "947bfcf187f74dbc5e146c9eb9c0f10c9f8b30743e341481c1e2ed3ecc18c20c" - url: "https://infyartifactory.jfrog.io/artifactory/api/pub/pub.dev-remote/" + url: "https://pub.dev" source: hosted version: "2.11.0" barcode: dependency: transitive description: name: barcode - sha256: ab180ce22c6555d77d45f0178a523669db67f95856e3378259ef2ffeb43e6003 - url: "https://infyartifactory.jfrog.io/artifactory/api/pub/pub.dev-remote/" + sha256: "7b6729c37e3b7f34233e2318d866e8c48ddb46c1f7ad01ff7bb2a8de1da2b9f4" + url: "https://pub.dev" source: hosted - version: "2.2.8" + version: "2.2.9" bidi: dependency: transitive description: name: bidi - sha256: "1a7d0c696324b2089f72e7671fd1f1f64fef44c980f3cebc84e803967c597b63" - url: "https://infyartifactory.jfrog.io/artifactory/api/pub/pub.dev-remote/" + sha256: "77f475165e94b261745cf1032c751e2032b8ed92ccb2bf5716036db79320637d" + url: "https://pub.dev" source: hosted - version: "2.0.10" + version: "2.0.13" boolean_selector: dependency: transitive description: name: boolean_selector sha256: "6cfb5af12253eaf2b368f07bacc5a80d1301a071c73360d746b7f2e32d762c66" - url: "https://infyartifactory.jfrog.io/artifactory/api/pub/pub.dev-remote/" + url: "https://pub.dev" source: hosted version: "2.1.1" build: @@ -78,7 +70,7 @@ packages: description: name: build sha256: "80184af8b6cb3e5c1c4ec6d8544d27711700bc3e6d2efad04238c7b5290889f0" - url: "https://infyartifactory.jfrog.io/artifactory/api/pub/pub.dev-remote/" + url: "https://pub.dev" source: hosted version: "2.4.1" build_config: @@ -86,63 +78,63 @@ packages: description: name: build_config sha256: bf80fcfb46a29945b423bd9aad884590fb1dc69b330a4d4700cac476af1708d1 - url: "https://infyartifactory.jfrog.io/artifactory/api/pub/pub.dev-remote/" + url: "https://pub.dev" source: hosted version: "1.1.1" build_daemon: dependency: transitive description: name: build_daemon - sha256: "79b2aef6ac2ed00046867ed354c88778c9c0f029df8a20fe10b5436826721ef9" - url: "https://infyartifactory.jfrog.io/artifactory/api/pub/pub.dev-remote/" + sha256: "0343061a33da9c5810b2d6cee51945127d8f4c060b7fbdd9d54917f0a3feaaa1" + url: "https://pub.dev" source: hosted - version: "4.0.2" + version: "4.0.1" build_resolvers: dependency: transitive description: name: build_resolvers sha256: "339086358431fa15d7eca8b6a36e5d783728cf025e559b834f4609a1fcfb7b0a" - url: "https://infyartifactory.jfrog.io/artifactory/api/pub/pub.dev-remote/" + url: "https://pub.dev" source: hosted version: "2.4.2" build_runner: dependency: "direct dev" description: name: build_runner - sha256: "644dc98a0f179b872f612d3eb627924b578897c629788e858157fa5e704ca0c7" - url: "https://infyartifactory.jfrog.io/artifactory/api/pub/pub.dev-remote/" + sha256: "3ac61a79bfb6f6cc11f693591063a7f19a7af628dc52f141743edac5c16e8c22" + url: "https://pub.dev" source: hosted - version: "2.4.11" + version: "2.4.9" build_runner_core: dependency: transitive description: name: build_runner_core - sha256: e3c79f69a64bdfcd8a776a3c28db4eb6e3fb5356d013ae5eb2e52007706d5dbe - url: "https://infyartifactory.jfrog.io/artifactory/api/pub/pub.dev-remote/" + sha256: "4ae8ffe5ac758da294ecf1802f2aff01558d8b1b00616aa7538ea9a8a5d50799" + url: "https://pub.dev" source: hosted - version: "7.3.1" + version: "7.3.0" built_collection: dependency: transitive description: name: built_collection sha256: "376e3dd27b51ea877c28d525560790aee2e6fbb5f20e2f85d5081027d94e2100" - url: "https://infyartifactory.jfrog.io/artifactory/api/pub/pub.dev-remote/" + url: "https://pub.dev" source: hosted version: "5.1.1" built_value: dependency: transitive description: name: built_value - sha256: c7913a9737ee4007efedaffc968c049fd0f3d0e49109e778edc10de9426005cb - url: "https://infyartifactory.jfrog.io/artifactory/api/pub/pub.dev-remote/" + sha256: ba95c961bafcd8686d1cf63be864eb59447e795e124d98d6a27d91fcd13602fb + url: "https://pub.dev" source: hosted - version: "8.9.2" + version: "8.11.1" characters: dependency: transitive description: name: characters sha256: "04a925763edad70e8443c99234dc3328f442e811f1d8fd1a72f1c8ad0f69a605" - url: "https://infyartifactory.jfrog.io/artifactory/api/pub/pub.dev-remote/" + url: "https://pub.dev" source: hosted version: "1.3.0" checked_yaml: @@ -150,7 +142,7 @@ packages: description: name: checked_yaml sha256: feb6bed21949061731a7a75fc5d2aa727cf160b91af9a3e464c5e3a32e28b5ff - url: "https://infyartifactory.jfrog.io/artifactory/api/pub/pub.dev-remote/" + url: "https://pub.dev" source: hosted version: "2.0.3" cli_util: @@ -158,7 +150,7 @@ packages: description: name: cli_util sha256: c05b7406fdabc7a49a3929d4af76bcaccbbffcbcdcf185b082e1ae07da323d19 - url: "https://infyartifactory.jfrog.io/artifactory/api/pub/pub.dev-remote/" + url: "https://pub.dev" source: hosted version: "0.4.1" clock: @@ -166,7 +158,7 @@ packages: description: name: clock sha256: cb6d7f03e1de671e34607e909a7213e31d7752be4fb66a86d29fe1eb14bfb5cf - url: "https://infyartifactory.jfrog.io/artifactory/api/pub/pub.dev-remote/" + url: "https://pub.dev" source: hosted version: "1.1.1" code_builder: @@ -174,23 +166,23 @@ packages: description: name: code_builder sha256: f692079e25e7869c14132d39f223f8eec9830eb76131925143b2129c4bb01b37 - url: "https://infyartifactory.jfrog.io/artifactory/api/pub/pub.dev-remote/" + url: "https://pub.dev" source: hosted version: "4.10.0" collection: dependency: transitive description: name: collection - sha256: ee67cb0715911d28db6bf4af1026078bd6f0128b07a5f66fb2ed94ec6783c09a - url: "https://infyartifactory.jfrog.io/artifactory/api/pub/pub.dev-remote/" + sha256: "4a07be6cb69c84d677a6c3096fcf960cc3285a8330b4603e0d463d15d9bd934c" + url: "https://pub.dev" source: hosted - version: "1.18.0" + version: "1.17.1" colorful_progress_indicators: dependency: "direct main" description: name: colorful_progress_indicators sha256: "5a37014775368b37ebfcd9a47e758785438b2bd7ccbf3d6ec8066cb37207d87f" - url: "https://infyartifactory.jfrog.io/artifactory/api/pub/pub.dev-remote/" + url: "https://pub.dev" source: hosted version: "1.0.2" connectivity_plus: @@ -198,7 +190,7 @@ packages: description: name: connectivity_plus sha256: "77a180d6938f78ca7d2382d2240eb626c0f6a735d0bfdce227d8ffb80f95c48b" - url: "https://infyartifactory.jfrog.io/artifactory/api/pub/pub.dev-remote/" + url: "https://pub.dev" source: hosted version: "4.0.2" connectivity_plus_platform_interface: @@ -206,7 +198,7 @@ packages: description: name: connectivity_plus_platform_interface sha256: cf1d1c28f4416f8c654d7dc3cd638ec586076255d407cef3ddbdaf178272a71a - url: "https://infyartifactory.jfrog.io/artifactory/api/pub/pub.dev-remote/" + url: "https://pub.dev" source: hosted version: "1.2.4" convert: @@ -214,23 +206,23 @@ packages: description: name: convert sha256: "0f08b14755d163f6e2134cb58222dd25ea2a2ee8a195e53983d57c075324d592" - url: "https://infyartifactory.jfrog.io/artifactory/api/pub/pub.dev-remote/" + url: "https://pub.dev" source: hosted version: "3.1.1" cross_file: dependency: transitive description: name: cross_file - sha256: "7caf6a750a0c04effbb52a676dce9a4a592e10ad35c34d6d2d0e4811160d5670" - url: "https://infyartifactory.jfrog.io/artifactory/api/pub/pub.dev-remote/" + sha256: "2f9d2cbccb76127ba28528cb3ae2c2326a122446a83de5a056aaa3880d3882c5" + url: "https://pub.dev" source: hosted - version: "0.3.4+2" + version: "0.3.3+7" crypto: dependency: transitive description: name: crypto sha256: ff625774173754681d66daaf4a448684fb04b78f902da9cb3d308c19cc5e8bab - url: "https://infyartifactory.jfrog.io/artifactory/api/pub/pub.dev-remote/" + url: "https://pub.dev" source: hosted version: "3.0.3" csslib: @@ -238,39 +230,39 @@ packages: description: name: csslib sha256: "831883fb353c8bdc1d71979e5b342c7d88acfbc643113c14ae51e2442ea0f20f" - url: "https://infyartifactory.jfrog.io/artifactory/api/pub/pub.dev-remote/" + url: "https://pub.dev" source: hosted version: "0.17.3" cupertino_icons: dependency: "direct main" description: name: cupertino_icons - sha256: ba631d1c7f7bef6b729a622b7b752645a2d076dba9976925b8f25725a30e1ee6 - url: "https://infyartifactory.jfrog.io/artifactory/api/pub/pub.dev-remote/" + sha256: d57953e10f9f8327ce64a508a355f0b1ec902193f66288e8cb5070e7c47eeb2d + url: "https://pub.dev" source: hosted - version: "1.0.8" + version: "1.0.6" dart_style: dependency: transitive description: name: dart_style sha256: "1efa911ca7086affd35f463ca2fc1799584fb6aa89883cf0af8e3664d6a02d55" - url: "https://infyartifactory.jfrog.io/artifactory/api/pub/pub.dev-remote/" + url: "https://pub.dev" source: hosted version: "2.3.2" dbus: dependency: transitive description: name: dbus - sha256: "365c771ac3b0e58845f39ec6deebc76e3276aa9922b0cc60840712094d9047ac" - url: "https://infyartifactory.jfrog.io/artifactory/api/pub/pub.dev-remote/" + sha256: "79e0c23480ff85dc68de79e2cd6334add97e48f7f4865d17686dd6ea81a47e8c" + url: "https://pub.dev" source: hosted - version: "0.7.10" + version: "0.7.11" document_scanner: dependency: "direct main" description: name: document_scanner sha256: "6e0663f86cf7182a98d9a98f2dd8de82eeb3685dfa19282e5d3e1802f6b8b6e5" - url: "https://infyartifactory.jfrog.io/artifactory/api/pub/pub.dev-remote/" + url: "https://pub.dev" source: hosted version: "0.2.1" dotted_border: @@ -278,7 +270,7 @@ packages: description: name: dotted_border sha256: "108837e11848ca776c53b30bc870086f84b62ed6e01c503ed976e8f8c7df9c04" - url: "https://infyartifactory.jfrog.io/artifactory/api/pub/pub.dev-remote/" + url: "https://pub.dev" source: hosted version: "2.1.0" dropdown_button2: @@ -286,7 +278,7 @@ packages: description: name: dropdown_button2 sha256: b0fe8d49a030315e9eef6c7ac84ca964250155a6224d491c1365061bc974a9e1 - url: "https://infyartifactory.jfrog.io/artifactory/api/pub/pub.dev-remote/" + url: "https://pub.dev" source: hosted version: "2.3.9" fake_async: @@ -294,39 +286,39 @@ packages: description: name: fake_async sha256: "511392330127add0b769b75a987850d136345d9227c6b94c96a04cf4a391bf78" - url: "https://infyartifactory.jfrog.io/artifactory/api/pub/pub.dev-remote/" + url: "https://pub.dev" source: hosted version: "1.3.1" faker: dependency: "direct main" description: name: faker - sha256: "746e59f91d8b06a389e74cf76e909a05ed69c12691768e2f93557fdf29200fd0" - url: "https://infyartifactory.jfrog.io/artifactory/api/pub/pub.dev-remote/" + sha256: "544c34e9e1d322824156d5a8d451bc1bb778263b892aded24ec7ba77b0706624" + url: "https://pub.dev" source: hosted - version: "2.1.0" + version: "2.2.0" ffi: dependency: transitive description: name: ffi - sha256: "493f37e7df1804778ff3a53bd691d8692ddf69702cf4c1c1096a2e41b4779e21" - url: "https://infyartifactory.jfrog.io/artifactory/api/pub/pub.dev-remote/" + sha256: "7bf0adc28a23d395f19f3f1eb21dd7cfd1dd9f8e1c50051c069122e6853bc878" + url: "https://pub.dev" source: hosted - version: "2.1.2" + version: "2.1.0" file: dependency: transitive description: name: file - sha256: "5fc22d7c25582e38ad9a8515372cd9a93834027aacf1801cf01164dac0ffa08c" - url: "https://infyartifactory.jfrog.io/artifactory/api/pub/pub.dev-remote/" + sha256: "1b92bec4fc2a72f59a8e15af5f52cd441e4a7860b49499d69dfa817af20e925d" + url: "https://pub.dev" source: hosted - version: "7.0.0" + version: "6.1.4" file_picker: dependency: "direct main" description: name: file_picker sha256: be325344c1f3070354a1d84a231a1ba75ea85d413774ec4bdf444c023342e030 - url: "https://infyartifactory.jfrog.io/artifactory/api/pub/pub.dev-remote/" + url: "https://pub.dev" source: hosted version: "5.5.0" file_selector_linux: @@ -334,39 +326,39 @@ packages: description: name: file_selector_linux sha256: "045d372bf19b02aeb69cacf8b4009555fb5f6f0b7ad8016e5f46dd1387ddd492" - url: "https://infyartifactory.jfrog.io/artifactory/api/pub/pub.dev-remote/" + url: "https://pub.dev" source: hosted version: "0.9.2+1" file_selector_macos: dependency: transitive description: name: file_selector_macos - sha256: f42eacb83b318e183b1ae24eead1373ab1334084404c8c16e0354f9a3e55d385 - url: "https://infyartifactory.jfrog.io/artifactory/api/pub/pub.dev-remote/" + sha256: b15c3da8bd4908b9918111fa486903f5808e388b8d1c559949f584725a6594d6 + url: "https://pub.dev" source: hosted - version: "0.9.4" + version: "0.9.3+3" file_selector_platform_interface: dependency: transitive description: name: file_selector_platform_interface sha256: a3994c26f10378a039faa11de174d7b78eb8f79e4dd0af2a451410c1a5c3f66b - url: "https://infyartifactory.jfrog.io/artifactory/api/pub/pub.dev-remote/" + url: "https://pub.dev" source: hosted version: "2.6.2" file_selector_windows: dependency: transitive description: name: file_selector_windows - sha256: "2ad726953f6e8affbc4df8dc78b77c3b4a060967a291e528ef72ae846c60fb69" - url: "https://infyartifactory.jfrog.io/artifactory/api/pub/pub.dev-remote/" + sha256: d3547240c20cabf205c7c7f01a50ecdbc413755814d6677f3cb366f04abcead0 + url: "https://pub.dev" source: hosted - version: "0.9.3+2" + version: "0.9.3+1" fixnum: dependency: transitive description: name: fixnum sha256: "25517a4deb0c03aa0f32fd12db525856438902d9c16536311e76cdc57b31d7d1" - url: "https://infyartifactory.jfrog.io/artifactory/api/pub/pub.dev-remote/" + url: "https://pub.dev" source: hosted version: "1.1.0" flutter: @@ -379,7 +371,7 @@ packages: description: name: flutter_config sha256: a07e6156bb6e776e29c6357be433155acda87d1dab1a3f787a72091a1b71ffbf - url: "https://infyartifactory.jfrog.io/artifactory/api/pub/pub.dev-remote/" + url: "https://pub.dev" source: hosted version: "2.0.2" flutter_driver: @@ -392,7 +384,7 @@ packages: description: name: flutter_html sha256: "02ad69e813ecfc0728a455e4bf892b9379983e050722b1dce00192ee2e41d1ee" - url: "https://infyartifactory.jfrog.io/artifactory/api/pub/pub.dev-remote/" + url: "https://pub.dev" source: hosted version: "3.0.0-beta.2" flutter_launcher_icons: @@ -400,7 +392,7 @@ packages: description: name: flutter_launcher_icons sha256: "526faf84284b86a4cb36d20a5e45147747b7563d921373d4ee0559c54fcdbcea" - url: "https://infyartifactory.jfrog.io/artifactory/api/pub/pub.dev-remote/" + url: "https://pub.dev" source: hosted version: "0.13.1" flutter_lints: @@ -408,7 +400,7 @@ packages: description: name: flutter_lints sha256: a25a15ebbdfc33ab1cd26c63a6ee519df92338a9c10f122adda92938253bef04 - url: "https://infyartifactory.jfrog.io/artifactory/api/pub/pub.dev-remote/" + url: "https://pub.dev" source: hosted version: "2.0.3" flutter_localizations: @@ -420,48 +412,48 @@ packages: dependency: transitive description: name: flutter_plugin_android_lifecycle - sha256: "9d98bd47ef9d34e803d438f17fd32b116d31009f534a6fa5ce3a1167f189a6de" - url: "https://infyartifactory.jfrog.io/artifactory/api/pub/pub.dev-remote/" + sha256: b068ffc46f82a55844acfa4fdbb61fad72fa2aef0905548419d97f0f95c456da + url: "https://pub.dev" source: hosted - version: "2.0.21" + version: "2.0.17" flutter_screenutil: dependency: "direct main" description: name: flutter_screenutil sha256: "8239210dd68bee6b0577aa4a090890342d04a136ce1c81f98ee513fc0ce891de" - url: "https://infyartifactory.jfrog.io/artifactory/api/pub/pub.dev-remote/" + url: "https://pub.dev" source: hosted version: "5.9.3" flutter_secure_storage: dependency: "direct main" description: name: flutter_secure_storage - sha256: "165164745e6afb5c0e3e3fcc72a012fb9e58496fb26ffb92cf22e16a821e85d0" - url: "https://infyartifactory.jfrog.io/artifactory/api/pub/pub.dev-remote/" + sha256: "9cad52d75ebc511adfae3d447d5d13da15a55a92c9410e50f67335b6d21d16ea" + url: "https://pub.dev" source: hosted - version: "9.2.2" + version: "9.2.4" flutter_secure_storage_linux: dependency: transitive description: name: flutter_secure_storage_linux - sha256: "4d91bfc23047422cbcd73ac684bc169859ee766482517c22172c86596bf1464b" - url: "https://infyartifactory.jfrog.io/artifactory/api/pub/pub.dev-remote/" + sha256: be76c1d24a97d0b98f8b54bce6b481a380a6590df992d0098f868ad54dc8f688 + url: "https://pub.dev" source: hosted - version: "1.2.1" + version: "1.2.3" flutter_secure_storage_macos: dependency: transitive description: name: flutter_secure_storage_macos - sha256: "1693ab11121a5f925bbea0be725abfcfbbcf36c1e29e571f84a0c0f436147a81" - url: "https://infyartifactory.jfrog.io/artifactory/api/pub/pub.dev-remote/" + sha256: "6c0a2795a2d1de26ae202a0d78527d163f4acbb11cde4c75c670f3a0fc064247" + url: "https://pub.dev" source: hosted - version: "3.1.2" + version: "3.1.3" flutter_secure_storage_platform_interface: dependency: transitive description: name: flutter_secure_storage_platform_interface sha256: cf91ad32ce5adef6fba4d736a542baca9daf3beac4db2d04be350b87f69ac4a8 - url: "https://infyartifactory.jfrog.io/artifactory/api/pub/pub.dev-remote/" + url: "https://pub.dev" source: hosted version: "1.1.2" flutter_secure_storage_web: @@ -469,7 +461,7 @@ packages: description: name: flutter_secure_storage_web sha256: f4ebff989b4f07b2656fb16b47852c0aab9fed9b4ec1c70103368337bc1886a9 - url: "https://infyartifactory.jfrog.io/artifactory/api/pub/pub.dev-remote/" + url: "https://pub.dev" source: hosted version: "1.2.1" flutter_secure_storage_windows: @@ -477,7 +469,7 @@ packages: description: name: flutter_secure_storage_windows sha256: b20b07cb5ed4ed74fc567b78a72936203f587eba460af1df11281c9326cd3709 - url: "https://infyartifactory.jfrog.io/artifactory/api/pub/pub.dev-remote/" + url: "https://pub.dev" source: hosted version: "3.1.2" flutter_svg: @@ -485,7 +477,7 @@ packages: description: name: flutter_svg sha256: d39e7f95621fc84376bc0f7d504f05c3a41488c562f4a8ad410569127507402c - url: "https://infyartifactory.jfrog.io/artifactory/api/pub/pub.dev-remote/" + url: "https://pub.dev" source: hosted version: "2.0.9" flutter_test: @@ -503,7 +495,7 @@ packages: description: name: freezed sha256: a434911f643466d78462625df76fd9eb13e57348ff43fe1f77bbe909522c67a1 - url: "https://infyartifactory.jfrog.io/artifactory/api/pub/pub.dev-remote/" + url: "https://pub.dev" source: hosted version: "2.5.2" freezed_annotation: @@ -511,7 +503,7 @@ packages: description: name: freezed_annotation sha256: c2e2d632dd9b8a2b7751117abcfc2b4888ecfe181bd9fca7170d9ef02e595fe2 - url: "https://infyartifactory.jfrog.io/artifactory/api/pub/pub.dev-remote/" + url: "https://pub.dev" source: hosted version: "2.4.4" frontend_server_client: @@ -519,7 +511,7 @@ packages: description: name: frontend_server_client sha256: f64a0333a82f30b0cca061bc3d143813a486dc086b574bfb233b7c1372427694 - url: "https://infyartifactory.jfrog.io/artifactory/api/pub/pub.dev-remote/" + url: "https://pub.dev" source: hosted version: "4.0.0" fuchsia_remote_debug_protocol: @@ -532,23 +524,23 @@ packages: description: name: glob sha256: "0e7014b3b7d4dac1ca4d6114f82bf1782ee86745b9b42a92c9289c23d8a0ab63" - url: "https://infyartifactory.jfrog.io/artifactory/api/pub/pub.dev-remote/" + url: "https://pub.dev" source: hosted version: "2.1.2" graphs: dependency: transitive description: name: graphs - sha256: "741bbf84165310a68ff28fe9e727332eef1407342fca52759cb21ad8177bb8d0" - url: "https://infyartifactory.jfrog.io/artifactory/api/pub/pub.dev-remote/" + sha256: aedc5a15e78fc65a6e23bcd927f24c64dd995062bcd1ca6eda65a3cff92a4d19 + url: "https://pub.dev" source: hosted - version: "2.3.2" + version: "2.3.1" html: dependency: transitive description: name: html sha256: "3a7812d5bcd2894edf53dfaf8cd640876cf6cef50a8f238745c8b8120ea74d3a" - url: "https://infyartifactory.jfrog.io/artifactory/api/pub/pub.dev-remote/" + url: "https://pub.dev" source: hosted version: "0.15.4" http: @@ -556,7 +548,7 @@ packages: description: name: http sha256: "5895291c13fa8a3bd82e76d5627f69e0d85ca6a30dcac95c4ea19a5d555879c2" - url: "https://infyartifactory.jfrog.io/artifactory/api/pub/pub.dev-remote/" + url: "https://pub.dev" source: hosted version: "0.13.6" http_multi_server: @@ -564,7 +556,7 @@ packages: description: name: http_multi_server sha256: "97486f20f9c2f7be8f514851703d0119c3596d14ea63227af6f7a481ef2b2f8b" - url: "https://infyartifactory.jfrog.io/artifactory/api/pub/pub.dev-remote/" + url: "https://pub.dev" source: hosted version: "3.2.1" http_parser: @@ -572,79 +564,55 @@ packages: description: name: http_parser sha256: "2aa08ce0341cc9b354a498388e30986515406668dbcc4f7c950c3e715496693b" - url: "https://infyartifactory.jfrog.io/artifactory/api/pub/pub.dev-remote/" + url: "https://pub.dev" source: hosted version: "4.0.2" image: dependency: transitive description: name: image - sha256: "2237616a36c0d69aef7549ab439b833fb7f9fb9fc861af2cc9ac3eedddd69ca8" - url: "https://infyartifactory.jfrog.io/artifactory/api/pub/pub.dev-remote/" - source: hosted - version: "4.2.0" - image_cropper: - dependency: "direct main" - description: - name: image_cropper - sha256: "710ab4b7953e9ce1d27d833f741e5f8f3afb0b0ba3556dc0b844741b5f55c2b3" - url: "https://infyartifactory.jfrog.io/artifactory/api/pub/pub.dev-remote/" - source: hosted - version: "3.0.3" - image_cropper_for_web: - dependency: transitive - description: - name: image_cropper_for_web - sha256: "09e93a8ec0435adcaa23622ac090442872f18145d70b9ff605ffedcf97d56255" - url: "https://infyartifactory.jfrog.io/artifactory/api/pub/pub.dev-remote/" - source: hosted - version: "1.0.3" - image_cropper_platform_interface: - dependency: transitive - description: - name: image_cropper_platform_interface - sha256: "62349e3aab63873ea9b9ab9f69d036ab8a0d74b3004beec4303981386cb9273f" - url: "https://infyartifactory.jfrog.io/artifactory/api/pub/pub.dev-remote/" + sha256: "4e973fcf4caae1a4be2fa0a13157aa38a8f9cb049db6529aa00b4d71abc4d928" + url: "https://pub.dev" source: hosted - version: "3.0.3" + version: "4.5.4" image_picker: dependency: "direct main" description: name: image_picker sha256: b6951e25b795d053a6ba03af5f710069c99349de9341af95155d52665cb4607c - url: "https://infyartifactory.jfrog.io/artifactory/api/pub/pub.dev-remote/" + url: "https://pub.dev" source: hosted version: "0.8.9" image_picker_android: dependency: transitive description: name: image_picker_android - sha256: c0e72ecd170b00a5590bb71238d57dc8ad22ee14c60c6b0d1a4e05cafbc5db4b - url: "https://infyartifactory.jfrog.io/artifactory/api/pub/pub.dev-remote/" + sha256: "39f2bfe497e495450c81abcd44b62f56c2a36a37a175da7d137b4454977b51b1" + url: "https://pub.dev" source: hosted - version: "0.8.12+11" + version: "0.8.9+3" image_picker_for_web: dependency: transitive description: name: image_picker_for_web sha256: "869fe8a64771b7afbc99fc433a5f7be2fea4d1cb3d7c11a48b6b579eb9c797f0" - url: "https://infyartifactory.jfrog.io/artifactory/api/pub/pub.dev-remote/" + url: "https://pub.dev" source: hosted version: "2.2.0" image_picker_ios: dependency: transitive description: name: image_picker_ios - sha256: "6703696ad49f5c3c8356d576d7ace84d1faf459afb07accbb0fae780753ff447" - url: "https://infyartifactory.jfrog.io/artifactory/api/pub/pub.dev-remote/" + sha256: fadafce49e8569257a0cad56d24438a6fa1f0cbd7ee0af9b631f7492818a4ca3 + url: "https://pub.dev" source: hosted - version: "0.8.12" + version: "0.8.9+1" image_picker_linux: dependency: transitive description: name: image_picker_linux sha256: "4ed1d9bb36f7cd60aa6e6cd479779cc56a4cb4e4de8f49d487b1aaad831300fa" - url: "https://infyartifactory.jfrog.io/artifactory/api/pub/pub.dev-remote/" + url: "https://pub.dev" source: hosted version: "0.2.1+1" image_picker_macos: @@ -652,39 +620,39 @@ packages: description: name: image_picker_macos sha256: "3f5ad1e8112a9a6111c46d0b57a7be2286a9a07fc6e1976fdf5be2bd31d4ff62" - url: "https://infyartifactory.jfrog.io/artifactory/api/pub/pub.dev-remote/" + url: "https://pub.dev" source: hosted version: "0.2.1+1" image_picker_platform_interface: dependency: transitive description: name: image_picker_platform_interface - sha256: "9ec26d410ff46f483c5519c29c02ef0e02e13a543f882b152d4bfd2f06802f80" - url: "https://infyartifactory.jfrog.io/artifactory/api/pub/pub.dev-remote/" + sha256: fa4e815e6fcada50e35718727d83ba1c92f1edf95c0b4436554cec301b56233b + url: "https://pub.dev" source: hosted - version: "2.10.0" + version: "2.9.3" image_picker_windows: dependency: transitive description: name: image_picker_windows sha256: "6ad07afc4eb1bc25f3a01084d28520496c4a3bb0cb13685435838167c9dcedeb" - url: "https://infyartifactory.jfrog.io/artifactory/api/pub/pub.dev-remote/" + url: "https://pub.dev" source: hosted version: "0.2.1+1" intl: dependency: "direct main" description: name: intl - sha256: d6f56758b7d3014a48af9701c085700aac781a92a87a62b1333b46d8879661cf - url: "https://infyartifactory.jfrog.io/artifactory/api/pub/pub.dev-remote/" + sha256: a3715e3bc90294e971cb7dc063fbf3cd9ee0ebf8604ffeafabd9e6f16abbdbe6 + url: "https://pub.dev" source: hosted - version: "0.19.0" + version: "0.18.0" io: dependency: transitive description: name: io sha256: "2ec25704aba361659e10e3e5f5d672068d332fc8ac516421d483a11e5cbd061e" - url: "https://infyartifactory.jfrog.io/artifactory/api/pub/pub.dev-remote/" + url: "https://pub.dev" source: hosted version: "1.0.4" js: @@ -692,7 +660,7 @@ packages: description: name: js sha256: f2c445dce49627136094980615a031419f7f3eb393237e4ecd97ac15dea343f3 - url: "https://infyartifactory.jfrog.io/artifactory/api/pub/pub.dev-remote/" + url: "https://pub.dev" source: hosted version: "0.6.7" json_annotation: @@ -700,7 +668,7 @@ packages: description: name: json_annotation sha256: "1ce844379ca14835a50d2f019a3099f419082cfdd231cd86a142af94dd5c6bb1" - url: "https://infyartifactory.jfrog.io/artifactory/api/pub/pub.dev-remote/" + url: "https://pub.dev" source: hosted version: "4.9.0" json_serializable: @@ -708,39 +676,15 @@ packages: description: name: json_serializable sha256: ea1432d167339ea9b5bb153f0571d0039607a873d6e04e0117af043f14a1fd4b - url: "https://infyartifactory.jfrog.io/artifactory/api/pub/pub.dev-remote/" + url: "https://pub.dev" source: hosted version: "6.8.0" - leak_tracker: - dependency: transitive - description: - name: leak_tracker - sha256: "7f0df31977cb2c0b88585095d168e689669a2cc9b97c309665e3386f3e9d341a" - url: "https://infyartifactory.jfrog.io/artifactory/api/pub/pub.dev-remote/" - source: hosted - version: "10.0.4" - leak_tracker_flutter_testing: - dependency: transitive - description: - name: leak_tracker_flutter_testing - sha256: "06e98f569d004c1315b991ded39924b21af84cf14cc94791b8aea337d25b57f8" - url: "https://infyartifactory.jfrog.io/artifactory/api/pub/pub.dev-remote/" - source: hosted - version: "3.0.3" - leak_tracker_testing: - dependency: transitive - description: - name: leak_tracker_testing - sha256: "6ba465d5d76e67ddf503e1161d1f4a6bc42306f9d66ca1e8f079a47290fb06d3" - url: "https://infyartifactory.jfrog.io/artifactory/api/pub/pub.dev-remote/" - source: hosted - version: "3.0.1" lints: dependency: transitive description: name: lints sha256: "0a217c6c989d21039f1498c3ed9f3ed71b354e69873f13a8dfc3c9fe76f1b452" - url: "https://infyartifactory.jfrog.io/artifactory/api/pub/pub.dev-remote/" + url: "https://pub.dev" source: hosted version: "2.1.1" list_counter: @@ -748,7 +692,7 @@ packages: description: name: list_counter sha256: c447ae3dfcd1c55f0152867090e67e219d42fe6d4f2807db4bbe8b8d69912237 - url: "https://infyartifactory.jfrog.io/artifactory/api/pub/pub.dev-remote/" + url: "https://pub.dev" source: hosted version: "1.0.2" logging: @@ -756,71 +700,71 @@ packages: description: name: logging sha256: "623a88c9594aa774443aa3eb2d41807a48486b5613e67599fb4c41c0ad47c340" - url: "https://infyartifactory.jfrog.io/artifactory/api/pub/pub.dev-remote/" + url: "https://pub.dev" source: hosted version: "1.2.0" matcher: dependency: transitive description: name: matcher - sha256: d2323aa2060500f906aa31a895b4030b6da3ebdcc5619d14ce1aada65cd161cb - url: "https://infyartifactory.jfrog.io/artifactory/api/pub/pub.dev-remote/" + sha256: "6501fbd55da300384b768785b83e5ce66991266cec21af89ab9ae7f5ce1c4cbb" + url: "https://pub.dev" source: hosted - version: "0.12.16+1" + version: "0.12.15" material_color_utilities: dependency: transitive description: name: material_color_utilities - sha256: "0e0a020085b65b6083975e499759762399b4475f766c21668c4ecca34ea74e5a" - url: "https://infyartifactory.jfrog.io/artifactory/api/pub/pub.dev-remote/" + sha256: d92141dc6fe1dad30722f9aa826c7fbc896d021d792f80678280601aff8cf724 + url: "https://pub.dev" source: hosted - version: "0.8.0" + version: "0.2.0" meta: dependency: transitive description: name: meta - sha256: "7687075e408b093f36e6bbf6c91878cc0d4cd10f409506f7bc996f68220b9136" - url: "https://infyartifactory.jfrog.io/artifactory/api/pub/pub.dev-remote/" + sha256: "3c74dbf8763d36539f114c799d8a2d87343b5067e9d796ca22b5eb8437090ee3" + url: "https://pub.dev" source: hosted - version: "1.12.0" + version: "1.9.1" mime: dependency: transitive description: name: mime - sha256: "2e123074287cc9fd6c09de8336dae606d1ddb88d9ac47358826db698c176a1f2" - url: "https://infyartifactory.jfrog.io/artifactory/api/pub/pub.dev-remote/" + sha256: e4ff8e8564c03f255408decd16e7899da1733852a9110a58fe6d1b817684a63e + url: "https://pub.dev" source: hosted - version: "1.0.5" + version: "1.0.4" mockito: dependency: "direct main" description: name: mockito - sha256: "6841eed20a7befac0ce07df8116c8b8233ed1f4486a7647c7fc5a02ae6163917" - url: "https://infyartifactory.jfrog.io/artifactory/api/pub/pub.dev-remote/" + sha256: "7d5b53bcd556c1bc7ffbe4e4d5a19c3e112b7e925e9e172dd7c6ad0630812616" + url: "https://pub.dev" source: hosted - version: "5.4.4" + version: "5.4.2" native_image_cropper: dependency: "direct main" description: name: native_image_cropper - sha256: "50b7b53d2757ee0b898d3d46a9a1ffa6cf5406641a9d3904be386e1ec6fda75f" - url: "https://infyartifactory.jfrog.io/artifactory/api/pub/pub.dev-remote/" + sha256: d9cb7c7e5904e5dc28c37ebf0d68d2fed2d46b161960e7770c078e98c80e66b0 + url: "https://pub.dev" source: hosted - version: "0.4.0" + version: "0.6.0" native_image_cropper_android: dependency: transitive description: name: native_image_cropper_android - sha256: "27ef9de059d195398795f862c2dd594c1a77a13168f7a97b9cbf70fe2e7e4677" - url: "https://infyartifactory.jfrog.io/artifactory/api/pub/pub.dev-remote/" + sha256: "77106960beee19fd080dc8bd609709da44e13824175cd6c1d330a8b7178a152e" + url: "https://pub.dev" source: hosted - version: "0.2.0" + version: "0.3.1" native_image_cropper_ios: dependency: transitive description: name: native_image_cropper_ios sha256: "4c40ffc8ea1e52078384bba6adfae8a90bef064ebbb25a0d52211b828b3895aa" - url: "https://infyartifactory.jfrog.io/artifactory/api/pub/pub.dev-remote/" + url: "https://pub.dev" source: hosted version: "0.2.0" native_image_cropper_macos: @@ -828,7 +772,7 @@ packages: description: name: native_image_cropper_macos sha256: f3815264a7755047f0b38413c69f5b76ed4ffdd7af28edeacfc134b08b1d5a74 - url: "https://infyartifactory.jfrog.io/artifactory/api/pub/pub.dev-remote/" + url: "https://pub.dev" source: hosted version: "0.2.0" native_image_cropper_platform_interface: @@ -836,7 +780,7 @@ packages: description: name: native_image_cropper_platform_interface sha256: "3ac1484f83abd62be7ff1d74c475137c59008aa01e671d8678d5e25c46c98d59" - url: "https://infyartifactory.jfrog.io/artifactory/api/pub/pub.dev-remote/" + url: "https://pub.dev" source: hosted version: "0.2.0" native_image_cropper_web: @@ -844,7 +788,7 @@ packages: description: name: native_image_cropper_web sha256: "4767ca067ff2b5d1d3dd02c14eb00124da5d203ff917c9528b35f294bcf9227e" - url: "https://infyartifactory.jfrog.io/artifactory/api/pub/pub.dev-remote/" + url: "https://pub.dev" source: hosted version: "0.2.0" nested: @@ -852,7 +796,7 @@ packages: description: name: nested sha256: "03bac4c528c64c95c722ec99280375a6f2fc708eec17c7b3f07253b626cd2a20" - url: "https://infyartifactory.jfrog.io/artifactory/api/pub/pub.dev-remote/" + url: "https://pub.dev" source: hosted version: "1.0.0" nm: @@ -860,7 +804,7 @@ packages: description: name: nm sha256: "2c9aae4127bdc8993206464fcc063611e0e36e72018696cd9631023a31b24254" - url: "https://infyartifactory.jfrog.io/artifactory/api/pub/pub.dev-remote/" + url: "https://pub.dev" source: hosted version: "0.5.0" package_config: @@ -868,23 +812,23 @@ packages: description: name: package_config sha256: "1c5b77ccc91e4823a5af61ee74e6b972db1ef98c2ff5a18d3161c982a55448bd" - url: "https://infyartifactory.jfrog.io/artifactory/api/pub/pub.dev-remote/" + url: "https://pub.dev" source: hosted version: "2.1.0" path: dependency: transitive description: name: path - sha256: "087ce49c3f0dc39180befefc60fdb4acd8f8620e5682fe2476afd0b3688bb4af" - url: "https://infyartifactory.jfrog.io/artifactory/api/pub/pub.dev-remote/" + sha256: "8829d8a55c13fc0e37127c29fedf290c102f4e40ae94ada574091fe0ff96c917" + url: "https://pub.dev" source: hosted - version: "1.9.0" + version: "1.8.3" path_drawing: dependency: transitive description: name: path_drawing sha256: bbb1934c0cbb03091af082a6389ca2080345291ef07a5fa6d6e078ba8682f977 - url: "https://infyartifactory.jfrog.io/artifactory/api/pub/pub.dev-remote/" + url: "https://pub.dev" source: hosted version: "1.0.1" path_parsing: @@ -892,39 +836,39 @@ packages: description: name: path_parsing sha256: e3e67b1629e6f7e8100b367d3db6ba6af4b1f0bb80f64db18ef1fbabd2fa9ccf - url: "https://infyartifactory.jfrog.io/artifactory/api/pub/pub.dev-remote/" + url: "https://pub.dev" source: hosted version: "1.0.1" path_provider: dependency: "direct main" description: name: path_provider - sha256: fec0d61223fba3154d87759e3cc27fe2c8dc498f6386c6d6fc80d1afdd1bf378 - url: "https://infyartifactory.jfrog.io/artifactory/api/pub/pub.dev-remote/" + sha256: b27217933eeeba8ff24845c34003b003b2b22151de3c908d0e679e8fe1aa078b + url: "https://pub.dev" source: hosted - version: "2.1.4" + version: "2.1.2" path_provider_android: dependency: transitive description: name: path_provider_android - sha256: "490539678396d4c3c0b06efdaab75ae60675c3e0c66f72bc04c2e2c1e0e2abeb" - url: "https://infyartifactory.jfrog.io/artifactory/api/pub/pub.dev-remote/" + sha256: "477184d672607c0a3bf68fbbf601805f92ef79c82b64b4d6eb318cbca4c48668" + url: "https://pub.dev" source: hosted - version: "2.2.9" + version: "2.2.2" path_provider_foundation: dependency: transitive description: name: path_provider_foundation - sha256: f234384a3fdd67f989b4d54a5d73ca2a6c422fa55ae694381ae0f4375cd1ea16 - url: "https://infyartifactory.jfrog.io/artifactory/api/pub/pub.dev-remote/" + sha256: "5a7999be66e000916500be4f15a3633ebceb8302719b47b9cc49ce924125350f" + url: "https://pub.dev" source: hosted - version: "2.4.0" + version: "2.3.2" path_provider_linux: dependency: transitive description: name: path_provider_linux sha256: f7a1fe3a634fe7734c8d3f2766ad746ae2a2884abe22e241a8b301bf5cac3279 - url: "https://infyartifactory.jfrog.io/artifactory/api/pub/pub.dev-remote/" + url: "https://pub.dev" source: hosted version: "2.2.1" path_provider_platform_interface: @@ -932,47 +876,47 @@ packages: description: name: path_provider_platform_interface sha256: "88f5779f72ba699763fa3a3b06aa4bf6de76c8e5de842cf6f29e2e06476c2334" - url: "https://infyartifactory.jfrog.io/artifactory/api/pub/pub.dev-remote/" + url: "https://pub.dev" source: hosted version: "2.1.2" path_provider_windows: dependency: transitive description: name: path_provider_windows - sha256: bd6f00dbd873bfb70d0761682da2b3a2c2fccc2b9e84c495821639601d81afe7 - url: "https://infyartifactory.jfrog.io/artifactory/api/pub/pub.dev-remote/" + sha256: "8bc9f22eee8690981c22aa7fc602f5c85b497a6fb2ceb35ee5a5e5ed85ad8170" + url: "https://pub.dev" source: hosted - version: "2.3.0" + version: "2.2.1" pdf: dependency: transitive description: name: pdf - sha256: "05df53f8791587402493ac97b9869d3824eccbc77d97855f4545cf72df3cae07" - url: "https://infyartifactory.jfrog.io/artifactory/api/pub/pub.dev-remote/" + sha256: "28eacad99bffcce2e05bba24e50153890ad0255294f4dd78a17075a2ba5c8416" + url: "https://pub.dev" source: hosted - version: "3.11.1" + version: "3.11.3" pdf_widget_wrapper: dependency: transitive description: name: pdf_widget_wrapper - sha256: c930860d987213a3d58c7ec3b7ecf8085c3897f773e8dc23da9cae60a5d6d0f5 - url: "https://infyartifactory.jfrog.io/artifactory/api/pub/pub.dev-remote/" + sha256: e9d31fd7782ce28ae346b127ea7d1cd748d799bddee379f31191693610e23749 + url: "https://pub.dev" source: hosted - version: "1.0.4" + version: "1.0.1" percent_indicator: dependency: "direct main" description: name: percent_indicator - sha256: c37099ad833a883c9d71782321cb65c3a848c21b6939b6185f0ff6640d05814c - url: "https://infyartifactory.jfrog.io/artifactory/api/pub/pub.dev-remote/" + sha256: "157d29133bbc6ecb11f923d36e7960a96a3f28837549a20b65e5135729f0f9fd" + url: "https://pub.dev" source: hosted - version: "4.2.3" + version: "4.2.5" permission_handler: dependency: "direct main" description: name: permission_handler sha256: bc56bfe9d3f44c3c612d8d393bd9b174eb796d706759f9b495ac254e4294baa5 - url: "https://infyartifactory.jfrog.io/artifactory/api/pub/pub.dev-remote/" + url: "https://pub.dev" source: hosted version: "10.4.5" permission_handler_android: @@ -980,7 +924,7 @@ packages: description: name: permission_handler_android sha256: "59c6322171c29df93a22d150ad95f3aa19ed86542eaec409ab2691b8f35f9a47" - url: "https://infyartifactory.jfrog.io/artifactory/api/pub/pub.dev-remote/" + url: "https://pub.dev" source: hosted version: "10.3.6" permission_handler_apple: @@ -988,7 +932,7 @@ packages: description: name: permission_handler_apple sha256: "99e220bce3f8877c78e4ace901082fb29fa1b4ebde529ad0932d8d664b34f3f5" - url: "https://infyartifactory.jfrog.io/artifactory/api/pub/pub.dev-remote/" + url: "https://pub.dev" source: hosted version: "9.1.4" permission_handler_platform_interface: @@ -996,7 +940,7 @@ packages: description: name: permission_handler_platform_interface sha256: "6760eb5ef34589224771010805bea6054ad28453906936f843a8cc4d3a55c4a4" - url: "https://infyartifactory.jfrog.io/artifactory/api/pub/pub.dev-remote/" + url: "https://pub.dev" source: hosted version: "3.12.0" permission_handler_windows: @@ -1004,39 +948,39 @@ packages: description: name: permission_handler_windows sha256: cc074aace208760f1eee6aa4fae766b45d947df85bc831cde77009cdb4720098 - url: "https://infyartifactory.jfrog.io/artifactory/api/pub/pub.dev-remote/" + url: "https://pub.dev" source: hosted version: "0.1.3" petitparser: dependency: transitive description: name: petitparser - sha256: c15605cd28af66339f8eb6fbe0e541bfe2d1b72d5825efc6598f3e0a31b9ad27 - url: "https://infyartifactory.jfrog.io/artifactory/api/pub/pub.dev-remote/" + sha256: cb3798bef7fc021ac45b308f4b51208a152792445cce0448c9a4ba5879dd8750 + url: "https://pub.dev" source: hosted - version: "6.0.2" + version: "5.4.0" pigeon: dependency: "direct main" description: name: pigeon sha256: d1ab184e028cfecd957d4de34f705b4f84b98661e6a4be1d9cac9dade278b937 - url: "https://infyartifactory.jfrog.io/artifactory/api/pub/pub.dev-remote/" + url: "https://pub.dev" source: hosted version: "10.1.6" platform: dependency: transitive description: name: platform - sha256: "12220bb4b65720483f8fa9450b4332347737cf8213dd2840d8b2c823e47243ec" - url: "https://infyartifactory.jfrog.io/artifactory/api/pub/pub.dev-remote/" + sha256: "4a451831508d7d6ca779f7ac6e212b4023dd5a7d08a27a63da33756410e32b76" + url: "https://pub.dev" source: hosted - version: "3.1.4" + version: "3.1.0" plugin_platform_interface: dependency: transitive description: name: plugin_platform_interface sha256: "4820fbfdb9478b1ebae27888254d445073732dae3d6ea81f0b7e06d5dedc3f02" - url: "https://infyartifactory.jfrog.io/artifactory/api/pub/pub.dev-remote/" + url: "https://pub.dev" source: hosted version: "2.1.8" pool: @@ -1044,39 +988,47 @@ packages: description: name: pool sha256: "20fe868b6314b322ea036ba325e6fc0711a22948856475e2c2b6306e8ab39c2a" - url: "https://infyartifactory.jfrog.io/artifactory/api/pub/pub.dev-remote/" + url: "https://pub.dev" source: hosted version: "1.5.1" + posix: + dependency: transitive + description: + name: posix + sha256: "6323a5b0fa688b6a010df4905a56b00181479e6d10534cecfecede2aa55add61" + url: "https://pub.dev" + source: hosted + version: "6.0.3" printing: dependency: "direct main" description: name: printing - sha256: de1889f30b34029fc46e5de6a9841498850b23d32942a9ee810ca36b0cb1b234 - url: "https://infyartifactory.jfrog.io/artifactory/api/pub/pub.dev-remote/" + sha256: "1c99cab90ebcc1fff65831d264627d5b529359d563e53f33ab9b8117f2d280bc" + url: "https://pub.dev" source: hosted - version: "5.13.2" + version: "5.12.0" process: dependency: transitive description: name: process - sha256: "21e54fd2faf1b5bdd5102afd25012184a6793927648ea81eea80552ac9405b32" - url: "https://infyartifactory.jfrog.io/artifactory/api/pub/pub.dev-remote/" + sha256: "53fd8db9cec1d37b0574e12f07520d582019cb6c44abf5479a01505099a34a09" + url: "https://pub.dev" source: hosted - version: "5.0.2" + version: "4.2.4" provider: dependency: "direct main" description: name: provider - sha256: c8a055ee5ce3fd98d6fc872478b03823ffdb448699c6ebdbbc71d59b596fd48c - url: "https://infyartifactory.jfrog.io/artifactory/api/pub/pub.dev-remote/" + sha256: "4e82183fa20e5ca25703ead7e05de9e4cceed1fbd1eadc1ac3cb6f565a09f272" + url: "https://pub.dev" source: hosted - version: "6.1.2" + version: "6.1.5+1" pub_semver: dependency: transitive description: name: pub_semver sha256: "40d3ab1bbd474c4c2328c91e3a7df8c6dd629b79ece4c4bd04bee496a224fb0c" - url: "https://infyartifactory.jfrog.io/artifactory/api/pub/pub.dev-remote/" + url: "https://pub.dev" source: hosted version: "2.1.4" pubspec_parse: @@ -1084,113 +1036,113 @@ packages: description: name: pubspec_parse sha256: c799b721d79eb6ee6fa56f00c04b472dcd44a30d258fac2174a6ec57302678f8 - url: "https://infyartifactory.jfrog.io/artifactory/api/pub/pub.dev-remote/" + url: "https://pub.dev" source: hosted version: "1.3.0" qr: dependency: transitive description: name: qr - sha256: "5a1d2586170e172b8a8c8470bbbffd5eb0cd38a66c0d77155ea138d3af3a4445" - url: "https://infyartifactory.jfrog.io/artifactory/api/pub/pub.dev-remote/" + sha256: "64957a3930367bf97cc211a5af99551d630f2f4625e38af10edd6b19131b64b3" + url: "https://pub.dev" source: hosted - version: "3.0.2" + version: "3.0.1" qr_code_scanner: dependency: "direct main" description: name: qr_code_scanner sha256: f23b68d893505a424f0bd2e324ebea71ed88465d572d26bb8d2e78a4749591fd - url: "https://infyartifactory.jfrog.io/artifactory/api/pub/pub.dev-remote/" + url: "https://pub.dev" source: hosted version: "1.0.1" quiver: dependency: transitive description: name: quiver - sha256: b1c1ac5ce6688d77f65f3375a9abb9319b3cb32486bdc7a1e0fdf004d7ba4e47 - url: "https://infyartifactory.jfrog.io/artifactory/api/pub/pub.dev-remote/" + sha256: ea0b925899e64ecdfbf9c7becb60d5b50e706ade44a85b2363be2a22d88117d2 + url: "https://pub.dev" source: hosted - version: "3.2.1" + version: "3.2.2" responsive_grid_list: dependency: "direct main" description: name: responsive_grid_list sha256: e6cd1754240795cb8b08a4520c9eb5d28856ecf71de5fe6e64535a68c0913563 - url: "https://infyartifactory.jfrog.io/artifactory/api/pub/pub.dev-remote/" + url: "https://pub.dev" source: hosted version: "1.4.0" shared_preferences: dependency: "direct main" description: name: shared_preferences - sha256: c272f9cabca5a81adc9b0894381e9c1def363e980f960fa903c604c471b22f68 - url: "https://infyartifactory.jfrog.io/artifactory/api/pub/pub.dev-remote/" + sha256: "81429e4481e1ccfb51ede496e916348668fd0921627779233bd24cc3ff6abd02" + url: "https://pub.dev" source: hosted - version: "2.3.1" + version: "2.2.2" shared_preferences_android: dependency: transitive description: name: shared_preferences_android - sha256: "041be4d9d2dc6079cf342bc8b761b03787e3b71192d658220a56cac9c04a0294" - url: "https://infyartifactory.jfrog.io/artifactory/api/pub/pub.dev-remote/" + sha256: "8568a389334b6e83415b6aae55378e158fbc2314e074983362d20c562780fb06" + url: "https://pub.dev" source: hosted - version: "2.3.0" + version: "2.2.1" shared_preferences_foundation: dependency: transitive description: name: shared_preferences_foundation - sha256: "671e7a931f55a08aa45be2a13fe7247f2a41237897df434b30d2012388191833" - url: "https://infyartifactory.jfrog.io/artifactory/api/pub/pub.dev-remote/" + sha256: "7708d83064f38060c7b39db12aefe449cb8cdc031d6062280087bc4cdb988f5c" + url: "https://pub.dev" source: hosted - version: "2.5.0" + version: "2.3.5" shared_preferences_linux: dependency: transitive description: name: shared_preferences_linux - sha256: "2ba0510d3017f91655b7543e9ee46d48619de2a2af38e5c790423f7007c7ccc1" - url: "https://infyartifactory.jfrog.io/artifactory/api/pub/pub.dev-remote/" + sha256: "9f2cbcf46d4270ea8be39fa156d86379077c8a5228d9dfdb1164ae0bb93f1faa" + url: "https://pub.dev" source: hosted - version: "2.4.0" + version: "2.3.2" shared_preferences_platform_interface: dependency: transitive description: name: shared_preferences_platform_interface - sha256: "57cbf196c486bc2cf1f02b85784932c6094376284b3ad5779d1b1c6c6a816b80" - url: "https://infyartifactory.jfrog.io/artifactory/api/pub/pub.dev-remote/" + sha256: "22e2ecac9419b4246d7c22bfbbda589e3acf5c0351137d87dd2939d984d37c3b" + url: "https://pub.dev" source: hosted - version: "2.4.1" + version: "2.3.2" shared_preferences_web: dependency: transitive description: name: shared_preferences_web - sha256: "59dc807b94d29d52ddbb1b3c0d3b9d0a67fc535a64e62a5542c8db0513fcb6c2" - url: "https://infyartifactory.jfrog.io/artifactory/api/pub/pub.dev-remote/" + sha256: d762709c2bbe80626ecc819143013cc820fa49ca5e363620ee20a8b15a3e3daf + url: "https://pub.dev" source: hosted - version: "2.4.1" + version: "2.2.1" shared_preferences_windows: dependency: transitive description: name: shared_preferences_windows - sha256: "398084b47b7f92110683cac45c6dc4aae853db47e470e5ddcd52cab7f7196ab2" - url: "https://infyartifactory.jfrog.io/artifactory/api/pub/pub.dev-remote/" + sha256: "841ad54f3c8381c480d0c9b508b89a34036f512482c407e6df7a9c4aa2ef8f59" + url: "https://pub.dev" source: hosted - version: "2.4.0" + version: "2.3.2" shelf: dependency: transitive description: name: shelf sha256: ad29c505aee705f41a4d8963641f91ac4cee3c8fad5947e033390a7bd8180fa4 - url: "https://infyartifactory.jfrog.io/artifactory/api/pub/pub.dev-remote/" + url: "https://pub.dev" source: hosted version: "1.4.1" shelf_web_socket: dependency: transitive description: name: shelf_web_socket - sha256: "073c147238594ecd0d193f3456a5fe91c4b0abbcc68bf5cd95b36c4e194ac611" - url: "https://infyartifactory.jfrog.io/artifactory/api/pub/pub.dev-remote/" + sha256: "9ca081be41c60190ebcb4766b2486a7d50261db7bd0f5d9615f2d653637a84c1" + url: "https://pub.dev" source: hosted - version: "2.0.0" + version: "1.0.4" sky_engine: dependency: transitive description: flutter @@ -1201,7 +1153,7 @@ packages: description: name: source_gen sha256: "14658ba5f669685cd3d63701d01b31ea748310f7ab854e471962670abcf57832" - url: "https://infyartifactory.jfrog.io/artifactory/api/pub/pub.dev-remote/" + url: "https://pub.dev" source: hosted version: "1.5.0" source_helper: @@ -1209,39 +1161,39 @@ packages: description: name: source_helper sha256: "6adebc0006c37dd63fe05bca0a929b99f06402fc95aa35bf36d67f5c06de01fd" - url: "https://infyartifactory.jfrog.io/artifactory/api/pub/pub.dev-remote/" + url: "https://pub.dev" source: hosted version: "1.3.4" source_span: dependency: transitive description: name: source_span - sha256: "53e943d4206a5e30df338fd4c6e7a077e02254531b138a15aec3bd143c1a8b3c" - url: "https://infyartifactory.jfrog.io/artifactory/api/pub/pub.dev-remote/" + sha256: dd904f795d4b4f3b870833847c461801f6750a9fa8e61ea5ac53f9422b31f250 + url: "https://pub.dev" source: hosted - version: "1.10.0" + version: "1.9.1" stack_trace: dependency: transitive description: name: stack_trace - sha256: "73713990125a6d93122541237550ee3352a2d84baad52d375a4cad2eb9b7ce0b" - url: "https://infyartifactory.jfrog.io/artifactory/api/pub/pub.dev-remote/" + sha256: c3c7d8edb15bee7f0f74debd4b9c5f3c2ea86766fe4178eb2a18eb30a0bdaed5 + url: "https://pub.dev" source: hosted - version: "1.11.1" + version: "1.11.0" stream_channel: dependency: transitive description: name: stream_channel - sha256: ba2aa5d8cc609d96bbb2899c28934f9e1af5cddbd60a827822ea467161eb54e7 - url: "https://infyartifactory.jfrog.io/artifactory/api/pub/pub.dev-remote/" + sha256: "83615bee9045c1d322bbbd1ba209b7a749c2cbcdcb3fdd1df8eb488b3279c1c8" + url: "https://pub.dev" source: hosted - version: "2.1.2" + version: "2.1.1" stream_transform: dependency: transitive description: name: stream_transform sha256: "14a00e794c7c11aa145a170587321aedce29769c08d7f58b1d141da75e3b1c6f" - url: "https://infyartifactory.jfrog.io/artifactory/api/pub/pub.dev-remote/" + url: "https://pub.dev" source: hosted version: "2.1.0" string_scanner: @@ -1249,7 +1201,7 @@ packages: description: name: string_scanner sha256: "556692adab6cfa87322a115640c11f13cb77b3f076ddcc5d6ae3c20242bedcde" - url: "https://infyartifactory.jfrog.io/artifactory/api/pub/pub.dev-remote/" + url: "https://pub.dev" source: hosted version: "1.2.0" sync_http: @@ -1257,7 +1209,7 @@ packages: description: name: sync_http sha256: "7f0cd72eca000d2e026bcd6f990b81d0ca06022ef4e32fb257b30d3d1014a961" - url: "https://infyartifactory.jfrog.io/artifactory/api/pub/pub.dev-remote/" + url: "https://pub.dev" source: hosted version: "0.3.1" term_glyph: @@ -1265,23 +1217,23 @@ packages: description: name: term_glyph sha256: a29248a84fbb7c79282b40b8c72a1209db169a2e0542bce341da992fe1bc7e84 - url: "https://infyartifactory.jfrog.io/artifactory/api/pub/pub.dev-remote/" + url: "https://pub.dev" source: hosted version: "1.2.1" test_api: dependency: transitive description: name: test_api - sha256: "9955ae474176f7ac8ee4e989dadfb411a58c30415bcfb648fa04b2b8a03afa7f" - url: "https://infyartifactory.jfrog.io/artifactory/api/pub/pub.dev-remote/" + sha256: eb6ac1540b26de412b3403a163d919ba86f6a973fe6cc50ae3541b80092fdcfb + url: "https://pub.dev" source: hosted - version: "0.7.0" + version: "0.5.1" timing: dependency: transitive description: name: timing sha256: "70a3b636575d4163c477e6de42f247a23b315ae20e86442bebe32d3cabf61c32" - url: "https://infyartifactory.jfrog.io/artifactory/api/pub/pub.dev-remote/" + url: "https://pub.dev" source: hosted version: "1.0.1" typed_data: @@ -1289,79 +1241,79 @@ packages: description: name: typed_data sha256: facc8d6582f16042dd49f2463ff1bd6e2c9ef9f3d5da3d9b087e244a7b564b3c - url: "https://infyartifactory.jfrog.io/artifactory/api/pub/pub.dev-remote/" + url: "https://pub.dev" source: hosted version: "1.3.2" url_launcher: dependency: "direct main" description: name: url_launcher - sha256: "21b704ce5fa560ea9f3b525b43601c678728ba46725bab9b01187b4831377ed3" - url: "https://infyartifactory.jfrog.io/artifactory/api/pub/pub.dev-remote/" + sha256: "47e208a6711459d813ba18af120d9663c20bdf6985d6ad39fe165d2538378d27" + url: "https://pub.dev" source: hosted - version: "6.3.0" + version: "6.1.14" url_launcher_android: dependency: transitive description: name: url_launcher_android - sha256: "94d8ad05f44c6d4e2ffe5567ab4d741b82d62e3c8e288cc1fcea45965edf47c9" - url: "https://infyartifactory.jfrog.io/artifactory/api/pub/pub.dev-remote/" + sha256: d4ed0711849dd8e33eb2dd69c25db0d0d3fdc37e0a62e629fe32f57a22db2745 + url: "https://pub.dev" source: hosted - version: "6.3.8" + version: "6.3.0" url_launcher_ios: dependency: transitive description: name: url_launcher_ios - sha256: e43b677296fadce447e987a2f519dcf5f6d1e527dc35d01ffab4fff5b8a7063e - url: "https://infyartifactory.jfrog.io/artifactory/api/pub/pub.dev-remote/" + sha256: "75bb6fe3f60070407704282a2d295630cab232991eb52542b18347a8a941df03" + url: "https://pub.dev" source: hosted - version: "6.3.1" + version: "6.2.4" url_launcher_linux: dependency: transitive description: name: url_launcher_linux - sha256: e2b9622b4007f97f504cd64c0128309dfb978ae66adbe944125ed9e1750f06af - url: "https://infyartifactory.jfrog.io/artifactory/api/pub/pub.dev-remote/" + sha256: ab360eb661f8879369acac07b6bb3ff09d9471155357da8443fd5d3cf7363811 + url: "https://pub.dev" source: hosted - version: "3.2.0" + version: "3.1.1" url_launcher_macos: dependency: transitive description: name: url_launcher_macos - sha256: "9a1a42d5d2d95400c795b2914c36fdcb525870c752569438e4ebb09a2b5d90de" - url: "https://infyartifactory.jfrog.io/artifactory/api/pub/pub.dev-remote/" + sha256: b7244901ea3cf489c5335bdacda07264a6e960b1c1b1a9f91e4bc371d9e68234 + url: "https://pub.dev" source: hosted - version: "3.2.0" + version: "3.1.0" url_launcher_platform_interface: dependency: transitive description: name: url_launcher_platform_interface - sha256: "552f8a1e663569be95a8190206a38187b531910283c3e982193e4f2733f01029" - url: "https://infyartifactory.jfrog.io/artifactory/api/pub/pub.dev-remote/" + sha256: a932c3a8082e118f80a475ce692fde89dc20fddb24c57360b96bc56f7035de1f + url: "https://pub.dev" source: hosted - version: "2.3.2" + version: "2.3.1" url_launcher_web: dependency: transitive description: name: url_launcher_web - sha256: "772638d3b34c779ede05ba3d38af34657a05ac55b06279ea6edd409e323dca8e" - url: "https://infyartifactory.jfrog.io/artifactory/api/pub/pub.dev-remote/" + sha256: ba140138558fcc3eead51a1c42e92a9fb074a1b1149ed3c73e66035b2ccd94f2 + url: "https://pub.dev" source: hosted - version: "2.3.3" + version: "2.0.19" url_launcher_windows: dependency: transitive description: name: url_launcher_windows - sha256: "49c10f879746271804767cb45551ec5592cdab00ee105c06dddde1a98f73b185" - url: "https://infyartifactory.jfrog.io/artifactory/api/pub/pub.dev-remote/" + sha256: ecf9725510600aa2bb6d7ddabe16357691b6d2805f66216a97d1b881e21beff7 + url: "https://pub.dev" source: hosted - version: "3.1.2" + version: "3.1.1" vector_graphics: dependency: transitive description: name: vector_graphics sha256: "4ac59808bbfca6da38c99f415ff2d3a5d7ca0a6b4809c71d9cf30fba5daf9752" - url: "https://infyartifactory.jfrog.io/artifactory/api/pub/pub.dev-remote/" + url: "https://pub.dev" source: hosted version: "1.1.10+1" vector_graphics_codec: @@ -1369,7 +1321,7 @@ packages: description: name: vector_graphics_codec sha256: f3247e7ab0ec77dc759263e68394990edc608fb2b480b80db8aa86ed09279e33 - url: "https://infyartifactory.jfrog.io/artifactory/api/pub/pub.dev-remote/" + url: "https://pub.dev" source: hosted version: "1.1.10+1" vector_graphics_compiler: @@ -1377,7 +1329,7 @@ packages: description: name: vector_graphics_compiler sha256: "18489bdd8850de3dd7ca8a34e0c446f719ec63e2bab2e7a8cc66a9028dd76c5a" - url: "https://infyartifactory.jfrog.io/artifactory/api/pub/pub.dev-remote/" + url: "https://pub.dev" source: hosted version: "1.1.10+1" vector_math: @@ -1385,63 +1337,47 @@ packages: description: name: vector_math sha256: "80b3257d1492ce4d091729e3a67a60407d227c27241d6927be0130c98e741803" - url: "https://infyartifactory.jfrog.io/artifactory/api/pub/pub.dev-remote/" + url: "https://pub.dev" source: hosted version: "2.1.4" vm_service: dependency: transitive description: name: vm_service - sha256: "3923c89304b715fb1eb6423f017651664a03bf5f4b29983627c4da791f74a4ec" - url: "https://infyartifactory.jfrog.io/artifactory/api/pub/pub.dev-remote/" + sha256: f6deed8ed625c52864792459709183da231ebf66ff0cf09e69b573227c377efe + url: "https://pub.dev" source: hosted - version: "14.2.1" + version: "11.3.0" watcher: dependency: transitive description: name: watcher sha256: "3d2ad6751b3c16cf07c7fca317a1413b3f26530319181b37e3b9039b84fc01d8" - url: "https://infyartifactory.jfrog.io/artifactory/api/pub/pub.dev-remote/" + url: "https://pub.dev" source: hosted version: "1.1.0" - web: - dependency: transitive - description: - name: web - sha256: d43c1d6b787bf0afad444700ae7f4db8827f701bc61c255ac8d328c6f4d52062 - url: "https://infyartifactory.jfrog.io/artifactory/api/pub/pub.dev-remote/" - source: hosted - version: "1.0.0" - web_socket: - dependency: transitive - description: - name: web_socket - sha256: "3c12d96c0c9a4eec095246debcea7b86c0324f22df69893d538fcc6f1b8cce83" - url: "https://infyartifactory.jfrog.io/artifactory/api/pub/pub.dev-remote/" - source: hosted - version: "0.1.6" web_socket_channel: dependency: transitive description: name: web_socket_channel - sha256: "9f187088ed104edd8662ca07af4b124465893caf063ba29758f97af57e61da8f" - url: "https://infyartifactory.jfrog.io/artifactory/api/pub/pub.dev-remote/" + sha256: d88238e5eac9a42bb43ca4e721edba3c08c6354d4a53063afaa568516217621b + url: "https://pub.dev" source: hosted - version: "3.0.1" + version: "2.4.0" webdriver: dependency: transitive description: name: webdriver - sha256: "003d7da9519e1e5f329422b36c4dcdf18d7d2978d1ba099ea4e45ba490ed845e" - url: "https://infyartifactory.jfrog.io/artifactory/api/pub/pub.dev-remote/" + sha256: "3c923e918918feeb90c4c9fdf1fe39220fa4c0e8e2c0fffaded174498ef86c49" + url: "https://pub.dev" source: hosted - version: "3.0.3" + version: "3.0.2" webview_flutter: dependency: transitive description: name: webview_flutter sha256: "392c1d83b70fe2495de3ea2c84531268d5b8de2de3f01086a53334d8b6030a88" - url: "https://infyartifactory.jfrog.io/artifactory/api/pub/pub.dev-remote/" + url: "https://pub.dev" source: hosted version: "3.0.4" webview_flutter_android: @@ -1449,7 +1385,7 @@ packages: description: name: webview_flutter_android sha256: "8b3b2450e98876c70bfcead876d9390573b34b9418c19e28168b74f6cb252dbd" - url: "https://infyartifactory.jfrog.io/artifactory/api/pub/pub.dev-remote/" + url: "https://pub.dev" source: hosted version: "2.10.4" webview_flutter_platform_interface: @@ -1457,7 +1393,7 @@ packages: description: name: webview_flutter_platform_interface sha256: "812165e4e34ca677bdfbfa58c01e33b27fd03ab5fa75b70832d4b7d4ca1fa8cf" - url: "https://infyartifactory.jfrog.io/artifactory/api/pub/pub.dev-remote/" + url: "https://pub.dev" source: hosted version: "1.9.5" webview_flutter_plus: @@ -1465,7 +1401,7 @@ packages: description: name: webview_flutter_plus sha256: bea8756ae096529254725def7c4a633851a785c7d49206e0817125ab02b14307 - url: "https://infyartifactory.jfrog.io/artifactory/api/pub/pub.dev-remote/" + url: "https://pub.dev" source: hosted version: "0.3.0+2" webview_flutter_wkwebview: @@ -1473,41 +1409,41 @@ packages: description: name: webview_flutter_wkwebview sha256: a5364369c758892aa487cbf59ea41d9edd10f9d9baf06a94e80f1bd1b4c7bbc0 - url: "https://infyartifactory.jfrog.io/artifactory/api/pub/pub.dev-remote/" + url: "https://pub.dev" source: hosted version: "2.9.5" win32: dependency: transitive description: name: win32 - sha256: "015002c060f1ae9f41a818f2d5640389cc05283e368be19dc8d77cecb43c40c9" - url: "https://infyartifactory.jfrog.io/artifactory/api/pub/pub.dev-remote/" + sha256: "350a11abd2d1d97e0cc7a28a81b781c08002aa2864d9e3f192ca0ffa18b06ed3" + url: "https://pub.dev" source: hosted - version: "5.5.3" + version: "5.0.9" xdg_directories: dependency: transitive description: name: xdg_directories sha256: faea9dee56b520b55a566385b84f2e8de55e7496104adada9962e0bd11bcff1d - url: "https://infyartifactory.jfrog.io/artifactory/api/pub/pub.dev-remote/" + url: "https://pub.dev" source: hosted version: "1.0.4" xml: dependency: transitive description: name: xml - sha256: b015a8ad1c488f66851d762d3090a21c600e479dc75e68328c52774040cf9226 - url: "https://infyartifactory.jfrog.io/artifactory/api/pub/pub.dev-remote/" + sha256: "5bc72e1e45e941d825fd7468b9b4cc3b9327942649aeb6fc5cdbf135f0a86e84" + url: "https://pub.dev" source: hosted - version: "6.5.0" + version: "6.3.0" yaml: dependency: transitive description: name: yaml sha256: "75769501ea3489fca56601ff33454fe45507ea3bfb014161abc3b43ae25989d5" - url: "https://infyartifactory.jfrog.io/artifactory/api/pub/pub.dev-remote/" + url: "https://pub.dev" source: hosted version: "3.1.2" sdks: - dart: ">=3.4.0 <4.0.0" - flutter: ">=3.22.0" + dart: ">=3.0.0 <4.0.0" + flutter: ">=3.10.0" From c41b7ed864b0fe28f7b5c354a2bfae399e2bb6ae Mon Sep 17 00:00:00 2001 From: Madhuravas reddy Date: Fri, 29 Aug 2025 08:16:04 +0530 Subject: [PATCH 14/44] RCF-784 implemented auto logout feature if the device is idle (#544) * RCF-784 implemented auto logout forr idle Signed-off-by: Madhuravas reddy * Resolved logout description issue and clearing cache after logout Signed-off-by: Madhuravas reddy * if app is syncing timer will be restart Signed-off-by: Madhuravas reddy --------- Signed-off-by: Madhuravas reddy --- .../api_services/AuthenticationApi.java | 12 + .../constant/RegistrationConstants.java | 2 + .../repository/GlobalParamRepository.java | 8 + assets/l10n/app_ar.arb | 6 + assets/l10n/app_en.arb | 6 + assets/l10n/app_fr.arb | 6 + assets/l10n/app_hi.arb | 6 + assets/l10n/app_kn.arb | 6 + assets/l10n/app_ta.arb | 6 + lib/main.dart | 141 +++++++-- lib/platform_android/auth_service_impl.dart | 24 ++ lib/platform_spi/auth_service.dart | 4 + lib/provider/auth_provider.dart | 16 + lib/utils/inactivity_tracker.dart | 295 ++++++++++++++++++ pigeon/auth_response.dart | 5 + 15 files changed, 513 insertions(+), 30 deletions(-) create mode 100644 lib/utils/inactivity_tracker.dart diff --git a/android/app/src/main/java/io/mosip/registration_client/api_services/AuthenticationApi.java b/android/app/src/main/java/io/mosip/registration_client/api_services/AuthenticationApi.java index e0c2e4437..386e65609 100644 --- a/android/app/src/main/java/io/mosip/registration_client/api_services/AuthenticationApi.java +++ b/android/app/src/main/java/io/mosip/registration_client/api_services/AuthenticationApi.java @@ -242,4 +242,16 @@ public void forgotPasswordUrl(@NonNull AuthResponsePigeon.Result result) String response = this.globalParamRepository.getCachedStringForgotPassword(); result.success(response); } + + @Override + public void getIdleTime(@NonNull AuthResponsePigeon.Result result) { + String response = this.globalParamRepository.getCachedStringIdleTime(); + result.success(response); + } + + @Override + public void getAutoLogoutPopupTimeout(@NonNull AuthResponsePigeon.Result result) { + String response = this.globalParamRepository.getCachedStringRefreshedLoginTime(); + result.success(response); + } } diff --git a/android/clientmanager/src/main/java/io/mosip/registration/clientmanager/constant/RegistrationConstants.java b/android/clientmanager/src/main/java/io/mosip/registration/clientmanager/constant/RegistrationConstants.java index c9a8f4207..56e2abffb 100644 --- a/android/clientmanager/src/main/java/io/mosip/registration/clientmanager/constant/RegistrationConstants.java +++ b/android/clientmanager/src/main/java/io/mosip/registration/clientmanager/constant/RegistrationConstants.java @@ -61,6 +61,8 @@ public class RegistrationConstants { public static final String AGEGROUP_CONFIG = "mosip.registration.agegroup-config"; public static final String ALLOWED_BIO_ATTRIBUTES = "mosip.registration.allowed-bioattributes"; public static final String DEFAULT_APP_TYPE_CODE = "mosip.registration.default-app-type-code"; + public static final String IDLE_TIME = "mosip.registration.idle_time"; + public static final String REFRESHED_LOGIN_TIME = "mosip.registration.refreshed_login_time"; public static final String RESPONSE = "response"; public static final String ERRORS = "errors"; diff --git a/android/clientmanager/src/main/java/io/mosip/registration/clientmanager/repository/GlobalParamRepository.java b/android/clientmanager/src/main/java/io/mosip/registration/clientmanager/repository/GlobalParamRepository.java index 9138bbcb2..4ee407067 100644 --- a/android/clientmanager/src/main/java/io/mosip/registration/clientmanager/repository/GlobalParamRepository.java +++ b/android/clientmanager/src/main/java/io/mosip/registration/clientmanager/repository/GlobalParamRepository.java @@ -122,4 +122,12 @@ public List getSelectedHandles() { public String getCachedStringForgotPassword() { return globalParamMap.get(RegistrationConstants.FORGOT_PASSWORD_URL); } + + public String getCachedStringIdleTime() { + return globalParamMap.get(RegistrationConstants.IDLE_TIME); + } + + public String getCachedStringRefreshedLoginTime() { + return globalParamMap.get(RegistrationConstants.REFRESHED_LOGIN_TIME); + } } diff --git a/assets/l10n/app_ar.arb b/assets/l10n/app_ar.arb index 467f3eee1..798785fa3 100644 --- a/assets/l10n/app_ar.arb +++ b/assets/l10n/app_ar.arb @@ -56,6 +56,12 @@ "network_error": "لم يتم العثور على شبكة!", "delete": "يمسح", "newRegistrationProcess": "{language, select, eng{New Registration} ara{تسجيل جديد} fra{Nouvelle inscription} other{New Registration}}", + "inactive_logout_heading": "لقد كنت خاملاً", + "inactive_logout_description": "لأسباب أمنية، سيتم تسجيل خروجك في $TIMER", + "seconds": " ثواني.", + "minutes": " دقائق.", + "logout_button": "تسجيل الخروج", + "stay_logged_in_button": "البقاء مسجلاً الدخول", "@newRegistrationProcess": { "description": "New Registration Process Header", "placeholders": { diff --git a/assets/l10n/app_en.arb b/assets/l10n/app_en.arb index 0071d8c3a..8f56b0648 100644 --- a/assets/l10n/app_en.arb +++ b/assets/l10n/app_en.arb @@ -56,6 +56,12 @@ "network_error": "No network found!", "delete": "DELETE", "newRegistrationProcess": "{language, select, eng{New Registration} ara{تسجيل جديد} fra{Nouvelle inscription} other{New Registration}}", + "inactive_logout_heading": "You have been idle", + "inactive_logout_description": "For security reasons, you'll be logged out in $TIMER", + "seconds": " Seconds.", + "minutes": " Minutes.", + "logout_button": "LOG OUT", + "stay_logged_in_button": "STAY LOGGED IN", "@newRegistrationProcess": { "description": "New Registration Process Header", "placeholders": { diff --git a/assets/l10n/app_fr.arb b/assets/l10n/app_fr.arb index 2c4a7cd0c..326894d57 100644 --- a/assets/l10n/app_fr.arb +++ b/assets/l10n/app_fr.arb @@ -56,6 +56,12 @@ "network_error": "Aucun réseau trouvé!", "delete": "SUPPRIMER", "newRegistrationProcess": "{language, select, eng{New Registration} ara{تسجيل جديد} fra{Nouvelle inscription} other{New Registration}}", + "inactive_logout_heading": "Tu as été inactif", + "inactive_logout_description": "Pour des raisons de sécurité, vous serez déconnecté de $TIMER", + "seconds": " Seconds.", + "minutes": " Minutes.", + "logout_button": "LOG OUT", + "stay_logged_in_button": "DÉCONNEXION", "@newRegistrationProcess": { "description": "New Registration Process Header", "placeholders": { diff --git a/assets/l10n/app_hi.arb b/assets/l10n/app_hi.arb index cd7e6df6b..55253d332 100644 --- a/assets/l10n/app_hi.arb +++ b/assets/l10n/app_hi.arb @@ -56,6 +56,12 @@ "network_error": "कोई नेटवर्क नहीं मिला!", "delete": "मिटाना", "newRegistrationProcess": "{language, select, eng{New Registration} ara{تسجيل جديد} fra{Nouvelle inscription} other{New Registration}}", + "inactive_logout_heading": "तुम निष्क्रिय हो गए हो", + "inactive_logout_description": "ससुरक्षा कारणों से, आपको $TIMER में लॉग आउट कर दिया जाएगा", + "seconds": " सेकंड.", + "minutes": " मिनट.", + "logout_button": "लॉग आउट", + "stay_logged_in_button": "लॉग इन रहें", "@newRegistrationProcess": { "description": "New Registration Process Header", "placeholders": { diff --git a/assets/l10n/app_kn.arb b/assets/l10n/app_kn.arb index fbb56952c..da34b390a 100644 --- a/assets/l10n/app_kn.arb +++ b/assets/l10n/app_kn.arb @@ -56,6 +56,12 @@ "network_error": "ಯಾವುದೇ ನೆಟ್ವರ್ಕ್ ಸಿಗಲಿಲ್ಲ!", "delete": "ಅಳಿಸಿ", "newRegistrationProcess": "{language, select, eng{New Registration} ara{تسجيل جديد} fra{Nouvelle inscription} other{New Registration}}", + "inactive_logout_heading": "ನೀವು ಸುಮ್ಮನಿದ್ದಿರಿ", + "inactive_logout_description": "ಭದ್ರತಾ ಕಾರಣಗಳಿಗಾಗಿ, ನೀವು $TIMER ನಲ್ಲಿ ಲಾಗ್ ಔಟ್ ಆಗುತ್ತೀರಿ", + "seconds": " ಸೆಕೆಂಡುಗಳು.", + "minutes": " ನಿಮಿಷಗಳು.", + "logout_button": "ಲಾಗ್ ಔಟ್ ಮಾಡಿ", + "stay_logged_in_button": "ಲಾಗಿನ್ ಆಗಿರಿ", "@newRegistrationProcess": { "description": "New Registration Process Header", "placeholders": { diff --git a/assets/l10n/app_ta.arb b/assets/l10n/app_ta.arb index a225d9696..176137b12 100644 --- a/assets/l10n/app_ta.arb +++ b/assets/l10n/app_ta.arb @@ -57,6 +57,12 @@ "network_error": "நெட்வொர்க் இல்லை!", "delete": "அழி", "newRegistrationProcess": "{language, select, eng{New Registration} ara{تسجيل جديد} fra{Nouvelle inscription} other{New Registration}}", + "inactive_logout_heading": "நீங்கள் சும்மா இருந்தீர்கள்", + "inactive_logout_description": "பாதுகாப்பு காரணங்களுக்காக, நீங்கள் $TIMER இல் வெளியேற்றப்படுவீர்கள்", + "seconds": " நொடிகள்.", + "minutes": " நிமிடங்கள்.", + "logout_button": "வெளியேறு", + "stay_logged_in_button": "உள்நுழைந்தே இருங்கள்", "@newRegistrationProcess": { "description": "New Registration Process Header", "placeholders": { diff --git a/lib/main.dart b/lib/main.dart index 2e1d7741a..db4d4d40a 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -12,7 +12,6 @@ import 'package:registration_client/app_router.dart'; import 'package:registration_client/provider/approve_packets_provider.dart'; import 'package:registration_client/provider/auth_provider.dart'; import 'package:registration_client/provider/connectivity_provider.dart'; - import 'package:provider/provider.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:registration_client/provider/global_provider.dart'; @@ -21,6 +20,11 @@ import 'package:registration_client/provider/sync_provider.dart'; import 'package:registration_client/ui/login_page.dart'; import 'package:registration_client/utils/app_config.dart'; import 'package:flutter_driver/driver_extension.dart'; +import 'package:registration_client/utils/inactivity_tracker.dart'; + +final GlobalKey rootNavigatorKey = GlobalKey(); +final GlobalKey rootScaffoldMessengerKey = +GlobalKey(); void main() async { enableFlutterDriverExtension(enableTextEntryEmulation: false); @@ -33,6 +37,29 @@ void main() async { ); } +Future _handleAutoLogout() async { + final ctx = rootNavigatorKey.currentContext; + if (ctx == null) return; // Safety guard + + // final syncProvider = ctx.read(); + final authProvider = ctx.read(); + final loc = AppLocalizations.of(ctx)!; + + final String result = await authProvider.logoutUser(); + + if (result.contains('Logout Success')) { + rootScaffoldMessengerKey.currentState?.showSnackBar( + SnackBar(content: Text(loc.logout_success)), + ); + rootNavigatorKey.currentState + ?.pushNamedAndRemoveUntil('/login-page', (_) => false); + } else { + rootScaffoldMessengerKey.currentState?.showSnackBar( + SnackBar(content: Text(loc.logout_failure)), + ); + } +} + class RegistrationClientApp extends StatelessWidget { const RegistrationClientApp({super.key}); @@ -70,44 +97,98 @@ class RegistrationClientApp extends StatelessWidget { } } -class BuildApp extends StatelessWidget { +class BuildApp extends StatefulWidget { const BuildApp({super.key}); + @override + State createState() => _BuildAppState(); +} + +class _BuildAppState extends State { + late AuthProvider authProvider; + /// Default to 5 minutes until server value arrives + Duration _idleDuration = const Duration(seconds: 900); + Duration _graceDuration = const Duration(seconds: 600); + + @override + void initState() { + super.initState(); + _loadIdleTimeFromServer(); + } + + Future _loadIdleTimeFromServer() async { + try { + final authProvider = Provider.of(context, listen: false); + + // Run both API calls in parallel + await Future.wait([ + authProvider.getIdleTime(), + authProvider.getRefreshedLoginTime(), + ]); + + final int idleSecs = int.tryParse(authProvider.idleTime) ?? 0; + final int graceSecs = int.tryParse(authProvider.refreshedLoginTime) ?? 0; + + if (mounted) { + setState(() { + if (idleSecs > 0) _idleDuration = Duration(seconds: idleSecs); + if (graceSecs > 0) _graceDuration = Duration(seconds: graceSecs); + }); + } + } catch (e) { + debugPrint('Failed to load idle time / grace period: $e'); + } + } + @override Widget build(BuildContext context) { - return MaterialApp( - title: 'Registration Client', - routes: AppRouter.routes, - debugShowCheckedModeBanner: false, - localizationsDelegates: AppLocalizations.localizationsDelegates, - supportedLocales: AppLocalizations.supportedLocales, - locale: Provider.of(context).appLocal, - theme: ThemeData( - colorScheme: ColorScheme.light(primary: solidPrimary), - primaryColor: solidPrimary, - textTheme: const TextTheme( - titleLarge: TextStyle(fontSize: 24), - bodyLarge: TextStyle(fontSize: 18), + return Consumer( + builder: (_, authProvider, __) { + return MaterialApp( + navigatorKey: rootNavigatorKey, + scaffoldMessengerKey: rootScaffoldMessengerKey, + title: 'Registration Client', + routes: AppRouter.routes, + debugShowCheckedModeBanner: false, + localizationsDelegates: AppLocalizations.localizationsDelegates, + supportedLocales: AppLocalizations.supportedLocales, + locale: context.watch().appLocal, + theme: ThemeData( + colorScheme: ColorScheme.light(primary: solidPrimary), + primaryColor: solidPrimary, + textTheme: const TextTheme( + titleLarge: TextStyle(fontSize: 24), + bodyLarge: TextStyle(fontSize: 18), + ), + elevatedButtonTheme: + const ElevatedButtonThemeData(style: ButtonStyle()), ), - elevatedButtonTheme: - const ElevatedButtonThemeData(style: ButtonStyle())), - builder: (context, child) { - MediaQueryData mediaQueryData = MediaQuery.of(context); - Orientation orientation = mediaQueryData.orientation; - ScreenUtil.init( - context, - designSize: orientation == Orientation.portrait - ? mediaQueryData.size.width < 750 + builder: (context, child) { + MediaQueryData mediaQueryData = MediaQuery.of(context); + Orientation orientation = mediaQueryData.orientation; + ScreenUtil.init( + context, + designSize: orientation == Orientation.portrait + ? mediaQueryData.size.width < 750 ? const Size(390, 844) : const Size(800, 1280) - : const Size(1024, 768), - minTextAdapt: true, - splitScreenMode: true, - ); + : const Size(1024, 768), + minTextAdapt: true, + splitScreenMode: true, + ); - return child!; + /// Wrap entire app in the tracker with server-configured timeout + return InactivityTracker( + timeout: _idleDuration, + gracePeriod: _graceDuration,// ← dynamic duration + isUserLoggedIn: authProvider.isLoggedIn, + onTimeout: _handleAutoLogout, // global callback (already defined) + child: child!, + ); + }, + home: const LoginPage(), + ); }, - home: const LoginPage(), ); } } diff --git a/lib/platform_android/auth_service_impl.dart b/lib/platform_android/auth_service_impl.dart index c8478ddc6..6446f7876 100644 --- a/lib/platform_android/auth_service_impl.dart +++ b/lib/platform_android/auth_service_impl.dart @@ -98,7 +98,31 @@ class AuthServiceImpl implements AuthService { return forgotPasswordResponse; } + @override + Future getIdleTime() async { + late String idleTime; + try { + idleTime = await AuthResponseApi().getIdleTime(); + } on PlatformException { + debugPrint('getIdleTime call failed!'); + } catch (e) { + debugPrint(e.toString()); + } + return idleTime; + } + @override + Future getAutoLogoutPopupTimeout() async { + late String refreshLoginTime; + try { + refreshLoginTime = await AuthResponseApi().getAutoLogoutPopupTimeout(); + } on PlatformException { + debugPrint('getIdleTime call failed!'); + } catch (e) { + debugPrint(e.toString()); + } + return refreshLoginTime; + } } AuthService getAuthServiceImpl() => AuthServiceImpl(); diff --git a/lib/platform_spi/auth_service.dart b/lib/platform_spi/auth_service.dart index bf3fce5db..c3d750fa7 100644 --- a/lib/platform_spi/auth_service.dart +++ b/lib/platform_spi/auth_service.dart @@ -25,5 +25,9 @@ abstract class AuthService { Future forgotPasswordUrl(); + Future getIdleTime(); + + Future getAutoLogoutPopupTimeout(); + factory AuthService() => getAuthServiceImpl(); } diff --git a/lib/provider/auth_provider.dart b/lib/provider/auth_provider.dart index 3592d8342..8fd257ad8 100644 --- a/lib/provider/auth_provider.dart +++ b/lib/provider/auth_provider.dart @@ -32,6 +32,8 @@ class AuthProvider with ChangeNotifier { String _userEmail = ""; bool _isNetworkPresent = false; String _forgotPasswordUrl = ""; + String _refreshedLoginTime = ""; + String _idleTime = ""; bool get isLoggedIn => _isLoggedIn; bool get isSyncing => _isSyncing; @@ -53,6 +55,8 @@ class AuthProvider with ChangeNotifier { String get userEmail => _userEmail; bool get isNetworkPresent => _isNetworkPresent; String get forgotPasswordUrl => _forgotPasswordUrl; + String get refreshedLoginTime => _refreshedLoginTime; + String get idleTime => _idleTime; setIsLoggedIn(bool value) { _isLoggedIn = value; @@ -223,4 +227,16 @@ class AuthProvider with ChangeNotifier { notifyListeners(); } + getIdleTime() async { + String idleTime = await auth.getIdleTime(); + _idleTime = idleTime; + notifyListeners(); + } + + getRefreshedLoginTime() async { + String refreshedLoginTime = await auth.getAutoLogoutPopupTimeout(); + _refreshedLoginTime = refreshedLoginTime; + notifyListeners(); + } + } diff --git a/lib/utils/inactivity_tracker.dart b/lib/utils/inactivity_tracker.dart new file mode 100644 index 000000000..3c1bfee90 --- /dev/null +++ b/lib/utils/inactivity_tracker.dart @@ -0,0 +1,295 @@ +import 'dart:async'; +import 'package:flutter/material.dart'; +import 'package:flutter_gen/gen_l10n/app_localizations.dart'; +import 'package:provider/provider.dart'; +import 'package:registration_client/provider/global_provider.dart'; +import 'package:registration_client/provider/sync_provider.dart'; + +import '../main.dart'; + +class InactivityTracker extends StatefulWidget { + final Widget child; + final Duration timeout; // inactivity before warning + final Duration gracePeriod; // countdown inside dialog + final bool isUserLoggedIn; + final Future Function() onTimeout; + + const InactivityTracker({ + Key? key, + required this.child, + required this.timeout, + required this.gracePeriod, + required this.isUserLoggedIn, + required this.onTimeout, + }) : super(key: key); + + @override + State createState() => _InactivityTrackerState(); +} + +class _InactivityTrackerState extends State with WidgetsBindingObserver { + Timer? _inactivityTimer; + Timer? _logoutTicker; + bool _warningShown = false; + final ValueNotifier _countdown = ValueNotifier(0); + DateTime? _pausedAt; + bool _dialogOpen = false; + late GlobalProvider globalProvider; + + @override + void initState() { + super.initState(); + globalProvider = Provider.of(context, listen: false); + WidgetsBinding.instance.addObserver(this); + _startInactivityTimer(); + } + + @override + void didUpdateWidget(covariant InactivityTracker oldWidget) { + super.didUpdateWidget(oldWidget); + if (oldWidget.isUserLoggedIn != widget.isUserLoggedIn || + oldWidget.timeout != widget.timeout || + oldWidget.gracePeriod != widget.gracePeriod) { + _resetAllTimers(); + } + } + + @override + void dispose() { + _countdown.dispose(); + _cancelAllTimers(); + WidgetsBinding.instance.removeObserver(this); + super.dispose(); + } + + void _startInactivityTimer() { + if (!widget.isUserLoggedIn) return; + _inactivityTimer = Timer(widget.timeout, _showWarningDialog); + } + + void _resetAllTimers() { + _inactivityTimer?.cancel(); + _logoutTicker?.cancel(); + _warningShown = false; + _startInactivityTimer(); + } + + void _cancelAllTimers() { + _inactivityTimer?.cancel(); + _logoutTicker?.cancel(); + } + + void _showWarningDialog() async { + if (!widget.isUserLoggedIn) return; + + // Prevent warning dialog if sync is in progress + final syncProvider = Provider.of(context, listen: false); + final bool isAnySyncInProgress = syncProvider.isSyncInProgress || + syncProvider.isSyncAndUploadInProgress; + if (isAnySyncInProgress) { + _resetAllTimers(); + return; + } + + _warningShown = true; + _dialogOpen = true; + _countdown.value = widget.gracePeriod.inSeconds; + + _logoutTicker = Timer.periodic(const Duration(seconds: 1), (t) { + _countdown.value -= 1; + if (_countdown.value <= 0) { + t.cancel(); + // Clear registration process data on auto logout + globalProvider.clearRegistrationProcessData(); + widget.onTimeout(); + } + }); + + final dialogCtx = rootNavigatorKey.currentContext!; + final loc = AppLocalizations.of(dialogCtx)!; + + showDialog( + context: dialogCtx, + barrierDismissible: false, + builder: (_) => _IdleWarningDialog( + countdown: _countdown, + onStayLoggedIn: () { + _logoutTicker?.cancel(); + _warningShown = false; + _dialogOpen = false; + Navigator.of(dialogCtx, rootNavigator: true).pop(); + _resetAllTimers(); + }, + onLogOut: () async { + Navigator.of(dialogCtx, rootNavigator: true).pop(); + _dialogOpen = false; + await widget.onTimeout(); + globalProvider.clearRegistrationProcessData(); + }, + loc: loc, + ), + ); + } + + void _onUserInteraction() { + if (!widget.isUserLoggedIn) return; + if (_dialogOpen) return; + if (_warningShown) { + _logoutTicker?.cancel(); + Navigator.of(rootNavigatorKey.currentContext!, rootNavigator: true).maybePop(); + _warningShown = false; + } + _resetAllTimers(); + } + + void didChangeAppLifecycleState(AppLifecycleState state) { + switch (state) { + case AppLifecycleState.paused: + case AppLifecycleState.inactive: + case AppLifecycleState.detached: + _pausedAt = DateTime.now(); + _cancelAllTimers(); + break; + + case AppLifecycleState.resumed: + if (!widget.isUserLoggedIn) return; + + if (_pausedAt != null) { + final away = DateTime.now().difference(_pausedAt!); + + if (away >= widget.timeout + widget.gracePeriod) { + widget.onTimeout(); + _pausedAt = null; + return; + } + + if (away >= widget.timeout) { + final remainingGrace = widget.gracePeriod - (away - widget.timeout); + _countdown.value = remainingGrace.inSeconds; + _showWarningDialog(); + _pausedAt = null; + return; + } + } + + _pausedAt = null; + _resetAllTimers(); + break; + } + } + + @override + Widget build(BuildContext context) { + return GestureDetector( + behavior: HitTestBehavior.translucent, + onTap: _onUserInteraction, + onPanDown: (_) => _onUserInteraction(), + onScaleStart: (_) => _onUserInteraction(), + child: widget.child, + ); + } +} + +class _IdleWarningDialog extends StatelessWidget { + const _IdleWarningDialog({ + required this.countdown, + required this.onStayLoggedIn, + required this.onLogOut, + required this.loc, + }); + + final ValueNotifier countdown; + final VoidCallback onStayLoggedIn; + final Future Function() onLogOut; + final AppLocalizations loc; + + @override + Widget build(BuildContext context) { + final theme = Theme.of(context); + + return Dialog( + shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8)), + child: ConstrainedBox( + constraints: const BoxConstraints(maxWidth: 420), + child: Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + Container( + padding: const EdgeInsets.fromLTRB(24, 20, 24, 20), + decoration: const BoxDecoration( + border: Border( + bottom: BorderSide(color: Color(0xFFE5EBFA), width: 1), + ), + ), + child: Text( + loc.inactive_logout_heading, + style: theme.textTheme.titleMedium?.copyWith( + fontWeight: FontWeight.bold, + fontSize: 22, + ), + ), + ), + Container( + padding: const EdgeInsets.fromLTRB(24, 20, 24, 20), + decoration: const BoxDecoration( + border: Border( + bottom: BorderSide(color: Color(0xFFE5EBFA), width: 1), + ), + ), + child: ValueListenableBuilder( + valueListenable: countdown, + builder: (_, secs, __) { + // Decide which unit to show + final String timeLeft = secs >= 60 + ? '${(secs / 60).ceil()}${loc.minutes}' // e.g. “2 minutes” + : '$secs${loc.seconds}'; // e.g. “45 seconds” + + // Replace $TIMER in the localized string with timeLeft, and style it + final parts = loc.inactive_logout_description.split('\$TIMER'); + return RichText( + text: TextSpan( + style: theme.textTheme.bodyMedium, + children: [ + TextSpan(text: parts[0]), + TextSpan( + text: timeLeft, + style: const TextStyle( + fontWeight: FontWeight.bold, + fontSize: 16, + ), + ), + if (parts.length > 1) TextSpan(text: parts[1]), + ], + ), + ); + }, + ), + ), + const SizedBox(height: 24), + Padding( + padding: const EdgeInsets.fromLTRB(24, 0, 24, 24), + child: Row( + children: [ + Expanded( + child: OutlinedButton( + onPressed: onLogOut, + child: Text(loc.logout_button), // You can localize this too + ), + ), + const SizedBox(width: 16), + Expanded( + child: ElevatedButton( + onPressed: onStayLoggedIn, + child: Text(loc.stay_logged_in_button), // And this + ), + ), + ], + ), + ), + ], + ), + ), + ); + } +} diff --git a/pigeon/auth_response.dart b/pigeon/auth_response.dart index 2c143718f..b252d9426 100644 --- a/pigeon/auth_response.dart +++ b/pigeon/auth_response.dart @@ -34,4 +34,9 @@ abstract class AuthResponseApi { String stopAlarmService(); @async String forgotPasswordUrl(); + @async + String getIdleTime(); + @async + String getAutoLogoutPopupTimeout(); + } From d77348bc8040b1df46a5318f256b3e33e35e398d Mon Sep 17 00:00:00 2001 From: Sachin S P <52343650+SachinPremkumar@users.noreply.github.com> Date: Fri, 29 Aug 2025 13:05:09 +0530 Subject: [PATCH 15/44] RCF-40 added setting spec logic (#559) * added setting spec logic Signed-off-by: sachin.sp * added setting spec logic Signed-off-by: sachin.sp * added setting spec logic Signed-off-by: sachin.sp * updated settings screen based on user role Signed-off-by: sachin.sp * updated settings screen based on user role Signed-off-by: sachin.sp * upadted the review comment Signed-off-by: sachin.sp * upadted the review comment Signed-off-by: sachin.sp * upadted the review comment Signed-off-by: sachin.sp * upadted the review comment Signed-off-by: sachin.sp --------- Signed-off-by: sachin.sp Co-authored-by: sachin.sp --- .../api_services/AuthenticationApi.java | 11 ++ .../api_services/ProcessSpecDetailsApi.java | 21 +++ android/build.gradle | 2 +- .../clientmanager/config/AppModule.java | 5 +- .../clientmanager/config/ClientDatabase.java | 6 +- .../clientmanager/config/RoomModule.java | 14 ++ .../clientmanager/dao/UserRoleDao.java | 28 ++++ .../dto/http/IdSchemaResponse.java | 2 + .../dto/uispec/SettingsSpecDto.java | 30 ++++ .../clientmanager/entity/UserRole.java | 27 +++ .../repository/IdentitySchemaRepository.java | 10 ++ .../repository/UserRoleRepository.java | 35 ++++ .../clientmanager/service/LoginService.java | 12 +- .../clientmanager/config/AppModuleTest.java | 3 +- .../service/LoginServiceTest.java | 40 ++--- lib/model/settings.dart | 22 +++ lib/platform_android/auth_service_impl.dart | 14 ++ .../process_spec_service_impl.dart | 15 ++ lib/platform_spi/auth_service.dart | 2 + lib/platform_spi/process_spec_service.dart | 1 + lib/provider/auth_provider.dart | 3 + lib/provider/registration_task_provider.dart | 17 ++ lib/ui/onboard/home_page.dart | 9 + lib/ui/onboard/portrait/mobile_home_page.dart | 38 +++-- .../process_ui/widgets/settings_screen.dart | 156 ++++++++++++++++++ pigeon/auth_response.dart | 3 +- pigeon/process_spec.dart | 5 +- 27 files changed, 488 insertions(+), 43 deletions(-) create mode 100644 android/clientmanager/src/main/java/io/mosip/registration/clientmanager/dao/UserRoleDao.java create mode 100644 android/clientmanager/src/main/java/io/mosip/registration/clientmanager/dto/uispec/SettingsSpecDto.java create mode 100644 android/clientmanager/src/main/java/io/mosip/registration/clientmanager/entity/UserRole.java create mode 100644 android/clientmanager/src/main/java/io/mosip/registration/clientmanager/repository/UserRoleRepository.java create mode 100644 lib/model/settings.dart create mode 100644 lib/ui/process_ui/widgets/settings_screen.dart diff --git a/android/app/src/main/java/io/mosip/registration_client/api_services/AuthenticationApi.java b/android/app/src/main/java/io/mosip/registration_client/api_services/AuthenticationApi.java index 386e65609..6a2768c11 100644 --- a/android/app/src/main/java/io/mosip/registration_client/api_services/AuthenticationApi.java +++ b/android/app/src/main/java/io/mosip/registration_client/api_services/AuthenticationApi.java @@ -19,6 +19,7 @@ import androidx.annotation.NonNull; +import java.util.Arrays; import java.util.List; import javax.inject.Inject; @@ -254,4 +255,14 @@ public void getAutoLogoutPopupTimeout(@NonNull AuthResponsePigeon.Result String response = this.globalParamRepository.getCachedStringRefreshedLoginTime(); result.success(response); } + + @Override + public void getRolesByUserId(@NonNull String userId, @NonNull AuthResponsePigeon.Result> result) { + try { + List roles = loginService.getRolesByUserId(userId); + result.success(roles); + } catch (Exception e) { + Log.e(getClass().getSimpleName(), "Getting user role failed!" + Arrays.toString(e.getStackTrace())); + } + } } diff --git a/android/app/src/main/java/io/mosip/registration_client/api_services/ProcessSpecDetailsApi.java b/android/app/src/main/java/io/mosip/registration_client/api_services/ProcessSpecDetailsApi.java index 3092d9369..c33033326 100644 --- a/android/app/src/main/java/io/mosip/registration_client/api_services/ProcessSpecDetailsApi.java +++ b/android/app/src/main/java/io/mosip/registration_client/api_services/ProcessSpecDetailsApi.java @@ -23,6 +23,7 @@ import javax.inject.Singleton; import io.mosip.registration.clientmanager.dto.uispec.ProcessSpecDto; +import io.mosip.registration.clientmanager.dto.uispec.SettingsSpecDto; import io.mosip.registration.clientmanager.repository.GlobalParamRepository; import io.mosip.registration.clientmanager.repository.IdentitySchemaRepository; import io.mosip.registration.clientmanager.spi.AuditManagerService; @@ -37,6 +38,8 @@ public class ProcessSpecDetailsApi implements ProcessSpecPigeon.ProcessSpecApi { GlobalParamRepository globalParamRepository; AuditManagerService auditManagerService; RegistrationService registrationService; + ObjectMapper objectMapper; + ObjectWriter objectWriter; @Inject public ProcessSpecDetailsApi(Context context, @@ -50,6 +53,8 @@ public ProcessSpecDetailsApi(Context context, this.globalParamRepository = globalParamRepository; this.registrationService = registrationService; this.auditManagerService = auditManagerService; + this.objectMapper = new ObjectMapper(); + this.objectWriter = objectMapper.writer().withDefaultPrettyPrinter(); } @Override @@ -148,4 +153,20 @@ public void getMaxLanguageCount(@NonNull ProcessSpecPigeon.Result result) } result.success((long) maxLangCount); } + + @Override + public void getSettingSpec(@NonNull ProcessSpecPigeon.Result> result) { + List settingSpecList = new ArrayList<>(); + try { + List settingsSpecDto = identitySchemaRepository.getSettingsSchema(context, identitySchemaRepository.getLatestSchemaVersion()); + settingsSpecDto = settingsSpecDto == null ? new ArrayList<>() : settingsSpecDto; + for (SettingsSpecDto dto : settingsSpecDto) { + String json = objectWriter.writeValueAsString(dto); + settingSpecList.add(json); + } + } catch (Exception e) { + Log.e(getClass().getSimpleName(), "Error in getSettingSpec", e); + } + result.success(settingSpecList); + } } diff --git a/android/build.gradle b/android/build.gradle index cb3cd355e..5e1ffbad1 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -58,7 +58,7 @@ ext { clientmanagerLibVersionCode = 1 clientmanagerLibVersionName = "\"1.0.0\"" - serverBaseURL = "\"https://api-internal.qa-core.mosip.net\"" + serverBaseURL = "\"https://api-internal.qa-base.mosip.net\"" serverHealthCheckPath = "\"/v1/syncdata/actuator/health\"" serverActuatorInfoPath = "\"/v1/syncdata/actuator/info\"" debugPassword = "\"APTyKejHxACQyKBSRciR\"" diff --git a/android/clientmanager/src/main/java/io/mosip/registration/clientmanager/config/AppModule.java b/android/clientmanager/src/main/java/io/mosip/registration/clientmanager/config/AppModule.java index d82266c66..6eb940ed6 100644 --- a/android/clientmanager/src/main/java/io/mosip/registration/clientmanager/config/AppModule.java +++ b/android/clientmanager/src/main/java/io/mosip/registration/clientmanager/config/AppModule.java @@ -34,6 +34,7 @@ import io.mosip.registration.clientmanager.repository.TemplateRepository; import io.mosip.registration.clientmanager.repository.UserBiometricRepository; import io.mosip.registration.clientmanager.repository.UserDetailRepository; +import io.mosip.registration.clientmanager.repository.UserRoleRepository; import io.mosip.registration.clientmanager.service.AuditManagerServiceImpl; import io.mosip.registration.clientmanager.service.Biometrics095Service; import io.mosip.registration.clientmanager.service.JobManagerServiceImpl; @@ -180,8 +181,8 @@ SyncRestUtil provideSyncRestFactory(ClientCryptoManagerService clientCryptoManag @Provides @Singleton - LoginService provideLoginService(ClientCryptoManagerService clientCryptoManagerService, UserDetailRepository userDetailRepository) { - return new LoginService(appContext, clientCryptoManagerService, userDetailRepository); + LoginService provideLoginService(ClientCryptoManagerService clientCryptoManagerService, UserDetailRepository userDetailRepository, UserRoleRepository userRoleRepository) { + return new LoginService(appContext, clientCryptoManagerService, userDetailRepository, userRoleRepository); } @Provides diff --git a/android/clientmanager/src/main/java/io/mosip/registration/clientmanager/config/ClientDatabase.java b/android/clientmanager/src/main/java/io/mosip/registration/clientmanager/config/ClientDatabase.java index 353da3b60..7217795f6 100644 --- a/android/clientmanager/src/main/java/io/mosip/registration/clientmanager/config/ClientDatabase.java +++ b/android/clientmanager/src/main/java/io/mosip/registration/clientmanager/config/ClientDatabase.java @@ -30,6 +30,7 @@ import io.mosip.registration.clientmanager.dao.UserDetailDao; import io.mosip.registration.clientmanager.dao.UserPasswordDao; import io.mosip.registration.clientmanager.dao.UserTokenDao; +import io.mosip.registration.clientmanager.dao.UserRoleDao; import io.mosip.registration.clientmanager.entity.ApplicantValidDocument; import io.mosip.registration.clientmanager.entity.Audit; import io.mosip.registration.clientmanager.entity.BlocklistedWord; @@ -54,12 +55,13 @@ import io.mosip.registration.clientmanager.entity.UserDetail; import io.mosip.registration.clientmanager.entity.UserPassword; import io.mosip.registration.clientmanager.entity.UserToken; +import io.mosip.registration.clientmanager.entity.UserRole; import io.mosip.registration.keymanager.dao.CACertificateStoreDao; import io.mosip.registration.keymanager.dao.KeyStoreDao; import io.mosip.registration.keymanager.entity.CACertificateStore; import io.mosip.registration.keymanager.entity.KeyStore; -@Database(entities = {UserToken.class, Registration.class, ReasonList.class, RegistrationCenter.class, +@Database(entities = {UserToken.class, UserRole.class, Registration.class, ReasonList.class, RegistrationCenter.class, MachineMaster.class, DocumentType.class, DynamicField.class, ApplicantValidDocument.class, Template.class, KeyStore.class, Location.class, GlobalParam.class, IdentitySchema.class, LocationHierarchy.class, @@ -86,6 +88,8 @@ public static ClientDatabase buildDatabase(Context context) { public abstract UserTokenDao userTokenDao(); + public abstract UserRoleDao userRoleDao(); + public abstract RegistrationDao registrationDao(); public abstract ReasonListDao reasonListDao(); diff --git a/android/clientmanager/src/main/java/io/mosip/registration/clientmanager/config/RoomModule.java b/android/clientmanager/src/main/java/io/mosip/registration/clientmanager/config/RoomModule.java index 2f8797848..52430fbcc 100644 --- a/android/clientmanager/src/main/java/io/mosip/registration/clientmanager/config/RoomModule.java +++ b/android/clientmanager/src/main/java/io/mosip/registration/clientmanager/config/RoomModule.java @@ -49,6 +49,7 @@ import io.mosip.registration.clientmanager.dao.UserBiometricDao; import io.mosip.registration.clientmanager.dao.UserDetailDao; import io.mosip.registration.clientmanager.dao.UserPasswordDao; +import io.mosip.registration.clientmanager.dao.UserRoleDao; import io.mosip.registration.clientmanager.dao.UserTokenDao; import io.mosip.registration.clientmanager.entity.UserBiometric; import io.mosip.registration.clientmanager.repository.ApplicantValidDocRepository; @@ -68,6 +69,7 @@ import io.mosip.registration.clientmanager.repository.TemplateRepository; import io.mosip.registration.clientmanager.repository.UserBiometricRepository; import io.mosip.registration.clientmanager.repository.UserDetailRepository; +import io.mosip.registration.clientmanager.repository.UserRoleRepository; import io.mosip.registration.keymanager.dao.CACertificateStoreDao; import io.mosip.registration.keymanager.dao.KeyStoreDao; import io.mosip.registration.keymanager.repository.CACertificateStoreRepository; @@ -275,6 +277,12 @@ UserPasswordDao providesUserPasswordDao(ClientDatabase clientDatabase) { return clientDatabase.userPasswordDao(); } + @Singleton + @Provides + UserRoleDao providesUserRoleDao(ClientDatabase clientDatabase) { + return clientDatabase.userRoleDao(); + } + @Singleton @Provides JobTransactionDao providesJobTransactionDao(ClientDatabase clientDatabase) { @@ -397,6 +405,12 @@ UserDetailRepository provideUserDetailRepository(UserDetailDao userDetailDao, Us return new UserDetailRepository(userDetailDao, userTokenDao, userPasswordDao); } + @Provides + @Singleton + UserRoleRepository provideUserRoleRepository(UserRoleDao userRoleDao) { + return new UserRoleRepository(userRoleDao); + } + @Provides @Singleton UserBiometricRepository provideUserBiometricRepository(UserBiometricDao userBiometricDao, UserDetailDao userDetailDao) { diff --git a/android/clientmanager/src/main/java/io/mosip/registration/clientmanager/dao/UserRoleDao.java b/android/clientmanager/src/main/java/io/mosip/registration/clientmanager/dao/UserRoleDao.java new file mode 100644 index 000000000..6aa7effc9 --- /dev/null +++ b/android/clientmanager/src/main/java/io/mosip/registration/clientmanager/dao/UserRoleDao.java @@ -0,0 +1,28 @@ +package io.mosip.registration.clientmanager.dao; + +import androidx.room.Dao; +import androidx.room.Insert; +import androidx.room.OnConflictStrategy; +import androidx.room.Query; + +import java.util.List; + +import io.mosip.registration.clientmanager.entity.UserRole; + +@Dao +public interface UserRoleDao { + + @Query("SELECT * FROM user_role WHERE usr_id = :usrId") + List findByUsrId(String usrId); + + @Insert(onConflict = OnConflictStrategy.REPLACE) + void insert(UserRole userRole); + + @Query("DELETE FROM user_role WHERE usr_id = :usrId") + void deleteByUsrId(String usrId); + + @Query("DELETE FROM user_role") + void deleteAll(); +} + + diff --git a/android/clientmanager/src/main/java/io/mosip/registration/clientmanager/dto/http/IdSchemaResponse.java b/android/clientmanager/src/main/java/io/mosip/registration/clientmanager/dto/http/IdSchemaResponse.java index fee13d73e..f5249fb13 100644 --- a/android/clientmanager/src/main/java/io/mosip/registration/clientmanager/dto/http/IdSchemaResponse.java +++ b/android/clientmanager/src/main/java/io/mosip/registration/clientmanager/dto/http/IdSchemaResponse.java @@ -6,6 +6,7 @@ import io.mosip.registration.clientmanager.dto.uispec.FieldSpecDto; import io.mosip.registration.clientmanager.dto.uispec.ProcessSpecDto; +import io.mosip.registration.clientmanager.dto.uispec.SettingsSpecDto; import lombok.Data; @@ -19,4 +20,5 @@ public class IdSchemaResponse { private List schema; private String schemaJson; private String effectiveFrom; + private List settings; } diff --git a/android/clientmanager/src/main/java/io/mosip/registration/clientmanager/dto/uispec/SettingsSpecDto.java b/android/clientmanager/src/main/java/io/mosip/registration/clientmanager/dto/uispec/SettingsSpecDto.java new file mode 100644 index 000000000..edc9bbca5 --- /dev/null +++ b/android/clientmanager/src/main/java/io/mosip/registration/clientmanager/dto/uispec/SettingsSpecDto.java @@ -0,0 +1,30 @@ +package io.mosip.registration.clientmanager.dto.uispec; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonProperty; + +import java.util.HashMap; +import java.util.List; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@AllArgsConstructor +@NoArgsConstructor +@JsonIgnoreProperties(ignoreUnknown = true) +public class SettingsSpecDto { + + private String name; + private HashMap description; + private HashMap label; + private String fxml; + private String icon; + @JsonProperty("shortcut-icon") + private String shortcutIcon; + private String order; + @JsonProperty("access-control") + private List accessControl; + +} diff --git a/android/clientmanager/src/main/java/io/mosip/registration/clientmanager/entity/UserRole.java b/android/clientmanager/src/main/java/io/mosip/registration/clientmanager/entity/UserRole.java new file mode 100644 index 000000000..8d9276899 --- /dev/null +++ b/android/clientmanager/src/main/java/io/mosip/registration/clientmanager/entity/UserRole.java @@ -0,0 +1,27 @@ +package io.mosip.registration.clientmanager.entity; + +import androidx.annotation.NonNull; +import androidx.room.ColumnInfo; +import androidx.room.Entity; + +import lombok.AllArgsConstructor; +import lombok.Data; + +@Entity(tableName = "user_role", primaryKeys = {"usr_id", "role_code"}) +@Data +@AllArgsConstructor +public class UserRole { + + @NonNull + @ColumnInfo(name = "usr_id") + private String usrId; + + @NonNull + @ColumnInfo(name = "role_code") + private String roleCode; + + @ColumnInfo(name = "lang_code") + private String langCode; +} + + diff --git a/android/clientmanager/src/main/java/io/mosip/registration/clientmanager/repository/IdentitySchemaRepository.java b/android/clientmanager/src/main/java/io/mosip/registration/clientmanager/repository/IdentitySchemaRepository.java index f59912ac8..b34073a33 100644 --- a/android/clientmanager/src/main/java/io/mosip/registration/clientmanager/repository/IdentitySchemaRepository.java +++ b/android/clientmanager/src/main/java/io/mosip/registration/clientmanager/repository/IdentitySchemaRepository.java @@ -17,6 +17,7 @@ import io.mosip.registration.clientmanager.dto.uispec.ProcessSpecDto; import io.mosip.registration.clientmanager.dto.uispec.RequiredDto; import io.mosip.registration.clientmanager.dto.uispec.ScreenSpecDto; +import io.mosip.registration.clientmanager.dto.uispec.SettingsSpecDto; import io.mosip.registration.clientmanager.entity.IdentitySchema; import io.mosip.registration.clientmanager.entity.ProcessSpec; import io.mosip.registration.packetmanager.util.HMACUtils2; @@ -120,6 +121,15 @@ public ProcessSpecDto getNewProcessSpec(Context context, Double version) throws return getIdSchemaResponse(context, identitySchema).getNewProcess(); } + public List getSettingsSchema(Context context, Double version) throws Exception { + IdentitySchema identitySchema = identitySchemaDao.findIdentitySchema(version, SCHEMA_PREFIX+version); + + if(identitySchema == null) + throw new Exception("Identity schema not found for version : " + version); + + return getIdSchemaResponse(context, identitySchema).getSettings(); + } + public List getAllFieldSpec(Context context, Double version) throws Exception { List schemaFields = new ArrayList<>(); ProcessSpecDto processSpec = getNewProcessSpec(context, version); diff --git a/android/clientmanager/src/main/java/io/mosip/registration/clientmanager/repository/UserRoleRepository.java b/android/clientmanager/src/main/java/io/mosip/registration/clientmanager/repository/UserRoleRepository.java new file mode 100644 index 000000000..baccd8c2e --- /dev/null +++ b/android/clientmanager/src/main/java/io/mosip/registration/clientmanager/repository/UserRoleRepository.java @@ -0,0 +1,35 @@ +package io.mosip.registration.clientmanager.repository; + +import java.util.ArrayList; +import java.util.List; + +import javax.inject.Inject; + +import io.mosip.registration.clientmanager.dao.UserRoleDao; +import io.mosip.registration.clientmanager.entity.UserRole; + +public class UserRoleRepository { + + private final UserRoleDao userRoleDao; + + @Inject + public UserRoleRepository(UserRoleDao userRoleDao) { + this.userRoleDao = userRoleDao; + } + + public void saveRoles(String userId, List roleCodes) { + userRoleDao.deleteByUsrId(userId); + for (String code : roleCodes) { + userRoleDao.insert(new UserRole(userId, code, null)); + } + } + + public List getRolesByUserId(String userId) { + List rows = userRoleDao.findByUsrId(userId); + List codes = new ArrayList<>(); + for (UserRole r : rows) { + codes.add(r.getRoleCode()); + } + return codes; + } +} \ No newline at end of file diff --git a/android/clientmanager/src/main/java/io/mosip/registration/clientmanager/service/LoginService.java b/android/clientmanager/src/main/java/io/mosip/registration/clientmanager/service/LoginService.java index 0c1ab1ab2..7c14efa11 100644 --- a/android/clientmanager/src/main/java/io/mosip/registration/clientmanager/service/LoginService.java +++ b/android/clientmanager/src/main/java/io/mosip/registration/clientmanager/service/LoginService.java @@ -10,6 +10,7 @@ import org.json.JSONObject; import io.mosip.registration.clientmanager.repository.UserDetailRepository; +import io.mosip.registration.clientmanager.repository.UserRoleRepository; import io.mosip.registration.keymanager.dto.CryptoRequestDto; import io.mosip.registration.keymanager.dto.CryptoResponseDto; import io.mosip.registration.keymanager.spi.ClientCryptoManagerService; @@ -34,12 +35,16 @@ public class LoginService { @Inject UserDetailRepository userDetailRepository; + @Inject + UserRoleRepository userRoleRepository; + @Inject ClientCryptoManagerService clientCryptoManagerService; - public LoginService(Context context, ClientCryptoManagerService clientCryptoManagerService, UserDetailRepository userDetailRepository) { + public LoginService(Context context, ClientCryptoManagerService clientCryptoManagerService, UserDetailRepository userDetailRepository, UserRoleRepository userRoleRepository) { this.clientCryptoManagerService = clientCryptoManagerService; this.userDetailRepository = userDetailRepository; + this.userRoleRepository = userRoleRepository; this.sessionManager = SessionManager.getSessionManager(context); } @@ -80,6 +85,7 @@ public List saveAuthToken(String authResponse, String userId) throws Exc long rExpiry = Long.parseLong(jsonObject.getString("refreshExpiryTime")); userDetailRepository.saveUserAuthToken(userId, token, refreshToken, tExpiry, rExpiry); List roles=this.sessionManager.saveAuthToken(token); + userRoleRepository.saveRoles(userId, roles); return roles; } catch (Exception ex) { Log.e(TAG, ex.getMessage(), ex); @@ -111,4 +117,8 @@ public void clearAuthToken(Context context){ throw ex; } } + + public List getRolesByUserId(String userId) { + return userRoleRepository.getRolesByUserId(userId); + } } diff --git a/android/clientmanager/src/test/java/io/mosip/registration/clientmanager/config/AppModuleTest.java b/android/clientmanager/src/test/java/io/mosip/registration/clientmanager/config/AppModuleTest.java index 67dee3a0d..b744f7bc0 100644 --- a/android/clientmanager/src/test/java/io/mosip/registration/clientmanager/config/AppModuleTest.java +++ b/android/clientmanager/src/test/java/io/mosip/registration/clientmanager/config/AppModuleTest.java @@ -75,6 +75,7 @@ public class AppModuleTest { @Mock SyncJobDefRepository syncJobDefRepository; @Mock UserDetailRepository userDetailRepository; @Mock LanguageRepository languageRepository; + @Mock UserRoleRepository userRoleRepository; @Mock JobManagerService jobManagerService; @Mock FileSignatureDao fileSignatureDao; @Mock UserBiometricRepository userBiometricRepository; @@ -159,7 +160,7 @@ public void testProvideSyncRestFactory() { @Test public void testProvideLoginService() { - LoginService service = appModule.provideLoginService(clientCryptoManagerService, userDetailRepository); + LoginService service = appModule.provideLoginService(clientCryptoManagerService, userDetailRepository,userRoleRepository); assertNotNull(service); } diff --git a/android/clientmanager/src/test/java/io/mosip/registration/clientmanager/service/LoginServiceTest.java b/android/clientmanager/src/test/java/io/mosip/registration/clientmanager/service/LoginServiceTest.java index b6b34634f..b7191a7bf 100644 --- a/android/clientmanager/src/test/java/io/mosip/registration/clientmanager/service/LoginServiceTest.java +++ b/android/clientmanager/src/test/java/io/mosip/registration/clientmanager/service/LoginServiceTest.java @@ -11,6 +11,7 @@ import com.auth0.android.jwt.DecodeException; import io.mosip.registration.clientmanager.config.SessionManager; import io.mosip.registration.clientmanager.entity.UserDetail; +import io.mosip.registration.clientmanager.repository.UserRoleRepository; import io.mosip.registration.keymanager.dto.CryptoRequestDto; import io.mosip.registration.keymanager.dto.CryptoResponseDto; import org.json.JSONObject; @@ -34,6 +35,7 @@ @RunWith(MockitoJUnitRunner.class) public class LoginServiceTest { @Mock UserDetailRepository userDetailRepository; + @Mock UserRoleRepository userRoleRepository; @Mock ClientCryptoManagerService clientCryptoManagerService; @Mock Context context; LoginService loginService; @@ -42,7 +44,7 @@ public class LoginServiceTest { @Before public void setUp() { MockitoAnnotations.openMocks(this); - loginService = new LoginService(context, clientCryptoManagerService, userDetailRepository); + loginService = new LoginService(context, clientCryptoManagerService, userDetailRepository,userRoleRepository); } @Test(expected = InvalidMachineSpecIDException.class) @@ -71,7 +73,7 @@ public void isValidUserId_WithInactiveUser_Test() { @Test public void test_save_valid_auth_token_successfully() throws Exception { - LoginService loginService = new LoginService(context, clientCryptoManagerService, userDetailRepository); + LoginService loginService = new LoginService(context, clientCryptoManagerService, userDetailRepository,userRoleRepository); Field userDetailRepositoryField = LoginService.class.getDeclaredField("userDetailRepository"); userDetailRepositoryField.setAccessible(true); @@ -97,7 +99,7 @@ public void test_save_valid_auth_token_successfully() throws Exception { @Test public void test_handle_null_token_from_repository() throws Exception { - LoginService loginService = new LoginService(context, clientCryptoManagerService, userDetailRepository); + LoginService loginService = new LoginService(context, clientCryptoManagerService, userDetailRepository,userRoleRepository); Field userDetailRepositoryField = LoginService.class.getDeclaredField("userDetailRepository"); userDetailRepositoryField.setAccessible(true); @@ -120,7 +122,7 @@ public void test_handle_null_token_from_repository() throws Exception { @Test public void test_handles_empty_token_from_repository() throws Exception { - LoginService loginService = new LoginService(context, clientCryptoManagerService, userDetailRepository); + LoginService loginService = new LoginService(context, clientCryptoManagerService, userDetailRepository,userRoleRepository); String userId = "testUser"; when(userDetailRepository.getUserAuthToken(userId)).thenReturn(""); @@ -133,7 +135,7 @@ public void test_handles_empty_token_from_repository() throws Exception { @Test public void test_handles_exceptions_from_session_manager() { - LoginService loginService = new LoginService(context, clientCryptoManagerService, userDetailRepository); + LoginService loginService = new LoginService(context, clientCryptoManagerService, userDetailRepository,userRoleRepository); String userId = "testUser"; String token = "validToken"; @@ -146,7 +148,7 @@ public void test_handles_exceptions_from_session_manager() { @Test (expected = InvalidMachineSpecIDException.class) public void test_successful_auth_token_save() throws Exception { - LoginService loginService = new LoginService(context, clientCryptoManagerService, userDetailRepository); + LoginService loginService = new LoginService(context, clientCryptoManagerService, userDetailRepository,userRoleRepository); ClientCryptoManagerService mockCryptoService = mock(ClientCryptoManagerService.class); UserDetailRepository mockUserDetailRepository = mock(UserDetailRepository.class); @@ -174,7 +176,7 @@ public void test_successful_auth_token_save() throws Exception { @Test public void test_null_crypto_response_throws_exception() { - LoginService loginService = new LoginService(context, clientCryptoManagerService, userDetailRepository); + LoginService loginService = new LoginService(context, clientCryptoManagerService, userDetailRepository,userRoleRepository); String authResponse = "encryptedAuthResponse"; String userId = "testUser"; @@ -192,7 +194,7 @@ public void test_null_crypto_response_throws_exception() { @Test public void test_clear_auth_token_successful() { - LoginService loginService = new LoginService(context, clientCryptoManagerService, userDetailRepository); + LoginService loginService = new LoginService(context, clientCryptoManagerService, userDetailRepository,userRoleRepository); try { Field sessionManagerField = LoginService.class.getDeclaredField("sessionManager"); @@ -211,7 +213,7 @@ public void test_clear_auth_token_successful() { @Test public void test_clear_auth_token_throws_exception() { - LoginService loginService = new LoginService(context, clientCryptoManagerService, userDetailRepository); + LoginService loginService = new LoginService(context, clientCryptoManagerService, userDetailRepository,userRoleRepository); try { Field sessionManagerField = LoginService.class.getDeclaredField("sessionManager"); @@ -234,7 +236,7 @@ public void test_clear_auth_token_throws_exception() { @Test public void test_session_manager_null() { - LoginService loginService = new LoginService(context, null, null); + LoginService loginService = new LoginService(context, null, null,null); Exception exception = assertThrows(Exception.class, () -> { loginService.clearAuthToken(context); @@ -245,7 +247,7 @@ public void test_session_manager_null() { @Test public void test_session_manager_returns_non_null_value() { - LoginService loginService = new LoginService(context, null, null); + LoginService loginService = new LoginService(context, null, null,null); lenient().when(sessionManager.clearAuthToken()).thenReturn("non-null-token"); @@ -262,7 +264,7 @@ public void test_validate_password_returns_true_for_valid_credentials() { String password = "validPassword"; Mockito.when(userDetailRepository.isValidPassword(userId, password)).thenReturn(true); - LoginService loginService = new LoginService(context, clientCryptoManagerService, userDetailRepository); + LoginService loginService = new LoginService(context, clientCryptoManagerService, userDetailRepository, userRoleRepository); loginService.userDetailRepository = userDetailRepository; boolean result = loginService.validatePassword(userId, password); @@ -277,7 +279,7 @@ public void test_validate_password_handles_null_userid() { String password = "somePassword"; Mockito.when(userDetailRepository.isValidPassword(userId, password)).thenReturn(false); - LoginService loginService = new LoginService(context, clientCryptoManagerService, userDetailRepository); + LoginService loginService = new LoginService(context, clientCryptoManagerService, userDetailRepository, userRoleRepository); loginService.userDetailRepository = userDetailRepository; boolean result = loginService.validatePassword(userId, password); @@ -290,7 +292,7 @@ public void test_validate_password_handles_null_userid() { public void test_password_hash_stored_successfully() { String userId = "testUser"; String password = "testPassword"; - LoginService loginService = new LoginService(context, clientCryptoManagerService, userDetailRepository); + LoginService loginService = new LoginService(context, clientCryptoManagerService, userDetailRepository, userRoleRepository); loginService.setPasswordHash(userId, password); @@ -302,7 +304,7 @@ public void test_returns_true_when_password_exists_for_valid_user() { String validUserId = "validUser"; Mockito.when(userDetailRepository.isPasswordPresent(validUserId)).thenReturn(true); - LoginService loginService = new LoginService(context, clientCryptoManagerService, userDetailRepository); + LoginService loginService = new LoginService(context, clientCryptoManagerService, userDetailRepository, userRoleRepository); boolean result = loginService.isPasswordPresent(validUserId); @@ -315,7 +317,7 @@ public void test_returns_false_when_user_id_is_null() { String nullUserId = null; Mockito.when(userDetailRepository.isPasswordPresent(nullUserId)).thenReturn(false); - LoginService loginService = new LoginService(context, clientCryptoManagerService, userDetailRepository); + LoginService loginService = new LoginService(context, clientCryptoManagerService, userDetailRepository, userRoleRepository); boolean result = loginService.isPasswordPresent(nullUserId); @@ -333,7 +335,7 @@ public void test_get_user_details_returns_user_when_valid_userid() { Mockito.when(userDetailRepository.getUserDetailByUserId(userId)).thenReturn(expectedUserDetail); - LoginService loginService = new LoginService(context, clientCryptoManagerService, userDetailRepository); + LoginService loginService = new LoginService(context, clientCryptoManagerService, userDetailRepository, userRoleRepository); loginService.userDetailRepository = userDetailRepository; UserDetail result = loginService.getUserDetailsByUserId(userId); @@ -352,7 +354,7 @@ public void test_get_user_details_with_null_userid() { Mockito.when(userDetailRepository.getUserDetailByUserId(userId)).thenReturn(null); - LoginService loginService = new LoginService(context, clientCryptoManagerService, userDetailRepository); + LoginService loginService = new LoginService(context, clientCryptoManagerService, userDetailRepository, userRoleRepository); loginService.userDetailRepository = userDetailRepository; UserDetail result = loginService.getUserDetailsByUserId(userId); @@ -365,7 +367,7 @@ public void test_get_user_details_with_null_userid() { @Test public void test_returns_true_when_user_detail_count_is_zero() { Mockito.when(userDetailRepository.getUserDetailCount()).thenReturn(0); - LoginService loginService = new LoginService(context, clientCryptoManagerService, userDetailRepository); + LoginService loginService = new LoginService(context, clientCryptoManagerService, userDetailRepository, userRoleRepository); boolean result = loginService.isValidUserId("anyUserId"); diff --git a/lib/model/settings.dart b/lib/model/settings.dart new file mode 100644 index 000000000..2b274374d --- /dev/null +++ b/lib/model/settings.dart @@ -0,0 +1,22 @@ +import 'package:freezed_annotation/freezed_annotation.dart'; +import 'package:flutter/foundation.dart'; + +part 'settings.freezed.dart'; +part 'settings.g.dart'; + +@freezed +class Settings with _$Settings { + const factory Settings({ + Map? description, + String? fxml, + String? icon, + Map? label, + String? name, + String? order, + @JsonKey(name: 'access-control') List? accessControl, + @JsonKey(name: 'shortcut-icon') String? shortcutIcon, + }) = _Settings; + + factory Settings.fromJson(Map json) => + _$SettingsFromJson(json); +} diff --git a/lib/platform_android/auth_service_impl.dart b/lib/platform_android/auth_service_impl.dart index 6446f7876..59c36731b 100644 --- a/lib/platform_android/auth_service_impl.dart +++ b/lib/platform_android/auth_service_impl.dart @@ -123,6 +123,20 @@ class AuthServiceImpl implements AuthService { } return refreshLoginTime; } + + @override + Future> getRolesByUserId(String userId) async { + List rolesList = []; + try { + rolesList = await AuthResponseApi().getRolesByUserId(userId); + } on PlatformException { + debugPrint('getRolesByUserId call failed!'); + } catch (e) { + debugPrint(e.toString()); + } + return rolesList; + } + } AuthService getAuthServiceImpl() => AuthServiceImpl(); diff --git a/lib/platform_android/process_spec_service_impl.dart b/lib/platform_android/process_spec_service_impl.dart index ffe005835..26b65dea6 100644 --- a/lib/platform_android/process_spec_service_impl.dart +++ b/lib/platform_android/process_spec_service_impl.dart @@ -106,6 +106,21 @@ class ProcessSpecServiceImpl implements ProcessSpecService { } return optionalLanguageCodes; } + + @override + Future> getSettingSpec() async { + List settingSpec; + try { + settingSpec = await ProcessSpecApi().getSettingSpec(); + } on PlatformException { + debugPrint("Settings Spec Api failed!"); + settingSpec = List.empty(); + } catch (e) { + settingSpec = List.empty(); + debugPrint("Settings spec fetch error: $e"); + } + return settingSpec; + } } ProcessSpecService getProcessSpecServiceImpl() => ProcessSpecServiceImpl(); \ No newline at end of file diff --git a/lib/platform_spi/auth_service.dart b/lib/platform_spi/auth_service.dart index c3d750fa7..6b1f8bdb7 100644 --- a/lib/platform_spi/auth_service.dart +++ b/lib/platform_spi/auth_service.dart @@ -29,5 +29,7 @@ abstract class AuthService { Future getAutoLogoutPopupTimeout(); + Future> getRolesByUserId(String userId); + factory AuthService() => getAuthServiceImpl(); } diff --git a/lib/platform_spi/process_spec_service.dart b/lib/platform_spi/process_spec_service.dart index 8cb440d02..665dbb0c9 100644 --- a/lib/platform_spi/process_spec_service.dart +++ b/lib/platform_spi/process_spec_service.dart @@ -15,6 +15,7 @@ abstract class ProcessSpecService { Future> getOptionalLanguageCodes(); Future getMinLanguageCount(); Future getMaxLanguageCount(); + Future> getSettingSpec(); factory ProcessSpecService() => getProcessSpecServiceImpl(); } \ No newline at end of file diff --git a/lib/provider/auth_provider.dart b/lib/provider/auth_provider.dart index 8fd257ad8..c949f7e39 100644 --- a/lib/provider/auth_provider.dart +++ b/lib/provider/auth_provider.dart @@ -239,4 +239,7 @@ class AuthProvider with ChangeNotifier { notifyListeners(); } + Future> getUserRole(String userId) async { + return await auth.getRolesByUserId(userId); + } } diff --git a/lib/provider/registration_task_provider.dart b/lib/provider/registration_task_provider.dart index 60912808a..d3c9b740d 100644 --- a/lib/provider/registration_task_provider.dart +++ b/lib/provider/registration_task_provider.dart @@ -39,6 +39,7 @@ class RegistrationTaskProvider with ChangeNotifier { ); List _listOfProcesses = List.empty(growable: true); + List _listOfSettings = List.empty(growable: true); String _stringValueGlobalParam = ""; String _uiSchema = ""; String _registrationStartError = ''; @@ -52,6 +53,7 @@ class RegistrationTaskProvider with ChangeNotifier { int _numberOfPackets = 0; List get listOfProcesses => _listOfProcesses; + List get listOfSettings => _listOfSettings; String get stringValueGlobalParam => _stringValueGlobalParam; String get uiSchema => _uiSchema; String get previewTemplate => _previewTemplate; @@ -67,6 +69,11 @@ class RegistrationTaskProvider with ChangeNotifier { notifyListeners(); } + set listOfSettings(List value) { + _listOfSettings = value; + notifyListeners(); + } + setNumberOfPackets(int value) { _numberOfPackets = value; notifyListeners(); @@ -117,6 +124,16 @@ class RegistrationTaskProvider with ChangeNotifier { notifyListeners(); } + getListOfSettings() async { + List result = await processSpecService.getSettingSpec(); + if (result.isEmpty) { + _listOfSettings = []; + } else { + _listOfSettings = result; + } + notifyListeners(); + } + startRegistration( List languages, String flowType, String process) async { _registrationStartError = await registrationService.startRegistration( diff --git a/lib/ui/onboard/home_page.dart b/lib/ui/onboard/home_page.dart index b44145515..f50936ff5 100644 --- a/lib/ui/onboard/home_page.dart +++ b/lib/ui/onboard/home_page.dart @@ -13,6 +13,7 @@ import 'package:flutter_svg/flutter_svg.dart'; import 'package:intl/intl.dart'; import 'package:provider/provider.dart'; import 'package:registration_client/model/process.dart'; +import 'package:registration_client/model/settings.dart'; import 'package:registration_client/pigeon/biometrics_pigeon.dart'; import 'package:registration_client/pigeon/dynamic_response_pigeon.dart'; import 'package:registration_client/provider/approve_packets_provider.dart'; @@ -107,6 +108,11 @@ class _HomePageState extends State { globalProvider.setNotificationLanguages(fieldValues); } + Future> getSettingsUI(BuildContext context) async { + await registrationTaskProvider.getListOfSettings(); + return registrationTaskProvider.listOfSettings; + } + Widget getProcessUI(BuildContext context, Process process) { List sortedScreens; sortedScreens = process.screens!.toList()..sort((e1, e2) => e1!.order!.compareTo(e2!.order!)); @@ -259,6 +265,9 @@ class _HomePageState extends State { syncData: (BuildContext context) { syncData(context); }, + getSettingsUI: (BuildContext context) async { + return await getSettingsUI(context); + }, ); } } diff --git a/lib/ui/onboard/portrait/mobile_home_page.dart b/lib/ui/onboard/portrait/mobile_home_page.dart index eaa4cdabf..6f2ef03e7 100644 --- a/lib/ui/onboard/portrait/mobile_home_page.dart +++ b/lib/ui/onboard/portrait/mobile_home_page.dart @@ -9,6 +9,7 @@ import 'package:flutter/material.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart'; import 'package:provider/provider.dart'; import 'package:registration_client/model/process.dart'; +import 'package:registration_client/model/settings.dart'; import 'package:registration_client/provider/global_provider.dart'; import 'package:registration_client/ui/dashboard/user_dashboard.dart'; import 'package:registration_client/ui/onboard/portrait/tasks_page.dart'; @@ -16,6 +17,7 @@ import 'package:registration_client/ui/onboard/widgets/bottom_navbar_widget.dart import 'package:registration_client/utils/app_config.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; +import '../../process_ui/widgets/settings_screen.dart'; import '../../profile/profile.dart'; class MobileHomePage extends StatefulWidget { @@ -24,20 +26,22 @@ class MobileHomePage extends StatefulWidget { required this.operationalTasks, required this.getProcessUI, required this.syncData, + required this.getSettingsUI, }); final List> operationalTasks; final Function getProcessUI; final Function syncData; + final Function getSettingsUI; @override State createState() => _MobileHomePageState(); } class _MobileHomePageState extends State { - int selectedTab = 1; + int selectedTab = 2; changeTab(int index) { - if (index == 0 || index == 1 || index == 2) { + if (index == 0 || index == 1 || index == 2 || index == 3) { setState(() { selectedTab = index; }); @@ -48,9 +52,11 @@ class _MobileHomePageState extends State { Widget build(BuildContext context) { List bottomNavPages = [ const UserDashBoard(), - // const Center( - // child: Text("Settings"), - // ), + SettingsScreen( + getSettingsUI: (BuildContext context) async { + return await widget.getSettingsUI(context); + } + ), Container( height: ScreenUtil().screenHeight, width: ScreenUtil().screenWidth, @@ -127,16 +133,16 @@ class _MobileHomePageState extends State { title: AppLocalizations.of(context)!.dashboard, ), ), - // BottomNavigationBarItem( - // label: "", - // icon: BottomNavBarWidget( - // index: 1, - // selectedIndex: selectedTab, - // imagePath: settingsIcon, - // selectedImagePath: settingsSelectedIcon, - // title: AppLocalizations.of(context)!.settings, - // ), - // ), + BottomNavigationBarItem( + label: "", + icon: BottomNavBarWidget( + index: 1, + selectedIndex: selectedTab, + imagePath: settingsIcon, + selectedImagePath: settingsSelectedIcon, + title: AppLocalizations.of(context)!.settings, + ), + ), BottomNavigationBarItem( label: "", icon: SizedBox( @@ -162,7 +168,7 @@ class _MobileHomePageState extends State { BottomNavigationBarItem( label: "", icon: BottomNavBarWidget( - index: 2, + index: 3, selectedIndex: selectedTab, imagePath: profileIcon, selectedImagePath: profileSelectedIcon, diff --git a/lib/ui/process_ui/widgets/settings_screen.dart b/lib/ui/process_ui/widgets/settings_screen.dart new file mode 100644 index 000000000..561754af0 --- /dev/null +++ b/lib/ui/process_ui/widgets/settings_screen.dart @@ -0,0 +1,156 @@ +import 'dart:convert'; + +import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; +import 'package:registration_client/model/settings.dart'; +import 'package:registration_client/provider/auth_provider.dart'; +import 'package:registration_client/provider/global_provider.dart'; +import 'package:registration_client/utils/app_config.dart'; +import 'package:flutter_gen/gen_l10n/app_localizations.dart'; + +class SettingsScreen extends StatefulWidget { + const SettingsScreen({ + super.key, + required this.getSettingsUI, + }); + + final Future> Function(BuildContext) getSettingsUI; + + @override + State createState() => _SettingsScreenState(); +} + +class _SettingsScreenState extends State { + List settingUiSpec = []; + List settingUiByRole = []; + bool isLoadingUiSpec = true; + late AuthProvider authProvider; + + @override + void initState() { + super.initState(); + authProvider = Provider.of(context, listen: false); + _loadUiSpec(); + } + + Future _loadUiSpec() async { + final specList = await widget.getSettingsUI(context); + settingUiSpec = specList + .whereType() + .map((e) => Settings.fromJson(json.decode(e) as Map)) + .toList(); + + // Get current user roles + final userId = authProvider.userId; + final List userRoles = await authProvider.getUserRole(userId); + + // Filter tabs accessible to the user based on roles + settingUiByRole = settingUiSpec.where((settings) { + final access = settings.accessControl ?? []; + return access.any((role) => userRoles.contains(role)); + }).toList(); + + setState(() => isLoadingUiSpec = false); + } + + @override + Widget build(BuildContext context) { + if (isLoadingUiSpec) { + return const Center(child: CircularProgressIndicator()); + } + + + if (settingUiByRole.isEmpty) { + return const Center( + child: Text( + "You don't have access to this page.", + style: TextStyle(fontSize: 18, color: Colors.black), + ), + ); + } + + return DefaultTabController( + length: settingUiByRole.length, + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Container( + width: MediaQuery.of(context).size.width, + color: solidPrimary, + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Padding( + padding: const EdgeInsets.symmetric(horizontal: 16.0, vertical: 20.0), + child: Text( + AppLocalizations.of(context)!.settings, + style: const TextStyle( + fontSize: 22, + color: Colors.white, + fontWeight: FontWeight.w500, + ), + ), + ), + Container( + padding: const EdgeInsets.only(top: 8.0, bottom: 3.0), + decoration: const BoxDecoration( + border: Border( + top: BorderSide( + color: Color(0xFFE5EBFA), + width: .3, + ), + bottom: BorderSide( + color: Colors.blueAccent, + width: 1, + ), + ), + ), + child: TabBar( + labelColor: Colors.white, + unselectedLabelColor: Colors.white70, + indicatorColor: Colors.white, + indicatorWeight: 2.0, + indicatorSize: TabBarIndicatorSize.label, + tabs: [ + for (final settings in settingUiByRole) + Tab( + text: + settings.label?[context.read().selectedLanguage] ?? + settings.label?['eng'] ?? + (settings.label?.values.first ?? 'Unknown'), + ), + ], + ), + ), + ], + ), + ), + SizedBox( + height: 400, + child: TabBarView( + children: [ + for (final settings in settingUiByRole) _buildTabContent(settings), + ], + ), + ), + ], + ), + ); + } + + Widget _buildTabContent(Settings settings) { + final selectedLang = context.read().selectedLanguage; + return _buildDescriptionOnlyTab(settings, selectedLang); + } + + Widget _buildDescriptionOnlyTab(Settings settings, String selectedLang) { + return Center( + child: Text( + settings.description?[selectedLang] ?? + settings.description?['eng'] ?? + (settings.description?.values.first ?? 'No description available'), + style: const TextStyle(color: Colors.black), + ), + ); + } +} diff --git a/pigeon/auth_response.dart b/pigeon/auth_response.dart index b252d9426..1c1587ffa 100644 --- a/pigeon/auth_response.dart +++ b/pigeon/auth_response.dart @@ -38,5 +38,6 @@ abstract class AuthResponseApi { String getIdleTime(); @async String getAutoLogoutPopupTimeout(); - + @async + List getRolesByUserId(String userId); } diff --git a/pigeon/process_spec.dart b/pigeon/process_spec.dart index e7793466b..76848983e 100644 --- a/pigeon/process_spec.dart +++ b/pigeon/process_spec.dart @@ -21,5 +21,8 @@ abstract class ProcessSpecApi { int getMinLanguageCount(); @async - int getMaxLanguageCount(); + int getMaxLanguageCount(); + + @async + List getSettingSpec(); } \ No newline at end of file From 9fc83ec5106a77ee9b559ab415388e9213c7c97e Mon Sep 17 00:00:00 2001 From: Rakshithasai123 Date: Fri, 29 Aug 2025 17:56:42 +0530 Subject: [PATCH 16/44] UI Chnages (#572) Signed-off-by: Rakshithasai123 --- lib/ui/process_ui/widgets/dropdown_control.dart | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/lib/ui/process_ui/widgets/dropdown_control.dart b/lib/ui/process_ui/widgets/dropdown_control.dart index fdcdcab81..0ebede31b 100644 --- a/lib/ui/process_ui/widgets/dropdown_control.dart +++ b/lib/ui/process_ui/widgets/dropdown_control.dart @@ -271,13 +271,10 @@ class _CustomDropDownState extends State { items: list .map((option) => DropdownMenuItem( value: option, - child: Flexible( - child: - Text(option!.concatenatedName ?? option.name, - overflow: TextOverflow.ellipsis, - maxLines: 1, - softWrap: false, - ), + child: Text(option!.concatenatedName ?? option.name, + overflow: TextOverflow.ellipsis, + maxLines: 1, + softWrap: false, ), )) .toList(), From 328106dca57463d8b948f7d239db8ffe2bc7194e Mon Sep 17 00:00:00 2001 From: Rakshithasai123 Date: Fri, 29 Aug 2025 17:57:18 +0530 Subject: [PATCH 17/44] added review_status in other languages (#571) * added review_status in other languages Signed-off-by: Rakshithasai123 * added review_status in other languages Signed-off-by: Rakshithasai123 * Remove duplicate review_status key in Arabic translations Signed-off-by: Rakshithasai123 --------- Signed-off-by: Rakshithasai123 --- assets/l10n/app_ar.arb | 1 + assets/l10n/app_fr.arb | 1 + assets/l10n/app_hi.arb | 1 + assets/l10n/app_kn.arb | 1 + assets/l10n/app_ta.arb | 1 + 5 files changed, 5 insertions(+) diff --git a/assets/l10n/app_ar.arb b/assets/l10n/app_ar.arb index 798785fa3..a208cf437 100644 --- a/assets/l10n/app_ar.arb +++ b/assets/l10n/app_ar.arb @@ -175,6 +175,7 @@ }, "client_status": " حالة العميل", "server_status": "حالة الملقم", + "review_status": "حالة المراجعة", "clear_filter": "مرشح واضح", "serial_number": "س.ن", "application_id": "رقم الاستمارة", diff --git a/assets/l10n/app_fr.arb b/assets/l10n/app_fr.arb index 326894d57..03b063b60 100644 --- a/assets/l10n/app_fr.arb +++ b/assets/l10n/app_fr.arb @@ -176,6 +176,7 @@ "client_status": "Statut du client", "server_status": "État du serveur", "clear_filter": "Effacer le filtre", + "review_status": "Statut d'examen", "serial_number": "S.non", "application_id": "ID d'application", "reg_date": "Rég. Date", diff --git a/assets/l10n/app_hi.arb b/assets/l10n/app_hi.arb index 55253d332..cd78d034b 100644 --- a/assets/l10n/app_hi.arb +++ b/assets/l10n/app_hi.arb @@ -176,6 +176,7 @@ "client_status": "ग्राहक स्थिति", "server_status": "सर्वर की स्थिति", "clear_filter": "फ़िल्टर साफ़ करें", + "review_status": "समीक्षा स्थिति", "serial_number": "क्र.सं", "application_id": "आवेदन पहचान पत्र", "reg_date": "रजि. तारीख", diff --git a/assets/l10n/app_kn.arb b/assets/l10n/app_kn.arb index da34b390a..d9d51a0a7 100644 --- a/assets/l10n/app_kn.arb +++ b/assets/l10n/app_kn.arb @@ -176,6 +176,7 @@ "client_status": "ಕ್ಲೈಂಟ್ ಸ್ಥಿತಿ", "server_status": "ಸರ್ವರ್ ಸ್ಥಿತಿ", "clear_filter": "Clear Filter", + "review_status": "ಪುನರ್ ಪರಿಶೀಲನೆ ಸ್ಥಿತಿ", "serial_number": "ಎಸ್.ಎನ್", "application_id": "ಅಪ್ಲಿಕೇಶನ್ ಐಡಿ", "reg_date": "ರೆಗ್. ದಿನಾಂಕ", diff --git a/assets/l10n/app_ta.arb b/assets/l10n/app_ta.arb index 176137b12..a61562ac4 100644 --- a/assets/l10n/app_ta.arb +++ b/assets/l10n/app_ta.arb @@ -167,6 +167,7 @@ }, "client_status": "வாடிக்கையாளர் நிலை", "server_status": "சேவையக நிலை", + "review_status": "மீளாய்வு நிலை", "clear_filter": "Clear Filter", "serial_number": "எஸ்.என்", "application_id": "விண்ணப்ப ஐடி", From 8e193bb6da520127ff80ccc8bc552c92671915a3 Mon Sep 17 00:00:00 2001 From: Rakshithasai123 Date: Thu, 25 Sep 2025 11:27:33 +0530 Subject: [PATCH 18/44] fixed the issue When navigating from preview to Document upload, POI document value is getting reset during Update UIN (#578) Signed-off-by: Rakshithasai123 --- .../widgets/update_process_screen_content.dart | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/lib/ui/process_ui/widgets/update_process_screen_content.dart b/lib/ui/process_ui/widgets/update_process_screen_content.dart index 6305b8b61..9ea1d7a73 100644 --- a/lib/ui/process_ui/widgets/update_process_screen_content.dart +++ b/lib/ui/process_ui/widgets/update_process_screen_content.dart @@ -147,11 +147,11 @@ class _UpdateProcessScreenContentState evaluateMVELRequired(String fieldData, Field e) async { registrationTaskProvider.evaluateMVELRequired(fieldData).then((value) { - if (!value && globalProvider.selectedUpdateFields[e.group] == null) { - globalProvider.removeFieldFromMap( - e.id!, globalProvider.fieldInputValue); - registrationTaskProvider.removeDemographicField(e.id!); - } + // if (!value && globalProvider.selectedUpdateFields[e.group] == null) { + // globalProvider.removeFieldFromMap( + // e.id!, globalProvider.fieldInputValue); + // registrationTaskProvider.removeDemographicField(e.id!); + // } globalProvider.setMvelRequiredFields(e.id!, value); }); } From e54a443d86a81f7214097bf8cac786b8fc953d37 Mon Sep 17 00:00:00 2001 From: Rakshithasai123 Date: Thu, 25 Sep 2025 11:28:37 +0530 Subject: [PATCH 19/44] fixed the fetch invalid application id from pre-reg,the page is not refreshing (#574) Signed-off-by: Rakshithasai123 --- lib/ui/process_ui/widgets/pre_reg_data_control.dart | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/lib/ui/process_ui/widgets/pre_reg_data_control.dart b/lib/ui/process_ui/widgets/pre_reg_data_control.dart index a6a9d1b4b..466e72c87 100644 --- a/lib/ui/process_ui/widgets/pre_reg_data_control.dart +++ b/lib/ui/process_ui/widgets/pre_reg_data_control.dart @@ -272,6 +272,13 @@ class _PreRegDataControlState extends State { context: context, builder: (BuildContext context) => ValidatorAlert(errorMessage: AppLocalizations.of(context)!.application_id_not_exist,subError: AppLocalizations.of(context)!.correct_application_id), ); + await context.read< + RegistrationTaskProvider>() + .fetchPreRegistrationDetail( + preRegIdController.text); + + globalProvider.clearMap(); + globalProvider.clearScannedPages(); globalProvider.preRegControllerRefresh = false; } else { globalProvider.preRegControllerRefresh = true; From a2cfa5aa523d39c4fca0be680caea6d6a6a2bc2f Mon Sep 17 00:00:00 2001 From: Rakshithasai123 Date: Tue, 30 Sep 2025 01:05:02 +0530 Subject: [PATCH 20/44] Fixed quality % in red color, if the threshold is not crossed instead of yellow (#587) Signed-off-by: Rakshithasai123 --- .../widgets_mobile/biometric_capture_control_portrait.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/ui/process_ui/widgets_mobile/biometric_capture_control_portrait.dart b/lib/ui/process_ui/widgets_mobile/biometric_capture_control_portrait.dart index 414467e08..49581005e 100644 --- a/lib/ui/process_ui/widgets_mobile/biometric_capture_control_portrait.dart +++ b/lib/ui/process_ui/widgets_mobile/biometric_capture_control_portrait.dart @@ -148,7 +148,7 @@ class _BiometricCaptureControlPortraitState .toInt() < int.parse(biometricAttributeData .thresholdPercentage)) - ? secondaryColors.elementAt(26) + ? secondaryColors.elementAt(16) : secondaryColors.elementAt(11), borderRadius: BorderRadius.circular(50)), height: 40, From abc887a79e671b41b008e6f148e1514a15a5ff28 Mon Sep 17 00:00:00 2001 From: Rakshithasai123 Date: Tue, 30 Sep 2025 01:07:59 +0530 Subject: [PATCH 21/44] fixed the issue removed the next arrow button when user is in last page-new ,lost and update reg (#585) Signed-off-by: Rakshithasai123 --- lib/ui/process_ui/lost_process.dart | 1 + lib/ui/process_ui/new_process.dart | 1 + lib/ui/process_ui/update_process.dart | 1 + 3 files changed, 3 insertions(+) diff --git a/lib/ui/process_ui/lost_process.dart b/lib/ui/process_ui/lost_process.dart index fd794c88d..e35904b10 100644 --- a/lib/ui/process_ui/lost_process.dart +++ b/lib/ui/process_ui/lost_process.dart @@ -1004,6 +1004,7 @@ class _LostProcessState extends State }), ), ), + if (context.watch().newProcessTabIndex < size + 2) Container( height: 36.h, width: 25.w, diff --git a/lib/ui/process_ui/new_process.dart b/lib/ui/process_ui/new_process.dart index bcd1c1296..93cb7433a 100644 --- a/lib/ui/process_ui/new_process.dart +++ b/lib/ui/process_ui/new_process.dart @@ -957,6 +957,7 @@ class _NewProcessState extends State with WidgetsBindingObserver { }), ), ), + if (context.watch().newProcessTabIndex < size + 2) Container( height: 36.h, width: 25.w, diff --git a/lib/ui/process_ui/update_process.dart b/lib/ui/process_ui/update_process.dart index bb61c0a01..7b6704ee1 100644 --- a/lib/ui/process_ui/update_process.dart +++ b/lib/ui/process_ui/update_process.dart @@ -944,6 +944,7 @@ class _UpdateProcessState extends State }), ), ), + if (context.watch().newProcessTabIndex < size + 2) Container( height: 36.h, width: 25.w, From d688d3e3f372d344bb829d6e8c038568eb2ff4fc Mon Sep 17 00:00:00 2001 From: Rakshithasai123 Date: Tue, 30 Sep 2025 01:09:29 +0530 Subject: [PATCH 22/44] The Attempt button should turn green and the captured biometrics should display a green tick mark once the biometric score crosses the threshold value (#584) * Fixed The Attempt button should turn green and the captured biometrics should display a green tick mark once the biometric score crosses the threshold value Signed-off-by: Rakshithasai123 * Renamed the files Signed-off-by: Rakshithasai123 * Update operator_biometrics_capture_view.dart Signed-off-by: Rakshithasai123 * Update operator_biometrics_capture_view.dart Signed-off-by: Rakshithasai123 * Update operator_biometrics_capture_view.dart Signed-off-by: Rakshithasai123 * Update operator_biometrics_capture_view.dart Signed-off-by: Rakshithasai123 --------- Signed-off-by: Rakshithasai123 --- .../{Group 57548@2x.png => Exception_Mark.png} | Bin .../images/{Group 57745@2x.png => Green_Check.png} | Bin .../widgets/operator_biometrics_capture_view.dart | 10 +++++----- .../biometric_capture_control_portrait.dart | 11 ++++++++--- .../biometric_capture_scan_block_portrait.dart | 4 +++- 5 files changed, 16 insertions(+), 9 deletions(-) rename assets/images/{Group 57548@2x.png => Exception_Mark.png} (100%) rename assets/images/{Group 57745@2x.png => Green_Check.png} (100%) diff --git a/assets/images/Group 57548@2x.png b/assets/images/Exception_Mark.png similarity index 100% rename from assets/images/Group 57548@2x.png rename to assets/images/Exception_Mark.png diff --git a/assets/images/Group 57745@2x.png b/assets/images/Green_Check.png similarity index 100% rename from assets/images/Group 57745@2x.png rename to assets/images/Green_Check.png diff --git a/lib/ui/onboard/widgets/operator_biometrics_capture_view.dart b/lib/ui/onboard/widgets/operator_biometrics_capture_view.dart index b14526942..87b03d798 100644 --- a/lib/ui/onboard/widgets/operator_biometrics_capture_view.dart +++ b/lib/ui/onboard/widgets/operator_biometrics_capture_view.dart @@ -111,17 +111,17 @@ class _OperatorBiometricsCaptureState right: 15, child: (biometricAttributeData.exceptions.contains(true)) ? Image.asset( - "assets/images/Group 57548@2x.png", - ) + "assets/images/Exception_Mark.png", + ) : Image.asset( - "assets/images/Group 57745@2x.png", - )), + "assets/images/Green_Check.png", + )), if (!biometricAttributeData.exceptions.contains(false)) Positioned( top: 15, right: 15, child: Image.asset( - "assets/images/Group 57548@2x.png", + "assets/images/Exception_Mark.png", )), if (biometricAttributeData.isScanned == true) Positioned( diff --git a/lib/ui/process_ui/widgets_mobile/biometric_capture_control_portrait.dart b/lib/ui/process_ui/widgets_mobile/biometric_capture_control_portrait.dart index 49581005e..81f8c3269 100644 --- a/lib/ui/process_ui/widgets_mobile/biometric_capture_control_portrait.dart +++ b/lib/ui/process_ui/widgets_mobile/biometric_capture_control_portrait.dart @@ -123,18 +123,23 @@ class _BiometricCaptureControlPortraitState top: 15, right: 15, child: (biometricAttributeData.exceptions.contains(true)) + ? Image.asset( + "assets/images/Exception_Mark.png", + ) + : (biometricAttributeData.qualityPercentage < + ((int.tryParse(biometricAttributeData.thresholdPercentage) ?? 0).toDouble())) ? Image.asset( - "assets/images/Group 57548@2x.png", + "assets/images/Exception_Mark.png", ) : Image.asset( - "assets/images/Group 57745@2x.png", + "assets/images/Green_Check.png", )), if (!biometricAttributeData.exceptions.contains(false)) Positioned( top: 15, right: 15, child: Image.asset( - "assets/images/Group 57548@2x.png", + "assets/images/Exception_Mark.png", )), if (biometricAttributeData.isScanned == true) Positioned( diff --git a/lib/ui/process_ui/widgets_mobile/biometric_capture_scan_block_portrait.dart b/lib/ui/process_ui/widgets_mobile/biometric_capture_scan_block_portrait.dart index f6c8e7649..abe9ba2a0 100644 --- a/lib/ui/process_ui/widgets_mobile/biometric_capture_scan_block_portrait.dart +++ b/lib/ui/process_ui/widgets_mobile/biometric_capture_scan_block_portrait.dart @@ -503,7 +503,9 @@ class _BiometricCaptureScanBlockPortraitState ), color: (biometricAttributeData.attemptNo < i) ? secondaryColors.elementAt(18) - : secondaryColors.elementAt(11), + : (biometricAttributeData.qualityPercentage < ((int.tryParse(biometricAttributeData.thresholdPercentage) ?? 0).toDouble()) + ? secondaryColors.elementAt(26) + : secondaryColors.elementAt(11)), ), child: Text( i.toString(), From 84d6a0d94841e3ea9bd86b728d614acda66d4621 Mon Sep 17 00:00:00 2001 From: jayesh12234 <111957576+jayesh12234@users.noreply.github.com> Date: Tue, 30 Sep 2025 01:16:12 +0530 Subject: [PATCH 23/44] RCF-916- added preg reg creation flow in Arc automation (#580) * RCF-916 Signed-off-by: Jayesh Kharode * 1 Signed-off-by: Jayesh Kharode * RCF-916 Signed-off-by: Jayesh Kharode --------- Signed-off-by: Jayesh Kharode Co-authored-by: Jayesh Kharode --- ui-test/pom.xml | 28 +- .../androidTestCases/AddMachineDetails.java | 5 +- .../androidTestCases/IntialLunch.java | 4 +- .../NewRegistrationAdult.java | 14 +- .../NewRegistrationAdultException.java | 8 +- .../NewRegistrationInfant.java | 8 +- .../NewRegistrationMinor.java | 8 +- .../NewRegistrationMinorException.java | 8 +- .../UpdateMyUINUpdateDemographicDetails.java | 8 +- .../androidTestCases/UpdateMyUinInfant.java | 8 +- .../androidTestCases/UpdateMyUinMinor.java | 8 +- .../UpdateMyUinUpdateBiometrics.java | 8 +- .../regclient/androidTestCases/logintest.java | 10 +- .../java/regclient/api/AdminTestUtil.java | 191 +++++- .../java/regclient/api/ArcConfigManager.java | 116 ++++ .../main/java/regclient/api/BaseTestCase.java | 6 +- .../java/regclient/api/ConfigManager.java | 601 ------------------ .../regclient/api/KernelAuthentication.java | 18 +- .../regclient/api/KeycloakUserManager.java | 20 +- .../main/java/regclient/api/RestClient.java | 2 +- .../java/regclient/utils/EmailableReport.java | 4 +- .../main/java/regclient/utils/TestRunner.java | 20 +- .../main/resources/config/Kernel.properties | 3 + .../resources/config/application.properties | 88 ++- .../resources/config/valueMapping.properties | 35 + 25 files changed, 544 insertions(+), 685 deletions(-) create mode 100644 ui-test/src/main/java/regclient/api/ArcConfigManager.java delete mode 100644 ui-test/src/main/java/regclient/api/ConfigManager.java create mode 100644 ui-test/src/main/resources/config/valueMapping.properties diff --git a/ui-test/pom.xml b/ui-test/pom.xml index 52debc1c9..3354d6a58 100644 --- a/ui-test/pom.xml +++ b/ui-test/pom.xml @@ -1,4 +1,6 @@ - + 4.0.0 io.mosip.regclient uitest-regclient @@ -60,7 +62,8 @@ - + regclient.utils.TestRunner @@ -81,6 +84,12 @@ json-simple 1.1.1 + + com.github.javafaker + javafaker + 1.0.2 + + org.testng testng @@ -176,6 +185,21 @@ resteasy-jaxb-provider 3.15.0.Final + + io.mosip.testrig.apitest.commons + apitest-commons + 1.3.4 + + + org.slf4j + slf4j-api + + + com.google.guava + guava + + + diff --git a/ui-test/src/main/java/regclient/androidTestCases/AddMachineDetails.java b/ui-test/src/main/java/regclient/androidTestCases/AddMachineDetails.java index f160e8389..cb1bed1da 100644 --- a/ui-test/src/main/java/regclient/androidTestCases/AddMachineDetails.java +++ b/ui-test/src/main/java/regclient/androidTestCases/AddMachineDetails.java @@ -1,7 +1,6 @@ package regclient.androidTestCases; import static org.testng.Assert.assertEquals; -import static org.testng.Assert.assertTrue; import java.awt.datatransfer.UnsupportedFlavorException; import java.io.IOException; @@ -10,7 +9,7 @@ import regclient.BaseTest.AndroidBaseTest; import regclient.api.AdminTestUtil; -import regclient.api.ConfigManager; +import regclient.api.ArcConfigManager; import regclient.api.KeycloakUserManager; import regclient.page.BasePage; import regclient.pages.english.LoginPageEnglish; @@ -27,7 +26,7 @@ public void addMachineDetails() throws UnsupportedFlavorException, IOException { loginPage.enterUserName(KeycloakUserManager.moduleSpecificUser); loginPage.clickOnNextButton(); - loginPage.enterPassword(ConfigManager.getIAMUsersPassword()); + loginPage.enterPassword(ArcConfigManager.getIAMUsersPassword()); loginPage.clickOnloginButton(); // assertTrue(loginPage.isMachineNotFoundMessageDisplayed(), "verify if the machine not found message displayed"); diff --git a/ui-test/src/main/java/regclient/androidTestCases/IntialLunch.java b/ui-test/src/main/java/regclient/androidTestCases/IntialLunch.java index 7c4b04eac..7d4fa844f 100644 --- a/ui-test/src/main/java/regclient/androidTestCases/IntialLunch.java +++ b/ui-test/src/main/java/regclient/androidTestCases/IntialLunch.java @@ -5,7 +5,7 @@ import org.testng.annotations.Test; import regclient.BaseTest.AndroidBaseTest; -import regclient.api.ConfigManager; +import regclient.api.ArcConfigManager; import regclient.api.KeycloakUserManager; import regclient.page.BasePage; import regclient.pages.english.LoginPageEnglish; @@ -26,7 +26,7 @@ public void initallLaunch() { assertTrue(loginPage.isBackButtonDisplayed(), "Verify if back button is displayed"); assertTrue(loginPage.isForgetOptionDisplayed(), "Verify if forget password option is displayed"); assertTrue(loginPage.isPasswordHeaderDisplayed(), "Verify if the password input box header displayed"); - loginPage.enterPassword(ConfigManager.getIAMUsersPassword()); + loginPage.enterPassword(ArcConfigManager.getIAMUsersPassword()); assertTrue(loginPage.isLoginButtonEnabled(), "Verify if the login button enabled"); loginPage.clickOnloginButton(); diff --git a/ui-test/src/main/java/regclient/androidTestCases/NewRegistrationAdult.java b/ui-test/src/main/java/regclient/androidTestCases/NewRegistrationAdult.java index 59cb84514..2d3e505dc 100644 --- a/ui-test/src/main/java/regclient/androidTestCases/NewRegistrationAdult.java +++ b/ui-test/src/main/java/regclient/androidTestCases/NewRegistrationAdult.java @@ -8,7 +8,7 @@ import org.testng.annotations.Test; import regclient.BaseTest.AndroidBaseTest; -import regclient.api.ConfigManager; +import regclient.api.ArcConfigManager; import regclient.api.FetchUiSpec; import regclient.api.KeycloakUserManager; import regclient.page.AcknowledgementPage; @@ -174,7 +174,7 @@ else if(TestDataReader.readData("language").equalsIgnoreCase("ara")){ loginPage.enterUserName(KeycloakUserManager.moduleSpecificUser); loginPage.clickOnNextButton(); - loginPage.enterPassword(ConfigManager.getIAMUsersPassword()); + loginPage.enterPassword(ArcConfigManager.getIAMUsersPassword()); loginPage.clickOnloginButton(); if(TestDataReader.readData("language").equalsIgnoreCase("eng")) { @@ -457,7 +457,7 @@ else if(TestDataReader.readData("language").equalsIgnoreCase("ara")){ } assertTrue(authenticationPage.isAuthenticationPageDisplayed(),"Verify if authentication details page is displayed"); authenticationPage.enterUserName(KeycloakUserManager.moduleSpecificUser); - authenticationPage.enterPassword(ConfigManager.getIAMUsersPassword()); + authenticationPage.enterPassword(ArcConfigManager.getIAMUsersPassword()); authenticationPage.clickOnAuthenticatenButton(); if(TestDataReader.readData("language").equalsIgnoreCase("eng")) { acknowledgementPage=new AcknowledgementPageEnglish(driver); @@ -548,7 +548,7 @@ else if(TestDataReader.readData("language").equalsIgnoreCase("ara")){ assertTrue(pendingApproval.isInvalidUsernameMessageDisplayed(), "Verify if invalid username messgae is displayed"); pendingApproval.enterUserName(KeycloakUserManager.moduleSpecificUser); - pendingApproval.enterPassword(ConfigManager.getIAMUsersPassword()); + pendingApproval.enterPassword(ArcConfigManager.getIAMUsersPassword()); pendingApproval.clickOnSubmitButton(); pendingApproval.clickOnBackButton(); assertTrue(operationalTaskPage.isApplicationUploadTitleDisplayed(), "Verify if application upload tite displayed"); @@ -663,7 +663,7 @@ else if(TestDataReader.readData("language").equalsIgnoreCase("ara")){ loginPage.enterUserName(KeycloakUserManager.moduleSpecificUser); loginPage.clickOnNextButton(); - loginPage.enterPassword(ConfigManager.getIAMUsersPassword()); + loginPage.enterPassword(ArcConfigManager.getIAMUsersPassword()); loginPage.clickOnloginButton(); if(TestDataReader.readData("language").equalsIgnoreCase("eng")) { registrationTasksPage=new RegistrationTasksPageEnglish(driver); @@ -1143,7 +1143,7 @@ else if(TestDataReader.readData("language").equalsIgnoreCase("ara")){ assertTrue(authenticationPage.isAuthenticationPageDisplayed(),"Username/password required error should be displayed"); authenticationPage.clickOnAuthenticatenButton(); authenticationPage.enterUserName(KeycloakUserManager.moduleSpecificUser); - authenticationPage.enterPassword(ConfigManager.getIAMUsersPassword()); + authenticationPage.enterPassword(ArcConfigManager.getIAMUsersPassword()); authenticationPage.clickOnAuthenticatenButton(); if(TestDataReader.readData("language").equalsIgnoreCase("eng")) { acknowledgementPage=new AcknowledgementPageEnglish(driver); @@ -1237,7 +1237,7 @@ else if(TestDataReader.readData("language").equalsIgnoreCase("ara")){ assertTrue(pendingApproval.isSupervisorAuthenticationTitleDisplayed(), "Verify if Supervisor Authentication page displayed"); pendingApproval.enterUserName(KeycloakUserManager.moduleSpecificUser); - pendingApproval.enterPassword(ConfigManager.getIAMUsersPassword()); + pendingApproval.enterPassword(ArcConfigManager.getIAMUsersPassword()); pendingApproval.clickOnSubmitButton(); pendingApproval.clickOnBackButton(); assertTrue(operationalTaskPage.isApplicationUploadTitleDisplayed(), "Verify if application upload tite displayed"); diff --git a/ui-test/src/main/java/regclient/androidTestCases/NewRegistrationAdultException.java b/ui-test/src/main/java/regclient/androidTestCases/NewRegistrationAdultException.java index c305b101f..9fe3dad1d 100644 --- a/ui-test/src/main/java/regclient/androidTestCases/NewRegistrationAdultException.java +++ b/ui-test/src/main/java/regclient/androidTestCases/NewRegistrationAdultException.java @@ -7,7 +7,7 @@ import org.testng.annotations.Test; import regclient.BaseTest.AndroidBaseTest; -import regclient.api.ConfigManager; +import regclient.api.ArcConfigManager; import regclient.api.FetchUiSpec; import regclient.api.KeycloakUserManager; import regclient.page.AcknowledgementPage; @@ -165,7 +165,7 @@ else if(TestDataReader.readData("language").equalsIgnoreCase("ara")){ loginPage.enterUserName(KeycloakUserManager.moduleSpecificUser); loginPage.clickOnNextButton(); - loginPage.enterPassword(ConfigManager.getIAMUsersPassword()); + loginPage.enterPassword(ArcConfigManager.getIAMUsersPassword()); loginPage.clickOnloginButton(); if(TestDataReader.readData("language").equalsIgnoreCase("eng")) { registrationTasksPage=new RegistrationTasksPageEnglish(driver); @@ -502,7 +502,7 @@ else if(TestDataReader.readData("language").equalsIgnoreCase("ara")){ } assertTrue(authenticationPage.isAuthenticationPageDisplayed(),"Verify if authentication details page is displayed"); authenticationPage.enterUserName(KeycloakUserManager.moduleSpecificUser); - authenticationPage.enterPassword(ConfigManager.getIAMUsersPassword()); + authenticationPage.enterPassword(ArcConfigManager.getIAMUsersPassword()); authenticationPage.clickOnAuthenticatenButton(); if(TestDataReader.readData("language").equalsIgnoreCase("eng")) { acknowledgementPage=new AcknowledgementPageEnglish(driver); @@ -585,7 +585,7 @@ else if(TestDataReader.readData("language").equalsIgnoreCase("ara")){ assertTrue(pendingApproval.isSupervisorAuthenticationTitleDisplayed(), "Verify if Supervisor Authentication page displayed"); pendingApproval.enterUserName(KeycloakUserManager.moduleSpecificUser); - pendingApproval.enterPassword(ConfigManager.getIAMUsersPassword()); + pendingApproval.enterPassword(ArcConfigManager.getIAMUsersPassword()); pendingApproval.clickOnSubmitButton(); pendingApproval.clickOnBackButton(); diff --git a/ui-test/src/main/java/regclient/androidTestCases/NewRegistrationInfant.java b/ui-test/src/main/java/regclient/androidTestCases/NewRegistrationInfant.java index c7524f302..453e9f155 100644 --- a/ui-test/src/main/java/regclient/androidTestCases/NewRegistrationInfant.java +++ b/ui-test/src/main/java/regclient/androidTestCases/NewRegistrationInfant.java @@ -7,7 +7,7 @@ import org.testng.annotations.Test; import regclient.BaseTest.AndroidBaseTest; -import regclient.api.ConfigManager; +import regclient.api.ArcConfigManager; import regclient.api.FetchUiSpec; import regclient.api.KeycloakUserManager; import regclient.page.AcknowledgementPage; @@ -173,7 +173,7 @@ else if(TestDataReader.readData("language").equalsIgnoreCase("ara")){ loginPage.enterUserName(KeycloakUserManager.moduleSpecificUser); loginPage.clickOnNextButton(); - loginPage.enterPassword(ConfigManager.getIAMUsersPassword()); + loginPage.enterPassword(ArcConfigManager.getIAMUsersPassword()); loginPage.clickOnloginButton(); if(TestDataReader.readData("language").equalsIgnoreCase("eng")) { registrationTasksPage=new RegistrationTasksPageEnglish(driver); @@ -468,7 +468,7 @@ else if(TestDataReader.readData("language").equalsIgnoreCase("ara")){ } assertTrue(authenticationPage.isAuthenticationPageDisplayed(),"Verify if authentication details page is displayed"); authenticationPage.enterUserName(KeycloakUserManager.moduleSpecificUser); - authenticationPage.enterPassword(ConfigManager.getIAMUsersPassword()); + authenticationPage.enterPassword(ArcConfigManager.getIAMUsersPassword()); authenticationPage.clickOnAuthenticatenButton(); if(TestDataReader.readData("language").equalsIgnoreCase("eng")) { acknowledgementPage=new AcknowledgementPageEnglish(driver); @@ -550,7 +550,7 @@ else if(TestDataReader.readData("language").equalsIgnoreCase("ara")){ assertTrue(pendingApproval.isSupervisorAuthenticationTitleDisplayed(), "Verify if Supervisor Authentication page displayed"); pendingApproval.enterUserName(KeycloakUserManager.moduleSpecificUser); - pendingApproval.enterPassword(ConfigManager.getIAMUsersPassword()); + pendingApproval.enterPassword(ArcConfigManager.getIAMUsersPassword()); pendingApproval.clickOnSubmitButton(); pendingApproval.clickOnBackButton(); diff --git a/ui-test/src/main/java/regclient/androidTestCases/NewRegistrationMinor.java b/ui-test/src/main/java/regclient/androidTestCases/NewRegistrationMinor.java index a07a3ecf1..b010180f5 100644 --- a/ui-test/src/main/java/regclient/androidTestCases/NewRegistrationMinor.java +++ b/ui-test/src/main/java/regclient/androidTestCases/NewRegistrationMinor.java @@ -7,7 +7,7 @@ import org.testng.annotations.Test; import regclient.BaseTest.AndroidBaseTest; -import regclient.api.ConfigManager; +import regclient.api.ArcConfigManager; import regclient.api.FetchUiSpec; import regclient.api.KeycloakUserManager; import regclient.page.AcknowledgementPage; @@ -172,7 +172,7 @@ else if(TestDataReader.readData("language").equalsIgnoreCase("ara")){ loginPage.enterUserName(KeycloakUserManager.moduleSpecificUser); loginPage.clickOnNextButton(); - loginPage.enterPassword(ConfigManager.getIAMUsersPassword()); + loginPage.enterPassword(ArcConfigManager.getIAMUsersPassword()); loginPage.clickOnloginButton(); if(TestDataReader.readData("language").equalsIgnoreCase("eng")) { registrationTasksPage=new RegistrationTasksPageEnglish(driver); @@ -520,7 +520,7 @@ else if(TestDataReader.readData("language").equalsIgnoreCase("ara")){ } assertTrue(authenticationPage.isAuthenticationPageDisplayed(),"Verify if authentication details page is displayed"); authenticationPage.enterUserName(KeycloakUserManager.moduleSpecificUser); - authenticationPage.enterPassword(ConfigManager.getIAMUsersPassword()); + authenticationPage.enterPassword(ArcConfigManager.getIAMUsersPassword()); authenticationPage.clickOnAuthenticatenButton(); if(TestDataReader.readData("language").equalsIgnoreCase("eng")) { acknowledgementPage=new AcknowledgementPageEnglish(driver); @@ -607,7 +607,7 @@ else if(TestDataReader.readData("language").equalsIgnoreCase("ara")){ assertTrue(pendingApproval.isSupervisorAuthenticationTitleDisplayed(), "Verify if Supervisor Authentication page displayed"); pendingApproval.enterUserName(KeycloakUserManager.moduleSpecificUser); - pendingApproval.enterPassword(ConfigManager.getIAMUsersPassword()); + pendingApproval.enterPassword(ArcConfigManager.getIAMUsersPassword()); pendingApproval.clickOnSubmitButton(); pendingApproval.clickOnBackButton(); assertTrue(operationalTaskPage.isApplicationUploadTitleDisplayed(), "Verify if application upload tite displayed"); diff --git a/ui-test/src/main/java/regclient/androidTestCases/NewRegistrationMinorException.java b/ui-test/src/main/java/regclient/androidTestCases/NewRegistrationMinorException.java index 26b90e4e6..ed44ca8e1 100644 --- a/ui-test/src/main/java/regclient/androidTestCases/NewRegistrationMinorException.java +++ b/ui-test/src/main/java/regclient/androidTestCases/NewRegistrationMinorException.java @@ -10,7 +10,7 @@ import org.testng.annotations.Test; import regclient.BaseTest.AndroidBaseTest; -import regclient.api.ConfigManager; +import regclient.api.ArcConfigManager; import regclient.api.FetchUiSpec; import regclient.api.KeycloakUserManager; import regclient.page.AcknowledgementPage; @@ -175,7 +175,7 @@ else if(TestDataReader.readData("language").equalsIgnoreCase("ara")){ loginPage.enterUserName(KeycloakUserManager.moduleSpecificUser); loginPage.clickOnNextButton(); - loginPage.enterPassword(ConfigManager.getIAMUsersPassword()); + loginPage.enterPassword(ArcConfigManager.getIAMUsersPassword()); loginPage.clickOnloginButton(); if(TestDataReader.readData("language").equalsIgnoreCase("eng")) { registrationTasksPage=new RegistrationTasksPageEnglish(driver); @@ -583,7 +583,7 @@ else if(TestDataReader.readData("language").equalsIgnoreCase("ara")){ } assertTrue(authenticationPage.isAuthenticationPageDisplayed(),"Verify if authentication details page is displayed"); authenticationPage.enterUserName(KeycloakUserManager.moduleSpecificUser); - authenticationPage.enterPassword(ConfigManager.getIAMUsersPassword()); + authenticationPage.enterPassword(ArcConfigManager.getIAMUsersPassword()); authenticationPage.clickOnAuthenticatenButton(); if(TestDataReader.readData("language").equalsIgnoreCase("eng")) { acknowledgementPage=new AcknowledgementPageEnglish(driver); @@ -665,7 +665,7 @@ else if(TestDataReader.readData("language").equalsIgnoreCase("ara")){ assertTrue(pendingApproval.isSupervisorAuthenticationTitleDisplayed(), "Verify if Supervisor Authentication page displayed"); pendingApproval.enterUserName(KeycloakUserManager.moduleSpecificUser); - pendingApproval.enterPassword(ConfigManager.getIAMUsersPassword()); + pendingApproval.enterPassword(ArcConfigManager.getIAMUsersPassword()); pendingApproval.clickOnSubmitButton(); pendingApproval.clickOnBackButton(); assertTrue(operationalTaskPage.isApplicationUploadTitleDisplayed(), "Verify if application upload tite displayed"); diff --git a/ui-test/src/main/java/regclient/androidTestCases/UpdateMyUINUpdateDemographicDetails.java b/ui-test/src/main/java/regclient/androidTestCases/UpdateMyUINUpdateDemographicDetails.java index f1ecf30b8..41c756254 100644 --- a/ui-test/src/main/java/regclient/androidTestCases/UpdateMyUINUpdateDemographicDetails.java +++ b/ui-test/src/main/java/regclient/androidTestCases/UpdateMyUINUpdateDemographicDetails.java @@ -7,7 +7,7 @@ import org.testng.annotations.Test; import regclient.BaseTest.AndroidBaseTest; -import regclient.api.ConfigManager; +import regclient.api.ArcConfigManager; import regclient.api.FetchUiSpec; import regclient.api.KeycloakUserManager; import regclient.page.AcknowledgementPage; @@ -172,7 +172,7 @@ else if(TestDataReader.readData("language").equalsIgnoreCase("ara")){ loginPage.enterUserName(KeycloakUserManager.moduleSpecificUser); loginPage.clickOnNextButton(); - loginPage.enterPassword(ConfigManager.getIAMUsersPassword()); + loginPage.enterPassword(ArcConfigManager.getIAMUsersPassword()); loginPage.clickOnloginButton(); if(TestDataReader.readData("language").equalsIgnoreCase("eng")) { registrationTasksPage=new RegistrationTasksPageEnglish(driver); @@ -439,7 +439,7 @@ else if(TestDataReader.readData("language").equalsIgnoreCase("ara")){ } assertTrue(authenticationPage.isAuthenticationPageDisplayed(),"Verify if authentication details page is displayed"); authenticationPage.enterUserName(KeycloakUserManager.moduleSpecificUser); - authenticationPage.enterPassword(ConfigManager.getIAMUsersPassword()); + authenticationPage.enterPassword(ArcConfigManager.getIAMUsersPassword()); authenticationPage.clickOnAuthenticatenButton(); if(TestDataReader.readData("language").equalsIgnoreCase("eng")) { acknowledgementPage=new AcknowledgementPageEnglish(driver); @@ -522,7 +522,7 @@ else if(TestDataReader.readData("language").equalsIgnoreCase("ara")){ assertTrue(pendingApproval.isSupervisorAuthenticationTitleDisplayed(), "Verify if Supervisor Authentication page displayed"); pendingApproval.enterUserName(KeycloakUserManager.moduleSpecificUser); - pendingApproval.enterPassword(ConfigManager.getIAMUsersPassword()); + pendingApproval.enterPassword(ArcConfigManager.getIAMUsersPassword()); pendingApproval.clickOnSubmitButton(); pendingApproval.clickOnBackButton(); assertTrue(operationalTaskPage.isApplicationUploadTitleDisplayed(), "Verify if application upload tite displayed"); diff --git a/ui-test/src/main/java/regclient/androidTestCases/UpdateMyUinInfant.java b/ui-test/src/main/java/regclient/androidTestCases/UpdateMyUinInfant.java index 830d00757..a5b1414af 100644 --- a/ui-test/src/main/java/regclient/androidTestCases/UpdateMyUinInfant.java +++ b/ui-test/src/main/java/regclient/androidTestCases/UpdateMyUinInfant.java @@ -7,7 +7,7 @@ import org.testng.annotations.Test; import regclient.BaseTest.AndroidBaseTest; -import regclient.api.ConfigManager; +import regclient.api.ArcConfigManager; import regclient.api.FetchUiSpec; import regclient.api.KeycloakUserManager; import regclient.page.AcknowledgementPage; @@ -180,7 +180,7 @@ else if(TestDataReader.readData("language").equalsIgnoreCase("ara")){ loginPage.enterUserName(KeycloakUserManager.moduleSpecificUser); loginPage.clickOnNextButton(); - loginPage.enterPassword(ConfigManager.getIAMUsersPassword()); + loginPage.enterPassword(ArcConfigManager.getIAMUsersPassword()); loginPage.clickOnloginButton(); if(TestDataReader.readData("language").equalsIgnoreCase("eng")) { registrationTasksPage=new RegistrationTasksPageEnglish(driver); @@ -471,7 +471,7 @@ else if(TestDataReader.readData("language").equalsIgnoreCase("ara")){ } assertTrue(authenticationPage.isAuthenticationPageDisplayed(),"Verify if authentication details page is displayed"); authenticationPage.enterUserName(KeycloakUserManager.moduleSpecificUser); - authenticationPage.enterPassword(ConfigManager.getIAMUsersPassword()); + authenticationPage.enterPassword(ArcConfigManager.getIAMUsersPassword()); authenticationPage.clickOnAuthenticatenButton(); if(TestDataReader.readData("language").equalsIgnoreCase("eng")) { acknowledgementPage=new AcknowledgementPageEnglish(driver); @@ -558,7 +558,7 @@ else if(TestDataReader.readData("language").equalsIgnoreCase("ara")){ assertTrue(pendingApproval.isSupervisorAuthenticationTitleDisplayed(), "Verify if Supervisor Authentication page displayed"); pendingApproval.enterUserName(KeycloakUserManager.moduleSpecificUser); - pendingApproval.enterPassword(ConfigManager.getIAMUsersPassword()); + pendingApproval.enterPassword(ArcConfigManager.getIAMUsersPassword()); pendingApproval.clickOnSubmitButton(); pendingApproval.clickOnBackButton(); diff --git a/ui-test/src/main/java/regclient/androidTestCases/UpdateMyUinMinor.java b/ui-test/src/main/java/regclient/androidTestCases/UpdateMyUinMinor.java index 68cd2d60a..9ba1728b9 100644 --- a/ui-test/src/main/java/regclient/androidTestCases/UpdateMyUinMinor.java +++ b/ui-test/src/main/java/regclient/androidTestCases/UpdateMyUinMinor.java @@ -7,7 +7,7 @@ import org.testng.annotations.Test; import regclient.BaseTest.AndroidBaseTest; -import regclient.api.ConfigManager; +import regclient.api.ArcConfigManager; import regclient.api.FetchUiSpec; import regclient.api.KeycloakUserManager; import regclient.page.AcknowledgementPage; @@ -181,7 +181,7 @@ else if(TestDataReader.readData("language").equalsIgnoreCase("ara")){ loginPage.enterUserName(KeycloakUserManager.moduleSpecificUser); loginPage.clickOnNextButton(); - loginPage.enterPassword(ConfigManager.getIAMUsersPassword()); + loginPage.enterPassword(ArcConfigManager.getIAMUsersPassword()); loginPage.clickOnloginButton(); if(TestDataReader.readData("language").equalsIgnoreCase("eng")) { registrationTasksPage=new RegistrationTasksPageEnglish(driver); @@ -573,7 +573,7 @@ else if(TestDataReader.readData("language").equalsIgnoreCase("ara")){ } assertTrue(authenticationPage.isAuthenticationPageDisplayed(),"Verify if authentication details page is displayed"); authenticationPage.enterUserName(KeycloakUserManager.moduleSpecificUser); - authenticationPage.enterPassword(ConfigManager.getIAMUsersPassword()); + authenticationPage.enterPassword(ArcConfigManager.getIAMUsersPassword()); authenticationPage.clickOnAuthenticatenButton(); if(TestDataReader.readData("language").equalsIgnoreCase("eng")) { acknowledgementPage=new AcknowledgementPageEnglish(driver); @@ -657,7 +657,7 @@ else if(TestDataReader.readData("language").equalsIgnoreCase("ara")){ assertTrue(pendingApproval.isSupervisorAuthenticationTitleDisplayed(), "Verify if Supervisor Authentication page displayed"); pendingApproval.enterUserName(KeycloakUserManager.moduleSpecificUser); - pendingApproval.enterPassword(ConfigManager.getIAMUsersPassword()); + pendingApproval.enterPassword(ArcConfigManager.getIAMUsersPassword()); pendingApproval.clickOnSubmitButton(); pendingApproval.clickOnBackButton(); assertTrue(operationalTaskPage.isApplicationUploadTitleDisplayed(), "Verify if application upload tite displayed"); diff --git a/ui-test/src/main/java/regclient/androidTestCases/UpdateMyUinUpdateBiometrics.java b/ui-test/src/main/java/regclient/androidTestCases/UpdateMyUinUpdateBiometrics.java index ac1fc8abe..9a93261e0 100644 --- a/ui-test/src/main/java/regclient/androidTestCases/UpdateMyUinUpdateBiometrics.java +++ b/ui-test/src/main/java/regclient/androidTestCases/UpdateMyUinUpdateBiometrics.java @@ -7,7 +7,7 @@ import org.testng.annotations.Test; import regclient.BaseTest.AndroidBaseTest; -import regclient.api.ConfigManager; +import regclient.api.ArcConfigManager; import regclient.api.FetchUiSpec; import regclient.api.KeycloakUserManager; import regclient.page.AcknowledgementPage; @@ -172,7 +172,7 @@ else if(TestDataReader.readData("language").equalsIgnoreCase("ara")){ loginPage.enterUserName(KeycloakUserManager.moduleSpecificUser); loginPage.clickOnNextButton(); - loginPage.enterPassword(ConfigManager.getIAMUsersPassword()); + loginPage.enterPassword(ArcConfigManager.getIAMUsersPassword()); loginPage.clickOnloginButton(); if(TestDataReader.readData("language").equalsIgnoreCase("eng")) { registrationTasksPage=new RegistrationTasksPageEnglish(driver); @@ -469,7 +469,7 @@ else if(TestDataReader.readData("language").equalsIgnoreCase("ara")){ } assertTrue(authenticationPage.isAuthenticationPageDisplayed(),"Verify if authentication details page is displayed"); authenticationPage.enterUserName(KeycloakUserManager.moduleSpecificUser); - authenticationPage.enterPassword(ConfigManager.getIAMUsersPassword()); + authenticationPage.enterPassword(ArcConfigManager.getIAMUsersPassword()); authenticationPage.clickOnAuthenticatenButton(); if(TestDataReader.readData("language").equalsIgnoreCase("eng")) { acknowledgementPage=new AcknowledgementPageEnglish(driver); @@ -552,7 +552,7 @@ else if(TestDataReader.readData("language").equalsIgnoreCase("ara")){ assertTrue(pendingApproval.isSupervisorAuthenticationTitleDisplayed(), "Verify if Supervisor Authentication page displayed"); pendingApproval.enterUserName(KeycloakUserManager.moduleSpecificUser); - pendingApproval.enterPassword(ConfigManager.getIAMUsersPassword()); + pendingApproval.enterPassword(ArcConfigManager.getIAMUsersPassword()); pendingApproval.clickOnSubmitButton(); pendingApproval.clickOnBackButton(); assertTrue(operationalTaskPage.isApplicationUploadTitleDisplayed(), "Verify if application upload tite displayed"); diff --git a/ui-test/src/main/java/regclient/androidTestCases/logintest.java b/ui-test/src/main/java/regclient/androidTestCases/logintest.java index ae97160c4..ef6a3713d 100644 --- a/ui-test/src/main/java/regclient/androidTestCases/logintest.java +++ b/ui-test/src/main/java/regclient/androidTestCases/logintest.java @@ -6,7 +6,7 @@ import org.testng.annotations.Test; import regclient.BaseTest.AndroidBaseTest; -import regclient.api.ConfigManager; +import regclient.api.ArcConfigManager; import regclient.api.FetchUiSpec; import regclient.api.KeycloakUserManager; import regclient.page.BasePage; @@ -123,7 +123,7 @@ else if(TestDataReader.readData("language").equalsIgnoreCase("ara")){ assertTrue(loginPage.isPasswordHeaderDisplayed(), "Verify if the password input box header displayed"); - loginPage.enterPassword(ConfigManager.getIAMUsersPassword()+"123"); + loginPage.enterPassword(ArcConfigManager.getIAMUsersPassword()+"123"); assertTrue(loginPage.isLoginButtonEnabled(),"Verify if the login button enabled"); loginPage.clickOnloginButton(); @@ -137,7 +137,7 @@ else if(TestDataReader.readData("language").equalsIgnoreCase("ara")){ assertTrue(loginPage.isNextButtonEnabled(),"verify if the next button enabled"); loginPage.clickOnNextButton(); - loginPage.enterPassword(ConfigManager.getIAMUsersPassword()); + loginPage.enterPassword(ArcConfigManager.getIAMUsersPassword()); assertTrue(loginPage.isLoginButtonEnabled(),"Verify if the login button enabled"); loginPage.clickOnloginButton(); @@ -285,7 +285,7 @@ else if(TestDataReader.readData("language").equalsIgnoreCase("ara")){ assertTrue(loginPage.isBackButtonDisplayed(), "Verify if back button is displayed"); assertTrue(loginPage.isForgetOptionDisplayed(), "Verify if forget password option is displayed"); assertTrue(loginPage.isPasswordHeaderDisplayed(), "Verify if the password input box header displayed"); - loginPage.enterPassword(ConfigManager.getIAMUsersPassword()); + loginPage.enterPassword(ArcConfigManager.getIAMUsersPassword()); assertTrue(loginPage.isLoginButtonEnabled(), "Verify if the login button enabled"); loginPage.clickOnloginButton(); @@ -485,7 +485,7 @@ else if(TestDataReader.readData("language").equalsIgnoreCase("ara")){ assertTrue(loginPage.isBackButtonDisplayed(), "Verify if back button is displayed"); assertTrue(loginPage.isForgetOptionDisplayed(), "Verify if forget password option is displayed"); assertTrue(loginPage.isPasswordHeaderDisplayed(), "Verify if the password input box header displayed"); - loginPage.enterPassword(ConfigManager.getIAMUsersPassword()); + loginPage.enterPassword(ArcConfigManager.getIAMUsersPassword()); assertTrue(loginPage.isLoginButtonEnabled(), "Verify if the login button enabled"); loginPage.clickOnloginButton(); diff --git a/ui-test/src/main/java/regclient/api/AdminTestUtil.java b/ui-test/src/main/java/regclient/api/AdminTestUtil.java index a8640bfc8..3dacfd6b7 100644 --- a/ui-test/src/main/java/regclient/api/AdminTestUtil.java +++ b/ui-test/src/main/java/regclient/api/AdminTestUtil.java @@ -1,11 +1,15 @@ package regclient.api; +import io.mosip.testrig.apirig.testrunner.OTPListener; import io.restassured.response.Response; +import regclient.utils.TestDataReader; import org.apache.log4j.Logger; import org.json.JSONArray; import org.json.JSONObject; +import com.github.javafaker.Faker; + import javax.ws.rs.core.MediaType; import java.text.SimpleDateFormat; import java.util.Arrays; @@ -87,7 +91,7 @@ public static String creteaMachine(String signPublicKey, String publicKey ,Strin public static void initialize() { if (!initialized) { - ConfigManager.init(); + ArcConfigManager.init(); BaseTestCase.initialize(); KeycloakUserManager.createUsers(); mapUserToZone(BaseTestCase.currentModule +"-"+propsKernel.getProperty("iam-users-to-create"),propsKernel.getProperty("zone")); @@ -123,9 +127,9 @@ public static void mapUserToZone(String user, String zone) { public static List getLanguageList() { logger.info("We have created a Config Manager. Beginning to read properties!"); - environment = ConfigManager.getiam_apienvuser(); + environment = ArcConfigManager.getiam_apienvuser(); logger.info("Environemnt is ==== :" + environment); - ApplnURI = ConfigManager.getiam_apiinternalendpoint(); + ApplnURI = ArcConfigManager.getiam_apiinternalendpoint(); logger.info("Application URI ======" + ApplnURI); logger.info("Configs from properties file are set."); @@ -177,6 +181,187 @@ public static void mapUserToCenter(String user, String center) { System.out.println("responseJson = " + responseJson); } + public static void sendOtp(String userId, String langCode) { + String token = kernelAuthLib.getTokenByRole("globalAdmin"); + JSONObject requestJson = new JSONObject(); + requestJson.put("id", "mosip.pre-registration.login.sendotp"); + requestJson.put("version", "1.0"); + requestJson.put("requesttime", AdminTestUtil.generateCurrentUTCTimeStamp()); + JSONObject innerRequest = new JSONObject(); + innerRequest.put("userId", userId); + innerRequest.put("langCode", langCode); + requestJson.put("request", innerRequest); + Response response = RestClient.postRequestWithCookie( + BaseTestCase.ApplnURI +"/preregistration/v1/login/sendOtp/langcode", + requestJson.toString(), + MediaType.APPLICATION_JSON, + MediaType.APPLICATION_JSON, + BaseTestCase.COOKIENAME, token + ); + JSONObject responseJson = new JSONObject(response.asString()); + System.out.println("Response JSON = " + responseJson); + if (responseJson.has("response") + && responseJson.getJSONObject("response").has("status") + && "success".equalsIgnoreCase(responseJson.getJSONObject("response").getString("status"))) { + System.out.println("✅ OTP request sent successfully."); + } else { + throw new RuntimeException("❌ OTP request failed. Response: " + responseJson.toString()); + } + } + + public static Response validateOtp(String userId, String otp) { + String token = kernelAuthLib.getTokenByRole("globalAdmin"); + JSONObject requestJson = new JSONObject(); + requestJson.put("id", "mosip.pre-registration.login.useridotp"); + requestJson.put("version", "1.0"); + requestJson.put("requesttime", AdminTestUtil.generateCurrentUTCTimeStamp()); + + JSONObject innerRequest = new JSONObject(); + innerRequest.put("userId", userId); + innerRequest.put("otp", otp); + requestJson.put("request", innerRequest); + Response response = RestClient.postRequestWithCookie( + BaseTestCase.ApplnURI + "/preregistration/v1/login/validateOtp", + requestJson.toString(), + MediaType.APPLICATION_JSON, + MediaType.APPLICATION_JSON, + BaseTestCase.COOKIENAME, token + ); + + if (response == null) { + throw new RuntimeException("No response from validateOtp API"); + } + + int statusCode = response.getStatusCode(); + if (statusCode < 200 || statusCode >= 300) { + throw new RuntimeException("HTTP error from validateOtp API. Status: " + statusCode + " Body: " + response.asString()); + } + + JSONObject responseJson; + try { + responseJson = new JSONObject(response.asString()); + } catch (Exception e) { + throw new RuntimeException("Invalid JSON returned from validateOtp API: " + response.asString(), e); + } + if (responseJson.has("response") + && responseJson.getJSONObject("response").has("status") + && "success".equalsIgnoreCase(responseJson.getJSONObject("response").getString("status"))) { + System.out.println("✅ OTP validation successful."); + return response; + } else { + throw new RuntimeException("❌ OTP validation failed. Response: " + responseJson.toString()); + } + } + + public static String createPreRegistration(String userId) { + String token = kernelAuthLib.getTokenByRole("globalAdmin"); + + // Generate base prereg JSON (as String) + String baseJson = io.mosip.testrig.apirig.utils.AdminTestUtil.generateHbsForPrereg(false); + + // Parse into JSONObject + JSONObject requestJson = new JSONObject(baseJson); + + // Faker for dynamic values + Faker faker = new Faker(); + String randomName = faker.name().fullName(); + String address1 = faker.address().streetAddress(); + String address2 = faker.address().secondaryAddress(); + String address3 = faker.address().buildingNumber(); + String phone = faker.number().digits(10); + String email = faker.internet().emailAddress(); + String dob = "1990/01/01"; // Or faker.date().birthday() + + // Navigate to identity node + JSONObject request = requestJson.getJSONObject("request"); + JSONObject identity = request.getJSONObject("demographicDetails").getJSONObject("identity"); + + // Fill only if empty or placeholder + if (identity.optJSONArray("fullName") != null) { + for (int i = 0; i < identity.getJSONArray("fullName").length(); i++) { + identity.getJSONArray("fullName").getJSONObject(i).put("value", randomName); + } + } + + if (!identity.has("dateOfBirth") || identity.get("dateOfBirth").toString().contains("{{")) { + identity.put("dateOfBirth", dob); + } + + if (!identity.has("phone") || identity.get("phone").toString().contains("{{")) { + identity.put("phone", phone); + } + + if (!identity.has("email") || identity.get("email").toString().contains("{{")) { + identity.put("email", email); + } + + if (identity.optJSONArray("addressLine1") != null) { + for (int i = 0; i < identity.getJSONArray("addressLine1").length(); i++) { + identity.getJSONArray("addressLine1").getJSONObject(i).put("value", address1); + } + } + + if (identity.optJSONArray("addressLine2") != null) { + for (int i = 0; i < identity.getJSONArray("addressLine2").length(); i++) { + identity.getJSONArray("addressLine2").getJSONObject(i).put("value", address2); + } + } + + if (identity.optJSONArray("addressLine3") != null) { + for (int i = 0; i < identity.getJSONArray("addressLine3").length(); i++) { + identity.getJSONArray("addressLine3").getJSONObject(i).put("value", address3); + } + } + + if (!identity.has("postalCode") || identity.get("postalCode").toString().contains("{{")) { + identity.put("postalCode", propsKernel.getProperty("regCenterId")); + } + + // Replace placeholders for langCode, id, and version + if (request.has("langCode") && request.getString("langCode").contains("{{")) { + request.put("langCode", "eng"); + } + if (requestJson.has("id") && requestJson.getString("id").contains("{{")) { + requestJson.put("id", "mosip.pre-registration.demographic.create"); + } + if (requestJson.has("version") && requestJson.getString("version").contains("{{")) { + requestJson.put("version", "1.0"); + } + + // update requesttime + requestJson.put("requesttime", AdminTestUtil.generateCurrentUTCTimeStamp()); + + // Hit API + Response response = RestClient.postRequestWithCookie( + BaseTestCase.ApplnURI + "/preregistration/v1/applications/prereg", + requestJson.toString(), + MediaType.APPLICATION_JSON, + MediaType.APPLICATION_JSON, + BaseTestCase.COOKIENAME, token + ); + + String preRegId = null; + JSONObject responseJson = new JSONObject(response.asString()); + if (responseJson.has("response") && responseJson.getJSONObject("response").has("preRegistrationId")) { + preRegId = responseJson.getJSONObject("response").getString("preRegistrationId"); + System.out.println("✅ preRegistrationId = " + preRegId); + } else { + throw new RuntimeException("❌ preRegistrationId not found in response: " + responseJson.toString()); + } + return preRegId; + } + + + + public static String getPreRegistrationFlow() { + Faker faker = new Faker(); + String userId = faker.internet().emailAddress(); + sendOtp(userId, TestDataReader.readData("language")); + validateOtp(userId, OTPListener.getOtp(userId)); + String preRegId = createPreRegistration(userId); + return preRegId; + } + public static void mapCenter(String user) { String token = kernelAuthLib.getTokenByRole("globalAdmin"); String url = ApplnURI + "/v1/masterdata/usercentermapping"; diff --git a/ui-test/src/main/java/regclient/api/ArcConfigManager.java b/ui-test/src/main/java/regclient/api/ArcConfigManager.java new file mode 100644 index 000000000..270bae8d3 --- /dev/null +++ b/ui-test/src/main/java/regclient/api/ArcConfigManager.java @@ -0,0 +1,116 @@ +package regclient.api; + +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.InputStream; +import java.util.HashMap; +import java.util.Map; +import java.util.Properties; + +import org.apache.log4j.Level; +import org.apache.log4j.Logger; + +import io.mosip.testrig.apirig.utils.ConfigManager; + +public class ArcConfigManager extends io.mosip.testrig.apirig.utils.ConfigManager { + + private static final Logger LOGGER = Logger.getLogger(ArcConfigManager.class); + + public static void init() { + Logger configManagerLogger = Logger.getLogger(ConfigManager.class); + configManagerLogger.setLevel(Level.WARN); + + Map moduleSpecificPropertiesMap = new HashMap<>(); + // Load scope specific properties + try { + Properties configProps = new Properties(); + try (InputStream inputStream = ArcConfigManager.class.getClassLoader() + .getResourceAsStream("config.properties")) { + if (inputStream == null) { + LOGGER.error("config.properties resource not found in classpath"); + throw new FileNotFoundException("config.properties not found"); + } + configProps.load(inputStream); + LOGGER.info("Config properties loaded successfully."); + } catch (IOException e) { + LOGGER.error("Failed to load config.properties", e); + throw new RuntimeException("Failed to load config.properties file", e); + } + + // Convert Properties to Map and add to moduleSpecificPropertiesMap + for (String key : configProps.stringPropertyNames()) { + moduleSpecificPropertiesMap.put(key, configProps.getProperty(key)); + } + } catch (Exception e) { + LOGGER.error(e.getMessage()); + } + // Add module specific properties as well. + init(moduleSpecificPropertiesMap); + } + + public static String getDbUrl() { + return getProperty("db-server-es", ""); + } + + public static String getDbUser() { + return getProperty("db-su-user", ""); + } + + public static String getDbPassword() { + return getProperty("postgres-password", ""); + } + + public static String getDbSchema() { + return getProperty("es_db_schema", ""); + } + + public static String getiam_apienvuser() { + return getProperty("apiEnvUser", ""); + } + + public static String getiam_apiinternalendpoint() { + return getProperty("apiInternalEndPoint", ""); + } + + public static String getProperty(String key, String defaultValue) { + String value = propertiesMap.get(key) == null ? "" : propertiesMap.get(key).toString(); + return (value != null && !value.trim().isEmpty()) ? value : defaultValue; + } + + public static int getTimeout() { + try { + return Integer.parseInt(getProperty("explicitWaitTimeout", "10")); + } catch (NumberFormatException e) { + LOGGER.error("Invalid explicitWaitTimeout value in config.properties. Using default 10 seconds."); + return 10; + } + } + + public static String getIAMUrl() { + return getProperty("keycloak-external-url", "") + "/auth"; + } + + public static String getSignupPortalUrl() { + return getProperty("signup.portal.url", ""); + } + + public static String getIAMUsersPassword() { + return getProperty("iam-users-password", ""); + } + + public static String getEnv() { + return getProperty("db-server", ""); + } + + public static String getSmtpUrl() { + return getProperty("smtp.url", ""); + } + + public static String getHealthPortalUrl() { + return getProperty("baseurl", ""); + } + + public static String gettestcases() { + return getProperty("regclientScenariosToExecute", ""); + } +} \ No newline at end of file diff --git a/ui-test/src/main/java/regclient/api/BaseTestCase.java b/ui-test/src/main/java/regclient/api/BaseTestCase.java index 88bb7c017..c4b1bc71f 100644 --- a/ui-test/src/main/java/regclient/api/BaseTestCase.java +++ b/ui-test/src/main/java/regclient/api/BaseTestCase.java @@ -88,11 +88,11 @@ public static void initialize() { getOSType(); logger.info("We have created a Config Manager. Beginning to read properties!"); - environment = ConfigManager.getiam_apienvuser(); + environment = ArcConfigManager.getiam_apienvuser(); logger.info("Environemnt is ==== :" + environment); - ApplnURI = ConfigManager.getiam_apiinternalendpoint(); + ApplnURI = ArcConfigManager.getiam_apiinternalendpoint(); logger.info("Application URI ======" + ApplnURI); - ApplnURIForKeyCloak = ConfigManager.getIAMUrl(); + ApplnURIForKeyCloak = ArcConfigManager.getIAMUrl(); logger.info("Application URI ======" + ApplnURIForKeyCloak); testLevel = System.getProperty("env.testLevel"); logger.info("Test Level ======" + testLevel); diff --git a/ui-test/src/main/java/regclient/api/ConfigManager.java b/ui-test/src/main/java/regclient/api/ConfigManager.java deleted file mode 100644 index 104d783c4..000000000 --- a/ui-test/src/main/java/regclient/api/ConfigManager.java +++ /dev/null @@ -1,601 +0,0 @@ -package regclient.api; - - - -import java.io.File; -import java.io.FileInputStream; -import java.io.IOException; -import java.util.Properties; - -import regclient.utils.TestRunner; - - -public class ConfigManager { - - private static final org.slf4j.Logger LOGGER= org.slf4j.LoggerFactory.getLogger(ConfigManager.class); - - private static final String USEPRECONFIGOTP = "usePreConfiguredOtp"; - private static final String PRECONFIGOTP = "preconfiguredOtp"; - - private static final String MOSIP_IDREPO_CLIENT_SECRET = "mosip_idrepo_client_secret"; - private static final String MOSIP_IDREPO_CLIENT_ID = "mosip_idrepo_client_id"; - private static final String MOSIP_IDREPO_APP_ID = "mosip_idrepo_app_id"; - - private static final String MOSIP_ADMIN_CLIENT_SECRET = "mosip_admin_client_secret"; - private static final String MOSIP_ADMIN_CLIENT_ID = "mosip_admin_client_id"; - private static final String MOSIP_ADMIN_APP_ID = "mosip_admin_app_id"; - - private static final String MOSIP_REG_CLIENT_SECRET = "mosip_reg_client_secret"; - private static final String MOSIP_REG_CLIENT_ID = "mosip_reg_client_id"; - private static final String MOSIP_REGCLIENT_APP_ID = "mosip_regclient_app_id"; - - - - private static final String MOSIP_AUTOMATION_CLIENT_SECRET = "mosip_testrig_client_secret"; - private static final String MOSIP_AUTOMATION_CLIENT_ID = "mosip_testrig_client_id"; - private static final String MOSIP_AUTOMATION_APP_ID = "mosip_automation_app_id"; - - private static final String S3_HOST = "s3-host"; - private static String usePreConfiguredOtp; - private static final String S3_REGION = "s3-region"; - private static final String S3_USER_KEY = "s3-user-key"; - private static final String S3_SECRET_KEY = "s3-user-secret"; - private static final String S3_ACCOUNT = "s3-account"; - private static final String PUSH_TO_S3 = "push-reports-to-s3"; - private static final String ENABLE_DEBUG = "enableDebug"; - private static final String THREAD_COUNT = "threadCount"; - private static final String LANG_SELECT = "langselect"; - private static String Testcases = "regclientScenariosToExecute"; - private static String preconfiguredOtp; - - private static final String DB_PORT = "db-port"; - private static final String DB_DOMAIN = "db-server"; - private static final String HIBERNATE_CONNECTION_DRIVER_CLASS = "hibernate.connection.driver_class"; - private static final String HIBERNATE_CONNECTION_POOL_SIZE = "hibernate.connection.pool_size"; - private static final String HIBERNATE_DIALECT = "hibernate.dialect"; - private static final String HIBERNATE_SHOW_SQL = "hibernate.show_sql"; - private static final String HIBERNATE_CONTEXT_CLASS = "hibernate.current_session_context_class"; - - private static final String AUDIT_DB_USER = "db-su-user"; - private static final String AUDIT_DB_PASS = "postgresql-password"; - private static final String AUDIT_DB_SCHEMA = "audit_db_schema"; - - private static final String IDA_DB_USER = "db-su-user"; - private static final String IDA_DB_PASS = "postgresql-password"; - private static final String IDA_DB_SCHEMA = "ida_db_schema"; - - private static final String PMS_DB_USER = "db-su-user"; - private static final String PMS_DB_PASS = "postgresql-password"; - private static final String PMS_DB_SCHEMA = "pms_db_schema"; - - private static final String KM_DB_USER = "db-su-user"; - private static final String KM_DB_PASS = "postgresql-password"; - private static final String KM_DB_SCHEMA = "km_db_schema"; - - private static final String MASTER_DB_USER = "db-su-user"; - private static final String MASTER_DB_PASS = "postgresql-password"; - private static final String MASTER_DB_SCHEMA = "master_db_schema"; - - private static final String IAM_EXTERNAL_URL = "keycloak-external-url"; - private static final String IAM_ADMINPORTAL_PATH = "adminPortalPath"; - private static final String IAM_APIENVUSER = "apiEnvUser"; - private static final String IAM_APIINTERNALENDPOINT = "apiInternalEndPoint"; - private static final String IAM_REALM_ID = "keycloak-realm-id"; - private static final String IAM_USERS_TO_CREATE = "iam-users-to-create"; - private static final String IAM_USERS_PASSWORD = "iam-users-password"; - - private static final String AUTH_DEMO_SERVICE_PORT = "authDemoServicePort"; - private static final String AUTH_DEMO_SERVICE_BASE_URL = "authDemoServiceBaseURL"; - private static final String MOUNT_PATH = "mountPath"; - private static final String AUTHCERTS_PATH = "authCertsPath"; - private static final String MOUNT_PATH_FOR_SCENARIO = "mountPathForScenario"; - - private static final String PACKET_UTILITY_BASE_URL = "packetUtilityBaseUrl"; - - private static final String REPORT_EXPIRATION_IN_DAYS = "reportExpirationInDays"; - - private static String idrepo_client_secret; - private static String idrepo_client_id; - private static String idrepo_app_id; - - private static String admin_client_secret; - private static String admin_client_id; - private static String admin_app_id; - - private static String regproc_client_secret; - private static String regproc_client_id; - private static String regproc_app_id; - - private static String automation_client_secret; - private static String automation_client_id; - private static String automation_app_id; - - private static String s3_region; - private static String s3_host; - private static String s3_user_key; - private static String s3_account; - private static String s3_secret_key; - private static String push_reports_to_s3; - private static String enableDebug; - private static String threadCount; - private static String langselect; - private static String testcases; - - - private static String db_port; - private static String db_domain; - private static String hibernate_connection_driver_class; - private static String hibernate_connection_pool_size; - private static String hibernate_dialect; - private static String hibernate_show_sql; - private static String hibernate_current_session_context_class; - - private static String audit_db_user; - private static String audit_db_pass; - private static String audit_db_schema; - - private static String ida_db_user; - private static String ida_db_pass; - private static String ida_db_schema; - - private static String pms_db_user; - private static String pms_db_pass; - private static String pms_db_schema; - - private static String km_db_user; - private static String km_db_pass; - private static String km_db_schema; - - private static String master_db_user; - private static String master_db_pass; - private static String master_db_schema; - - private static String iam_external_url; - private static String iam_realm_id; - private static String iam_users_to_create; - private static String iam_adminportal_path; - private static String iam_apienvuser; - private static String iam_apiinternalendpoint; - private static String iam_users_password; - private static String authDemoServicePort; - private static String authDemoServiceBaseUrl; - - private static String mountPath; - private static String authCertsPath; - private static String mountPathForScenario; - private static String packetUtilityBaseUrl; - public static Properties propsKernel; - private static String reportExpirationInDays; - public static void setProperty(String key, String value) { - // Overwrite the value with only if the key exists - if (propsKernel.containsKey(key)) { - propsKernel.setProperty(key, value); - } - } - - public static String getValueForKey(String key) { - String value = System.getenv(key) == null ? propsKernel.getProperty(key) : System.getenv(key); - setProperty(key, value); - - return value; - } - - public static void init() { - propsKernel = getproperty(TestRunner.getResourcePath() + "/config/Kernel.properties"); - System.out.println(propsKernel); - - idrepo_client_secret = getValueForKey(MOSIP_IDREPO_CLIENT_SECRET); - idrepo_client_id = getValueForKey(MOSIP_IDREPO_CLIENT_ID); - idrepo_app_id = getValueForKey(MOSIP_IDREPO_APP_ID); - admin_client_secret = getValueForKey(MOSIP_ADMIN_CLIENT_SECRET); - admin_client_id = getValueForKey(MOSIP_ADMIN_CLIENT_ID); - admin_app_id = getValueForKey(MOSIP_ADMIN_APP_ID); - regproc_client_secret = getValueForKey(MOSIP_REG_CLIENT_SECRET); - regproc_client_id = getValueForKey(MOSIP_REG_CLIENT_ID); - regproc_app_id = getValueForKey(MOSIP_REGCLIENT_APP_ID); - automation_client_secret = getValueForKey(MOSIP_AUTOMATION_CLIENT_SECRET); - automation_client_id = getValueForKey(MOSIP_AUTOMATION_CLIENT_ID); - automation_app_id = getValueForKey(MOSIP_AUTOMATION_APP_ID); - s3_host = getValueForKey(S3_HOST); - s3_region = getValueForKey(S3_REGION); - s3_user_key = getValueForKey(S3_USER_KEY); - s3_secret_key = getValueForKey(S3_SECRET_KEY); - s3_account = getValueForKey(S3_ACCOUNT); - - iam_adminportal_path =System.getenv(IAM_ADMINPORTAL_PATH) == null - ? propsKernel.getProperty(IAM_ADMINPORTAL_PATH) - : System.getenv(IAM_ADMINPORTAL_PATH); - - LOGGER.info("adminportal_path from config manager::" + iam_adminportal_path); - iam_apienvuser = System.getenv(IAM_APIENVUSER) == null - ? propsKernel.getProperty(IAM_APIENVUSER) - : System.getenv(IAM_APIENVUSER); - LOGGER.info("apienvuser from config manager::" + iam_apienvuser); - iam_apiinternalendpoint = System.getenv(IAM_APIINTERNALENDPOINT) == null - ? propsKernel.getProperty(IAM_APIINTERNALENDPOINT) - : System.getenv(IAM_APIINTERNALENDPOINT); - LOGGER.info("apiinternalendpoint from config manager::" + iam_apiinternalendpoint); - // push_reports_to_s3 = getValueForKey(PUSH_TO_S3); - db_port = getValueForKey(DB_PORT); - db_domain = getValueForKey(DB_DOMAIN); - hibernate_connection_driver_class = getValueForKey(HIBERNATE_CONNECTION_DRIVER_CLASS); - hibernate_connection_pool_size = getValueForKey(HIBERNATE_CONNECTION_POOL_SIZE); - hibernate_dialect = getValueForKey(HIBERNATE_DIALECT); - hibernate_show_sql = getValueForKey(HIBERNATE_SHOW_SQL); - hibernate_current_session_context_class = getValueForKey(HIBERNATE_CONTEXT_CLASS); - audit_db_user = getValueForKey(AUDIT_DB_USER); - audit_db_pass = getValueForKey(AUDIT_DB_PASS); - audit_db_schema = getValueForKey(AUDIT_DB_SCHEMA); - ida_db_user = getValueForKey(IDA_DB_USER); - ida_db_pass = getValueForKey(IDA_DB_PASS); - ida_db_schema = getValueForKey(IDA_DB_SCHEMA); - pms_db_user = getValueForKey(PMS_DB_USER); - pms_db_pass = getValueForKey(PMS_DB_PASS); - pms_db_schema = getValueForKey(PMS_DB_SCHEMA); - km_db_user = getValueForKey(KM_DB_USER); - km_db_pass = getValueForKey(KM_DB_PASS); - km_db_schema = getValueForKey(KM_DB_SCHEMA); - master_db_user = getValueForKey(MASTER_DB_USER); - master_db_pass = getValueForKey(MASTER_DB_PASS); - master_db_schema = getValueForKey(MASTER_DB_SCHEMA); - iam_external_url = getValueForKey(IAM_EXTERNAL_URL); - System.out.println("keycloakendpoint from config manager::" + iam_external_url); - reportExpirationInDays = System.getenv(REPORT_EXPIRATION_IN_DAYS) == null - ? propsKernel.getProperty(REPORT_EXPIRATION_IN_DAYS) - : System.getenv(REPORT_EXPIRATION_IN_DAYS); - propsKernel.setProperty(REPORT_EXPIRATION_IN_DAYS, reportExpirationInDays); - iam_realm_id = getValueForKey(IAM_REALM_ID); - iam_users_to_create = getValueForKey(IAM_USERS_TO_CREATE); - iam_users_password = getValueForKey(IAM_USERS_PASSWORD); - - usePreConfiguredOtp = System.getenv(USEPRECONFIGOTP) == null ? propsKernel.getProperty(USEPRECONFIGOTP) - : System.getenv(USEPRECONFIGOTP); - propsKernel.setProperty(USEPRECONFIGOTP, usePreConfiguredOtp); - - preconfiguredOtp = System.getenv(PRECONFIGOTP) == null ? propsKernel.getProperty(PRECONFIGOTP) - : System.getenv(PRECONFIGOTP); - propsKernel.setProperty(PRECONFIGOTP, preconfiguredOtp); - - admin_client_secret = System.getenv(MOSIP_ADMIN_CLIENT_SECRET) == null - ? propsKernel.getProperty(MOSIP_ADMIN_CLIENT_SECRET) - : System.getenv(MOSIP_ADMIN_CLIENT_SECRET); - - propsKernel.setProperty(MOSIP_ADMIN_CLIENT_SECRET, admin_client_secret); - - authDemoServicePort = System.getenv(AUTH_DEMO_SERVICE_PORT) == null - ? propsKernel.getProperty(AUTH_DEMO_SERVICE_PORT) - : System.getenv(AUTH_DEMO_SERVICE_PORT); - propsKernel.setProperty(AUTH_DEMO_SERVICE_PORT, authDemoServicePort); - - authDemoServiceBaseUrl = System.getenv(AUTH_DEMO_SERVICE_BASE_URL) == null - ? propsKernel.getProperty(AUTH_DEMO_SERVICE_BASE_URL) - : System.getenv(AUTH_DEMO_SERVICE_BASE_URL); - propsKernel.setProperty(AUTH_DEMO_SERVICE_BASE_URL, authDemoServiceBaseUrl); - - mountPath = System.getenv(MOUNT_PATH) == null ? propsKernel.getProperty(MOUNT_PATH) : System.getenv(MOUNT_PATH); - propsKernel.setProperty(MOUNT_PATH, mountPath); - - authCertsPath = System.getenv(AUTHCERTS_PATH) == null ? propsKernel.getProperty(AUTHCERTS_PATH) : System.getenv(AUTHCERTS_PATH); - propsKernel.setProperty(AUTHCERTS_PATH, authCertsPath); - - mountPathForScenario = System.getenv(MOUNT_PATH_FOR_SCENARIO) == null ? propsKernel.getProperty(MOUNT_PATH_FOR_SCENARIO) : System.getenv(MOUNT_PATH_FOR_SCENARIO); - propsKernel.setProperty(MOUNT_PATH_FOR_SCENARIO, mountPathForScenario); - - packetUtilityBaseUrl = System.getenv(PACKET_UTILITY_BASE_URL) == null ? propsKernel.getProperty(PACKET_UTILITY_BASE_URL) : System.getenv(PACKET_UTILITY_BASE_URL); - propsKernel.setProperty(PACKET_UTILITY_BASE_URL, packetUtilityBaseUrl); - - push_reports_to_s3 =System.getenv(PUSH_TO_S3) == null ? propsKernel.getProperty(PUSH_TO_S3) : System.getenv(PUSH_TO_S3); - propsKernel.setProperty(PUSH_TO_S3, push_reports_to_s3); - - enableDebug =System.getenv(ENABLE_DEBUG) == null ? propsKernel.getProperty(ENABLE_DEBUG) : System.getenv(ENABLE_DEBUG); - propsKernel.setProperty(ENABLE_DEBUG, enableDebug); - - threadCount =System.getenv(THREAD_COUNT) == null ? propsKernel.getProperty(THREAD_COUNT) : System.getenv(THREAD_COUNT); - propsKernel.setProperty(THREAD_COUNT, threadCount); - - langselect =System.getenv(LANG_SELECT) == null ? propsKernel.getProperty(LANG_SELECT) : System.getenv(LANG_SELECT); - propsKernel.setProperty(LANG_SELECT, langselect); - - testcases =System.getenv(Testcases) == null ? propsKernel.getProperty(Testcases) : System.getenv(Testcases); - propsKernel.setProperty(Testcases, testcases); - } - - public static String gettestcases() { - return testcases; - } - - public static String getAuthDemoServicePort() { - return authDemoServicePort; - } - - public static String getAuthDemoServiceBaseUrl() { - return authDemoServiceBaseUrl; - - } - - - public static String getLangselect() { - return langselect; - - } - - public static String getThreadCount() { - return threadCount; - - } - - - - public static String getEnableDebug() { - return enableDebug; - - } - - public static String getmountPath() { - return mountPath; - } - - public static String getmountPathForScenario() { - return mountPathForScenario; - } - - public static String getpacketUtilityBaseUrl() { - return packetUtilityBaseUrl; - } - - public static String getauthCertsPath() { - return authCertsPath; - } - - public static Properties init(String abc) { - propsKernel = getproperty(TestRunner.getResourcePath() + "/" + "/config/Kernel.properties"); - - return propsKernel; - } - - - public static String getAdminClientSecret() { - return admin_client_secret; - } - - public static Boolean IsDebugEnabled() { - return enableDebug.equalsIgnoreCase("yes"); - } - - public static String getAdminClientId() { - return admin_client_id; - } - - public static String getAdminAppId() { - return admin_app_id; - } - - public static String getIdRepoClientSecret() { - return idrepo_client_secret; - } - - public static String getidRepoClientId() { - return idrepo_client_id; - } - - public static String getidRepoAppId() { - return idrepo_app_id; - } - - public static String getRegprocClientSecret() { - return regproc_client_secret; - } - - public static String getRegprocClientId() { - return regproc_client_id; - } - - public static String getRegprocAppId() { - return regproc_app_id; - } - - - public static String getAutomationClientSecret() { - return automation_client_secret; - } - - public static String getAutomationClientId() { - return automation_client_id; - } - - public static String getAutomationAppId() { - return automation_app_id; - } - - public static String getS3Host() { - return s3_host; - } - public static String getReportExpirationInDays() { - return reportExpirationInDays; - } - - public static String getS3Region() { - return s3_region; - } - - public static String getS3UserKey() { - return s3_user_key; - } - - public static String getS3SecretKey() { - return s3_secret_key; - } - - public static String getS3Account() { - return s3_account; - } - - public static String getPushReportsToS3() { - return push_reports_to_s3; - } - - public static String getIdaDbUrl() { - return "jdbc:postgresql://" + db_domain + ":" + db_port + "/mosip_ida"; - } - - public static String getAuditDbUrl() { - return "jdbc:postgresql://" + db_domain + ":" + db_port + "/mosip_audit"; - } - - public static String getDbDriverClass() { - return hibernate_connection_driver_class; - } - - public static String getDbConnectionPoolSize() { - return hibernate_connection_pool_size; - } - - public static String getDbDialect() { - return hibernate_dialect; - } - - public static String getShowSql() { - return hibernate_show_sql; - } - public static String getiam_adminportal_path() { - return iam_adminportal_path; - } - public static String getiam_apienvuser() { - return iam_apienvuser; - } - public static String getiam_apiinternalendpoint() { - return iam_apiinternalendpoint; - } - - public static String getDbSessionContext() { - return hibernate_current_session_context_class; - } - - public static String getAuditDbUser() { - return audit_db_user; - } - - public static String getAuditDbPass() { - System.out.println("DB Password from ENV::: " + System.getenv(AUDIT_DB_PASS)); - return audit_db_pass; - } - - public static String getAuditDbSchema() { - return audit_db_schema; - } - - public static String getIdaDbUser() { - return ida_db_user; - } - - public static String getIdaDbPass() { - return ida_db_pass; - } - - public static String getIdaDbSchema() { - return ida_db_schema; - } - - public static String getPMSDbUrl() { - return "jdbc:postgresql://" + db_domain + ":" + db_port + "/mosip_pms"; - } - - public static String getKMDbUrl() { - return "jdbc:postgresql://" + db_domain + ":" + db_port + "/mosip_keymgr"; - } - - public static String getMASTERDbUrl() { - return "jdbc:postgresql://" + db_domain + ":" + db_port + "/mosip_master"; - } - - public static String getPMSDbUser() { - return pms_db_user; - } - - public static String getPMSDbPass() { - return pms_db_pass; - } - - public static String getPMSDbSchema() { - return pms_db_schema; - } - - public static String getKMDbUser() { - return km_db_user; - } - - public static String getKMDbPass() { - return km_db_pass; - } - - public static String getKMDbSchema() { - return km_db_schema; - } - - public static String getMasterDbUser() { - return master_db_user; - } - - public static String getMasterDbPass() { - return master_db_pass; - } - - public static String getMasterDbSchema() { - return master_db_schema; - } - - // from docker env getting only host url - public static String getIAMUrl() { - System.out.println("keycloak url from ENV::: " + System.getenv(IAM_EXTERNAL_URL) + "/auth"); - System.out.println("keycloak url from Property::: " + System.getProperty(IAM_EXTERNAL_URL) + "/auth"); - System.out.println("keycloak url from Config::: " + propsKernel.getProperty(IAM_EXTERNAL_URL) + "/auth"); - System.out.println("keycloak url is:::" + iam_external_url + "/auth"); - return iam_external_url + "/auth"; - } - - public static String getIAMRealmId() { - return iam_realm_id; - } - - public static String getIAMUsersToCreate() { - return iam_users_to_create; - } - - public static String getIAMUsersPassword() { - return iam_users_password; - } - - public static String getUsePreConfiguredOtp() { - return usePreConfiguredOtp; - } - - public static String getPreConfiguredOtp() { - return preconfiguredOtp; - - } - - public static String getEnv() { - return db_domain; - } - - public static String getRolesForUser() { - propsKernel = getproperty(TestRunner.getResourcePath() + "/" + "/config/Kernel.properties"); - return propsKernel.getProperty("roles"); - } - - private static Properties getproperty(String path) { - Properties prop = new Properties(); - try { - File file = new File(path); - prop.load(new FileInputStream(file)); - } catch (IOException e) { - LOGGER.error("Exception " + e.getMessage()); - } - return prop; - } - - public static String getAuthDemoServiceUrl() { - return ConfigManager.getAuthDemoServiceBaseUrl() + ":" + ConfigManager.getAuthDemoServicePort(); - } - -} \ No newline at end of file diff --git a/ui-test/src/main/java/regclient/api/KernelAuthentication.java b/ui-test/src/main/java/regclient/api/KernelAuthentication.java index b25e574a7..30f4744f8 100644 --- a/ui-test/src/main/java/regclient/api/KernelAuthentication.java +++ b/ui-test/src/main/java/regclient/api/KernelAuthentication.java @@ -62,9 +62,9 @@ public String getAuthForIDREPO() { JSONObject actualrequest = getRequestJson(authRequest); JSONObject request=new JSONObject(); - request.put("appId", ConfigManager.getidRepoAppId()); - request.put("clientId", ConfigManager.getidRepoClientId()); - request.put("secretKey", ConfigManager.getIdRepoClientSecret()); + request.put("appId", ArcConfigManager.getidRepoAppId()); + request.put("clientId", ArcConfigManager.getidRepoClientId()); + request.put("secretKey", ArcConfigManager.getIdRepoClientSecret()); actualrequest.put("request", request); Response reponse=appl.postWithJson(props.get("authclientidsecretkeyURL"), actualrequest); @@ -78,14 +78,14 @@ public String getAuthForAdmin() { JSONObject actualrequest = getRequestJson(authInternalRequest); JSONObject request = new JSONObject(); - request.put("appId", ConfigManager.getAdminAppId()); + request.put("appId", ArcConfigManager.getAdminAppId()); request.put("password", admin_password); //if(BaseTestCase.currentModule==null) admin_userName= request.put("userName", BaseTestCase.currentModule +"-"+ admin_userName); - request.put("clientId", ConfigManager.getAdminClientId()); - request.put("clientSecret", ConfigManager.getAdminClientSecret()); + request.put("clientId", ArcConfigManager.getAdminClientId()); + request.put("clientSecret", ArcConfigManager.getAdminClientSecret()); actualrequest.put("request", request); Response reponse = appl.postWithJson(authenticationInternalEndpoint, actualrequest); @@ -100,11 +100,11 @@ public String getAuthForzoneMap() { JSONObject actualrequest = getRequestJson(authInternalRequest); JSONObject request = new JSONObject(); - request.put("appId", ConfigManager.getAdminAppId()); + request.put("appId", ArcConfigManager.getAdminAppId()); request.put("password", admin_password); request.put("userName", props.get("admin_zone_userName")); - request.put("clientId", ConfigManager.getAdminClientId()); - request.put("clientSecret", ConfigManager.getAdminClientSecret()); + request.put("clientId", ArcConfigManager.getAdminClientId()); + request.put("clientSecret", ArcConfigManager.getAdminClientSecret()); actualrequest.put("request", request); Response reponse = appl.postWithJson(authenticationInternalEndpoint, actualrequest); diff --git a/ui-test/src/main/java/regclient/api/KeycloakUserManager.java b/ui-test/src/main/java/regclient/api/KeycloakUserManager.java index bca9480da..28ce05a19 100644 --- a/ui-test/src/main/java/regclient/api/KeycloakUserManager.java +++ b/ui-test/src/main/java/regclient/api/KeycloakUserManager.java @@ -37,10 +37,10 @@ private static Keycloak getKeycloakInstance() { Keycloak key=null; try { - key=KeycloakBuilder.builder().serverUrl(ConfigManager.getIAMUrl()).realm(ConfigManager.getIAMRealmId()) - .grantType(OAuth2Constants.CLIENT_CREDENTIALS).clientId(ConfigManager.getAutomationClientId()).clientSecret(ConfigManager.getAutomationClientSecret()) + key=KeycloakBuilder.builder().serverUrl(ArcConfigManager.getIAMUrl()).realm(ArcConfigManager.getIAMRealmId()) + .grantType(OAuth2Constants.CLIENT_CREDENTIALS).clientId(ArcConfigManager.getAutomationClientId()).clientSecret(ArcConfigManager.getAutomationClientSecret()) .build(); - System.out.println(ConfigManager.getIAMUrl()); + System.out.println(ArcConfigManager.getIAMUrl()); System.out.println(key.toString() + key.realms()); }catch(Exception e) { @@ -62,7 +62,7 @@ public static Properties getproperty(String path) { } public static void createUsers() { - List needsToBeCreatedUsers = List.of(ConfigManager.getIAMUsersToCreate().split(",")); + List needsToBeCreatedUsers = List.of(ArcConfigManager.getIAMUsersToCreate().split(",")); Keycloak keycloakInstance = getKeycloakInstance(); for (String needsToBeCreatedUser : needsToBeCreatedUsers) { UserRepresentation user = new UserRepresentation(); @@ -86,7 +86,7 @@ else if(needsToBeCreatedUser.equals("masterdata-220005")){ user.setLastName(moduleSpecificUser); user.setEmail("automation" + moduleSpecificUser + "@automationlabs.com"); // Get realm - RealmResource realmResource = keycloakInstance.realm(ConfigManager.getIAMRealmId()); + RealmResource realmResource = keycloakInstance.realm(ArcConfigManager.getIAMRealmId()); UsersResource usersRessource = realmResource.users(); // Create user (requires manage-users role) Response response = null; @@ -107,7 +107,7 @@ else if(needsToBeCreatedUser.equals("masterdata-220005")){ passwordCred.setType(CredentialRepresentation.PASSWORD); //passwordCred.setValue(userPassword.get(passwordIndex)); - passwordCred.setValue(ConfigManager.getIAMUsersPassword()); + passwordCred.setValue(ArcConfigManager.getIAMUsersPassword()); UserResource userResource = usersRessource.get(userId); @@ -117,7 +117,7 @@ else if(needsToBeCreatedUser.equals("masterdata-220005")){ // Getting all the roles List allRoles = realmResource.roles().list(); List availableRoles = new ArrayList<>(); - List toBeAssignedRoles = List.of(ConfigManager.getRolesForUser().split(",")); + List toBeAssignedRoles = List.of(ArcConfigManager.getRolesForUser().split(",")); for(String role : toBeAssignedRoles) { if(allRoles.stream().anyMatch((r->r.getName().equalsIgnoreCase(role)))){ availableRoles.add(allRoles.stream().filter(r->r.getName().equals(role)).findFirst().get()); @@ -142,7 +142,7 @@ public static void createUsersWithOutDefaultRole() { user.setFirstName(onboardUser); user.setLastName(onboardUser); user.setEmail("automation" + onboardUser + "@automationlabs.com"); - RealmResource realmResource = keycloakInstance.realm(ConfigManager.getIAMRealmId()); + RealmResource realmResource = keycloakInstance.realm(ArcConfigManager.getIAMRealmId()); UsersResource usersRessource = realmResource.users(); Response response = null; response = usersRessource.create(user); @@ -156,7 +156,7 @@ public static void createUsersWithOutDefaultRole() { passwordCred.setTemporary(false); passwordCred.setType(CredentialRepresentation.PASSWORD); - passwordCred.setValue(ConfigManager.getIAMUsersPassword()); + passwordCred.setValue(ArcConfigManager.getIAMUsersPassword()); UserResource userResource = usersRessource.get(userId); @@ -164,7 +164,7 @@ public static void createUsersWithOutDefaultRole() { List allRoles = realmResource.roles().list(); List availableRoles = new ArrayList<>(); - List toBeAssignedRoles = List.of(ConfigManager.getRolesForUser().split(",")); + List toBeAssignedRoles = List.of(ArcConfigManager.getRolesForUser().split(",")); for(String role : toBeAssignedRoles) { if(!role.equalsIgnoreCase("Default")) { if(allRoles.stream().anyMatch((r->r.getName().equalsIgnoreCase(role)))){ diff --git a/ui-test/src/main/java/regclient/api/RestClient.java b/ui-test/src/main/java/regclient/api/RestClient.java index c2b5c4f19..07b4435fd 100644 --- a/ui-test/src/main/java/regclient/api/RestClient.java +++ b/ui-test/src/main/java/regclient/api/RestClient.java @@ -56,7 +56,7 @@ public static Response postRequestWithCookie(String url, Object body, String con // public static Response postReqestWithCookiesAndBody(String url, String body, String token, String opsToLog) { Response posttResponse = null; - if (ConfigManager.IsDebugEnabled()) { + if (ArcConfigManager.IsDebugEnabled()) { posttResponse = given().relaxedHTTPSValidation().body(body).contentType("application/json") .accept("*/*").log().all().when().cookie("Authorization", token).post(url).then().log().all() .extract().response(); diff --git a/ui-test/src/main/java/regclient/utils/EmailableReport.java b/ui-test/src/main/java/regclient/utils/EmailableReport.java index 1826aa3d8..91f2c5716 100644 --- a/ui-test/src/main/java/regclient/utils/EmailableReport.java +++ b/ui-test/src/main/java/regclient/utils/EmailableReport.java @@ -26,7 +26,7 @@ import org.testng.internal.Utils; import org.testng.xml.XmlSuite; -import regclient.api.ConfigManager; +import regclient.api.ArcConfigManager; @@ -170,7 +170,7 @@ protected void writeSuiteSummary() { for (SuiteResult suiteResult : suiteResults) { writer.print(""); - writer.print(Utils.escapeHtml("Android Regclient Ui Automation ------- Env - "+ConfigManager.getEnv() )); + writer.print(Utils.escapeHtml("Android Regclient Ui Automation ------- Env - "+ArcConfigManager.getEnv() )); writer.print(""); writer.print("
");
 			writer.print(Utils.escapeHtml("Date and Time  ")+printCurrentDateTime());
diff --git a/ui-test/src/main/java/regclient/utils/TestRunner.java b/ui-test/src/main/java/regclient/utils/TestRunner.java
index d18e805ff..050facd24 100644
--- a/ui-test/src/main/java/regclient/utils/TestRunner.java
+++ b/ui-test/src/main/java/regclient/utils/TestRunner.java
@@ -9,9 +9,10 @@
 import org.testng.xml.XmlSuite;
 import org.testng.xml.XmlTest;
 
+import io.mosip.testrig.apirig.testrunner.BaseTestCase;
+import io.mosip.testrig.apirig.testrunner.OTPListener;
 import regclient.api.AdminTestUtil;
-import regclient.api.BaseTestCase;
-import regclient.api.ConfigManager;
+import regclient.api.ArcConfigManager;
 import regclient.api.FetchUiSpec;
 
 public class TestRunner {
@@ -19,12 +20,22 @@ public class TestRunner {
 	public static String jarUrl = TestRunner.class.getProtectionDomain().getCodeSource().getLocation().getPath();
 	
 	public static void main(String[] args) {	
+		io.mosip.testrig.apirig.testrunner.BaseTestCase.currentModule = "androidregclient";
 		AdminTestUtil.initialize();
+		BaseTestCase.ApplnURI = ArcConfigManager.getiam_apiinternalendpoint();
+		OTPListener otpListener = new OTPListener();
+		otpListener.run();	
 		FetchUiSpec.getUiSpec("newProcess");
+		io.mosip.testrig.apirig.testrunner.BaseTestCase.setRunContext(checkRunType(), jarUrl);
+		io.mosip.testrig.apirig.testrunner.BaseTestCase.copymoduleSpecificAndConfigFile("config");
+		io.mosip.testrig.apirig.utils.AdminTestUtil.init();
 		FetchUiSpec.getBiometricDetails("individualBiometrics");
+		System.out.println("BaseTestCase.ApplnURI : " + BaseTestCase.ApplnURI);
+		AdminTestUtil.getPreRegistrationFlow();
+		
 		File homeDir = null;
 		TestNG runner = new TestNG();
-		if(!ConfigManager.gettestcases().equals("")) {
+		if(!ArcConfigManager.gettestcases().equals("")) {
 			XmlSuite suite = new XmlSuite();
 			suite.setName("MySuite");
 			suite.addListener("regclient.utils.EmailableReport");
@@ -44,7 +55,7 @@ public static void main(String[] args) {
 
 
 			List classes = new ArrayList<>();
-			String[] Scenarionames=ConfigManager.gettestcases().split(",");
+			String[] Scenarionames=ArcConfigManager.gettestcases().split(",");
 			for(String test:Scenarionames) {
 				String Scenarioname=test.toLowerCase();
 
@@ -106,6 +117,7 @@ public static void main(String[] args) {
 		System.getProperties().setProperty("emailable.report2.name", "AndroidRegClient-" + BaseTestCase.environment + 
 				 "-run-" + System.currentTimeMillis() + "-report.html");
 		runner.run();
+		otpListener.bTerminate=true;
 		System.exit(0);
 	}
 	
diff --git a/ui-test/src/main/resources/config/Kernel.properties b/ui-test/src/main/resources/config/Kernel.properties
index bc715fb69..025e61b6e 100644
--- a/ui-test/src/main/resources/config/Kernel.properties
+++ b/ui-test/src/main/resources/config/Kernel.properties
@@ -11,6 +11,9 @@ leafzonesURL=/v1/masterdata/zones/leafzones/eng
 zoneNameUrl=/v1/masterdata/zones/zonename
 zoneMappingActivateUrl=/v1/masterdata/zoneuser
 userCenterMappingUrl=/v1/masterdata/usercentermapping
+actuatorAdminEndpoint=/v1/admin/actuator/env
+actuatorMasterDataEndpoint=/v1/masterdata/actuator/env
+actuatorIDAEndpoint=/idauthentication/v1/actuator/env
 # OTP Details
 OTPTimeOut = 181
 attempt = 10
diff --git a/ui-test/src/main/resources/config/application.properties b/ui-test/src/main/resources/config/application.properties
index 834c7cee0..8c187fd2c 100644
--- a/ui-test/src/main/resources/config/application.properties
+++ b/ui-test/src/main/resources/config/application.properties
@@ -5,4 +5,90 @@ masterSchemaURL=/v1/masterdata/idschema/latest
 addIdentityURL=/idrepository/v1/identity/
 idRepoGenVidURL=/idrepository/v1/vid
 locationHierarchyLevels=/v1/masterdata/locationHierarchyLevels/
-locationhierarchy=/v1/masterdata/locations/locationhierarchy/
\ No newline at end of file
+locationhierarchy=/v1/masterdata/locations/locationhierarchy/
+## End point(s) relative URLs
+encryptionPath=v1/identity/encrypt?isInternal=false
+internalEncryptionPath=v1/identity/encrypt?isInternal=true
+encodePath=v1/identity/encode
+decodePath=v1/identity/decode
+signRequest=v1/identity/signRequest
+decryptPath=/idauthentication/v1/internal/decrypt
+decryptkycdataurl = v1/identity/decryptEkycData
+encodeFilePath=v1/identity/encodeFile
+decodeFilePath=v1/identity/decodeFile/?fileName=cbeff
+validateSignaturePath=v1/identity/validateSign?signature=$signature$
+splitEncryptedData=v1/identity/splitEncryptedData
+bioValueEncryptionTemplate=config/bioValueEncryptionTemplate.json
+idaMappingPath=config/mapping.properties
+getIdaCertificateUrl=/idauthentication/v1/internal/getCertificate
+getPartnerCertificateUrl=/v1/partnermanager/partners/{partnerId}/certificate
+putPartnerRegistrationUrl=/v1/partnermanager/partners
+getPartnerCertURL=v1/identity/generatePartnerKeys
+uploadCACertificateUrl=/v1/partnermanager/partners/certificate/ca/upload
+uploadIntermediateCertificateUrl=/v1/partnermanager/partners/certificate/ca/upload
+uploadPartnerCertificateUrl=/v1/partnermanager/partners/certificate/upload
+uploadSignedCertificateUrl=v1/identity/updatePartnerCertificate
+getKeyCloakTokenUrl = /auth/realms/master/protocol/openid-connect/token
+masterSchemaURL=/v1/masterdata/idschema/latest
+preregLoginConfigUrl=/preregistration/v1/login/config
+uploadIdaFirurl=v1/identity/uploadIDACertificate?certificateType=IDA_FIR&moduleName=$MODULENAME$&certsDir=$CERTSDIR$
+uploadPartnerurl=v1/identity/uploadIDACertificate?certificateType=PARTNER&moduleName=$MODULENAME$&certsDir=$CERTSDIR$
+uploadInternalurl=v1/identity/uploadIDACertificate?certificateType=INTERNAL&moduleName=$MODULENAME$&certsDir=$CERTSDIR$
+authPolicyUrl=/v1/policymanager/policies
+policyGroupUrl=/v1/policymanager/policies/group/new
+publishPolicyurl=/v1/policymanager/policies/POLICYID/group/POLICYGROUPID/publish
+clearCertificateURL=v1/identity/clearKeys?moduleName=$MODULENAME$&certsDir=$CERTSDIR$
+fetchLocationData=/v1/masterdata/locations/all
+fetchLocationLevel=/v1/masterdata/locations/level/
+fetchTitle=/v1/masterdata/title
+fetchZoneCode=/v1/masterdata/zones/hierarchy/
+fetchZone=/v1/masterdata/zones/zonename
+decryptKycUrl=/v1/identity/decryptEkycData
+retrieveIdByUin=/idrepository/v1/identity/idvid/
+fetchLocationHierarchyLevels=/v1/masterdata/locationHierarchyLevels/
+fetchLocationHierarchy=/v1/masterdata/locations/locationhierarchy/
+generateArgon2HashURL=/v1/keymanager/generateArgon2Hash
+appointmentavailabilityurl=/preregistration/v1/appointment/availability/
+validateSignatureUrl=v1/identity/validateSign
+vciContextURL=https://www.w3.org/2018/credentials/v1
+
+## As below are non changble values, move these out from properties file
+appIdForCertificate=IDA
+partnerrefId=PARTNER
+internalrefId=INTERNAL
+idaFirRefId=IDA-FIR
+proxyOTP=111111
+wrongOtp=123455
+
+## 
+regcentretobookappointment=10003
+keysToValidateInKYC=phoneNumber,emailId,age,dob,name_eng
+#partner certificate refId, used for getting the partner certificate
+partner=9998
+signatureheaderKey=response-signature
+uinGenMaxLoopCount=20
+uinGenDelayTime=10000
+Delaytime=90000
+
+
+## Remove this from properties file
+picturevalue=iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAIAAAACUFjqAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAAFiUAABYlAUlSJPAAAABCSURBVChTbYtBEgAgCAL7/6eNhBy09qDi6gpjXZSxUU8o/jrfpDmcmY1QAOWhgTswv6sSm8zVhULlgst++8T51IjYNUHdI+4XZHoAAAAASUVORK5CYII=
+
+
+## Check are we using these properties. If not remove them
+zoneCode_to_beMapped=NTH
+expireOtpTime=180000
+demoAppVersion=1.2.1-java21-SNAPSHOT
+AttributetoBeUpdate:Name
+ValuetoBeUpdate:Sohan
+
+## As these will be based on regEx, move these out from proprties file
+passwordForAddIdentity=12341234_Aa
+passwordToReset=12341234_AaB
+
+## Need to revisit these propeties
+XSRFTOKEN=7d01b2a8-b89d-41ad-9361-d7f6294021d1
+codeChallenge=E9Melhoa2OwvFrEMTJguCHaoeK1t8URWbuGJSstw-cM
+codeVerifier=dBjftJeZ4CVP-mB92K27uhbUJU1p1r_wW1gFWFOEjXk
+policyNumberForSunBirdRC=654321
+challengeValueForSunBirdRC=eyJmdWxsTmFtZSI6IkthaWYgU2lkZGlxdWUiLCJkb2IiOiIyMDAwLTA3LTI2In0=
\ No newline at end of file
diff --git a/ui-test/src/main/resources/config/valueMapping.properties b/ui-test/src/main/resources/config/valueMapping.properties
new file mode 100644
index 000000000..c9b1c8ebb
--- /dev/null
+++ b/ui-test/src/main/resources/config/valueMapping.properties
@@ -0,0 +1,35 @@
+# common properties
+residenceStatus=NFR
+fullName=TEST_FULLNAME
+firstName=TEST_FIRSTNAME
+dateOfBirth=1996/01/01
+gender=MLE
+pobCountry=POB_COUNTRY
+pobProvince=POB_PROVINCE
+pobCity=POB_CITY
+bloodType=BLOOD_TYPE
+permanentCountry=PERMANENT_COUNTRY
+permanentAddressLine1=PERMANENT_ADDRESS_LINE_1
+presentAddressLine1=PRESENT_ADDRESS_LINE_1
+modeOfClaim=MODE_OF_CLAIM
+presentCountry=PRESENT_COUNTRY
+addressLine1=TEST_ADDRESSLINE1
+addressLine2=TEST_ADDRESSLINE2
+addressLine3=TEST_ADDRESSLINE3
+postalCode=14022
+phone=8249742850
+email=test@mosip.net
+region=TEST_REGION
+fullName1=Lisa.GN
+firstName1=Lisa.GN
+province=TEST_PROVINCE
+city=TEST_CITY
+zone=TEST_ZONE
+introducerName=TEST_INTRODUCERNAME
+bloodGroup=O
+Miss-TitleFromServer=MIS
+Mr-TitleFromServer=MIR
+Mrs-TitleFromServer=MRS
+Miss-TitleFromServer.=MIS
+addressCopy=TEST_ADDRESSLINE3
+proofOfAddress=TEST_ADDRESSLINE2
\ No newline at end of file

From 26bc96507148503b3e9aa880a01a05d98982624a Mon Sep 17 00:00:00 2001
From: Sachin S  P <52343650+SachinPremkumar@users.noreply.github.com>
Date: Tue, 7 Oct 2025 10:48:34 +0530
Subject: [PATCH 24/44] RCF-92 : Global Config Settings Implementation (#582)

* RCF-92 global configue settings

Signed-off-by: sachin.sp 

* RCF-92 global configue settings

Signed-off-by: sachin.sp 

* RCF-92 : global configue settings implementation

Signed-off-by: sachin.sp 

* RCF-92 : global configue settings implementation

Signed-off-by: sachin.sp 

* RCF- 92: removed log's settings

Signed-off-by: sachin.sp 

* RCF- 92: updated the review comments

Signed-off-by: sachin.sp 

* RCF- 92: updated the review comments

Signed-off-by: sachin.sp 

---------

Signed-off-by: sachin.sp 
Co-authored-by: sachin.sp 
---
 .../registration_client/HostApiModule.java    |  17 +
 .../registration_client/MainActivity.java     |   6 +
 .../api_services/GlobalConfigSettingsApi.java |  77 +++
 .../clientmanager/config/AppModule.java       |   8 +-
 .../clientmanager/config/ClientDatabase.java  |  11 +-
 .../clientmanager/config/RoomModule.java      |  31 +-
 .../constant/RegistrationConstants.java       |   6 +
 .../clientmanager/dao/GlobalParamDao.java     |   3 +
 .../clientmanager/dao/LocalConfigDAO.java     |  30 ++
 .../clientmanager/dao/LocalConfigDAOImpl.java | 128 +++++
 .../dao/LocalPreferencesDao.java              |  30 ++
 .../dao/PermittedLocalConfigDao.java          |  21 +
 .../entity/LocalPreferences.java              |  48 ++
 .../entity/PermittedLocalConfig.java          |  36 ++
 .../repository/GlobalParamRepository.java     |  54 +-
 .../LocalPreferencesRepository.java           |  90 ++++
 .../PermittedLocalConfigRepository.java       |  45 ++
 .../service/LocalConfigServiceImpl.java       |  37 ++
 .../service/MasterDataServiceImpl.java        |  42 +-
 .../clientmanager/spi/LocalConfigService.java |  25 +
 .../clientmanager/spi/MasterDataService.java  |   3 +
 .../service/MasterDataServiceImplTest.java    |   6 +-
 .../service/SyncDataServiceImplTest.java      |   2 +-
 assets/l10n/app_ar.arb                        |   8 +-
 assets/l10n/app_en.arb                        |   8 +-
 assets/l10n/app_fr.arb                        |   8 +-
 assets/l10n/app_hi.arb                        |   8 +-
 assets/l10n/app_kn.arb                        |   8 +-
 assets/l10n/app_ta.arb                        |   8 +-
 .../global_config_service_impl.dart           |  63 +++
 lib/platform_spi/global_config_service.dart   |  13 +
 lib/ui/onboard/portrait/mobile_home_page.dart |   2 +-
 .../widgets => settings}/settings_screen.dart |  26 +-
 .../widgets/global_config_settings_tab.dart   | 485 ++++++++++++++++++
 pigeon.sh                                     |   5 +-
 pigeon/global_config_settings.dart            |  13 +
 pubspec.yaml                                  |   1 +
 37 files changed, 1389 insertions(+), 23 deletions(-)
 create mode 100644 android/app/src/main/java/io/mosip/registration_client/api_services/GlobalConfigSettingsApi.java
 create mode 100644 android/clientmanager/src/main/java/io/mosip/registration/clientmanager/dao/LocalConfigDAO.java
 create mode 100644 android/clientmanager/src/main/java/io/mosip/registration/clientmanager/dao/LocalConfigDAOImpl.java
 create mode 100644 android/clientmanager/src/main/java/io/mosip/registration/clientmanager/dao/LocalPreferencesDao.java
 create mode 100644 android/clientmanager/src/main/java/io/mosip/registration/clientmanager/dao/PermittedLocalConfigDao.java
 create mode 100644 android/clientmanager/src/main/java/io/mosip/registration/clientmanager/entity/LocalPreferences.java
 create mode 100644 android/clientmanager/src/main/java/io/mosip/registration/clientmanager/entity/PermittedLocalConfig.java
 create mode 100644 android/clientmanager/src/main/java/io/mosip/registration/clientmanager/repository/LocalPreferencesRepository.java
 create mode 100644 android/clientmanager/src/main/java/io/mosip/registration/clientmanager/repository/PermittedLocalConfigRepository.java
 create mode 100644 android/clientmanager/src/main/java/io/mosip/registration/clientmanager/service/LocalConfigServiceImpl.java
 create mode 100644 android/clientmanager/src/main/java/io/mosip/registration/clientmanager/spi/LocalConfigService.java
 create mode 100644 lib/platform_android/global_config_service_impl.dart
 create mode 100644 lib/platform_spi/global_config_service.dart
 rename lib/ui/{process_ui/widgets => settings}/settings_screen.dart (86%)
 create mode 100644 lib/ui/settings/widgets/global_config_settings_tab.dart
 create mode 100644 pigeon/global_config_settings.dart

diff --git a/android/app/src/main/java/io/mosip/registration_client/HostApiModule.java b/android/app/src/main/java/io/mosip/registration_client/HostApiModule.java
index 3866fc182..91b779f82 100644
--- a/android/app/src/main/java/io/mosip/registration_client/HostApiModule.java
+++ b/android/app/src/main/java/io/mosip/registration_client/HostApiModule.java
@@ -21,6 +21,7 @@
 import io.mosip.registration.clientmanager.dao.FileSignatureDao;
 import io.mosip.registration.clientmanager.dao.GlobalParamDao;
 import io.mosip.registration.clientmanager.dao.UserDetailDao;
+import io.mosip.registration.clientmanager.dao.LocalConfigDAO;
 import io.mosip.registration.clientmanager.repository.GlobalParamRepository;
 import io.mosip.registration.clientmanager.repository.IdentitySchemaRepository;
 import io.mosip.registration.clientmanager.repository.RegistrationCenterRepository;
@@ -29,7 +30,9 @@
 import io.mosip.registration.clientmanager.service.LoginService;
 import io.mosip.registration.clientmanager.service.TemplateService;
 import io.mosip.registration.clientmanager.service.UserOnboardService;
+import io.mosip.registration.clientmanager.service.LocalConfigServiceImpl;
 import io.mosip.registration.clientmanager.spi.AuditManagerService;
+import io.mosip.registration.clientmanager.spi.LocalConfigService;
 import io.mosip.registration.clientmanager.spi.MasterDataService;
 import io.mosip.registration.clientmanager.spi.PacketService;
 import io.mosip.registration.clientmanager.spi.PreRegistrationDataSyncService;
@@ -60,6 +63,7 @@
 import io.mosip.registration_client.api_services.DocumentDetailsApi;
 
 import io.mosip.registration_client.api_services.DynamicDetailsApi;
+import io.mosip.registration_client.api_services.GlobalConfigSettingsApi;
 import io.mosip.registration_client.api_services.MachineDetailsApi;
 import io.mosip.registration_client.api_services.PacketAuthenticationApi;
 import io.mosip.registration_client.api_services.MasterDataSyncApi;
@@ -224,5 +228,18 @@ DocumentCategoryApi getDocumentCategoryApi(RegistrationService registrationServi
     DashBoardDetailsApi getDashBoardDetailsApi(UserDetailDao userDetailDao, RegistrationRepository registrationRepository) {
         return new DashBoardDetailsApi(appContext,userDetailDao, registrationRepository);
     }
+
+
+    @Provides
+    @Singleton
+    LocalConfigService provideLocalConfigService(LocalConfigDAO localConfigDAO) {
+        return new LocalConfigServiceImpl(localConfigDAO);
+    }
+
+    @Provides
+    @Singleton
+    GlobalConfigSettingsApi getGlobalConfigSettingsApiImpl(MasterDataService masterDataService, LocalConfigService localConfigService, GlobalParamRepository globalParamRepository) {
+        return new GlobalConfigSettingsApi(masterDataService, localConfigService, globalParamRepository);
+    }
 }
 
diff --git a/android/app/src/main/java/io/mosip/registration_client/MainActivity.java b/android/app/src/main/java/io/mosip/registration_client/MainActivity.java
index 439a02fd9..7dc26fbf2 100644
--- a/android/app/src/main/java/io/mosip/registration_client/MainActivity.java
+++ b/android/app/src/main/java/io/mosip/registration_client/MainActivity.java
@@ -75,6 +75,7 @@
 import io.mosip.registration_client.api_services.DocumentCategoryApi;
 import io.mosip.registration_client.api_services.DocumentDetailsApi;
 import io.mosip.registration_client.api_services.DynamicDetailsApi;
+import io.mosip.registration_client.api_services.GlobalConfigSettingsApi;
 import io.mosip.registration_client.api_services.MachineDetailsApi;
 import io.mosip.registration_client.api_services.PacketAuthenticationApi;
 import io.mosip.registration_client.api_services.MasterDataSyncApi;
@@ -90,6 +91,7 @@
 import io.mosip.registration_client.model.DemographicsDataPigeon;
 import io.mosip.registration_client.model.DocumentCategoryPigeon;
 import io.mosip.registration_client.model.DynamicResponsePigeon;
+import io.mosip.registration_client.model.GlobalConfigSettingsPigeon;
 import io.mosip.registration_client.model.MachinePigeon;
 import io.mosip.registration_client.model.PacketAuthPigeon;
 import io.mosip.registration_client.model.MasterDataSyncPigeon;
@@ -192,6 +194,9 @@ public class MainActivity extends FlutterActivity {
     @Inject
     BatchJob batchJob;
 
+    @Inject
+    GlobalConfigSettingsApi globalConfigSettingsApi;
+
     private BroadcastReceiver broadcastReceiver = new BroadcastReceiver() {
         @Override
         public void onReceive(Context context, Intent intent) {
@@ -297,6 +302,7 @@ public void configureFlutterEngine(@NonNull FlutterEngine flutterEngine) {
         MasterDataSyncPigeon.SyncApi.setup(flutterEngine.getDartExecutor().getBinaryMessenger(), masterDataSyncApi);
         masterDataSyncApi.setCallbackActivity(this, batchJob);
         AuditResponsePigeon.AuditResponseApi.setup(flutterEngine.getDartExecutor().getBinaryMessenger(), auditDetailsApi);
+        GlobalConfigSettingsPigeon.GlobalConfigSettingsApi.setup(flutterEngine.getDartExecutor().getBinaryMessenger(), globalConfigSettingsApi);
     }
 
     @Override
diff --git a/android/app/src/main/java/io/mosip/registration_client/api_services/GlobalConfigSettingsApi.java b/android/app/src/main/java/io/mosip/registration_client/api_services/GlobalConfigSettingsApi.java
new file mode 100644
index 000000000..8b391a65e
--- /dev/null
+++ b/android/app/src/main/java/io/mosip/registration_client/api_services/GlobalConfigSettingsApi.java
@@ -0,0 +1,77 @@
+package io.mosip.registration_client.api_services;
+
+import android.util.Log;
+
+import androidx.annotation.NonNull;
+
+import java.util.List;
+import java.util.Map;
+
+import javax.inject.Inject;
+import javax.inject.Singleton;
+
+import io.mosip.registration.clientmanager.repository.GlobalParamRepository;
+import io.mosip.registration.clientmanager.spi.LocalConfigService;
+import io.mosip.registration.clientmanager.spi.MasterDataService;
+import io.mosip.registration_client.model.GlobalConfigSettingsPigeon;
+
+@Singleton
+public class GlobalConfigSettingsApi implements GlobalConfigSettingsPigeon.GlobalConfigSettingsApi {
+
+    MasterDataService masterDataService;
+
+    LocalConfigService localConfigService;
+
+    GlobalParamRepository globalParamRepository;
+
+    @Inject
+    public GlobalConfigSettingsApi(MasterDataService masterDataService, LocalConfigService localConfigService, GlobalParamRepository globalParamRepository) {
+        this.masterDataService = masterDataService;
+        this.localConfigService = localConfigService;
+        this.globalParamRepository = globalParamRepository;
+    }
+
+    @Override
+    public void getRegistrationParams(@NonNull GlobalConfigSettingsPigeon.Result> result) {
+        try {
+            Map response = masterDataService.getRegistrationParams();
+            result.success(response);
+        } catch (Exception e) {
+            Log.e(getClass().getSimpleName(), "Error fetching registration params.", e);
+            result.error(e);
+        }
+    }
+
+    @Override
+    public void getLocalConfigurations(@NonNull GlobalConfigSettingsPigeon.Result> result) {
+        try {
+            Map response = localConfigService.getLocalConfigurations();
+            result.success(response);
+        } catch (Exception e) {
+            Log.e(getClass().getSimpleName(), "Error fetching local configurations.", e);
+            result.error(e);
+        }
+    }
+
+    @Override
+    public void getPermittedConfigurationNames(@NonNull GlobalConfigSettingsPigeon.Result> result) {
+        try {
+            List response = localConfigService.getPermittedConfiguration();
+            result.success(response);
+        } catch (Exception e) {
+            Log.e(getClass().getSimpleName(), "Error fetching permitted configuration names.", e);
+            result.error(e);
+        }
+    }
+
+    @Override
+    public void modifyConfigurations(@NonNull Map localPreferences, @NonNull GlobalConfigSettingsPigeon.Result result) {
+        try {
+            localConfigService.modifyConfigurations(localPreferences);
+            result.success(null);
+        } catch (Exception e) {
+            Log.e(getClass().getSimpleName(), "Error modifying configurations.", e);
+            result.error(e);
+        }
+    }
+}
\ No newline at end of file
diff --git a/android/clientmanager/src/main/java/io/mosip/registration/clientmanager/config/AppModule.java b/android/clientmanager/src/main/java/io/mosip/registration/clientmanager/config/AppModule.java
index 6eb940ed6..701f5ab81 100644
--- a/android/clientmanager/src/main/java/io/mosip/registration/clientmanager/config/AppModule.java
+++ b/android/clientmanager/src/main/java/io/mosip/registration/clientmanager/config/AppModule.java
@@ -13,6 +13,7 @@
 import dagger.Provides;
 import io.mosip.registration.clientmanager.dao.ApplicantValidDocumentDao;
 import io.mosip.registration.clientmanager.dao.FileSignatureDao;
+import io.mosip.registration.clientmanager.dao.LocalConfigDAO;
 import io.mosip.registration.clientmanager.dao.PreRegistrationDataSyncDao;
 import io.mosip.registration.clientmanager.dao.PreRegistrationDataSyncRepositoryDao;
 import io.mosip.registration.clientmanager.entity.PreRegistrationList;
@@ -35,6 +36,7 @@
 import io.mosip.registration.clientmanager.repository.UserBiometricRepository;
 import io.mosip.registration.clientmanager.repository.UserDetailRepository;
 import io.mosip.registration.clientmanager.repository.UserRoleRepository;
+import io.mosip.registration.clientmanager.repository.PermittedLocalConfigRepository;
 import io.mosip.registration.clientmanager.service.AuditManagerServiceImpl;
 import io.mosip.registration.clientmanager.service.Biometrics095Service;
 import io.mosip.registration.clientmanager.service.JobManagerServiceImpl;
@@ -164,12 +166,14 @@ public MasterDataService provideMasterDataService(ObjectMapper objectMapper, Syn
                                                       CertificateManagerService certificateManagerService,
                                                       LanguageRepository languageRepository,
                                                       JobManagerService jobManagerService,
-                                                      FileSignatureDao fileSignatureDao) {
+                                                      FileSignatureDao fileSignatureDao,
+                                                      PermittedLocalConfigRepository permittedLocalConfigRepository,
+                                                      LocalConfigDAO localConfigDAO) {
         return new MasterDataServiceImpl(appContext, objectMapper, syncRestService, clientCryptoManagerService,
                 machineRepository, reasonListRepository, registrationCenterRepository, documentTypeRepository, applicantValidDocRepository,
                 templateRepository, dynamicFieldRepository, locationRepository,
                 globalParamRepository, identitySchemaRepository, blocklistedWordRepository, syncJobDefRepository, userDetailRepository,
-                certificateManagerService, languageRepository, jobManagerService, fileSignatureDao);
+                certificateManagerService, languageRepository, jobManagerService, fileSignatureDao, permittedLocalConfigRepository, localConfigDAO);
     }
 
 
diff --git a/android/clientmanager/src/main/java/io/mosip/registration/clientmanager/config/ClientDatabase.java b/android/clientmanager/src/main/java/io/mosip/registration/clientmanager/config/ClientDatabase.java
index 7217795f6..1980ee8dc 100644
--- a/android/clientmanager/src/main/java/io/mosip/registration/clientmanager/config/ClientDatabase.java
+++ b/android/clientmanager/src/main/java/io/mosip/registration/clientmanager/config/ClientDatabase.java
@@ -28,6 +28,8 @@
 import io.mosip.registration.clientmanager.dao.TemplateDao;
 import io.mosip.registration.clientmanager.dao.UserBiometricDao;
 import io.mosip.registration.clientmanager.dao.UserDetailDao;
+import io.mosip.registration.clientmanager.dao.PermittedLocalConfigDao;
+import io.mosip.registration.clientmanager.dao.LocalPreferencesDao;
 import io.mosip.registration.clientmanager.dao.UserPasswordDao;
 import io.mosip.registration.clientmanager.dao.UserTokenDao;
 import io.mosip.registration.clientmanager.dao.UserRoleDao;
@@ -44,6 +46,7 @@
 import io.mosip.registration.clientmanager.entity.Location;
 import io.mosip.registration.clientmanager.entity.LocationHierarchy;
 import io.mosip.registration.clientmanager.entity.MachineMaster;
+import io.mosip.registration.clientmanager.entity.PermittedLocalConfig;
 import io.mosip.registration.clientmanager.entity.ReasonList;
 import io.mosip.registration.clientmanager.entity.ProcessSpec;
 import io.mosip.registration.clientmanager.entity.PreRegistrationList;
@@ -56,6 +59,7 @@
 import io.mosip.registration.clientmanager.entity.UserPassword;
 import io.mosip.registration.clientmanager.entity.UserToken;
 import io.mosip.registration.clientmanager.entity.UserRole;
+import io.mosip.registration.clientmanager.entity.LocalPreferences;
 import io.mosip.registration.keymanager.dao.CACertificateStoreDao;
 import io.mosip.registration.keymanager.dao.KeyStoreDao;
 import io.mosip.registration.keymanager.entity.CACertificateStore;
@@ -66,7 +70,8 @@
         ApplicantValidDocument.class, Template.class, KeyStore.class,
         Location.class, GlobalParam.class, IdentitySchema.class, LocationHierarchy.class,
         BlocklistedWord.class, SyncJobDef.class, UserDetail.class, UserBiometric.class, UserPassword.class, JobTransaction.class,
-        CACertificateStore.class, Language.class, Audit.class, FileSignature.class, ProcessSpec.class,PreRegistrationList.class},
+        CACertificateStore.class, Language.class, Audit.class, FileSignature.class, ProcessSpec.class,PreRegistrationList.class,
+        PermittedLocalConfig.class, LocalPreferences.class},
         version = 1, exportSchema = false)
 public abstract class ClientDatabase extends RoomDatabase {
 
@@ -140,6 +145,10 @@ public static ClientDatabase buildDatabase(Context context) {
 
     public abstract PreRegistrationDataSyncRepositoryDao preRegistrationDataSyncRepositoryDao();
 
+    public abstract PermittedLocalConfigDao permittedLocalConfigDao();
+
+    public abstract LocalPreferencesDao localPreferencesDao();
+
     public static void destroyDB() {
         INSTANCE = null;
     }
diff --git a/android/clientmanager/src/main/java/io/mosip/registration/clientmanager/config/RoomModule.java b/android/clientmanager/src/main/java/io/mosip/registration/clientmanager/config/RoomModule.java
index 52430fbcc..8102ab32c 100644
--- a/android/clientmanager/src/main/java/io/mosip/registration/clientmanager/config/RoomModule.java
+++ b/android/clientmanager/src/main/java/io/mosip/registration/clientmanager/config/RoomModule.java
@@ -36,10 +36,14 @@
 import io.mosip.registration.clientmanager.dao.IdentitySchemaDao;
 import io.mosip.registration.clientmanager.dao.JobTransactionDao;
 import io.mosip.registration.clientmanager.dao.LanguageDao;
+import io.mosip.registration.clientmanager.dao.LocalConfigDAO;
+import io.mosip.registration.clientmanager.dao.LocalConfigDAOImpl;
+import io.mosip.registration.clientmanager.dao.LocalPreferencesDao;
 import io.mosip.registration.clientmanager.dao.LocationDao;
 import io.mosip.registration.clientmanager.dao.LocationHierarchyDao;
 import io.mosip.registration.clientmanager.dao.MachineMasterDao;
 import io.mosip.registration.clientmanager.dao.ProcessSpecDao;
+import io.mosip.registration.clientmanager.dao.PermittedLocalConfigDao;
 import io.mosip.registration.clientmanager.dao.PreRegistrationDataSyncRepositoryDao;
 import io.mosip.registration.clientmanager.dao.ReasonListDao;
 import io.mosip.registration.clientmanager.dao.RegistrationCenterDao;
@@ -60,6 +64,8 @@
 import io.mosip.registration.clientmanager.repository.GlobalParamRepository;
 import io.mosip.registration.clientmanager.repository.IdentitySchemaRepository;
 import io.mosip.registration.clientmanager.repository.JobTransactionRepository;
+import io.mosip.registration.clientmanager.repository.LocalPreferencesRepository;
+import io.mosip.registration.clientmanager.repository.PermittedLocalConfigRepository;
 import io.mosip.registration.clientmanager.repository.LanguageRepository;
 import io.mosip.registration.clientmanager.repository.LocationRepository;
 import io.mosip.registration.clientmanager.repository.MachineRepository;
@@ -376,8 +382,8 @@ LocationRepository provideLocationRepository(LocationDao locationDao, LocationHi
 
     @Provides
     @Singleton
-    GlobalParamRepository provideGlobalParamRepository(GlobalParamDao globalParamDao) {
-        return new GlobalParamRepository(globalParamDao);
+    GlobalParamRepository provideGlobalParamRepository(GlobalParamDao globalParamDao, LocalConfigDAO localConfigDAO) {
+        return new GlobalParamRepository(globalParamDao, localConfigDAO);
     }
 
     @Provides
@@ -447,4 +453,25 @@ AuditRepository provideAuditRepository(AuditDao auditDao) {
     PreRegistrationDataSyncRepositoryDao providesPreRegistrationDataSyncRepository(ClientDatabase clientDatabase) {
         return clientDatabase.preRegistrationDataSyncRepositoryDao();
     }
+
+    @Provides
+    @Singleton
+    PermittedLocalConfigDao providesPermittedLocalConfigDao(ClientDatabase clientDatabase) {
+        return clientDatabase.permittedLocalConfigDao();
+    }
+
+    @Provides
+    @Singleton
+    LocalPreferencesDao providesLocalPreferencesDao(ClientDatabase clientDatabase) {
+        return clientDatabase.localPreferencesDao();
+    }
+
+    @Provides
+    @Singleton
+    LocalConfigDAO provideLocalConfigDAO(PermittedLocalConfigDao permittedLocalConfigDao, LocalPreferencesDao localPreferencesDao) {
+        return new LocalConfigDAOImpl(
+            new PermittedLocalConfigRepository(permittedLocalConfigDao),
+            new LocalPreferencesRepository(localPreferencesDao)
+        );
+    }
 }
diff --git a/android/clientmanager/src/main/java/io/mosip/registration/clientmanager/constant/RegistrationConstants.java b/android/clientmanager/src/main/java/io/mosip/registration/clientmanager/constant/RegistrationConstants.java
index 56e2abffb..a3b07c302 100644
--- a/android/clientmanager/src/main/java/io/mosip/registration/clientmanager/constant/RegistrationConstants.java
+++ b/android/clientmanager/src/main/java/io/mosip/registration/clientmanager/constant/RegistrationConstants.java
@@ -29,6 +29,11 @@ public class RegistrationConstants {
     public static final String ENABLE = "Y";
     public static final String DISABLE = "N";
 
+    // Permitted Local Config Types
+    public static final String PERMITTED_JOB_TYPE = "JOB";
+    public static final String PERMITTED_CONFIG_TYPE = "CONFIGURATION";
+    public static final String PERMITTED_SHORTCUT = "SHORTCUT";
+
     //SBI intents
     public static final String DISCOVERY_INTENT_ACTION = "io.sbi.device";
     public static final String D_INFO_INTENT_ACTION = ".Info";
@@ -106,5 +111,6 @@ public class RegistrationConstants {
     public static final String RIGHT_THUMB = "Right Thumb";
     public static final String RIGHT = "Right";
     public static final String LEFT = "Left";
+    public static final String JOB_TRIGGER_POINT_USER = "User";
 
 }
diff --git a/android/clientmanager/src/main/java/io/mosip/registration/clientmanager/dao/GlobalParamDao.java b/android/clientmanager/src/main/java/io/mosip/registration/clientmanager/dao/GlobalParamDao.java
index e61c29732..d7cca1370 100644
--- a/android/clientmanager/src/main/java/io/mosip/registration/clientmanager/dao/GlobalParamDao.java
+++ b/android/clientmanager/src/main/java/io/mosip/registration/clientmanager/dao/GlobalParamDao.java
@@ -24,4 +24,7 @@ public interface GlobalParamDao {
     @Insert(onConflict = OnConflictStrategy.REPLACE)
     void insertAll(List globalParams);
 
+    @Query("SELECT * FROM global_param WHERE name LIKE :pattern AND status = 1 AND value IS NOT NULL")
+    List findByNameLikeAndIsActiveTrueAndValIsNotNull(String pattern);
+
 }
diff --git a/android/clientmanager/src/main/java/io/mosip/registration/clientmanager/dao/LocalConfigDAO.java b/android/clientmanager/src/main/java/io/mosip/registration/clientmanager/dao/LocalConfigDAO.java
new file mode 100644
index 000000000..357960bb3
--- /dev/null
+++ b/android/clientmanager/src/main/java/io/mosip/registration/clientmanager/dao/LocalConfigDAO.java
@@ -0,0 +1,30 @@
+package io.mosip.registration.clientmanager.dao;
+
+import java.util.List;
+import java.util.Map;
+
+import io.mosip.registration.clientmanager.entity.PermittedLocalConfig;
+
+/**
+ * DAO interface for local configuration operations
+ * Handles both permitted configurations and local preferences
+ */
+public interface LocalConfigDAO {
+
+    /**
+     * Get permitted configurations by type
+     */
+    List getPermittedConfigurations(String configType);
+
+    /**
+     * Get local configurations as a map (name -> value)
+     */
+    Map getLocalConfigurations();
+
+    /**
+     * Modify configurations by saving local preferences
+     */
+    void modifyConfigurations(Map localPreferences);
+
+    void cleanUpLocalPreferences();
+}
diff --git a/android/clientmanager/src/main/java/io/mosip/registration/clientmanager/dao/LocalConfigDAOImpl.java b/android/clientmanager/src/main/java/io/mosip/registration/clientmanager/dao/LocalConfigDAOImpl.java
new file mode 100644
index 000000000..04b328f41
--- /dev/null
+++ b/android/clientmanager/src/main/java/io/mosip/registration/clientmanager/dao/LocalConfigDAOImpl.java
@@ -0,0 +1,128 @@
+package io.mosip.registration.clientmanager.dao;
+
+import android.util.Log;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.UUID;
+
+import javax.inject.Inject;
+import javax.inject.Singleton;
+
+import io.mosip.registration.clientmanager.constant.RegistrationConstants;
+import io.mosip.registration.clientmanager.entity.LocalPreferences;
+import io.mosip.registration.clientmanager.entity.PermittedLocalConfig;
+import io.mosip.registration.clientmanager.repository.LocalPreferencesRepository;
+import io.mosip.registration.clientmanager.repository.PermittedLocalConfigRepository;
+
+@Singleton
+public class LocalConfigDAOImpl implements LocalConfigDAO {
+
+    private static final String TAG = LocalConfigDAOImpl.class.getSimpleName();
+    private PermittedLocalConfigRepository permittedLocalConfigRepository;
+    private LocalPreferencesRepository localPreferencesRepository;
+
+    @Inject
+    public LocalConfigDAOImpl(PermittedLocalConfigRepository permittedLocalConfigRepository,
+                             LocalPreferencesRepository localPreferencesRepository) {
+        this.permittedLocalConfigRepository = permittedLocalConfigRepository;
+        this.localPreferencesRepository = localPreferencesRepository;
+    }
+
+    @Override
+    public List getPermittedConfigurations(String configType) {
+        List permittedConfigs =
+            permittedLocalConfigRepository.getPermittedConfigsByType(configType);
+
+        List permittedConfigurations = new ArrayList<>();
+        if (permittedConfigs != null && !permittedConfigs.isEmpty()) {
+            for (PermittedLocalConfig config : permittedConfigs) {
+                permittedConfigurations.add(config.getName());
+            }
+        }
+        return permittedConfigurations;
+    }
+
+    @Override
+    public Map getLocalConfigurations() {
+        return localPreferencesRepository.getLocalConfigurations();
+    }
+
+    @Override
+    public void modifyConfigurations(Map localPreferences) {
+        
+        for (Map.Entry entry : localPreferences.entrySet()) {
+            String name = entry.getKey();
+            String value = entry.getValue();
+            
+            try {
+                LocalPreferences existingPreference = localPreferencesRepository.findByIsDeletedFalseAndName(name);
+
+                if (existingPreference != null) {
+                    // Update existing record
+                    existingPreference.setVal(value);
+                    existingPreference.setUpdBy(RegistrationConstants.JOB_TRIGGER_POINT_USER);
+                    existingPreference.setUpdDtimes(System.currentTimeMillis());
+                    localPreferencesRepository.save(existingPreference);
+                } else {
+                    // Create new record if it doesn't exist
+                    saveLocalPreference(name, value, RegistrationConstants.PERMITTED_CONFIG_TYPE);
+                }
+                
+            } catch (Exception e) {
+                Log.e(TAG, "Error modifying configuration: " + name, e);
+            }
+        }
+    }
+
+
+    /**
+     * Save local preference to database
+     */
+    private void saveLocalPreference(String name, String value, String configType) {
+        LocalPreferences localPreference = new LocalPreferences(UUID.randomUUID().toString());
+        localPreference.setName(name);
+        localPreference.setVal(value);
+        localPreference.setConfigType(configType);
+        localPreference.setCrBy(RegistrationConstants.JOB_TRIGGER_POINT_USER);
+        localPreference.setCrDtime(System.currentTimeMillis());
+        localPreference.setIsDeleted(false);
+        
+        localPreferencesRepository.save(localPreference);
+    }
+
+    /**
+     * Clean up local preferences based on permitted configs.
+     * Delete local preference if key is removed from permitted configs.
+     * Mark as deleted if key is deactivated in permitted configs.
+     */
+    public void cleanUpLocalPreferences() {
+        List permittedConfigs =
+            permittedLocalConfigRepository.getPermittedConfigsByType(RegistrationConstants.PERMITTED_CONFIG_TYPE);
+
+        Map localConfigs = getLocalConfigurations();
+
+        Map permittedStatusMap = new java.util.HashMap<>();
+        for (PermittedLocalConfig config : permittedConfigs) {
+            permittedStatusMap.put(config.getName(), config.getIsActive());
+        }
+
+        for (String key : localConfigs.keySet()) {
+            LocalPreferences pref = localPreferencesRepository.findByIsDeletedFalseAndName(key);
+            if (pref == null) continue;
+
+            if (!permittedStatusMap.containsKey(key)) {
+                localPreferencesRepository.delete(pref);
+                Log.i(TAG, "Local preference deleted (row removed): " + key);
+            } else if (!permittedStatusMap.get(key)) {
+                // Key deactivated, mark as deleted
+                pref.setIsDeleted(true);
+                pref.setUpdBy(RegistrationConstants.JOB_TRIGGER_POINT_USER);
+                pref.setUpdDtimes(System.currentTimeMillis());
+                localPreferencesRepository.save(pref);
+                Log.i(TAG, "Local preference marked deleted (row deactivated): " + key);
+            }
+        }
+    }
+}
diff --git a/android/clientmanager/src/main/java/io/mosip/registration/clientmanager/dao/LocalPreferencesDao.java b/android/clientmanager/src/main/java/io/mosip/registration/clientmanager/dao/LocalPreferencesDao.java
new file mode 100644
index 000000000..f283f269d
--- /dev/null
+++ b/android/clientmanager/src/main/java/io/mosip/registration/clientmanager/dao/LocalPreferencesDao.java
@@ -0,0 +1,30 @@
+package io.mosip.registration.clientmanager.dao;
+
+import androidx.room.Dao;
+import androidx.room.Insert;
+import androidx.room.OnConflictStrategy;
+import androidx.room.Query;
+import androidx.room.Update;
+
+import java.util.List;
+
+import io.mosip.registration.clientmanager.entity.LocalPreferences;
+
+@Dao
+public interface LocalPreferencesDao {
+
+    @Insert(onConflict = OnConflictStrategy.REPLACE)
+    void insert(LocalPreferences localPreference);
+
+    @Update
+    void update(LocalPreferences localPreference);
+
+    @Query("SELECT * FROM local_preferences WHERE is_deleted = 0 AND config_type = :configType")
+    List findByIsDeletedFalseAndConfigType(String configType);
+
+    @Query("SELECT * FROM local_preferences WHERE is_deleted = 0 AND name = :name")
+    LocalPreferences findByIsDeletedFalseAndName(String name);
+
+    @Query("DELETE FROM local_preferences WHERE name = :name")
+    void deleteByName(String name);
+}
diff --git a/android/clientmanager/src/main/java/io/mosip/registration/clientmanager/dao/PermittedLocalConfigDao.java b/android/clientmanager/src/main/java/io/mosip/registration/clientmanager/dao/PermittedLocalConfigDao.java
new file mode 100644
index 000000000..6e4e187de
--- /dev/null
+++ b/android/clientmanager/src/main/java/io/mosip/registration/clientmanager/dao/PermittedLocalConfigDao.java
@@ -0,0 +1,21 @@
+package io.mosip.registration.clientmanager.dao;
+
+import androidx.room.Dao;
+import androidx.room.Insert;
+import androidx.room.OnConflictStrategy;
+import androidx.room.Query;
+
+import java.util.List;
+
+import io.mosip.registration.clientmanager.entity.PermittedLocalConfig;
+
+@Dao
+public interface PermittedLocalConfigDao {
+
+    @Insert(onConflict = OnConflictStrategy.REPLACE)
+    void insertAll(List permittedConfigs);
+
+    @Query("SELECT * FROM permitted_local_config WHERE is_active = 1 AND is_deleted = 0 AND config_type = :configType")
+    List findByIsActiveTrueAndType(String configType);
+
+}
diff --git a/android/clientmanager/src/main/java/io/mosip/registration/clientmanager/entity/LocalPreferences.java b/android/clientmanager/src/main/java/io/mosip/registration/clientmanager/entity/LocalPreferences.java
new file mode 100644
index 000000000..2ae3e6152
--- /dev/null
+++ b/android/clientmanager/src/main/java/io/mosip/registration/clientmanager/entity/LocalPreferences.java
@@ -0,0 +1,48 @@
+package io.mosip.registration.clientmanager.entity;
+
+import androidx.annotation.NonNull;
+import androidx.room.ColumnInfo;
+import androidx.room.Entity;
+import androidx.room.PrimaryKey;
+import lombok.Data;
+
+/**
+ * The Entity Class for Local Preferences
+ * Stores user-specific configuration overrides that can override global parameters
+ */
+@Entity(tableName = "local_preferences")
+@Data
+public class LocalPreferences {
+
+    @PrimaryKey
+    @NonNull
+    @ColumnInfo(name = "id")
+    private String id;
+
+    @ColumnInfo(name = "name")
+    private String name;
+
+    @ColumnInfo(name = "val")
+    private String val;
+
+    @ColumnInfo(name = "config_type")
+    private String configType;
+
+    @ColumnInfo(name = "cr_by")
+    private String crBy;
+
+    @ColumnInfo(name = "cr_dtime")
+    private Long crDtime;
+
+    @ColumnInfo(name = "upd_by")
+    private String updBy;
+
+    @ColumnInfo(name = "upd_dtimes")
+    private Long updDtimes;
+
+    @ColumnInfo(name = "is_deleted")
+    private Boolean isDeleted;
+
+    @ColumnInfo(name = "del_dtimes")
+    private Long delDtimes;
+}
\ No newline at end of file
diff --git a/android/clientmanager/src/main/java/io/mosip/registration/clientmanager/entity/PermittedLocalConfig.java b/android/clientmanager/src/main/java/io/mosip/registration/clientmanager/entity/PermittedLocalConfig.java
new file mode 100644
index 000000000..9381c3163
--- /dev/null
+++ b/android/clientmanager/src/main/java/io/mosip/registration/clientmanager/entity/PermittedLocalConfig.java
@@ -0,0 +1,36 @@
+package io.mosip.registration.clientmanager.entity;
+
+import androidx.annotation.NonNull;
+import androidx.room.ColumnInfo;
+import androidx.room.Entity;
+import androidx.room.PrimaryKey;
+import lombok.Data;
+
+/**
+ * The Entity Class for Permitted Local Config
+ * Stores server-defined permitted configuration values that can be overridden locally
+ */
+@Entity(tableName = "permitted_local_config")
+@Data
+public class PermittedLocalConfig {
+
+    @PrimaryKey
+    @NonNull
+    @ColumnInfo(name = "code")
+    private String code;
+
+    @ColumnInfo(name = "name")
+    private String name;
+
+    @ColumnInfo(name = "config_type")
+    private String type;
+
+    @ColumnInfo(name = "is_active")
+    private Boolean isActive;
+
+    @ColumnInfo(name = "is_deleted")
+    private Boolean isDeleted;
+
+    @ColumnInfo(name = "del_dtimes")
+    private Long delDtimes;
+}
diff --git a/android/clientmanager/src/main/java/io/mosip/registration/clientmanager/repository/GlobalParamRepository.java b/android/clientmanager/src/main/java/io/mosip/registration/clientmanager/repository/GlobalParamRepository.java
index 4ee407067..8fdc67b21 100644
--- a/android/clientmanager/src/main/java/io/mosip/registration/clientmanager/repository/GlobalParamRepository.java
+++ b/android/clientmanager/src/main/java/io/mosip/registration/clientmanager/repository/GlobalParamRepository.java
@@ -4,16 +4,17 @@
 
 import io.mosip.registration.clientmanager.constant.RegistrationConstants;
 import io.mosip.registration.clientmanager.dao.GlobalParamDao;
+import io.mosip.registration.clientmanager.dao.LocalConfigDAO;
 import io.mosip.registration.clientmanager.entity.GlobalParam;
 
 import java.util.HashMap;
+import java.util.LinkedHashMap;
 import java.util.List;
 import java.util.Map;
 
 import javax.inject.Inject;
 
 import java.util.Arrays;
-import java.util.List;
 import java.util.stream.Collectors;
 
 public class GlobalParamRepository {
@@ -21,11 +22,14 @@ public class GlobalParamRepository {
     private static final String TAG = GlobalParamRepository.class.getSimpleName();
     private static Map globalParamMap = new HashMap<>();
     private GlobalParamDao globalParamDao;
+    private LocalConfigDAO localConfigDAO;
 
     @Inject
-    public GlobalParamRepository(GlobalParamDao globalParamDao) {
+    public GlobalParamRepository(GlobalParamDao globalParamDao, LocalConfigDAO localConfigDAO) {
         this.globalParamDao = globalParamDao;
-        refreshGlobalParams();
+        this.localConfigDAO = localConfigDAO;
+
+        refreshConfigurationCache();
     }
 
     public String getGlobalParamValue(String id) {
@@ -65,12 +69,14 @@ public int getMinLanguageCount() {
     public void saveGlobalParam(String id, String value) {
         GlobalParam globalParam = new GlobalParam(id, id, value, true);
         globalParamDao.insertGlobalParam(globalParam);
+        // Update the merged cache directly for immediate effect
         globalParamMap.put(id, value);
     }
 
     public void saveGlobalParams(List globalParam) {
         globalParamDao.insertAll(globalParam);
-        refreshGlobalParams();
+        // Refresh with merged configuration to include any local preferences
+        refreshConfigurationCache();
     }
 
     public List getGlobalParams() {
@@ -106,10 +112,22 @@ public String getCachedStringMAVELScript(){
         return globalParamMap.getOrDefault(RegistrationConstants.APPLICANT_TYPE_MVEL_SCRIPT,"applicanttype.mvel");
     }
 
-    public String getCachedStringPreRegPacketLocation(){
+    public String getCachedStringPreRegPacketLocation() {
         return globalParamMap.get(RegistrationConstants.PRE_REG_PACKET_LOCATION);
     }
 
+    public Map getGlobalParamsByPattern(String pattern) {
+
+        List globalParams = globalParamDao.findByNameLikeAndIsActiveTrueAndValIsNotNull(pattern);
+        Map globalParamMap = new LinkedHashMap<>();
+
+        for (GlobalParam param : globalParams) {
+            globalParamMap.put(param.getName(), param.getValue() != null ? param.getValue().trim() : param.getValue());
+        }
+
+        return globalParamMap;
+    }
+
     public List getSelectedHandles() {
         String value = globalParamMap.getOrDefault(RegistrationConstants.SELECTED_HANDLES, "");
         return Arrays.asList(value.split(RegistrationConstants.COMMA)).stream()
@@ -130,4 +148,30 @@ public String getCachedStringIdleTime() {
     public String getCachedStringRefreshedLoginTime() {
         return globalParamMap.get(RegistrationConstants.REFRESHED_LOGIN_TIME);
     }
+
+    /**
+     * Refresh configuration cache by merging global params with local preferences
+     */
+    public void refreshConfigurationCache() {
+
+        try {
+            // Get fresh global parameters from database
+            List globalParams = globalParamDao.getGlobalParams();
+            Map freshGlobalParams = new HashMap<>();
+            for (GlobalParam globalParam : globalParams) {
+                freshGlobalParams.put(globalParam.getId(), globalParam.getValue());
+            }
+
+            // Get local preferences (overrides)
+            Map localConfigs = localConfigDAO.getLocalConfigurations();
+
+            // Merge: local preferences override global parameters
+            globalParamMap.clear();
+            globalParamMap.putAll(freshGlobalParams);
+            globalParamMap.putAll(localConfigs); // Local preferences take precedence
+        } catch (Exception e) {
+            Log.e(TAG, "Error refreshing configuration cache", e);
+        }
+
+    }
 }
diff --git a/android/clientmanager/src/main/java/io/mosip/registration/clientmanager/repository/LocalPreferencesRepository.java b/android/clientmanager/src/main/java/io/mosip/registration/clientmanager/repository/LocalPreferencesRepository.java
new file mode 100644
index 000000000..55f9431b4
--- /dev/null
+++ b/android/clientmanager/src/main/java/io/mosip/registration/clientmanager/repository/LocalPreferencesRepository.java
@@ -0,0 +1,90 @@
+package io.mosip.registration.clientmanager.repository;
+
+import android.util.Log;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import javax.inject.Inject;
+
+import io.mosip.registration.clientmanager.constant.RegistrationConstants;
+import io.mosip.registration.clientmanager.dao.LocalPreferencesDao;
+import io.mosip.registration.clientmanager.entity.LocalPreferences;
+
+public class LocalPreferencesRepository {
+
+    private static final String TAG = LocalPreferencesRepository.class.getSimpleName();
+    private LocalPreferencesDao localPreferencesDao;
+
+    @Inject
+    public LocalPreferencesRepository(LocalPreferencesDao localPreferencesDao) {
+        this.localPreferencesDao = localPreferencesDao;
+    }
+
+    /**
+     * Get local configurations as a map (name -> value)
+     */
+    public Map getLocalConfigurations() {
+        try {
+            List localPreferences = localPreferencesDao
+                    .findByIsDeletedFalseAndConfigType(RegistrationConstants.PERMITTED_CONFIG_TYPE);
+            
+            Map localConfigMap = new HashMap<>();
+            if (localPreferences != null) {
+                for (LocalPreferences localPreference : localPreferences) {
+                    localConfigMap.put(localPreference.getName(), localPreference.getVal());
+                }
+            }
+            return localConfigMap;
+        } catch (Exception e) {
+            Log.e(TAG, "Error getting local configurations", e);
+            return new HashMap<>();
+        }
+    }
+
+    /**
+     * Find local preference by name
+     */
+    public LocalPreferences findByIsDeletedFalseAndName(String name) {
+        try {
+            return localPreferencesDao.findByIsDeletedFalseAndName(name);
+        } catch (Exception e) {
+            Log.e(TAG, "Error finding local preference by name: " + name, e);
+            return null;
+        }
+    }
+
+    /**
+     * Save local preference
+     */
+    public void save(LocalPreferences localPreference) {
+        try {
+            localPreferencesDao.insert(localPreference);
+        } catch (Exception e) {
+            Log.e(TAG, "Error saving local preference: " + localPreference.getName(), e);
+        }
+    }
+
+    /**
+     * Update local preference
+     */
+    public void update(LocalPreferences localPreference) {
+        try {
+            localPreferencesDao.update(localPreference);
+        } catch (Exception e) {
+            Log.e(TAG, "Error updating local preference: " + localPreference.getName(), e);
+        }
+    }
+
+    /**
+     * Delete local preference by name
+     */
+    public void delete(LocalPreferences localPreference) {
+        try {
+            localPreferencesDao.deleteByName(localPreference.getName());
+        } catch (Exception e) {
+            Log.e(TAG, "Error deleting local preference: " + localPreference.getName(), e);
+        }
+    }
+}
diff --git a/android/clientmanager/src/main/java/io/mosip/registration/clientmanager/repository/PermittedLocalConfigRepository.java b/android/clientmanager/src/main/java/io/mosip/registration/clientmanager/repository/PermittedLocalConfigRepository.java
new file mode 100644
index 000000000..e8e2b2a0b
--- /dev/null
+++ b/android/clientmanager/src/main/java/io/mosip/registration/clientmanager/repository/PermittedLocalConfigRepository.java
@@ -0,0 +1,45 @@
+package io.mosip.registration.clientmanager.repository;
+
+import android.util.Log;
+
+import java.util.List;
+
+import javax.inject.Inject;
+
+import io.mosip.registration.clientmanager.dao.PermittedLocalConfigDao;
+import io.mosip.registration.clientmanager.entity.PermittedLocalConfig;
+
+public class PermittedLocalConfigRepository {
+
+    private static final String TAG = PermittedLocalConfigRepository.class.getSimpleName();
+    private PermittedLocalConfigDao permittedLocalConfigDao;
+
+    @Inject
+    public PermittedLocalConfigRepository(PermittedLocalConfigDao permittedLocalConfigDao) {
+        this.permittedLocalConfigDao = permittedLocalConfigDao;
+    }
+
+    /**
+     * Save permitted local configurations
+     */
+    public void savePermittedConfigs(List permittedConfigs) {
+        try {
+            permittedLocalConfigDao.insertAll(permittedConfigs);
+        } catch (Exception e) {
+            Log.e(TAG, "Error saving permitted configurations", e);
+        }
+    }
+
+    /**
+     * Get permitted configurations by type
+     */
+    public List getPermittedConfigsByType(String configType) {
+        try {
+            return permittedLocalConfigDao.findByIsActiveTrueAndType(configType);
+        } catch (Exception e) {
+            Log.e(TAG, "Error getting permitted configurations by type: " + configType, e);
+            return null;
+        }
+    }
+
+}
diff --git a/android/clientmanager/src/main/java/io/mosip/registration/clientmanager/service/LocalConfigServiceImpl.java b/android/clientmanager/src/main/java/io/mosip/registration/clientmanager/service/LocalConfigServiceImpl.java
new file mode 100644
index 000000000..34df86013
--- /dev/null
+++ b/android/clientmanager/src/main/java/io/mosip/registration/clientmanager/service/LocalConfigServiceImpl.java
@@ -0,0 +1,37 @@
+package io.mosip.registration.clientmanager.service;
+
+import java.util.List;
+import java.util.Map;
+
+import javax.inject.Inject;
+import javax.inject.Singleton;
+
+import io.mosip.registration.clientmanager.constant.RegistrationConstants;
+import io.mosip.registration.clientmanager.dao.LocalConfigDAO;
+import io.mosip.registration.clientmanager.spi.LocalConfigService;
+
+@Singleton
+public class LocalConfigServiceImpl implements LocalConfigService {
+
+    private LocalConfigDAO localConfigDAO;
+
+    @Inject
+    public LocalConfigServiceImpl(LocalConfigDAO localConfigDAO) {
+        this.localConfigDAO = localConfigDAO;
+    }
+
+    @Override
+    public Map getLocalConfigurations() {
+        return localConfigDAO.getLocalConfigurations();
+    }
+
+    @Override
+    public void modifyConfigurations(Map localPreferences) {
+        localConfigDAO.modifyConfigurations(localPreferences);
+    }
+
+    @Override
+    public List getPermittedConfiguration() {
+        return localConfigDAO.getPermittedConfigurations(RegistrationConstants.PERMITTED_CONFIG_TYPE);
+    }
+}
diff --git a/android/clientmanager/src/main/java/io/mosip/registration/clientmanager/service/MasterDataServiceImpl.java b/android/clientmanager/src/main/java/io/mosip/registration/clientmanager/service/MasterDataServiceImpl.java
index 23f7109aa..b2acb77da 100644
--- a/android/clientmanager/src/main/java/io/mosip/registration/clientmanager/service/MasterDataServiceImpl.java
+++ b/android/clientmanager/src/main/java/io/mosip/registration/clientmanager/service/MasterDataServiceImpl.java
@@ -12,6 +12,7 @@
 import io.mosip.registration.clientmanager.R;
 import io.mosip.registration.clientmanager.constant.RegistrationConstants;
 import io.mosip.registration.clientmanager.dao.FileSignatureDao;
+import io.mosip.registration.clientmanager.dao.LocalConfigDAO;
 import io.mosip.registration.clientmanager.dto.CenterMachineDto;
 import io.mosip.registration.clientmanager.dto.ReasonListDto;
 import io.mosip.registration.clientmanager.dto.http.*;
@@ -23,6 +24,7 @@
 import io.mosip.registration.clientmanager.entity.Language;
 import io.mosip.registration.clientmanager.entity.Location;
 import io.mosip.registration.clientmanager.entity.MachineMaster;
+import io.mosip.registration.clientmanager.entity.PermittedLocalConfig;
 import io.mosip.registration.clientmanager.entity.ReasonList;
 import io.mosip.registration.clientmanager.entity.RegistrationCenter;
 import io.mosip.registration.clientmanager.entity.SyncJobDef;
@@ -105,6 +107,8 @@ public class MasterDataServiceImpl implements MasterDataService {
     private LanguageRepository languageRepository;
     private JobManagerService jobManagerService;
     private FileSignatureDao fileSignatureDao;
+    private PermittedLocalConfigRepository permittedLocalConfigRepository;
+    private LocalConfigDAO localConfigDAO;
     private String regCenterId;
     private String result = "";
     SharedPreferences sharedPreferences;
@@ -128,7 +132,9 @@ public MasterDataServiceImpl(Context context, ObjectMapper objectMapper, SyncRes
                                  CertificateManagerService certificateManagerService,
                                  LanguageRepository languageRepository,
                                  JobManagerService jobManagerService,
-                                 FileSignatureDao fileSignatureDao) {
+                                 FileSignatureDao fileSignatureDao,
+                                 PermittedLocalConfigRepository permittedLocalConfigRepository,
+                                 LocalConfigDAO localConfigDAO) {
         this.context = context;
         this.objectMapper = objectMapper;
         this.syncRestService = syncRestService;
@@ -150,6 +156,8 @@ public MasterDataServiceImpl(Context context, ObjectMapper objectMapper, SyncRes
         this.languageRepository = languageRepository;
         this.jobManagerService = jobManagerService;
         this.fileSignatureDao = fileSignatureDao;
+        this.permittedLocalConfigRepository = permittedLocalConfigRepository;
+        this.localConfigDAO = localConfigDAO;
         sharedPreferences = this.context.getSharedPreferences(
                 this.context.getString(R.string.app_name),
                 Context.MODE_PRIVATE);
@@ -376,11 +384,17 @@ public void onFailure(Call>> call, Throwable
     @SuppressWarnings("unchecked")
     private void saveGlobalParams(Map responseMap) {
         try {
+            
             Map globalParamMap = new HashMap<>();
 
             if (responseMap.get("configDetail") != null) {
                 Map configDetailJsonMap = (Map) responseMap.get("configDetail");
 
+                if (configDetailJsonMap != null && configDetailJsonMap.get("globalConfiguration") != null) {
+                    String encryptedGlobalConfigs = configDetailJsonMap.get("globalConfiguration").toString();
+                    parseToMap(getParams(encryptedGlobalConfigs), globalParamMap);
+                }
+
                 if (configDetailJsonMap != null && configDetailJsonMap.get("registrationConfiguration") != null) {
                     String encryptedConfigs = configDetailJsonMap.get("registrationConfiguration").toString();
                     parseToMap(getParams(encryptedConfigs), globalParamMap);
@@ -915,6 +929,26 @@ private void saveStructuredData(String entityName, String data, boolean applican
                     }
                 }
                 break;
+            case "PermittedLocalConfig":
+                JSONArray permittedConfigsJsonArray = getDecryptedDataList(data);
+                List permittedConfigs = new ArrayList<>();
+                for (int i = 0; i < permittedConfigsJsonArray.length(); i++) {
+                    JSONObject jsonObjects = new JSONObject(permittedConfigsJsonArray.getString(i));
+
+                    PermittedLocalConfig premittedConfig = new PermittedLocalConfig(jsonObjects.getString("code"));
+                    premittedConfig.setName(jsonObjects.getString("name"));
+                    premittedConfig.setType(jsonObjects.getString("type"));
+                    premittedConfig.setIsActive(jsonObjects.getBoolean("isActive"));
+                    premittedConfig.setIsDeleted(jsonObjects.optBoolean("isDeleted", false));
+                    premittedConfig.setDelDtimes(jsonObjects.optLong("delDtimes", 0L));
+                    permittedConfigs.add(premittedConfig);
+                }
+                permittedLocalConfigRepository.savePermittedConfigs(permittedConfigs);
+
+                if (localConfigDAO != null) {
+                    localConfigDAO.cleanUpLocalPreferences();
+                }
+                break;
         }
     }
 
@@ -1001,4 +1035,10 @@ public String getGlobalParamValue(String id) {
         String value = globalParamRepository.getGlobalParamValue(id);
         return value == null ? "" : value;
     }
+
+    @Override
+    public Map getRegistrationParams() {
+        return globalParamRepository.getGlobalParamsByPattern("mosip.registration%");
+    }
+
 }
diff --git a/android/clientmanager/src/main/java/io/mosip/registration/clientmanager/spi/LocalConfigService.java b/android/clientmanager/src/main/java/io/mosip/registration/clientmanager/spi/LocalConfigService.java
new file mode 100644
index 000000000..db3266aa3
--- /dev/null
+++ b/android/clientmanager/src/main/java/io/mosip/registration/clientmanager/spi/LocalConfigService.java
@@ -0,0 +1,25 @@
+package io.mosip.registration.clientmanager.spi;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Service interface for managing local configurations
+ */
+public interface LocalConfigService {
+
+    /**
+     * Get all local configurations as a map (name -> value)
+     */
+    Map getLocalConfigurations();
+
+    /**
+     * Modify configurations by saving local preferences
+     */
+    void modifyConfigurations(Map localPreferences);
+
+    /**
+     * Get permitted configuration names
+     */
+    List getPermittedConfiguration();
+}
diff --git a/android/clientmanager/src/main/java/io/mosip/registration/clientmanager/spi/MasterDataService.java b/android/clientmanager/src/main/java/io/mosip/registration/clientmanager/spi/MasterDataService.java
index eebf857f3..55fcda93a 100644
--- a/android/clientmanager/src/main/java/io/mosip/registration/clientmanager/spi/MasterDataService.java
+++ b/android/clientmanager/src/main/java/io/mosip/registration/clientmanager/spi/MasterDataService.java
@@ -8,6 +8,7 @@
 import io.mosip.registration.clientmanager.entity.Location;
 
 import java.util.List;
+import java.util.Map;
 
 public interface MasterDataService {
 
@@ -143,5 +144,7 @@ public interface MasterDataService {
 
     String getGlobalParamValue(String id);
 
+    Map getRegistrationParams();
+
 //    void downloadUrlData(Path path, JSONObject jsonObject);
 }
diff --git a/android/clientmanager/src/test/java/io/mosip/registration/clientmanager/service/MasterDataServiceImplTest.java b/android/clientmanager/src/test/java/io/mosip/registration/clientmanager/service/MasterDataServiceImplTest.java
index 2eed3a543..cbd92c192 100644
--- a/android/clientmanager/src/test/java/io/mosip/registration/clientmanager/service/MasterDataServiceImplTest.java
+++ b/android/clientmanager/src/test/java/io/mosip/registration/clientmanager/service/MasterDataServiceImplTest.java
@@ -89,6 +89,8 @@ public class MasterDataServiceImplTest {
     @Mock private Call> mockCACall;
     @Mock private Call> mockUserCall;
     @Mock private Call mockIdSchemaCall;
+    @Mock private PermittedLocalConfigRepository mockPermittedLocalConfigRepository;
+    @Mock private LocalConfigDAO mockLocalConfigDao;
 
     private final String TEST_APP_NAME = "MockAppName";
 
@@ -2137,7 +2139,9 @@ public void test_public_constructor_with_all_args() {
                 mockCertificateManagerService,
                 mockLanguageRepository,
                 mockJobManagerService,
-                mockFileSignatureDao
+                mockFileSignatureDao,
+                mockPermittedLocalConfigRepository,
+                mockLocalConfigDao
         );
         assertNotNull(service);
     }
diff --git a/android/clientmanager/src/test/java/io/mosip/registration/clientmanager/service/SyncDataServiceImplTest.java b/android/clientmanager/src/test/java/io/mosip/registration/clientmanager/service/SyncDataServiceImplTest.java
index e3fe66b6d..61f867d72 100644
--- a/android/clientmanager/src/test/java/io/mosip/registration/clientmanager/service/SyncDataServiceImplTest.java
+++ b/android/clientmanager/src/test/java/io/mosip/registration/clientmanager/service/SyncDataServiceImplTest.java
@@ -540,7 +540,7 @@ public void test_handle_null_server_version() throws Exception {
                 mockContext, mockObjectMapper, mockSyncRestService, mockClientCryptoManagerService,
                 null, null, null, null, null, null, null, null,
                 mockGlobalParamRepository, null, null, null, mockUserDetailRepository,
-                null, null, null, null
+                null, null, null, null,null,null
         );
 
         Runnable mockOnFinish = mock(Runnable.class);
diff --git a/assets/l10n/app_ar.arb b/assets/l10n/app_ar.arb
index a208cf437..70b7244a8 100644
--- a/assets/l10n/app_ar.arb
+++ b/assets/l10n/app_ar.arb
@@ -319,5 +319,11 @@
   "okay": "تمام",
   "no_internet_connection": "لا يوجد اتصال بالإنترنت!",
   "connect_and_retry": "يرجى الاتصال بالإنترنت وإعادة المحاولة.",
-  "retry": "إعادة المحاولة"
+  "retry": "إعادة المحاولة",
+  "key": "مفتاح",
+  "server_value": "قيمة الخادم",
+  "local_value": "القيمة المحلية",
+  "no_configuration_parameters_found": "لم يتم العثور على معلمات التكوين",
+  "no_configurations_found": "لم يتم العثور على أي تكوين",
+  "confirm": "تأكيد"
 }
\ No newline at end of file
diff --git a/assets/l10n/app_en.arb b/assets/l10n/app_en.arb
index 8f56b0648..f53feeda4 100644
--- a/assets/l10n/app_en.arb
+++ b/assets/l10n/app_en.arb
@@ -319,5 +319,11 @@
   "okay": "OKAY",
   "no_internet_connection": "No Internet Connection!",
   "connect_and_retry": "Please connect with internet and retry.",
-  "retry": "RETRY"
+  "retry": "RETRY",
+  "key": "Key",
+  "server_value": "Server Value",
+  "local_value": "Local Value",
+  "no_configuration_parameters_found": "No configuration parameters found",
+  "no_configurations_found": "No configurations found",
+  "confirm": "CONFIRM"
 }
\ No newline at end of file
diff --git a/assets/l10n/app_fr.arb b/assets/l10n/app_fr.arb
index 03b063b60..9d723a095 100644
--- a/assets/l10n/app_fr.arb
+++ b/assets/l10n/app_fr.arb
@@ -319,5 +319,11 @@
   "okay": "D'ACCORD",
   "no_internet_connection": "Pas de connexion Internet!",
   "connect_and_retry": "Veuillez vous connecter à Internet et réessayer.",
-  "retry": "RECOMMENCEZ"
+  "retry": "RECOMMENCEZ",
+  "key": "Clé",
+  "server_value": "Valeur du serveur",
+  "local_value": "Valeur locale",
+  "no_configuration_parameters_found": "Aucun paramètre de configuration trouvé",
+  "no_configurations_found": "Aucune configuration trouvée",
+  "confirm": "Confirmer"
 }
\ No newline at end of file
diff --git a/assets/l10n/app_hi.arb b/assets/l10n/app_hi.arb
index cd78d034b..9ee2a854f 100644
--- a/assets/l10n/app_hi.arb
+++ b/assets/l10n/app_hi.arb
@@ -319,5 +319,11 @@
   "okay": "ठीक है",
   "no_internet_connection": "कोई इंटरनेट कनेक्शन नहीं!",
   "connect_and_retry": "कृपया इंटरनेट से जुड़ें और पुनः प्रयास करें।",
-  "retry": "पुन: प्रयास"
+  "retry": "पुन: प्रयास",
+  "key": "कुंजी",
+  "server_value": "सर्वर मान",
+  "local_value": "स्थानीय मान",
+  "no_configuration_parameters_found": "कोई कॉन्फ़िगरेशन पैरामीटर नहीं मिला",
+  "no_configurations_found": "कोई कॉन्फ़िगरेशन नहीं मिला",
+  "confirm": "पुष्टि करें"
 }
\ No newline at end of file
diff --git a/assets/l10n/app_kn.arb b/assets/l10n/app_kn.arb
index d9d51a0a7..b26cb7544 100644
--- a/assets/l10n/app_kn.arb
+++ b/assets/l10n/app_kn.arb
@@ -319,5 +319,11 @@
   "okay": "ಸರಿ",
   "no_internet_connection": "ಇಂಟರ್ನೆಟ್ ಸಂಪರ್ಕವಿಲ್ಲ!",
   "connect_and_retry": "ದಯವಿಟ್ಟು ಇಂಟರ್ನೆಟ್\u200Cನೊಂದಿಗೆ ಸಂಪರ್ಕಿಸಿ ಮತ್ತು ಮರುಪ್ರಯತ್ನಿಸಿ.",
-  "retry": "ಮರುಪ್ರಯತ್ನಿಸಿ"
+  "retry": "ಮರುಪ್ರಯತ್ನಿಸಿ",
+  "key": "ಕೀ",
+  "server_value": "ಸರ್ವರ್ ಮೌಲ್ಯ",
+  "local_value": "ಸ್ಥಳೀಯ ಮೌಲ್ಯ",
+  "no_configuration_parameters_found": "ಯಾವುದೇ ಸಂರಚನಾ ನಿಯತಾಂಕಗಳು ಕಂಡುಬರಲಿಲ್ಲ",
+  "no_configurations_found": "ಯಾವುದೇ ಸಂರಚನೆಗಳು ಕಂಡುಬರಲಿಲ್ಲ",
+  "confirm": "ದೃಢೀಕರಿಸಿ"
 }
\ No newline at end of file
diff --git a/assets/l10n/app_ta.arb b/assets/l10n/app_ta.arb
index a61562ac4..1a7a34845 100644
--- a/assets/l10n/app_ta.arb
+++ b/assets/l10n/app_ta.arb
@@ -328,5 +328,11 @@
   "okay": "சரி",
   "no_internet_connection": "இணைய இணைப்பு இல்லை!",
   "connect_and_retry": "இணையத்துடன் இணைத்து மீண்டும் முயற்சிக்கவும்.",
-  "retry": "மீண்டும் முயற்சிக்கவும்"
+  "retry": "மீண்டும் முயற்சிக்கவும்",
+  "key": "விசை",
+  "server_value": "சர்வர் மதிப்பு",
+  "local_value": "உள்ளூர் மதிப்பு",
+  "no_configuration_parameters_found": "எந்த கட்டமைப்பு அளவுருக்களும் கிடைக்கவில்லை",
+  "no_configurations_found": "எந்த கட்டமைப்பும் கிடைக்கவில்லை",
+  "confirm": "உறுதிப்படுத்தவும்"
 }
\ No newline at end of file
diff --git a/lib/platform_android/global_config_service_impl.dart b/lib/platform_android/global_config_service_impl.dart
new file mode 100644
index 000000000..4f77a0016
--- /dev/null
+++ b/lib/platform_android/global_config_service_impl.dart
@@ -0,0 +1,63 @@
+
+
+import 'package:flutter/material.dart';
+import 'package:flutter/services.dart';
+import 'package:registration_client/pigeon/global_config_settings_pigeon.dart';
+import 'package:registration_client/platform_spi/global_config_service.dart';
+
+class GlobalConfigServiceImpl implements GlobalConfigService {
+  @override
+  Future> getLocalConfigurations() async {
+    Map localPreferences = {};
+    try {
+      localPreferences = await GlobalConfigSettingsApi().getLocalConfigurations();
+    } on PlatformException {
+      debugPrint('GlobalConfigServiceImpl call failed!');
+    } catch (e) {
+      debugPrint('Local Config value not fetched! ${e.toString()}');
+    }
+    return localPreferences;
+  }
+
+  @override
+  Future> getPermittedConfigurationNames() async {
+    List permittedConfiguration = [];
+    try {
+      permittedConfiguration =
+          await GlobalConfigSettingsApi().getPermittedConfigurationNames();
+    } on PlatformException {
+      debugPrint('GlobalConfigServiceImpl call failed!');
+    } catch (e) {
+      debugPrint(
+          'Permitted Configuration value not fetched! ${e.toString()}');
+    }
+    return permittedConfiguration;
+  }
+
+  @override
+  Future> getRegistrationParams() async {
+    Map registrationParams = {};
+    try {
+      registrationParams = await GlobalConfigSettingsApi().getRegistrationParams();
+    } on PlatformException {
+      debugPrint('GlobalConfigServiceImpl call failed!');
+    } catch (e) {
+      debugPrint('Registration Params value not fetched! ${e.toString()}');
+    }
+    return registrationParams;
+  }
+
+  @override
+  Future modifyConfigurations(Map localPreferences) async {
+    try {
+      await GlobalConfigSettingsApi().modifyConfigurations(localPreferences);
+    } on PlatformException {
+      debugPrint('GlobalConfigServiceImpl call failed!');
+    } catch (e) {
+      debugPrint('Modify Configurations failed! ${e.toString()}');
+    }
+  }
+
+}
+
+GlobalConfigService getGlobalConfigServiceImpl() => GlobalConfigServiceImpl();
\ No newline at end of file
diff --git a/lib/platform_spi/global_config_service.dart b/lib/platform_spi/global_config_service.dart
new file mode 100644
index 000000000..5671b5880
--- /dev/null
+++ b/lib/platform_spi/global_config_service.dart
@@ -0,0 +1,13 @@
+import 'package:registration_client/platform_android/global_config_service_impl.dart';
+
+abstract class GlobalConfigService {
+  Future> getRegistrationParams();
+
+  Future> getLocalConfigurations();
+
+  Future> getPermittedConfigurationNames();
+
+  Future modifyConfigurations(Map localPreferences);
+
+  factory GlobalConfigService() => getGlobalConfigServiceImpl();
+}
\ No newline at end of file
diff --git a/lib/ui/onboard/portrait/mobile_home_page.dart b/lib/ui/onboard/portrait/mobile_home_page.dart
index 6f2ef03e7..21a38ccc3 100644
--- a/lib/ui/onboard/portrait/mobile_home_page.dart
+++ b/lib/ui/onboard/portrait/mobile_home_page.dart
@@ -17,7 +17,7 @@ import 'package:registration_client/ui/onboard/widgets/bottom_navbar_widget.dart
 import 'package:registration_client/utils/app_config.dart';
 import 'package:flutter_gen/gen_l10n/app_localizations.dart';
 
-import '../../process_ui/widgets/settings_screen.dart';
+import '../../settings/settings_screen.dart';
 import '../../profile/profile.dart';
 
 class MobileHomePage extends StatefulWidget {
diff --git a/lib/ui/process_ui/widgets/settings_screen.dart b/lib/ui/settings/settings_screen.dart
similarity index 86%
rename from lib/ui/process_ui/widgets/settings_screen.dart
rename to lib/ui/settings/settings_screen.dart
index 561754af0..66053fdbb 100644
--- a/lib/ui/process_ui/widgets/settings_screen.dart
+++ b/lib/ui/settings/settings_screen.dart
@@ -8,6 +8,8 @@ import 'package:registration_client/provider/global_provider.dart';
 import 'package:registration_client/utils/app_config.dart';
 import 'package:flutter_gen/gen_l10n/app_localizations.dart';
 
+import 'widgets/global_config_settings_tab.dart';
+
 class SettingsScreen extends StatefulWidget {
   const SettingsScreen({
     super.key,
@@ -126,7 +128,7 @@ class _SettingsScreenState extends State {
             ),
           ),
           SizedBox(
-            height: 400,
+            height: MediaQuery.of(context).size.height/1.4,
             child: TabBarView(
               children: [
                 for (final settings in settingUiByRole) _buildTabContent(settings),
@@ -138,9 +140,29 @@ class _SettingsScreenState extends State {
     );
   }
 
+  String _getControllerName(Settings settings) {
+    if (settings.fxml != null && settings.fxml!.isNotEmpty) {
+      return settings.fxml!.replaceAll('.fxml', 'Controller');
+    } else {
+      return '${settings.name}Controller';
+    }
+  }
+
   Widget _buildTabContent(Settings settings) {
     final selectedLang = context.read().selectedLanguage;
-    return _buildDescriptionOnlyTab(settings, selectedLang);
+
+    final controllerName = _getControllerName(settings);
+
+    switch (controllerName) {
+      case 'ScheduledJobsController':
+        return Center(child: Text("${settings.name}"));
+      case 'GlobalConfigSettingsController':
+        return const GlobalConfigSettingsTab();
+      case 'DeviceSettingsController':
+        return Center(child: Text("${settings.name}"));
+      default:
+        return _buildDescriptionOnlyTab(settings, selectedLang);
+    }
   }
 
   Widget _buildDescriptionOnlyTab(Settings settings, String selectedLang) {
diff --git a/lib/ui/settings/widgets/global_config_settings_tab.dart b/lib/ui/settings/widgets/global_config_settings_tab.dart
new file mode 100644
index 000000000..ba8b7bd47
--- /dev/null
+++ b/lib/ui/settings/widgets/global_config_settings_tab.dart
@@ -0,0 +1,485 @@
+import 'package:flutter/material.dart';
+import 'package:registration_client/utils/app_config.dart';
+import '../../../pigeon/common_details_pigeon.dart';
+import '../../../pigeon/global_config_settings_pigeon.dart';
+import 'package:flutter_gen/gen_l10n/app_localizations.dart';
+import 'package:provider/provider.dart';
+import '../../../provider/global_provider.dart';
+import 'package:restart_app/restart_app.dart';
+
+class GlobalConfigSettingsTab extends StatefulWidget {
+  const GlobalConfigSettingsTab({Key? key}) : super(key: key);
+
+  @override
+  State createState() =>
+      _GlobalConfigSettingsTabState();
+}
+
+class _GlobalConfigSettingsTabState extends State {
+  Map? serverValues;
+  Map localValues = {};
+  Map localConfigurations = {};
+  List permittedConfigurations = [];
+  final Map _controllers = {};
+  bool isLoading = true;
+  String? errorMessage;
+
+  @override
+  void initState() {
+    super.initState();
+    _loadInitialData();
+  }
+
+  // Load initial data from the server and local storage
+  Future _loadInitialData() async {
+    setState(() {
+      isLoading = true;
+      errorMessage = null;
+    });
+    try {
+      // Load registration params, local configurations, and permitted configurations in parallel
+      serverValues = (await GlobalConfigSettingsApi().getRegistrationParams())
+          .cast();
+      localConfigurations =
+          (await GlobalConfigSettingsApi().getLocalConfigurations())
+              .cast();
+      permittedConfigurations =
+          (await GlobalConfigSettingsApi().getPermittedConfigurationNames())
+              .cast();
+
+      for (var key in serverValues!.keys) {
+        _controllers[key]?.dispose();
+        _controllers[key] = TextEditingController(
+          text: _getLocalValue(key) == '-' ? '' : _getLocalValue(key),
+        );
+      }
+
+      setState(() {
+        isLoading = false;
+      });
+    } catch (e) {
+      setState(() {
+        errorMessage = e.toString();
+        isLoading = false;
+      });
+    }
+  }
+
+  @override
+  void dispose() {
+    for (var controller in _controllers.values) {
+      controller.dispose();
+    }
+    super.dispose();
+  }
+
+  // Update _updateLocalValue to also update the controller's text if needed:
+  void _updateLocalValue(String key, String value) {
+    setState(() {
+      if (value.isEmpty) {
+        localValues.remove(key);
+      } else {
+        localValues[key] = value;
+      }
+    });
+  }
+
+  bool _isConfigurationPermitted(String configName) {
+    return permittedConfigurations.contains(configName);
+  }
+
+  String _getLocalValue(String key) {
+    // First check if user has modified it in this session
+    if (localValues.containsKey(key)) {
+      return localValues[key]!;
+    }
+    // Then check if there's a saved local configuration
+    if (localConfigurations.containsKey(key)) {
+      return localConfigurations[key]!;
+    }
+    // Return empty if no local value
+    return '';
+  }
+
+  bool _hasChanges() {
+    if (localValues.isEmpty) {
+      return false;
+    }
+
+    // Check if any local value is different from server value
+    for (String key in localValues.keys) {
+      String serverValue = serverValues?[key]?.toString() ?? '-';
+      String localValue = localValues[key]!;
+
+      // 1. Local value is not empty and different from server value, OR
+      // 2. Local value is empty but there was a previous local configuration
+      if (localValue.isNotEmpty && localValue != serverValue) {
+        return true;
+      }
+      if (localValue.isEmpty && localConfigurations.containsKey(key)) {
+        return true;
+      }
+    }
+    return false;
+  }
+
+  void _onSaveChanges() {
+    if (!_hasChanges()) {
+      ScaffoldMessenger.of(context).showSnackBar(
+        const SnackBar(content: Text('No changes to save')),
+      );
+      return;
+    }
+
+    showDialog(
+      context: context,
+      builder: (context) => AlertDialog(
+        title: const Text('Submit Changes'),
+        content: SizedBox(
+          width: 250,
+          height: 20,
+          child: Center(
+            child: Text('${localValues.length} configuration will be updated.'),
+          ),
+        ),
+        actions: [
+          TextButton(
+            onPressed: () => Navigator.pop(context),
+            child: Text(AppLocalizations.of(context)!.cancel),
+          ),
+          ElevatedButton(
+            onPressed: () async {
+              Navigator.pop(context);
+              await _saveChanges();
+            },
+            child: Text(AppLocalizations.of(context)!.confirm),
+          ),
+        ],
+      ),
+    );
+  }
+
+  Future _saveChanges() async {
+    try {
+      showDialog(
+        context: context,
+        barrierDismissible: false,
+        builder: (context) => const Center(
+          child: Column(
+            mainAxisSize: MainAxisSize.min,
+            children: [
+              CircularProgressIndicator(),
+              SizedBox(height: 16),
+              Text('Saving configuration changes...'),
+            ],
+          ),
+        ),
+      );
+
+      // Save configuration changes
+      await GlobalConfigSettingsApi().modifyConfigurations(localValues);
+
+      // Update local configurations with the saved values
+      setState(() {
+        localConfigurations.addAll(localValues);
+        localValues.clear();
+      });
+
+      // Hide loading indicator
+      if (mounted) {
+        Navigator.of(context).pop();
+      }
+
+      // Show success message
+      ScaffoldMessenger.of(context).showSnackBar(
+        const SnackBar(
+          content: Text('Configuration saved successfully. Restarting app...'),
+          duration: Duration(seconds: 2),
+        ),
+      );
+
+      // Wait a moment for the user to see the message, then restart the app
+      await Future.delayed(const Duration(seconds: 2));
+
+      // Restart the app to apply configuration changes
+      Restart.restartApp();
+    } catch (e) {
+      if (mounted) {
+        Navigator.of(context).pop();
+      }
+      ScaffoldMessenger.of(context).showSnackBar(
+        SnackBar(content: Text('Error saving changes: $e')),
+      );
+    }
+  }
+
+  List _getConfigurations() {
+    if (serverValues == null) return [];
+
+    List globalConfigItems = [];
+
+    for (String key in serverValues!.keys) {
+      String serverValue = serverValues![key]?.toString() ?? '-';
+      String localValue = _getLocalValue(key);
+      bool isEditable = _isConfigurationPermitted(key);
+      bool isModified =
+          localValues.containsKey(key) && localValues[key] != serverValue;
+
+      GlobalConfigItem item = GlobalConfigItem(
+        key: key,
+        serverValue: serverValue,
+        localValue: localValue,
+        editable: isEditable,
+        isModified: isModified,
+      );
+      globalConfigItems.add(item);
+    }
+
+    return globalConfigItems;
+  }
+
+  @override
+  Widget build(BuildContext context) {
+    return Scaffold(
+      body: Card(
+        margin: const EdgeInsets.all(5),
+        elevation: 2,
+        shape: RoundedRectangleBorder(
+          borderRadius: BorderRadius.circular(4),
+        ),
+        child: Column(
+          children: [
+            Container(
+              padding: const EdgeInsets.all(16),
+              decoration: BoxDecoration(
+                borderRadius: BorderRadius.circular(4),
+                color: Colors.blue[50],
+              ),
+              child: Column(
+                children: [
+                  Row(
+                    children: [
+                      Expanded(
+                        flex: 2,
+                        child: Text(
+                          AppLocalizations.of(context)!.key,
+                          style: const TextStyle(
+                            fontSize: 14,
+                            fontWeight: FontWeight.bold,
+                          ),
+                        ),
+                      ),
+                      Expanded(
+                        flex: 1,
+                        child: Text(
+                          AppLocalizations.of(context)!.server_value,
+                          style: const TextStyle(
+                            fontSize: 14,
+                            fontWeight: FontWeight.bold,
+                          ),
+                        ),
+                      ),
+                      Expanded(
+                        flex: 1,
+                        child: Text(
+                          AppLocalizations.of(context)!.local_value,
+                          style: const TextStyle(
+                            fontSize: 14,
+                            fontWeight: FontWeight.bold,
+                          ),
+                        ),
+                      ),
+                    ],
+                  ),
+                ],
+              ),
+            ),
+            Expanded(
+              child: _buildContent(),
+            ),
+            Container(
+              padding: const EdgeInsets.all(10),
+              alignment: Alignment.centerRight, // Align content to the end
+              child: ElevatedButton(
+                onPressed: () {
+                  _onSaveChanges();
+                },
+                style: ElevatedButton.styleFrom(
+                  backgroundColor: solidPrimary,
+                  foregroundColor: Colors.white,
+                  padding:
+                      const EdgeInsets.symmetric(vertical: 16, horizontal: 60),
+                  elevation: 4,
+                ),
+                child: Text(AppLocalizations.of(context)!.submit),
+              ),
+            ),
+          ],
+        ),
+      ),
+    );
+  }
+
+  Widget _buildContent() {
+    if (isLoading) {
+      return const Center(child: CircularProgressIndicator());
+    }
+    if (errorMessage != null) {
+      return Center(
+        child: Column(
+          mainAxisAlignment: MainAxisAlignment.center,
+          children: [
+            Icon(Icons.error, size: 64, color: Colors.red[300]),
+            const SizedBox(height: 16),
+            Text(
+              'Error: $errorMessage',
+              style: TextStyle(color: Colors.red[700]),
+              textAlign: TextAlign.center,
+            ),
+            const SizedBox(height: 16),
+            ElevatedButton(
+              onPressed: _loadInitialData,
+              child: Text(AppLocalizations.of(context)!.retry),
+            ),
+          ],
+        ),
+      );
+    }
+    if (serverValues == null || serverValues!.isEmpty) {
+      return Center(
+          child: Text(
+              AppLocalizations.of(context)!.no_configuration_parameters_found));
+    }
+
+    final configs = _getConfigurations();
+    if (configs.isEmpty) {
+      return Center(
+        child: Text(AppLocalizations.of(context)!.no_configurations_found),
+      );
+    }
+
+    return SizedBox(
+      width: double.infinity,
+      child: ListView.separated(
+        padding: const EdgeInsets.only(top: 10, bottom: 15),
+        itemCount: configs.length,
+        separatorBuilder: (_, __) =>
+            Divider(height: 1, color: Colors.grey[300]),
+        itemBuilder: (context, index) {
+          final config = configs[index];
+          return Padding(
+            padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 15),
+            child: Row(
+              mainAxisAlignment: MainAxisAlignment.spaceAround,
+              children: [
+                Expanded(
+                  flex: 2,
+                  child: Text(
+                    config.key,
+                    style: TextStyle(
+                      fontSize: 12,
+                      fontWeight: config.isModified
+                          ? FontWeight.bold
+                          : FontWeight.normal,
+                      color: config.isModified ? Colors.blue : Colors.black,
+                    ),
+                  ),
+                ),
+                const SizedBox(width: 10),
+                Expanded(
+                  flex: 1,
+                  child: Text(
+                    config.serverValue,
+                    style: const TextStyle(
+                      fontSize: 12,
+                    ),
+                  ),
+                ),
+                Expanded(
+                  flex: 1,
+                  child: _buildEditableCell(config),
+                ),
+              ],
+            ),
+          );
+        },
+      ),
+    );
+  }
+
+  // Builds either an editable TextField or read-only text based on config permissions
+  Widget _buildEditableCell(GlobalConfigItem config) {
+    if (config.editable) {
+      return _buildEditableTextField(config);
+    } else {
+      return _buildReadOnlyText(config);
+    }
+  }
+
+  // Builds an editable TextField for permitted configurations
+  Widget _buildEditableTextField(GlobalConfigItem config) {
+    final controller = _controllers[config.key]!;
+    return TextField(
+      controller: controller,
+      onChanged: (newValue) => _updateLocalValue(config.key, newValue),
+      style: TextStyle(
+        color: config.isModified ? Colors.blue : Colors.black,
+        fontSize: 12,
+        fontWeight: config.isModified ? FontWeight.bold : FontWeight.normal,
+      ),
+      decoration: InputDecoration(
+        border: OutlineInputBorder(
+          borderRadius: BorderRadius.circular(4),
+          borderSide: BorderSide(
+            color: config.isModified ? Colors.blue : Colors.grey,
+          ),
+        ),
+        contentPadding: const EdgeInsets.symmetric(
+          horizontal: 8,
+          vertical: 4,
+        ),
+        isDense: true,
+        hintText: config.serverValue,
+      ),
+    );
+  }
+
+  // Builds read-only styled text for non-permitted configurations
+  Widget _buildReadOnlyText(GlobalConfigItem config) {
+    return Container(
+      padding: const EdgeInsets.symmetric(
+        horizontal: 8,
+        vertical: 8,
+      ),
+      decoration: BoxDecoration(
+        border: Border.all(color: Colors.grey[300]!),
+        borderRadius: BorderRadius.circular(4),
+        color: Colors.grey[100],
+      ),
+      child: Text(
+        config.localValue.isEmpty ? '-' : config.localValue,
+        style: TextStyle(
+          color: config.isModified ? Colors.blue : Colors.grey[600],
+          fontSize: 12,
+          fontWeight: config.isModified ? FontWeight.bold : FontWeight.normal,
+        ),
+      ),
+    );
+  }
+}
+
+class GlobalConfigItem {
+  final String key;
+  final String serverValue;
+  final String localValue;
+  final bool editable;
+  final bool isModified;
+
+  GlobalConfigItem({
+    required this.key,
+    required this.serverValue,
+    required this.localValue,
+    required this.editable,
+    required this.isModified,
+  });
+}
diff --git a/pigeon.sh b/pigeon.sh
index 2d1e3f65f..3d9033560 100644
--- a/pigeon.sh
+++ b/pigeon.sh
@@ -56,4 +56,7 @@ dart run pigeon --input pigeon/transliteration.dart --dart_out lib/pigeon/transl
 dart run pigeon --input pigeon/document_category.dart --dart_out lib/pigeon/document_category_pigeon.dart --objc_header_out ios/Runner/pigeon.h --objc_source_out ios/Runner/pigeon.m --java_out ./android/app/src/main/java/io/mosip/registration_client/model/DocumentCategoryPigeon.java --java_package "io.mosip.registration_client.model"
 
 # Generate dash board files
-dart run pigeon --input pigeon/dash_board.dart --dart_out lib/pigeon/dash_board_pigeon.dart --objc_header_out ios/Runner/pigeon.h --objc_source_out ios/Runner/pigeon.m --java_out ./android/app/src/main/java/io/mosip/registration_client/model/DashBoardPigeon.java --java_package "io.mosip.registration_client.model"
\ No newline at end of file
+dart run pigeon --input pigeon/dash_board.dart --dart_out lib/pigeon/dash_board_pigeon.dart --objc_header_out ios/Runner/pigeon.h --objc_source_out ios/Runner/pigeon.m --java_out ./android/app/src/main/java/io/mosip/registration_client/model/DashBoardPigeon.java --java_package "io.mosip.registration_client.model"
+
+# Generate global config settings files
+dart run pigeon --input pigeon/global_config_settings.dart --dart_out lib/pigeon/global_config_settings_pigeon.dart --objc_header_out ios/Runner/pigeon.h --objc_source_out ios/Runner/pigeon.m --java_out ./android/app/src/main/java/io/mosip/registration_client/model/GlobalConfigSettingsPigeon.java --java_package "io.mosip.registration_client.model"
\ No newline at end of file
diff --git a/pigeon/global_config_settings.dart b/pigeon/global_config_settings.dart
new file mode 100644
index 000000000..b0386176a
--- /dev/null
+++ b/pigeon/global_config_settings.dart
@@ -0,0 +1,13 @@
+import 'package:pigeon/pigeon.dart';
+
+@HostApi()
+abstract class GlobalConfigSettingsApi {
+  @async
+  Map getRegistrationParams();
+  @async
+  Map getLocalConfigurations();
+  @async
+  List getPermittedConfigurationNames();
+  @async
+  void modifyConfigurations(Map localPreferences);
+}
\ No newline at end of file
diff --git a/pubspec.yaml b/pubspec.yaml
index 73071b751..6ce32ba3f 100644
--- a/pubspec.yaml
+++ b/pubspec.yaml
@@ -70,6 +70,7 @@ dependencies:
   flutter_config: ^2.0.2
   native_image_cropper: ^0.6.0
   qr_code_scanner: ^1.0.1
+  restart_app: ^1.2.1
 
 dev_dependencies:
   flutter_test:

From 196ffdaef1a94a30931a2f45a011af882e454c61 Mon Sep 17 00:00:00 2001
From: Sachin S  P <52343650+SachinPremkumar@users.noreply.github.com>
Date: Tue, 7 Oct 2025 11:20:45 +0530
Subject: [PATCH 25/44] RCF-93 Device settings (#573)

* RCF-93 Device settings

Signed-off-by: sachin.sp 

* RCF- 93: device settings implementation

Signed-off-by: sachin.sp 

* RCF- 93: updated the review comments

Signed-off-by: sachin.sp 

---------

Signed-off-by: sachin.sp 
Co-authored-by: sachin.sp 
---
 .../registration_client/MainActivity.java     |  19 +--
 .../api_services/BiometricsDetailsApi.java    |  86 ++++++++++-
 .../service/Biometrics095Service.java         |   4 +-
 assets/l10n/app_ar.arb                        |   3 +-
 assets/l10n/app_en.arb                        |   3 +-
 assets/l10n/app_fr.arb                        |   3 +-
 assets/l10n/app_hi.arb                        |   3 +-
 assets/l10n/app_kn.arb                        |   3 +-
 assets/l10n/app_ta.arb                        |   3 +-
 .../biometrics_service_impl.dart              |  15 +-
 lib/platform_spi/biometrics_service.dart      |   3 +
 .../widgets/device_settings_tab.dart          | 146 ++++++++++++++++++
 lib/ui/settings/settings_screen.dart          |   7 +-
 pigeon/biometrics.dart                        |  16 ++
 14 files changed, 285 insertions(+), 29 deletions(-)
 create mode 100644 lib/ui/process_ui/widgets/device_settings_tab.dart

diff --git a/android/app/src/main/java/io/mosip/registration_client/MainActivity.java b/android/app/src/main/java/io/mosip/registration_client/MainActivity.java
index 7dc26fbf2..5a51b1257 100644
--- a/android/app/src/main/java/io/mosip/registration_client/MainActivity.java
+++ b/android/app/src/main/java/io/mosip/registration_client/MainActivity.java
@@ -7,8 +7,6 @@
 
 package io.mosip.registration_client;
 
-import io.mosip.registration.clientmanager.constant.ClientManagerConstant;
-
 import android.app.Activity;
 import android.app.AlarmManager;
 import android.app.PendingIntent;
@@ -26,8 +24,6 @@
 
 import com.fasterxml.jackson.databind.ObjectWriter;
 
-import java.util.List;
-import java.util.Objects;
 import java.util.concurrent.Executors;
 import java.util.concurrent.ScheduledExecutorService;
 import java.util.concurrent.TimeUnit;
@@ -40,21 +36,13 @@
 import io.mosip.registration.clientmanager.config.AppModule;
 import io.mosip.registration.clientmanager.config.NetworkModule;
 import io.mosip.registration.clientmanager.config.RoomModule;
-import io.mosip.registration.clientmanager.constant.AuditEvent;
-import io.mosip.registration.clientmanager.constant.Components;
-import io.mosip.registration.clientmanager.constant.PacketClientStatus;
-import io.mosip.registration.clientmanager.constant.PacketTaskStatus;
 import io.mosip.registration.clientmanager.dao.GlobalParamDao;
-import io.mosip.registration.clientmanager.entity.GlobalParam;
-import io.mosip.registration.clientmanager.entity.Registration;
-import io.mosip.registration.clientmanager.entity.SyncJobDef;
 import io.mosip.registration.clientmanager.repository.GlobalParamRepository;
 import io.mosip.registration.clientmanager.repository.IdentitySchemaRepository;
 import io.mosip.registration.clientmanager.repository.RegistrationCenterRepository;
 import io.mosip.registration.clientmanager.repository.SyncJobDefRepository;
 import io.mosip.registration.clientmanager.repository.UserDetailRepository;
 import io.mosip.registration.clientmanager.service.LoginService;
-import io.mosip.registration.clientmanager.spi.AsyncPacketTaskCallBack;
 import io.mosip.registration.clientmanager.spi.AuditManagerService;
 import io.mosip.registration.clientmanager.spi.JobManagerService;
 import io.mosip.registration.clientmanager.spi.JobTransactionService;
@@ -101,7 +89,6 @@
 import io.mosip.registration_client.model.UserPigeon;
 import io.mosip.registration_client.model.DocumentDataPigeon;
 import io.mosip.registration_client.utils.BatchJob;
-import io.mosip.registration_client.utils.CustomToast;
 
 import android.net.Uri;
 
@@ -319,6 +306,12 @@ protected void onActivityResult(int requestCode, int resultCode, Intent data) {
                 case 3:
                     biometricsDetailsApi.parseRCaptureResponse(data.getExtras());
                     break;
+                case 4:
+                    biometricsDetailsApi.parseDiscoverResponseForList(data.getExtras());
+                    break;
+                case 5:
+                    biometricsDetailsApi.handleDeviceInfoResponseForList(data.getExtras());
+                    break;
             }
         }
     }
diff --git a/android/app/src/main/java/io/mosip/registration_client/api_services/BiometricsDetailsApi.java b/android/app/src/main/java/io/mosip/registration_client/api_services/BiometricsDetailsApi.java
index 108d5c50d..467b30178 100644
--- a/android/app/src/main/java/io/mosip/registration_client/api_services/BiometricsDetailsApi.java
+++ b/android/app/src/main/java/io/mosip/registration_client/api_services/BiometricsDetailsApi.java
@@ -29,11 +29,8 @@
 import java.lang.reflect.Field;
 import java.util.ArrayList;
 import java.util.HashMap;
-import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
-import java.util.Set;
-import java.util.concurrent.atomic.AtomicInteger;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 import java.util.stream.Collectors;
@@ -56,7 +53,6 @@
 import io.mosip.registration.clientmanager.exception.ClientCheckedException;
 import io.mosip.registration.clientmanager.repository.GlobalParamRepository;
 import io.mosip.registration.clientmanager.service.Biometrics095Service;
-import io.mosip.registration.clientmanager.service.RegistrationServiceImpl;
 import io.mosip.registration.clientmanager.service.UserOnboardService;
 import io.mosip.registration.clientmanager.spi.AuditManagerService;
 import io.mosip.registration.clientmanager.spi.RegistrationService;
@@ -87,7 +83,7 @@ public class BiometricsDetailsApi implements BiometricsPigeon.BiometricsApi {
     private int qualityThreshold;
     List biometricsDtoList;
 
-    private List listBitmaps1 = new ArrayList<>();
+    private final List listBitmaps1 = new ArrayList<>();
     private byte[] byteArrayTester;
     private List listByteArrayTester1 = new ArrayList<>();
     BiometricsPigeon.Result result1;
@@ -108,6 +104,11 @@ public class BiometricsDetailsApi implements BiometricsPigeon.BiometricsApi {
     private static final String RIGHT = "Right";
     private static final String LEFT = "Left";
 
+    private final List deviceDetailsList = new ArrayList<>();
+    private BiometricsPigeon.Result> deviceListResult;
+
+    private Modality currentDeviceListModality;
+
 
 
 
@@ -663,6 +664,81 @@ public void conditionalBioAttributeValidation(@NonNull String fieldId, @NonNull
         }
     }
 
+    @Override
+    public void getListOfDevices(@NonNull String modality, @NonNull BiometricsPigeon.Result> result) {
+        deviceDetailsList.clear();
+        deviceListResult = result;
+        currentDeviceListModality = getModality(modality);
+        try {
+            Intent intent = new Intent();
+            intent.setAction(RegistrationConstants.DISCOVERY_INTENT_ACTION);
+            queryPackage(intent);
+            DiscoverRequest discoverRequest = new DiscoverRequest();
+            discoverRequest.setType(currentDeviceListModality.getSingleType().value());
+            intent.putExtra(RegistrationConstants.SBI_INTENT_REQUEST_KEY,
+                    objectMapper.writeValueAsBytes(discoverRequest));
+            activity.startActivityForResult(intent, 4);
+        } catch (Exception e) {
+            Log.e(TAG, "Error starting device discovery", e);
+            result.success(new ArrayList<>());
+        }
+    }
+
+    public void handleDeviceInfoResponseForList(Bundle bundle) {
+        try {
+            byte[] infoBytes = bundle.getByteArray(RegistrationConstants.SBI_INTENT_RESPONSE_KEY);
+            String[] deviceInfo = biometricsService.handleDeviceInfoResponse(currentDeviceListModality, infoBytes);
+            BiometricsPigeon.DeviceInfo deviceInfoObj = new BiometricsPigeon.DeviceInfo.Builder()
+                    .setDeviceName(deviceInfo[0])
+                    .setDeviceId(deviceInfo[1])
+                    .setConnectionStatus(deviceInfo[2])
+                    .build();
+
+            deviceDetailsList.add(deviceInfoObj);
+
+            if (deviceListResult != null) deviceListResult.success(deviceDetailsList);
+        } catch (Exception e) {
+            Log.e(TAG, "Error handling device info response", e);
+            if (deviceListResult != null) deviceListResult.success(new ArrayList<>());
+        }
+    }
+
+    // Device listing flow: parse discovery response, then request device info
+    public void parseDiscoverResponseForList(Bundle bundle) {
+        try {
+            byte[] bytes = bundle.getByteArray(RegistrationConstants.SBI_INTENT_RESPONSE_KEY);
+            String discoveredCallbackId = biometricsService.handleDiscoveryResponse(currentDeviceListModality, bytes);
+            if (discoveredCallbackId != null) {
+                infoForList(discoveredCallbackId);
+            } else {
+                if (deviceListResult != null) deviceListResult.success(new ArrayList<>());
+            }
+        } catch (BiometricsServiceException e) {
+            auditManagerService.audit(AuditEvent.DISCOVER_SBI_PARSE_FAILED, Components.REGISTRATION, e.getMessage());
+            Log.e(TAG, "Failed to parse discover response for list", e);
+            if (deviceListResult != null) deviceListResult.success(new ArrayList<>());
+        }
+    }
+
+    private void infoForList(String callbackId) {
+        if (callbackId == null) {
+            Log.e(TAG, "No SBI found");
+            if (deviceListResult != null) deviceListResult.success(new ArrayList<>());
+            return;
+        }
+
+        try {
+            Intent intent = new Intent();
+            intent.setAction(callbackId + RegistrationConstants.D_INFO_INTENT_ACTION);
+            queryPackage(intent);
+            activity.startActivityForResult(intent, 5);
+        } catch (ClientCheckedException ex) {
+            auditManagerService.audit(AuditEvent.DEVICE_INFO_FAILED, Components.REGISTRATION, ex.getMessage());
+            Log.e(TAG, ex.getMessage(), ex);
+            if (deviceListResult != null) deviceListResult.success(new ArrayList<>());
+        }
+    }
+
     public static Boolean customMatcher(String str1, String str2) {
         Boolean result = false;
         if (str1.matches(LEFT_INDEX_FINGER) && str2.matches("leftIndex")) {
diff --git a/android/clientmanager/src/main/java/io/mosip/registration/clientmanager/service/Biometrics095Service.java b/android/clientmanager/src/main/java/io/mosip/registration/clientmanager/service/Biometrics095Service.java
index a19e8e476..c0c2d7ee2 100644
--- a/android/clientmanager/src/main/java/io/mosip/registration/clientmanager/service/Biometrics095Service.java
+++ b/android/clientmanager/src/main/java/io/mosip/registration/clientmanager/service/Biometrics095Service.java
@@ -167,6 +167,7 @@ public List handleRCaptureResponse(Modality modality, InputStream
     public String[] handleDeviceInfoResponse(Modality modality, byte[] response) throws BiometricsServiceException {
         String callbackId = null;
         String serialNo = null;
+        String deviceStatus = null;
         try {
             List list = objectMapper.readValue(response, new TypeReference>() {});
 
@@ -187,6 +188,7 @@ public String[] handleDeviceInfoResponse(Modality modality, byte[] response) thr
             if(deviceDto.getCallbackId().contains(".Info")) {
                 callbackId = deviceDto.getCallbackId().replace(".Info", "");
             }
+            deviceStatus = deviceDto.getDeviceStatus();
             String digitalIdPayload = getJWTPayLoad(deviceDto.getDigitalId());
             byte[] decodedDigitalIdPayload = Base64.getUrlDecoder().decode(digitalIdPayload);
             DigitalId digitalId = objectMapper.readValue(decodedDigitalIdPayload, DigitalId.class);
@@ -201,7 +203,7 @@ public String[] handleDeviceInfoResponse(Modality modality, byte[] response) thr
             throw new BiometricsServiceException(SBIError.SBI_DINFO_INVALID_REPSONSE.getErrorCode(),
                     SBIError.SBI_DINFO_INVALID_REPSONSE.getErrorMessage());
         }
-        return new String[] { callbackId, serialNo };
+        return new String[] { callbackId, serialNo, deviceStatus};
     }
 
     public String handleDiscoveryResponse(Modality modality, byte[] response) throws BiometricsServiceException {
diff --git a/assets/l10n/app_ar.arb b/assets/l10n/app_ar.arb
index 70b7244a8..e114d1ca5 100644
--- a/assets/l10n/app_ar.arb
+++ b/assets/l10n/app_ar.arb
@@ -325,5 +325,6 @@
   "local_value": "القيمة المحلية",
   "no_configuration_parameters_found": "لم يتم العثور على معلمات التكوين",
   "no_configurations_found": "لم يتم العثور على أي تكوين",
-  "confirm": "تأكيد"
+  "confirm": "تأكيد",
+  "scan_now": "امسح الآن"
 }
\ No newline at end of file
diff --git a/assets/l10n/app_en.arb b/assets/l10n/app_en.arb
index f53feeda4..7a8da0e4f 100644
--- a/assets/l10n/app_en.arb
+++ b/assets/l10n/app_en.arb
@@ -325,5 +325,6 @@
   "local_value": "Local Value",
   "no_configuration_parameters_found": "No configuration parameters found",
   "no_configurations_found": "No configurations found",
-  "confirm": "CONFIRM"
+  "confirm": "CONFIRM",
+  "scan_now": "Scan Now"
 }
\ No newline at end of file
diff --git a/assets/l10n/app_fr.arb b/assets/l10n/app_fr.arb
index 9d723a095..e2b62efdd 100644
--- a/assets/l10n/app_fr.arb
+++ b/assets/l10n/app_fr.arb
@@ -325,5 +325,6 @@
   "local_value": "Valeur locale",
   "no_configuration_parameters_found": "Aucun paramètre de configuration trouvé",
   "no_configurations_found": "Aucune configuration trouvée",
-  "confirm": "Confirmer"
+  "confirm": "Confirmer",
+  "scan_now": "Analyser maintenant"
 }
\ No newline at end of file
diff --git a/assets/l10n/app_hi.arb b/assets/l10n/app_hi.arb
index 9ee2a854f..5dd313f39 100644
--- a/assets/l10n/app_hi.arb
+++ b/assets/l10n/app_hi.arb
@@ -325,5 +325,6 @@
   "local_value": "स्थानीय मान",
   "no_configuration_parameters_found": "कोई कॉन्फ़िगरेशन पैरामीटर नहीं मिला",
   "no_configurations_found": "कोई कॉन्फ़िगरेशन नहीं मिला",
-  "confirm": "पुष्टि करें"
+  "confirm": "पुष्टि करें",
+  "scan_now": "अभी स्कैन करें"
 }
\ No newline at end of file
diff --git a/assets/l10n/app_kn.arb b/assets/l10n/app_kn.arb
index b26cb7544..92f0ab57a 100644
--- a/assets/l10n/app_kn.arb
+++ b/assets/l10n/app_kn.arb
@@ -325,5 +325,6 @@
   "local_value": "ಸ್ಥಳೀಯ ಮೌಲ್ಯ",
   "no_configuration_parameters_found": "ಯಾವುದೇ ಸಂರಚನಾ ನಿಯತಾಂಕಗಳು ಕಂಡುಬರಲಿಲ್ಲ",
   "no_configurations_found": "ಯಾವುದೇ ಸಂರಚನೆಗಳು ಕಂಡುಬರಲಿಲ್ಲ",
-  "confirm": "ದೃಢೀಕರಿಸಿ"
+  "confirm": "ದೃಢೀಕರಿಸಿ",
+  "scan_now": "ಈಗಸ್ಕ್ಯಾನ್ ಮಾಡಿ"
 }
\ No newline at end of file
diff --git a/assets/l10n/app_ta.arb b/assets/l10n/app_ta.arb
index 1a7a34845..bf417626b 100644
--- a/assets/l10n/app_ta.arb
+++ b/assets/l10n/app_ta.arb
@@ -334,5 +334,6 @@
   "local_value": "உள்ளூர் மதிப்பு",
   "no_configuration_parameters_found": "எந்த கட்டமைப்பு அளவுருக்களும் கிடைக்கவில்லை",
   "no_configurations_found": "எந்த கட்டமைப்பும் கிடைக்கவில்லை",
-  "confirm": "உறுதிப்படுத்தவும்"
+  "confirm": "உறுதிப்படுத்தவும்",
+  "scan_now": "இப்போது ஸ்கேன் செய்யுங்கள்"
 }
\ No newline at end of file
diff --git a/lib/platform_android/biometrics_service_impl.dart b/lib/platform_android/biometrics_service_impl.dart
index b8de0dd06..c7f87bc83 100644
--- a/lib/platform_android/biometrics_service_impl.dart
+++ b/lib/platform_android/biometrics_service_impl.dart
@@ -160,13 +160,26 @@ class BiometricsServiceImpl implements BiometricsService {
     try {
       response = await BiometricsApi().removeBioException(fieldId, modality, attribute);
     } on PlatformException {
-      debugPrint('BiomtericsApi call failed!');
+      debugPrint('BiometricsApi call failed!');
     } catch (e) {
       debugPrint('Remove Bio Exception failed: ${e.toString()}');
     }
     return response;
   }
 
+  @override
+  Future> getListOfDevices(String modality) async {
+    List deviceList = List.empty();
+    try {
+      deviceList = await BiometricsApi().getListOfDevices(modality);
+    } on PlatformException {
+      debugPrint('BiometricsApi call failed!');
+    } catch (e) {
+      debugPrint('Fetch List of Device failed: ${e.toString()}');
+    }
+    return deviceList;
+  }
+
 }
 
 BiometricsService getBiometricsServiceImpl() => BiometricsServiceImpl();
diff --git a/lib/platform_spi/biometrics_service.dart b/lib/platform_spi/biometrics_service.dart
index 2be3d25b8..49337280a 100644
--- a/lib/platform_spi/biometrics_service.dart
+++ b/lib/platform_spi/biometrics_service.dart
@@ -7,6 +7,7 @@
 
 import 'dart:typed_data';
 
+import 'package:registration_client/pigeon/biometrics_pigeon.dart';
 import 'package:registration_client/platform_android/biometrics_service_impl.dart';
 
 abstract class BiometricsService {
@@ -36,5 +37,7 @@ abstract class BiometricsService {
 
   Future conditionalBioAttributeValidation(String fieldId, String expression);
 
+  Future> getListOfDevices(String modality);
+
   factory BiometricsService() => getBiometricsServiceImpl();
 }
diff --git a/lib/ui/process_ui/widgets/device_settings_tab.dart b/lib/ui/process_ui/widgets/device_settings_tab.dart
new file mode 100644
index 000000000..6fd29f944
--- /dev/null
+++ b/lib/ui/process_ui/widgets/device_settings_tab.dart
@@ -0,0 +1,146 @@
+import 'dart:convert';
+import 'package:flutter/material.dart';
+import 'package:registration_client/pigeon/biometrics_pigeon.dart';
+import '../../../model/settings.dart';
+import '../../../platform_spi/biometrics_service.dart';
+import '../../../utils/app_config.dart';
+import 'package:flutter_gen/gen_l10n/app_localizations.dart';
+
+class DeviceSettingsTab extends StatefulWidget {
+  DeviceSettingsTab(
+      {super.key, required this.settings, required this.selectedLan});
+  Settings settings;
+  String selectedLan;
+
+  @override
+  _DeviceSettingsTabState createState() => _DeviceSettingsTabState();
+}
+
+class _DeviceSettingsTabState extends State {
+  late Future> _devicesFuture;
+
+  @override
+  void initState() {
+    super.initState();
+    _devicesFuture = fetchDeviceDetails();
+  }
+
+  Future> fetchDeviceDetails() async {
+    List deviceDetails = [];
+    try {
+      await Future.delayed(const Duration(seconds: 1));
+      List modality = ["Face", "Iris", "Thumbs"];
+
+      for (var modalityType in modality) {
+        List data = await BiometricsService().getListOfDevices(modalityType);
+        deviceDetails.addAll(data.whereType());
+      }
+      return deviceDetails;
+    } catch (e) {
+      debugPrint('Error fetching device details: $e');
+      return [];
+    }
+  }
+
+  @override
+  Widget build(BuildContext context) {
+    return FutureBuilder>(
+      future: _devicesFuture,
+      builder: (context, snapshot) {
+        if (snapshot.connectionState == ConnectionState.waiting) {
+          return const Center(child: CircularProgressIndicator());
+        }
+
+        if (snapshot.hasError) {
+          return const Center(child: Text("Error loading device details"));
+        }
+
+        final devices = snapshot.data ?? [];
+        if (devices.isEmpty) {
+          return const Center(child: Text("No devices found"));
+        }
+
+        return Padding(
+          padding: const EdgeInsets.all(16.0),
+          child: Column(
+            children: [
+              Row(
+                mainAxisAlignment: MainAxisAlignment.spaceBetween,
+                children: [
+                  Text(
+                    widget.settings.label?[widget.selectedLan] ??
+                        widget.settings.label?['eng'] ??
+                        (widget.settings.label?.values.first ?? 'UnKnown'),
+                    style: const TextStyle(
+                      fontSize: 20,
+                      fontWeight: FontWeight.bold,
+                    ),
+                  ),
+                  ElevatedButton(
+                    style: ElevatedButton.styleFrom(
+                      backgroundColor: solidPrimary,
+                      padding: const EdgeInsets.symmetric(
+                          vertical: 12, horizontal: 20),
+                    ),
+                    onPressed: () {
+                      setState(() {});
+                      _devicesFuture = fetchDeviceDetails();
+                    },
+                    child: Text(AppLocalizations.of(context)!.scan_now),
+                  ),
+                ],
+              ),
+              const SizedBox(height: 16),
+              Expanded(
+                child: GridView.builder(
+                  itemCount: devices.length,
+                  gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
+                    crossAxisCount: 2,
+                    crossAxisSpacing: 16,
+                    mainAxisSpacing: 16,
+                    childAspectRatio: 3.5,
+                  ),
+                  itemBuilder: (context, index) {
+                    final device = devices[index];
+                    return Container(
+                      padding: const EdgeInsets.all(8), // even less padding
+                      decoration: BoxDecoration(
+                        border: Border.all(color: Colors.grey.shade300),
+                        borderRadius: BorderRadius.circular(8),
+                      ),
+                      child: Row(
+                        crossAxisAlignment: CrossAxisAlignment.center,
+                        mainAxisAlignment: MainAxisAlignment.start,
+                        mainAxisSize: MainAxisSize.min,
+                        children: [
+                          Icon(Icons.scanner, size: 25, color: solidPrimary),
+                          const SizedBox(width: 10),
+                          Flexible(
+                            child: Column(
+                              crossAxisAlignment: CrossAxisAlignment.start,
+                              mainAxisSize: MainAxisSize.min,
+                              children: [
+                                Text("ID: ${device.deviceId ?? ''}",
+                                    style: const TextStyle(fontSize: 12)),
+                                Text(
+                                    "Name: ${device.deviceName?? ''}",
+                                    style: const TextStyle(fontSize: 12)),
+                                Text(
+                                    "Status: ${device.connectionStatus ?? ''}",
+                                    style: const TextStyle(fontSize: 12)),
+                              ],
+                            ),
+                          ),
+                        ],
+                      ),
+                    );
+                  },
+                ),
+              ),
+            ],
+          ),
+        );
+      },
+    );
+  }
+}
diff --git a/lib/ui/settings/settings_screen.dart b/lib/ui/settings/settings_screen.dart
index 66053fdbb..81b1c4179 100644
--- a/lib/ui/settings/settings_screen.dart
+++ b/lib/ui/settings/settings_screen.dart
@@ -5,6 +5,7 @@ import 'package:provider/provider.dart';
 import 'package:registration_client/model/settings.dart';
 import 'package:registration_client/provider/auth_provider.dart';
 import 'package:registration_client/provider/global_provider.dart';
+import 'package:registration_client/ui/process_ui/widgets/device_settings_tab.dart';
 import 'package:registration_client/utils/app_config.dart';
 import 'package:flutter_gen/gen_l10n/app_localizations.dart';
 
@@ -82,7 +83,7 @@ class _SettingsScreenState extends State {
             child: Column(
               crossAxisAlignment: CrossAxisAlignment.start,
               children: [
-                 Padding(
+                Padding(
                   padding: const EdgeInsets.symmetric(horizontal: 16.0, vertical: 20.0),
                   child: Text(
                     AppLocalizations.of(context)!.settings,
@@ -159,7 +160,7 @@ class _SettingsScreenState extends State {
       case 'GlobalConfigSettingsController':
         return const GlobalConfigSettingsTab();
       case 'DeviceSettingsController':
-        return Center(child: Text("${settings.name}"));
+        return DeviceSettingsTab(settings: settings, selectedLan: selectedLang);
       default:
         return _buildDescriptionOnlyTab(settings, selectedLang);
     }
@@ -175,4 +176,4 @@ class _SettingsScreenState extends State {
       ),
     );
   }
-}
+}
\ No newline at end of file
diff --git a/pigeon/biometrics.dart b/pigeon/biometrics.dart
index 7a6bce709..e844ebbe8 100644
--- a/pigeon/biometrics.dart
+++ b/pigeon/biometrics.dart
@@ -1,5 +1,18 @@
 import 'package:pigeon/pigeon.dart';
 
+
+class DeviceInfo {
+  final String deviceName;
+  final String deviceId;
+  final String connectionStatus;
+
+  DeviceInfo({
+    required this.deviceName,
+    required this.deviceId,
+    required this.connectionStatus,
+  });
+}
+
 @HostApi()
 abstract class BiometricsApi {
   @async
@@ -47,4 +60,7 @@ abstract class BiometricsApi {
 
   @async
   bool conditionalBioAttributeValidation(String fieldId, String expression);
+
+  @async
+  List getListOfDevices(String modality);
 }

From c13d0b87f4e0c612cfbac7ec6ad6a1d1c1005ad5 Mon Sep 17 00:00:00 2001
From: Rakshithasai123 
Date: Sun, 26 Oct 2025 22:42:46 +0530
Subject: [PATCH 26/44] update vulnerable libraries (#592)

Signed-off-by: Rakshithasai123 
---
 android/app/build.gradle           | 15 +++++-----
 android/clientmanager/build.gradle |  9 ++++--
 android/keymanager/build.gradle    |  2 +-
 android/packetmanager/build.gradle |  2 +-
 ui-test/pom.xml                    | 48 +++++++++++++++++++++++-------
 5 files changed, 53 insertions(+), 23 deletions(-)

diff --git a/android/app/build.gradle b/android/app/build.gradle
index 2dc12ee81..17c60e724 100644
--- a/android/app/build.gradle
+++ b/android/app/build.gradle
@@ -135,8 +135,9 @@ dependencies {
     annotationProcessor 'com.google.dagger:dagger-compiler:2.41'
     annotationProcessor 'com.google.dagger:dagger-android-processor:2.41'
     implementation 'androidx.appcompat:appcompat:1.4.1'
-    implementation 'com.squareup.okhttp3:mockwebserver:3.14.9'
-//    implementation 'com.google.code.gson:gson:2.8.9'
+    implementation 'com.squareup.okhttp3:okhttp:4.9.2'
+    implementation 'com.squareup.okio:okio@1.17.6'
+    implementation 'com.google.code.gson:gson:2.8.9'
     implementation 'com.google.android.material:material:1.4.0'
     implementation 'androidx.lifecycle:lifecycle-extensions:2.2.0'
     implementation 'androidx.lifecycle:lifecycle-runtime:2.4.1'
@@ -144,7 +145,7 @@ dependencies {
     implementation "androidx.fragment:fragment:$fragment_version"
     implementation "androidx.room:room-runtime:$room_version"
     annotationProcessor "androidx.room:room-compiler:$room_version"
-    implementation 'com.cronutils:cron-utils:9.1.5'
+    implementation 'com.cronutils:cron-utils:9.1.7'
 
     androidTestImplementation 'androidx.test.ext:junit:1.1.3'
     androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
@@ -181,9 +182,9 @@ dependencies {
     implementation 'org.apache.commons:commons-lang3:3.12.0'
     // https://mvnrepository.com/artifact/commons-codec/commons-codec
     implementation 'commons-codec:commons-codec:1.15'
-    implementation group: 'commons-io', name: 'commons-io', version: '2.11.0'
+    implementation group: 'commons-io', name: 'commons-io', version: '2.14.0'
 
-    implementation 'org.bouncycastle:bcprov-jdk15on:1.59'
+    implementation 'org.bouncycastle:bcprov-jdk15on:1.66'
     implementation 'com.auth0.android:jwtdecode:2.0.1'
 
     implementation project(':clientmanager')
@@ -240,8 +241,8 @@ dependencies {
     implementation 'androidx.navigation:navigation-ui:2.4.2'
 
     implementation 'javax.inject:javax.inject:1'
-    implementation 'com.fasterxml.jackson.core:jackson-core:2.13.2'
-    implementation 'com.fasterxml.jackson.core:jackson-databind:2.13.2'
+    implementation 'com.fasterxml.jackson.core:jackson-core:2.15.0-rc1'
+    implementation 'com.fasterxml.jackson.core:jackson-databind:2.13.4.1'
     implementation 'com.fasterxml.jackson.core:jackson-annotations:2.13.2'
 
 
diff --git a/android/clientmanager/build.gradle b/android/clientmanager/build.gradle
index 35246dc8d..61b5191dc 100644
--- a/android/clientmanager/build.gradle
+++ b/android/clientmanager/build.gradle
@@ -105,16 +105,18 @@ dependencies {
 
     // https://mvnrepository.com/artifact/com.squareup.retrofit2/retrofit
     implementation 'com.squareup.retrofit2:retrofit:2.9.0'
+    implementation 'com.squareup.okio:okio:3.4.0'
+    implementation 'com.squareup.okhttp3:okhttp:4.9.2'
     implementation 'com.squareup.retrofit2:converter-gson:2.9.0'
 
     // JWT decoding library
     implementation 'com.auth0.android:jwtdecode:2.0.1'
 
     // https://mvnrepository.com/artifact/commons-io/commons-io
-    implementation group: 'commons-io', name: 'commons-io', version: '2.11.0'
+    implementation group: 'commons-io', name: 'commons-io', version: '2.14.0'
 
-    implementation 'com.fasterxml.jackson.core:jackson-core:2.13.2'
-    implementation 'com.fasterxml.jackson.core:jackson-databind:2.13.2.2'
+    implementation 'com.fasterxml.jackson.core:jackson-core:2.15.0-rc1'
+    implementation 'com.fasterxml.jackson.core:jackson-databind:2.13.4.1'
     implementation 'com.fasterxml.jackson.core:jackson-annotations:2.13.2'
 
     implementation 'org.apache.velocity:velocity:1.7'
@@ -144,4 +146,5 @@ dependencies {
     implementation("io.mosip.kernel:kernel-biometrics-api:1.2.0.3"){
         transitive = false
     }
+    implementation 'com.google.code.gson:gson:2.10.1'
 }
diff --git a/android/keymanager/build.gradle b/android/keymanager/build.gradle
index 57401bc9c..7c8ea93c8 100644
--- a/android/keymanager/build.gradle
+++ b/android/keymanager/build.gradle
@@ -74,7 +74,7 @@ dependencies {
     // https://mvnrepository.com/artifact/commons-io/commons-io
     implementation group: 'commons-io', name: 'commons-io', version: '2.11.0'
 
-    implementation 'org.bouncycastle:bcprov-jdk15on:1.59'
+    implementation 'org.bouncycastle:bcprov-jdk15on:1.60'
     implementation 'org.bouncycastle:bcpkix-jdk15on:1.47'
 
     implementation 'com.madgag.spongycastle:core:1.58.0.0'
diff --git a/android/packetmanager/build.gradle b/android/packetmanager/build.gradle
index 344705ee9..8d4a6bfa7 100644
--- a/android/packetmanager/build.gradle
+++ b/android/packetmanager/build.gradle
@@ -78,7 +78,7 @@ dependencies {
 
     implementation 'com.fasterxml.jackson.core:jackson-databind:2.13.3'
 
-    implementation 'commons-io:commons-io:2.11.0'
+    implementation 'commons-io:commons-io:2.14.0'
 
     implementation 'org.apache.commons:commons-lang3:3.12.0'
 
diff --git a/ui-test/pom.xml b/ui-test/pom.xml
index 3354d6a58..d484b2f97 100644
--- a/ui-test/pom.xml
+++ b/ui-test/pom.xml
@@ -79,6 +79,21 @@
 			java-client
 			8.6.0
 		
+		
+			org.asynchttpclient
+			async-http-client
+			2.12.4
+		
+		
+			org.apache.commons
+			commons-lang3
+			3.18.0
+		
+		
+			io.netty
+			netty-codec-http
+			4.1.125.Final
+		
 		
 			com.googlecode.json-simple
 			json-simple
@@ -98,12 +113,12 @@
 		
 			com.fasterxml.jackson.core
 			jackson-databind
-			2.13.3
+			2.13.4.1
 		
 		
 			org.keycloak
 			keycloak-admin-client
-			17.0.1
+			23.0.4
 		
 		
 			com.fasterxml.jackson.core
@@ -118,12 +133,12 @@
 		
 			org.json
 			json
-			20230227
+			20231013
 		
 		
 			commons-io
 			commons-io
-			2.13.0
+			2.14.0
 		
 		
 			com.aventstack
@@ -138,22 +153,22 @@
 		
 			org.apache.logging.log4j
 			log4j-api
-			2.11.1
+			2.17.1
 		
 		
 			org.slf4j
 			slf4j-log4j12
-			1.6.2
+			1.7.34
 		
 		
 			org.yaml
 			snakeyaml
-			1.29
+			2.0
 		
 		
 			commons-beanutils
 			commons-beanutils
-			1.9.4
+			1.11.0
 		
 		
 			org.apache.logging.log4j
@@ -163,23 +178,34 @@
 		
 			org.jboss.resteasy
 			resteasy-multipart-provider
-			3.15.0.Final
+			4.7.8.Final
 		
+		
+			com.sun.mail
+			jakarta.mail
+			2.0.2
+		
+
 		
 			org.jboss.resteasy
 			resteasy-client
-			3.15.0.Final
+			4.5.8.SP1
 		
 		
 			org.jboss.resteasy
 			resteasy-client-microprofile
-			3.15.0.Final
+			4.5.8.SP1
 		
 		
 			org.jboss.resteasy
 			resteasy-jackson2-provider
 			3.15.0.Final
 		
+		
+			com.google.guava
+			guava
+			32.0.0-jre
+		
 		
 			org.jboss.resteasy
 			resteasy-jaxb-provider

From 74a50d8aff3e1ebe28452805aad1336805974030 Mon Sep 17 00:00:00 2001
From: Rakshithasai123 
Date: Sun, 26 Oct 2025 22:46:03 +0530
Subject: [PATCH 27/44] Size of uploaded document should mention in upload
 document screen (#590)

* image size fix

Signed-off-by: Rakshithasai123 

* updated the code for tab view

Signed-off-by: Rakshithasai123 

---------

Signed-off-by: Rakshithasai123 
---
 .../widgets/document_upload_control.dart      | 21 ++++++++++++++++---
 1 file changed, 18 insertions(+), 3 deletions(-)

diff --git a/lib/ui/process_ui/widgets/document_upload_control.dart b/lib/ui/process_ui/widgets/document_upload_control.dart
index 5e3affb81..88295345a 100644
--- a/lib/ui/process_ui/widgets/document_upload_control.dart
+++ b/lib/ui/process_ui/widgets/document_upload_control.dart
@@ -42,6 +42,11 @@ class _DocumentUploadControlState extends State {
   late RegistrationTaskProvider registrationTaskProvider;
   Map transliterationLangMapper = {};
   bool hasInteractedWithDropdown = false;
+  String getReadableFileSize(int bytes) {
+    if (bytes < 1024) return "$bytes B";
+    if (bytes < 1024 * 1024) return "${(bytes / 1024).toStringAsFixed(2)} KB";
+    return "${(bytes / (1024 * 1024)).toStringAsFixed(2)} MB";
+  }
 
 
   FixedExtentScrollController scrollController = FixedExtentScrollController();
@@ -509,7 +514,7 @@ class _DocumentUploadControlState extends State {
                     ),
                     imageBytesList.isNotEmpty
                         ? SizedBox(
-                            height: 110.h,
+                            height: 120.h,
                             child: ListView(
                               scrollDirection: Axis.horizontal,
                               children: imageBytesList.map((item) {
@@ -531,7 +536,12 @@ class _DocumentUploadControlState extends State {
                                           child: Image.memory(item!),
                                         ),
                                       ),
-                                      SizedBox(height: 10.h),
+                                      SizedBox(height: 2.h),
+                                      Text(
+                                        'Size: ${getReadableFileSize(item.length)}',
+                                        style: TextStyle(fontSize: 12.sp, color: Colors.grey),
+                                      ),
+                                      SizedBox(height: 2.h),
                                       GestureDetector(
                                         onTap: () {
                                           _deleteImage(widget.field, item);
@@ -771,7 +781,7 @@ class _DocumentUploadControlState extends State {
                     ),
                     imageBytesList.isNotEmpty
                         ? SizedBox(
-                            height: 110.h,
+                            height: 130.h,
                             child: ListView(
                               scrollDirection: Axis.horizontal,
                               children: imageBytesList.map((item) {
@@ -794,6 +804,11 @@ class _DocumentUploadControlState extends State {
                                         ),
                                       ),
                                       SizedBox(height: 10.h),
+                                      Text(
+                                        'Size: ${getReadableFileSize(item.length)}',
+                                        style: TextStyle(fontSize: 12.sp, color: Colors.grey),
+                                      ),
+                                      SizedBox(height: 10.h),
                                       GestureDetector(
                                         onTap: () {
                                           _deleteImage(widget.field, item);

From 4e4212e385f0a0c74094d04959c87cb2fa31dda9 Mon Sep 17 00:00:00 2001
From: Rakshithasai123 
Date: Mon, 27 Oct 2025 13:45:37 +0530
Subject: [PATCH 28/44] improper and vulnerable use of log4j (#591)

Signed-off-by: Rakshithasai123 
---
 ui-test/pom.xml | 13 +++++++++----
 1 file changed, 9 insertions(+), 4 deletions(-)

diff --git a/ui-test/pom.xml b/ui-test/pom.xml
index d484b2f97..b420ca776 100644
--- a/ui-test/pom.xml
+++ b/ui-test/pom.xml
@@ -153,12 +153,17 @@
 		
 			org.apache.logging.log4j
 			log4j-api
-			2.17.1
+			2.23.1
 		
 		
 			org.slf4j
-			slf4j-log4j12
-			1.7.34
+			slf4j-api
+			2.0.13
+		
+		
+			org.apache.logging.log4j
+			log4j-slf4j2-impl
+			2.23.1 
 		
 		
 			org.yaml
@@ -173,7 +178,7 @@
 		
 			org.apache.logging.log4j
 			log4j-core
-			2.11.1
+			2.23.1
 		
 		
 			org.jboss.resteasy

From 81673ddd2648f53b67eb860adbdd8a20ddba7717 Mon Sep 17 00:00:00 2001
From: Madhuravas reddy 
Date: Mon, 27 Oct 2025 16:05:02 +0530
Subject: [PATCH 29/44] RCF-502 Created biometric correction feature (#564)

* taken new changes from develop

Signed-off-by: Madhuravas Reddy 

* Removed debug logs

Signed-off-by: Madhuravas reddy 

* adding same AID for biometric correction

Signed-off-by: Madhuravas reddy 

* Added new biometric changes

Signed-off-by: Madhuravas Reddy 

* resolved packet reprocess issue

Signed-off-by: Madhuravas Reddy 

* Resolved review comments

Signed-off-by: Madhuravas Reddy 

* Changed bimetric correction class name

Signed-off-by: Madhuravas Reddy 

---------

Signed-off-by: Madhuravas Reddy 
Signed-off-by: Madhuravas reddy 
---
 .../api_services/RegistrationApi.java         |   17 +-
 .../clientmanager/config/AppModule.java       |    5 +-
 .../dto/registration/RegistrationDto.java     |    2 +
 .../dto/uispec/ScreenSpecDto.java             |    2 +-
 .../clientmanager/entity/Registration.java    |    3 +
 .../repository/IdentitySchemaRepository.java  |    8 +-
 .../repository/RegistrationRepository.java    |    4 +-
 .../service/Biometrics095Service.java         |   22 +
 .../service/PacketServiceImpl.java            |    4 +-
 .../service/RegistrationServiceImpl.java      |   99 +-
 .../RegistrationRepositoryTest.java           |    2 +-
 .../service/RegistrationServiceImplTest.java  |   15 +-
 .../service/PacketWriterServiceImpl.java      |   26 +-
 assets/l10n/app_ar.arb                        |    4 +-
 assets/l10n/app_en.arb                        |    4 +-
 assets/l10n/app_fr.arb                        |    4 +-
 assets/l10n/app_hi.arb                        |    4 +-
 assets/l10n/app_kn.arb                        |    4 +-
 assets/l10n/app_ta.arb                        |    4 +-
 lib/app_router.dart                           |    2 +
 lib/model/registration.dart                   |    1 +
 .../registration_service_impl.dart            |   11 +
 lib/platform_spi/registration_service.dart    |    1 +
 lib/provider/global_provider.dart             |    7 +
 lib/provider/registration_task_provider.dart  |    4 +
 .../approve_packet/widget/approve_table.dart  |    2 +-
 .../widget/template_bottom_sheet.dart         |    2 +-
 .../export_packet/widgets/export_table.dart   |    2 +-
 lib/ui/onboard/home_page.dart                 |    3 +-
 lib/ui/process_ui/correction_process.dart     | 1002 +++++++++++++++++
 .../additional_Info_ReqId_control.dart        |   86 ++
 .../process_ui/widgets/language_selector.dart |   13 +-
 .../widgets/new_process_screen_content.dart   |    4 +
 ...biometric_capture_scan_block_portrait.dart |  114 +-
 pigeon/registration_data.dart                 |    3 +
 pubspec.yaml                                  |    2 +-
 36 files changed, 1387 insertions(+), 105 deletions(-)
 create mode 100644 lib/ui/process_ui/correction_process.dart
 create mode 100644 lib/ui/process_ui/widgets/additional_Info_ReqId_control.dart

diff --git a/android/app/src/main/java/io/mosip/registration_client/api_services/RegistrationApi.java b/android/app/src/main/java/io/mosip/registration_client/api_services/RegistrationApi.java
index 534e23319..7972ecc4e 100644
--- a/android/app/src/main/java/io/mosip/registration_client/api_services/RegistrationApi.java
+++ b/android/app/src/main/java/io/mosip/registration_client/api_services/RegistrationApi.java
@@ -106,10 +106,16 @@ public void submitRegistrationDto(@NonNull String makerName, @NonNull Registrati
         String response = "";
         String errorCode = "";
         try {
-            response = this.registrationService.getRegistrationDto().getRId();
+            RegistrationDto registrationDto = this.registrationService.getRegistrationDto();
+            if (registrationDto.getAdditionalInfoRequestId() != null) {
+                response = registrationDto.getAdditionalInfoRequestId().split("-")[0];
+            } else {
+                response = registrationDto.getRId();
+            }
             registrationService.submitRegistrationDto(makerName);
         } catch (Exception e) {
             errorCode = e.getMessage();
+            Log.i("RegistrationApi", "Registration submission failed: " + errorCode);
             auditManagerService.audit(AuditEvent.CREATE_PACKET_FAILED, Components.REGISTRATION, errorCode);
             Log.e(getClass().getSimpleName(), "Failed on registration submission", e);
         }
@@ -130,5 +136,14 @@ public void setApplicationId(@NonNull String applicationId, @NonNull Registratio
             Log.e(getClass().getSimpleName(), "Set application ID failed: " + Arrays.toString(e.getStackTrace()));
         }
     }
+
+    @Override
+    public void setAdditionalReqId(@NonNull String additionalReqId, @NonNull RegistrationDataPigeon.Result result) {
+        try {
+            this.registrationDto.setAdditionalInfoRequestId(additionalReqId);
+        } catch (Exception e) {
+            Log.e(getClass().getSimpleName(), "Set additional request ID failed: " + Arrays.toString(e.getStackTrace()));
+        }
+    }
 }
 
diff --git a/android/clientmanager/src/main/java/io/mosip/registration/clientmanager/config/AppModule.java b/android/clientmanager/src/main/java/io/mosip/registration/clientmanager/config/AppModule.java
index 701f5ab81..2c2f3571e 100644
--- a/android/clientmanager/src/main/java/io/mosip/registration/clientmanager/config/AppModule.java
+++ b/android/clientmanager/src/main/java/io/mosip/registration/clientmanager/config/AppModule.java
@@ -198,10 +198,11 @@ RegistrationService provideRegistrationService(PacketWriterService packetWriterS
                                                    ClientCryptoManagerService clientCryptoManagerService,
                                                    KeyStoreRepository keyStoreRepository,
                                                    GlobalParamRepository globalParamRepository,
-                                                   AuditManagerService auditManagerService) {
+                                                   AuditManagerService auditManagerService,
+                                                   Biometrics095Service biometricService) {
         return new RegistrationServiceImpl(appContext, packetWriterService, registrationRepository,
                 masterDataService, identitySchemaRepository, clientCryptoManagerService,
-                keyStoreRepository, globalParamRepository, auditManagerService);
+                keyStoreRepository, globalParamRepository, auditManagerService,biometricService);
     }
 
     @Provides
diff --git a/android/clientmanager/src/main/java/io/mosip/registration/clientmanager/dto/registration/RegistrationDto.java b/android/clientmanager/src/main/java/io/mosip/registration/clientmanager/dto/registration/RegistrationDto.java
index e9edbe8dc..d5745c0c5 100644
--- a/android/clientmanager/src/main/java/io/mosip/registration/clientmanager/dto/registration/RegistrationDto.java
+++ b/android/clientmanager/src/main/java/io/mosip/registration/clientmanager/dto/registration/RegistrationDto.java
@@ -56,6 +56,7 @@ public class RegistrationDto extends Observable {
     public static final String AGE_GROUP_CONFIG = "{'INFANT':'0-5','MINOR':'6-17','ADULT':'18-200'}";
 
     private String rId;
+    private String packetId;
     private String flowType;
     private String process;
     private String preRegistrationId;
@@ -85,6 +86,7 @@ public class RegistrationDto extends Observable {
     public Map SELECTED_CODES = new HashMap<>();
 
     private String applicationId;
+    private String additionalInfoRequestId;
 
     public RegistrationDto(@NonNull String rid, @NonNull String flowType, @NonNull String process,
                            @NonNull Double schemaVersion, @NonNull List languages,
diff --git a/android/clientmanager/src/main/java/io/mosip/registration/clientmanager/dto/uispec/ScreenSpecDto.java b/android/clientmanager/src/main/java/io/mosip/registration/clientmanager/dto/uispec/ScreenSpecDto.java
index e7b3d9b57..d84f82015 100644
--- a/android/clientmanager/src/main/java/io/mosip/registration/clientmanager/dto/uispec/ScreenSpecDto.java
+++ b/android/clientmanager/src/main/java/io/mosip/registration/clientmanager/dto/uispec/ScreenSpecDto.java
@@ -20,5 +20,5 @@ public class ScreenSpecDto {
     private List fields;
     private Integer order;
     private Boolean preRegFetchRequired;
-
+    private Boolean additionalInfoRequestIdRequired;
 }
diff --git a/android/clientmanager/src/main/java/io/mosip/registration/clientmanager/entity/Registration.java b/android/clientmanager/src/main/java/io/mosip/registration/clientmanager/entity/Registration.java
index 6507d904f..a8287a781 100644
--- a/android/clientmanager/src/main/java/io/mosip/registration/clientmanager/entity/Registration.java
+++ b/android/clientmanager/src/main/java/io/mosip/registration/clientmanager/entity/Registration.java
@@ -99,6 +99,9 @@ public class Registration {
     @ColumnInfo(name = "upd_dtimes")
     private Long updDtimes;
 
+    @ColumnInfo(name = "id")
+    private String id;
+
     @Override
     public String toString() {
         return packetId + "\n" + (serverStatus == null ? clientStatus : serverStatus);
diff --git a/android/clientmanager/src/main/java/io/mosip/registration/clientmanager/repository/IdentitySchemaRepository.java b/android/clientmanager/src/main/java/io/mosip/registration/clientmanager/repository/IdentitySchemaRepository.java
index b34073a33..141772129 100644
--- a/android/clientmanager/src/main/java/io/mosip/registration/clientmanager/repository/IdentitySchemaRepository.java
+++ b/android/clientmanager/src/main/java/io/mosip/registration/clientmanager/repository/IdentitySchemaRepository.java
@@ -339,7 +339,7 @@ private IdSchemaResponse migrate115UiSpecToLTSProcessSpec(IdSchemaResponse idSch
                     FieldSpecDto field = objectMapper.treeToValue(element, FieldSpecDto.class);
                     consentFields.add(field);
                 }
-                ScreenSpecDto consentScreen = new ScreenSpecDto("Consent", consentScreenLabel, consentFields, 1, false);
+                ScreenSpecDto consentScreen = new ScreenSpecDto("Consent", consentScreenLabel, consentFields, 1, false, false);
                 screens.add(consentScreen);
             } catch (JsonProcessingException e) {
                 Log.e(TAG, "Failed to build consent screen", e);
@@ -351,7 +351,7 @@ private IdSchemaResponse migrate115UiSpecToLTSProcessSpec(IdSchemaResponse idSch
             demoScreenLabel.put(primaryLanguage, this.globalParamRepository.getCachedStringGlobalParam("demographicsScreenName_"+primaryLanguage));
             if (secondaryLanguage != null)
                 demoScreenLabel.put(secondaryLanguage, this.globalParamRepository.getCachedStringGlobalParam("demographicsScreenName_"+secondaryLanguage));
-            ScreenSpecDto demographicScreen = new ScreenSpecDto("DemographicDetails", demoScreenLabel, demographics, 2, true);
+            ScreenSpecDto demographicScreen = new ScreenSpecDto("DemographicDetails", demoScreenLabel, demographics, 2, true, false);
             screens.add(demographicScreen);
             Log.i(TAG, "Building demographics screen completed");
 
@@ -360,7 +360,7 @@ private IdSchemaResponse migrate115UiSpecToLTSProcessSpec(IdSchemaResponse idSch
             docScreenLabel.put(primaryLanguage, this.globalParamRepository.getCachedStringGlobalParam("documentsScreenName_"+primaryLanguage));
             if (secondaryLanguage != null)
                 docScreenLabel.put(secondaryLanguage, this.globalParamRepository.getCachedStringGlobalParam("documentsScreenName_"+secondaryLanguage));
-            ScreenSpecDto documentsScreen = new ScreenSpecDto("Documents", docScreenLabel, documents, 3, false);
+            ScreenSpecDto documentsScreen = new ScreenSpecDto("Documents", docScreenLabel, documents, 3, false, false);
             screens.add(documentsScreen);
             Log.i(TAG, "Building documents screen completed");
 
@@ -369,7 +369,7 @@ private IdSchemaResponse migrate115UiSpecToLTSProcessSpec(IdSchemaResponse idSch
             bioScreenLabel.put(primaryLanguage, this.globalParamRepository.getCachedStringGlobalParam("biometricsScreenName_"+primaryLanguage));
             if (secondaryLanguage != null)
                 bioScreenLabel.put(secondaryLanguage, this.globalParamRepository.getCachedStringGlobalParam("biometricsScreenName_"+secondaryLanguage));
-            ScreenSpecDto biometricsScreen = new ScreenSpecDto("BiometricDetails", bioScreenLabel, biometrics, 4, false);
+            ScreenSpecDto biometricsScreen = new ScreenSpecDto("BiometricDetails", bioScreenLabel, biometrics, 4, false, false);
             screens.add(biometricsScreen);
             Log.i(TAG, "Building biometrics screen completed");
 
diff --git a/android/clientmanager/src/main/java/io/mosip/registration/clientmanager/repository/RegistrationRepository.java b/android/clientmanager/src/main/java/io/mosip/registration/clientmanager/repository/RegistrationRepository.java
index 29b1eb236..f11505b8d 100644
--- a/android/clientmanager/src/main/java/io/mosip/registration/clientmanager/repository/RegistrationRepository.java
+++ b/android/clientmanager/src/main/java/io/mosip/registration/clientmanager/repository/RegistrationRepository.java
@@ -67,7 +67,7 @@ public void updateStatus(String packetId, String serverStatus, String clientStat
     }
 
     public Registration insertRegistration(String packetId, String containerPath, String centerId,
-                                           String registrationType, JSONObject additionalInfo) throws Exception {
+                                           String registrationType, JSONObject additionalInfo, String additionalInfoReqId, String rid) throws Exception {
         Registration registration = new Registration(packetId);
         registration.setFilePath(containerPath);
         registration.setRegType(registrationType);
@@ -76,8 +76,10 @@ public Registration insertRegistration(String packetId, String containerPath, St
         registration.setServerStatus(null);
         registration.setCrDtime(System.currentTimeMillis());
         registration.setCrBy("110006");
+        registration.setId(rid);
         //TODO use objectMapper
         registration.setAdditionalInfo(additionalInfo.toString().getBytes(StandardCharsets.UTF_8));
+        registration.setAdditionalInfoReqId(additionalInfoReqId);
         this.registrationDao.insert(registration);
         return registration;
     }
diff --git a/android/clientmanager/src/main/java/io/mosip/registration/clientmanager/service/Biometrics095Service.java b/android/clientmanager/src/main/java/io/mosip/registration/clientmanager/service/Biometrics095Service.java
index c0c2d7ee2..b22bc55a9 100644
--- a/android/clientmanager/src/main/java/io/mosip/registration/clientmanager/service/Biometrics095Service.java
+++ b/android/clientmanager/src/main/java/io/mosip/registration/clientmanager/service/Biometrics095Service.java
@@ -13,7 +13,10 @@
 import java.io.InputStream;
 import java.util.ArrayList;
 import java.util.Base64;
+import java.util.HashMap;
+import java.util.LinkedHashMap;
 import java.util.List;
+import java.util.Map;
 
 import javax.inject.Inject;
 
@@ -66,6 +69,7 @@ public class Biometrics095Service extends BiometricsService {
     private final UserBiometricRepository userBiometricRepository;
     private IBioApiV2 iBioApiV2;
     SharedPreferences sharedPreferences;
+    public Map BIO_DEVICES;
 
 
     @Inject
@@ -78,6 +82,7 @@ public Biometrics095Service(Context context, ObjectMapper objectMapper,
         this.clientCryptoManagerService = clientCryptoManagerService;
         this.userBiometricRepository = userBiometricRepository;
         this.iBioApiV2 = new MatchSDK();
+        this.BIO_DEVICES = new HashMap<>();
         sharedPreferences = this.context.getSharedPreferences(
                 this.context.getString(R.string.app_name),
                 Context.MODE_PRIVATE);
@@ -193,6 +198,7 @@ public String[] handleDeviceInfoResponse(Modality modality, byte[] response) thr
             byte[] decodedDigitalIdPayload = Base64.getUrlDecoder().decode(digitalIdPayload);
             DigitalId digitalId = objectMapper.readValue(decodedDigitalIdPayload, DigitalId.class);
             serialNo = digitalId.getSerialNo();
+            addBioDevice(modality, deviceDto.getDeviceCode(), digitalId);
         } catch (BiometricsServiceException e) {
             auditManagerService.audit(AuditEvent.DEVICE_INFO_PARSE_FAILED, Components.REGISTRATION, e.getMessage());
             Toast.makeText(context, "No SBI found!", Toast.LENGTH_LONG).show();
@@ -291,4 +297,20 @@ public void validateJWTResponse(final String signedData, final String domain)
         }
     }
 
+    public void addBioDevice(Modality modality, String deviceCode, DigitalId digitalId) {
+        Map registeredDevice = new LinkedHashMap<>();
+        Map digitalIdMap = new HashMap<>();
+        digitalIdMap.put("serialNo", digitalId.getSerialNo());
+        digitalIdMap.put("make", digitalId.getMake());
+        digitalIdMap.put("model", digitalId.getModel());
+        digitalIdMap.put("type", digitalId.getType());
+        digitalIdMap.put("deviceProviderId", digitalId.getDeviceProviderId());
+        digitalIdMap.put("deviceProvider", digitalId.getDeviceProvider());
+        digitalIdMap.put("dateTime", digitalId.getDateTime());
+        digitalIdMap.put("deviceSubType", digitalId.getDeviceSubType());
+        registeredDevice.put("deviceServiceVersion", "0.9.5");
+        registeredDevice.put("digitalId", digitalIdMap);
+        registeredDevice.put("deviceCode", deviceCode);
+        BIO_DEVICES.put(modality, registeredDevice);
+    }
 }
diff --git a/android/clientmanager/src/main/java/io/mosip/registration/clientmanager/service/PacketServiceImpl.java b/android/clientmanager/src/main/java/io/mosip/registration/clientmanager/service/PacketServiceImpl.java
index a4c228425..8d31c65b7 100644
--- a/android/clientmanager/src/main/java/io/mosip/registration/clientmanager/service/PacketServiceImpl.java
+++ b/android/clientmanager/src/main/java/io/mosip/registration/clientmanager/service/PacketServiceImpl.java
@@ -132,7 +132,7 @@ public void syncRegistration(@NonNull String packetId, AsyncPacketTaskCallBack c
         wrapper.setVersion(PACKET_SYNC_VERSION);
         wrapper.setRequest(new ArrayList());
         SyncRIDRequest syncRIDRequest = new SyncRIDRequest();
-        syncRIDRequest.setRegistrationId(registration.getPacketId());
+        syncRIDRequest.setRegistrationId(registration.getId());
         syncRIDRequest.setRegistrationType(registration.getRegType().toUpperCase());
         if (!serverVersion.startsWith(SERVER_VERSION_1_1_5)) {
             syncRIDRequest.setPacketId(registration.getPacketId());
@@ -301,7 +301,7 @@ public void syncAllPacketStatus() {
         for (Registration reg : registrations) {
             PacketIdDto packet = new PacketIdDto();
             if (serverVersion!=null && serverVersion.startsWith(SERVER_VERSION_1_1_5)) {
-                packet.setRegistrationId(reg.getPacketId());
+                packet.setRegistrationId(reg.getId());
             } else {
                 packet.setPacketId(reg.getPacketId());
             }
diff --git a/android/clientmanager/src/main/java/io/mosip/registration/clientmanager/service/RegistrationServiceImpl.java b/android/clientmanager/src/main/java/io/mosip/registration/clientmanager/service/RegistrationServiceImpl.java
index 5031bcf62..49cee2254 100644
--- a/android/clientmanager/src/main/java/io/mosip/registration/clientmanager/service/RegistrationServiceImpl.java
+++ b/android/clientmanager/src/main/java/io/mosip/registration/clientmanager/service/RegistrationServiceImpl.java
@@ -1,6 +1,7 @@
 package io.mosip.registration.clientmanager.service;
 
 import static io.mosip.registration.keymanager.util.KeyManagerConstant.EMPTY;
+import static io.mosip.registration.packetmanager.util.PacketManagerConstant.OTHER_KEY_CONFIGURED;
 import static io.mosip.registration.packetmanager.util.PacketManagerConstant.OTHER_KEY_EXCEPTION;
 import static io.mosip.registration.packetmanager.util.PacketManagerConstant.OTHER_KEY_FORCE_CAPTURED;
 import static io.mosip.registration.packetmanager.util.PacketManagerConstant.OTHER_KEY_PAYLOAD;
@@ -12,6 +13,7 @@
 import android.content.SharedPreferences;
 import android.util.Log;
 
+import com.fasterxml.jackson.databind.ObjectMapper;
 import com.tom_roush.pdfbox.pdmodel.PDDocument;
 import com.tom_roush.pdfbox.pdmodel.PDPage;
 import com.tom_roush.pdfbox.pdmodel.PDPageContentStream;
@@ -29,6 +31,7 @@
 import java.time.ZoneOffset;
 import java.util.ArrayList;
 import java.util.Arrays;
+import java.util.Collections;
 import java.util.HashMap;
 import java.util.LinkedHashMap;
 import java.util.LinkedList;
@@ -76,6 +79,7 @@
 import io.mosip.registration.packetmanager.dto.PacketWriter.BiometricRecord;
 import io.mosip.registration.packetmanager.dto.PacketWriter.BiometricType;
 import io.mosip.registration.packetmanager.dto.PacketWriter.Document;
+import io.mosip.registration.packetmanager.dto.PacketWriter.PacketInfo;
 import io.mosip.registration.packetmanager.dto.SimpleType;
 import io.mosip.registration.packetmanager.spi.PacketWriterService;
 import io.mosip.registration.packetmanager.util.DateUtils;
@@ -102,6 +106,8 @@ public class RegistrationServiceImpl implements RegistrationService {
     private AuditManagerService auditManagerService;
     public static final String BOOLEAN_FALSE = "false";
 
+    private Biometrics095Service biometricService;
+
     @Inject
     public RegistrationServiceImpl(Context context, PacketWriterService packetWriterService,
                                    RegistrationRepository registrationRepository,
@@ -110,7 +116,7 @@ public RegistrationServiceImpl(Context context, PacketWriterService packetWriter
                                    ClientCryptoManagerService clientCryptoManagerService,
                                    KeyStoreRepository keyStoreRepository,
                                    GlobalParamRepository globalParamRepository,
-                                   AuditManagerService auditManagerService) {
+                                   AuditManagerService auditManagerService, Biometrics095Service biometricService) {
         this.context = context;
         this.registrationDto = null;
         this.packetWriterService = packetWriterService;
@@ -121,6 +127,7 @@ public RegistrationServiceImpl(Context context, PacketWriterService packetWriter
         this.keyStoreRepository = keyStoreRepository;
         this.globalParamRepository = globalParamRepository;
         this.auditManagerService = auditManagerService;
+        this.biometricService = biometricService;
     }
 
     @Override
@@ -188,7 +195,11 @@ public void submitRegistrationDto(String makerName) throws Exception {
         if (this.registrationDto == null) {
             throw new ClientCheckedException(context, R.string.err_004);
         }
-
+        if (this.registrationDto.getAdditionalInfoRequestId() != null) {
+            String newAppId = this.registrationDto.getAdditionalInfoRequestId().split("-")[0];
+            this.registrationDto.setApplicationId(newAppId);
+            this.registrationDto.setRId(newAppId);
+        }
         List selectedHandles = this.globalParamRepository.getSelectedHandles();
         if(selectedHandles != null) {
             if (this.registrationDto.getFlowType().equals("NEW") ||
@@ -225,6 +236,7 @@ public void submitRegistrationDto(String makerName) throws Exception {
                 document.setDocument(("pdf".equalsIgnoreCase(entry.getValue().getFormat()))?combineByteArray(entry.getValue().getContent()):convertImageToPDF(entry.getValue().getContent()));
                 Log.i(TAG, entry.getKey() + " >> PDF document size :" + document.getDocument().length);
                 packetWriterService.setDocument(this.registrationDto.getRId(), entry.getKey(), document);
+                packetWriterService.addMetaInfo(this.registrationDto.getRId(),"documents", document);
             });
 
             if (serverVersion!=null && serverVersion.startsWith("1.1.5")) {
@@ -239,17 +251,13 @@ public void submitRegistrationDto(String makerName) throws Exception {
                 });
             }
 
-            this.registrationDto.CAPTURED_BIO_FIELDS.forEach( field -> {
-                BiometricRecord biometricRecord = getBiometricRecord(field, serverVersion);
-                biometricRecord.getSegments().removeIf(Objects::isNull);
-                packetWriterService.setBiometric(this.registrationDto.getRId(), field, biometricRecord);
-            });
+            // Process biometrics and add metadata to packet
+            setBiometrics(this.registrationDto);
 
             CenterMachineDto centerMachineDto = this.masterDataService.getRegistrationCenterMachineDetails();
 
             packetWriterService.addAudits(this.registrationDto.getRId(), getAudits());
             addMetaInfoMap(centerMachineDto.getCenterId(), centerMachineDto.getMachineId(), makerName);
-
             String containerPath = packetWriterService.persistPacket(this.registrationDto.getRId(),
                     this.registrationDto.getSchemaVersion().toString(),
                     identitySchemaRepository.getSchemaJson(context, this.registrationDto.getSchemaVersion()),
@@ -257,10 +265,10 @@ public void submitRegistrationDto(String makerName) throws Exception {
                     this.registrationDto.getProcess(),
                     true, centerMachineDto.getMachineRefId());
 
-            Log.i(TAG, "Packet created : " + containerPath);
-
-            if (containerPath == null || containerPath.trim().isEmpty()) {
-                throw new ClientCheckedException(context, R.string.err_005);
+            if (containerPath != null || !containerPath.trim().isEmpty()) {
+               String packetId = containerPath.substring(containerPath.lastIndexOf("/") + 1);
+               packetId = packetId.replace(".zip", "");
+               this.registrationDto.setPacketId(packetId);
             }
 
             JSONObject additionalInfo = new JSONObject();
@@ -282,9 +290,9 @@ public void submitRegistrationDto(String makerName) throws Exception {
             additionalInfo.put("name", String.join(" ", fullName));
             additionalInfo.put("email", getAdditionalInfo(emailObj));
             additionalInfo.put("phone", getAdditionalInfo(phoneObj));
-            
-            registrationRepository.insertRegistration(this.registrationDto.getRId(), containerPath,
-                    centerMachineDto.getCenterId(), this.registrationDto.getProcess(), additionalInfo);
+
+            registrationRepository.insertRegistration(this.registrationDto.getPacketId(), containerPath,
+                    centerMachineDto.getCenterId(), this.registrationDto.getProcess(), additionalInfo, this.registrationDto.getAdditionalInfoRequestId(), this.registrationDto.getRId());
 
 //        } finally {
             clearRegistration();
@@ -411,7 +419,9 @@ private void addMetaInfoMap(String centerId, String machineId, String makerId) t
         metaData.put(PacketManagerConstant.META_CENTER_ID, centerId);
         metaData.put(PacketManagerConstant.META_KEYINDEX, this.clientCryptoManagerService.getClientKeyIndex());
         metaData.put(PacketManagerConstant.META_REGISTRATION_ID, rid);
-        metaData.put(PacketManagerConstant.META_APPLICATION_ID, rid);
+        String appIdForMeta = this.registrationDto.getApplicationId() == null || this.registrationDto.getApplicationId().trim().isEmpty()
+                ? rid : this.registrationDto.getApplicationId();
+        metaData.put(PacketManagerConstant.META_APPLICATION_ID, appIdForMeta);
         metaData.put(PacketManagerConstant.META_CREATION_DATE,
                 DateUtils.formatToISOString(LocalDateTime.now(ZoneOffset.UTC)));
         metaData.put(PacketManagerConstant.META_CLIENT_VERSION, BuildConfig.CLIENT_VERSION);
@@ -442,9 +452,16 @@ private void addMetaInfoMap(String centerId, String machineId, String makerId) t
 
         //biometric device details
         List> capturedRegisteredDevices = new ArrayList<>();
-        for(Modality modality : this.registrationDto.BIO_DEVICES.keySet()) {
-            capturedRegisteredDevices.add((Map) this.registrationDto.BIO_DEVICES.get(modality));
+        for(Modality modality : this.biometricService.BIO_DEVICES.keySet()) {
+            Map deviceInfo = (Map) this.biometricService.BIO_DEVICES.get(modality);
+            if (deviceInfo != null) {
+                capturedRegisteredDevices.add(deviceInfo);
+            } else {
+                Log.w(TAG, "Device info is null for modality: " + modality);
+            }
         }
+
+
         packetWriterService.addMetaInfo(rid, "capturedRegisteredDevices", capturedRegisteredDevices);
     }
 
@@ -623,4 +640,50 @@ private int getAttemptsCount(Modality modality) {
         }
         return 0;
     }
+
+    private void setBiometrics(RegistrationDto registrationDto) throws RegBaseCheckedException {
+        Map> capturedBiometrics = new HashMap<>();
+        Map> capturedMetaInfo = new LinkedHashMap<>();
+        Map> exceptionMetaInfo = new LinkedHashMap<>();
+
+        for(String key : registrationDto.getBiometrics().keySet()) {
+            String fieldId = key.split("_")[0];
+            String bioAttribute = key.split("_")[1];
+            BIR bir = buildBIR(registrationDto.getBiometrics().get(key));
+            if (!capturedBiometrics.containsKey(fieldId)) {
+                capturedBiometrics.put(fieldId, new ArrayList<>());
+            }
+            capturedBiometrics.get(fieldId).add(bir);
+            if (!capturedMetaInfo.containsKey(fieldId)) {
+                capturedMetaInfo.put(fieldId, new HashMap<>());
+            }
+            Map metaInfo = new HashMap<>();
+            metaInfo.put("numOfRetries", registrationDto.getBiometrics().get(key).getNumOfRetries());
+            metaInfo.put("isForceCaptured", registrationDto.getBiometrics().get(key).isForceCaptured());
+            metaInfo.put("index", bir.getBdbInfo().getIndex());
+            capturedMetaInfo.get(fieldId).put(bioAttribute, metaInfo);
+        }
+
+        for(String key : registrationDto.EXCEPTIONS.keySet()) {
+            String fieldId = key.split("_")[0];
+            String bioAttribute = key.split("_")[1];
+            BIR bir = buildBIR(new BiometricsDto(null, bioAttribute, null, null, true, null, null, false, 0, 0.0, 0.0f));
+            capturedBiometrics.getOrDefault(fieldId, new ArrayList<>()).add(bir);
+            exceptionMetaInfo.computeIfAbsent(fieldId, field -> new HashMap<>()).put(bioAttribute,
+                    registrationDto.EXCEPTIONS.get(key));
+        }
+
+        capturedBiometrics.keySet().forEach(fieldId -> {
+            BiometricRecord biometricRecord = new BiometricRecord();
+            biometricRecord.setOthers(new HashMap<>());
+            biometricRecord.getOthers().put(OTHER_KEY_CONFIGURED, String.join(",",
+                    registrationDto.CAPTURED_BIO_FIELDS.contains(fieldId) ? Collections.singletonList(fieldId) : Collections.EMPTY_LIST));
+            biometricRecord.setSegments(capturedBiometrics.get(fieldId));
+            Log.d(TAG, "Adding biometric to packet manager for field : " + fieldId);
+            packetWriterService.setBiometric(registrationDto.getRId(), fieldId, biometricRecord);
+        });
+
+        packetWriterService.addMetaInfo(registrationDto.getRId(), "biometrics", capturedMetaInfo);
+        packetWriterService.addMetaInfo(registrationDto.getRId(), "exceptionBiometrics", exceptionMetaInfo);
+    }
 }
diff --git a/android/clientmanager/src/test/java/io/mosip/registration/clientmanager/repository/RegistrationRepositoryTest.java b/android/clientmanager/src/test/java/io/mosip/registration/clientmanager/repository/RegistrationRepositoryTest.java
index ce316116d..372e123bc 100644
--- a/android/clientmanager/src/test/java/io/mosip/registration/clientmanager/repository/RegistrationRepositoryTest.java
+++ b/android/clientmanager/src/test/java/io/mosip/registration/clientmanager/repository/RegistrationRepositoryTest.java
@@ -121,7 +121,7 @@ public void testInsertRegistration() throws Exception {
 
         // Execute method
         Registration result = registrationRepository.insertRegistration("10001155851003120250220055513", "/path/to/container",
-                "10011", "NEW", mockJson);
+                "10011", "NEW", mockJson, "", "");
 
         // Capture inserted object
         ArgumentCaptor captor = ArgumentCaptor.forClass(Registration.class);
diff --git a/android/clientmanager/src/test/java/io/mosip/registration/clientmanager/service/RegistrationServiceImplTest.java b/android/clientmanager/src/test/java/io/mosip/registration/clientmanager/service/RegistrationServiceImplTest.java
index b0c795438..3183af700 100644
--- a/android/clientmanager/src/test/java/io/mosip/registration/clientmanager/service/RegistrationServiceImplTest.java
+++ b/android/clientmanager/src/test/java/io/mosip/registration/clientmanager/service/RegistrationServiceImplTest.java
@@ -75,6 +75,9 @@ public class RegistrationServiceImplTest {
     private ClientCryptoManagerService clientCryptoManagerService;
     private RegistrationService registrationService;
 
+    @Mock
+    private Biometrics095Service biometricService;
+
     @Before
     public void setUp() {
         MockitoAnnotations.openMocks(this);
@@ -84,7 +87,7 @@ public void setUp() {
         when(mockApplicationContext.getSharedPreferences(anyString(), anyInt())).thenReturn(mockSharedPreferences);
         registrationService = new RegistrationServiceImpl(mockApplicationContext, packetWriterService,
                 registrationRepository, masterDataService, identitySchemaRepository, clientCryptoManagerService,
-                keyStoreRepository, globalParamRepository, auditManagerService);
+                keyStoreRepository, globalParamRepository, auditManagerService, biometricService);
     }
     
     @Test(expected = ClientCheckedException.class)
@@ -683,7 +686,7 @@ public void testSubmitRegistrationDto_UpdateFlow_UINField() throws Exception {
         when(identitySchemaRepository.getSchemaJson(Mockito.any(), Mockito.anyDouble())).thenReturn("{}");
         when(packetWriterService.persistPacket(Mockito.anyString(), Mockito.anyString(), Mockito.anyString(), Mockito.anyString(), Mockito.anyString(), Mockito.anyBoolean(), Mockito.anyString())).thenReturn("containerPath123");
         Registration mockRegistration = mock(Registration.class);
-        when(registrationRepository.insertRegistration(Mockito.anyString(), Mockito.anyString(), Mockito.anyString(), Mockito.anyString(), Mockito.any())).thenReturn(mockRegistration);
+        when(registrationRepository.insertRegistration(Mockito.anyString(), Mockito.anyString(), Mockito.anyString(), Mockito.anyString(), Mockito.any(), "", "")).thenReturn(mockRegistration);
 
         registrationService.submitRegistrationDto("makerName");
         Mockito.verify(packetWriterService).setField("RID456", "UIN", "uinValue");
@@ -724,7 +727,7 @@ public void testSubmitRegistrationDto_NewFlow_AllFields() throws Exception {
         when(identitySchemaRepository.getSchemaJson(Mockito.any(), Mockito.anyDouble())).thenReturn("{}");
         when(packetWriterService.persistPacket(Mockito.anyString(), Mockito.anyString(), Mockito.anyString(), Mockito.anyString(), Mockito.anyString(), Mockito.anyBoolean(), Mockito.anyString())).thenReturn("containerPath123");
         Registration mockRegistration = mock(Registration.class);
-        when(registrationRepository.insertRegistration(Mockito.anyString(), Mockito.anyString(), Mockito.anyString(), Mockito.anyString(), Mockito.any())).thenReturn(mockRegistration);
+        when(registrationRepository.insertRegistration(Mockito.anyString(), Mockito.anyString(), Mockito.anyString(), Mockito.anyString(), Mockito.any(), "", "")).thenReturn(mockRegistration);
 
         registrationService.submitRegistrationDto("makerName");
         Mockito.verify(packetWriterService).setField("RID789", "field1", "value1");
@@ -765,7 +768,7 @@ public void testSubmitRegistrationDto_CorrectionFlow() throws Exception {
         when(identitySchemaRepository.getSchemaJson(Mockito.any(), Mockito.anyDouble())).thenReturn("{}");
         when(packetWriterService.persistPacket(Mockito.anyString(), Mockito.anyString(), Mockito.anyString(), Mockito.anyString(), Mockito.anyString(), Mockito.anyBoolean(), Mockito.anyString())).thenReturn("containerPath123");
         Registration mockRegistration = mock(Registration.class);
-        when(registrationRepository.insertRegistration(Mockito.anyString(), Mockito.anyString(), Mockito.anyString(), Mockito.anyString(), Mockito.any())).thenReturn(mockRegistration);
+        when(registrationRepository.insertRegistration(Mockito.anyString(), Mockito.anyString(), Mockito.anyString(), Mockito.anyString(), Mockito.any(), "", "")).thenReturn(mockRegistration);
 
         registrationService.submitRegistrationDto("makerName");
         Mockito.verify(packetWriterService).setField("RID999", "field2", "value2");
@@ -806,7 +809,7 @@ public void testSubmitRegistrationDto_LostFlow() throws Exception {
         when(identitySchemaRepository.getSchemaJson(Mockito.any(), Mockito.anyDouble())).thenReturn("{}");
         when(packetWriterService.persistPacket(Mockito.anyString(), Mockito.anyString(), Mockito.anyString(), Mockito.anyString(), Mockito.anyString(), Mockito.anyBoolean(), Mockito.anyString())).thenReturn("containerPath123");
         Registration mockRegistration = mock(Registration.class);
-        when(registrationRepository.insertRegistration(Mockito.anyString(), Mockito.anyString(), Mockito.anyString(), Mockito.anyString(), Mockito.any())).thenReturn(mockRegistration);
+        when(registrationRepository.insertRegistration(Mockito.anyString(), Mockito.anyString(), Mockito.anyString(), Mockito.anyString(), Mockito.any(), "", "")).thenReturn(mockRegistration);
 
         registrationService.submitRegistrationDto("makerName");
         Mockito.verify(packetWriterService).setField("RID888", "field3", "value3");
@@ -1070,7 +1073,7 @@ public void testSubmitRegistrationDto_SelectedHandles_UpdateFlow() throws Except
         when(identitySchemaRepository.getSchemaJson(Mockito.any(), Mockito.anyDouble())).thenReturn("{}");
         when(packetWriterService.persistPacket(Mockito.anyString(), Mockito.anyString(), Mockito.anyString(), Mockito.anyString(), Mockito.anyString(), Mockito.anyBoolean(), Mockito.anyString())).thenReturn("containerPath123");
         Registration mockRegistration = mock(Registration.class);
-        when(registrationRepository.insertRegistration(Mockito.anyString(), Mockito.anyString(), Mockito.anyString(), Mockito.anyString(), Mockito.any())).thenReturn(mockRegistration);
+        when(registrationRepository.insertRegistration(Mockito.anyString(), Mockito.anyString(), Mockito.anyString(), Mockito.anyString(), Mockito.any(), "", "")).thenReturn(mockRegistration);
 
         registrationService.submitRegistrationDto("makerName");
         Mockito.verify(packetWriterService).setField("RID123", "UIN", "uinValue");
diff --git a/android/packetmanager/src/main/java/io/mosip/registration/packetmanager/service/PacketWriterServiceImpl.java b/android/packetmanager/src/main/java/io/mosip/registration/packetmanager/service/PacketWriterServiceImpl.java
index 734954ce7..672875e4e 100644
--- a/android/packetmanager/src/main/java/io/mosip/registration/packetmanager/service/PacketWriterServiceImpl.java
+++ b/android/packetmanager/src/main/java/io/mosip/registration/packetmanager/service/PacketWriterServiceImpl.java
@@ -13,7 +13,10 @@
 import java.io.ByteArrayOutputStream;
 import java.io.IOException;
 import java.security.NoSuchAlgorithmException;
+import java.time.LocalDateTime;
 import java.time.OffsetDateTime;
+import java.time.ZoneId;
+import java.time.format.DateTimeFormatter;
 import java.util.*;
 import java.util.zip.ZipEntry;
 import java.util.zip.ZipOutputStream;
@@ -65,6 +68,7 @@ public class PacketWriterServiceImpl implements PacketWriterService {
     private String defaultProviderVersion;
     private Context context;
     private String timeFormat;
+    private String zipDatetimePattern = "yyyyMMddHHmmss";
 
     @Inject
     public PacketWriterServiceImpl(Context appContext, PacketManagerHelper packetManagerHelper,
@@ -72,6 +76,10 @@ public PacketWriterServiceImpl(Context appContext, PacketManagerHelper packetMan
         this.context = appContext;
         this.packetKeeper = packetKeeper;
         this.packetManagerHelper = packetManagerHelper;
+        String pattern = ConfigService.getProperty("packetmanager.zip.datetime.pattern", context);
+        if (pattern != null && !pattern.isEmpty()) {
+            this.zipDatetimePattern = pattern;
+        }
     }
 
     public RegistrationPacket initialize(String id) {
@@ -129,11 +137,20 @@ public String persistPacket(String id, String version, String schemaJson, String
         return null;
     }
 
+    private String generatePacketId(String id, String refId) {
+        return id + "-" + refId + "-" + this.getCurrentTimeStamp();
+    }
+
+    private String getCurrentTimeStamp() {
+        DateTimeFormatter format = DateTimeFormatter.ofPattern(this.zipDatetimePattern);
+        return LocalDateTime.now(ZoneId.of("UTC")).format(format);
+    }
+
     private String createPacket(String id, String version, String schemaJson, String source, String process, boolean offlineMode, String refId) throws Exception {
-        Log.i(TAG, "Started packet creation");
 
         if (this.registrationPacket == null || !registrationPacket.getRegistrationId().equalsIgnoreCase(id))
             throw new Exception("Registration packet is null or registration id does not exists");
+            String packetId = generatePacketId(id, refId);
 
         String containerPath = null;
         Map> identityProperties = loadSchemaFields(schemaJson);
@@ -141,7 +158,6 @@ private String createPacket(String id, String version, String schemaJson, String
         try {
             int counter = 1;
             for (String subPacketName : identityProperties.keySet()) {
-                Log.i(TAG, "Started Subpacket: " + subPacketName);
 
                 List schemaFields = identityProperties.get(subPacketName);
                 byte[] subpacketBytes = createSubpacket(Double.valueOf(version), schemaFields, defaultSubpacketName.equalsIgnoreCase(subPacketName),
@@ -150,7 +166,7 @@ private String createPacket(String id, String version, String schemaJson, String
                 PacketInfo packetInfo = new PacketInfo();
                 packetInfo.setProviderName(this.getClass().getSimpleName());
                 packetInfo.setSchemaVersion(new Double(version).toString());
-                packetInfo.setId(id);
+                packetInfo.setId(packetId);
                 packetInfo.setRefId(refId);
                 packetInfo.setSource(source);
                 packetInfo.setProcess(process);
@@ -162,12 +178,11 @@ private String createPacket(String id, String version, String schemaJson, String
                 packet.setPacketInfo(packetInfo);
                 packet.setPacket(subpacketBytes);
                 packetKeeper.putPacket(packet);
-                Log.i(TAG, "Completed SubPacket Creation");
 
                 if (counter == identityProperties.keySet().size()) {
                     containerPath = packetKeeper.pack(packetInfo.getId(), packetInfo.getSource(), packetInfo.getProcess(), refId);
                     if (containerPath == null) {
-                        packetKeeper.deletePacket(id, source, process);
+                        packetKeeper.deletePacket(packetId, source, process);
                         throw new Exception("Failed to pack the created zip");
                     }
                 }
@@ -181,7 +196,6 @@ private String createPacket(String id, String version, String schemaJson, String
         } finally {
             this.registrationPacket = null;
         }
-        Log.i(TAG, "Exiting packet creation");
         return containerPath;
     }
 
diff --git a/assets/l10n/app_ar.arb b/assets/l10n/app_ar.arb
index e114d1ca5..c89887c53 100644
--- a/assets/l10n/app_ar.arb
+++ b/assets/l10n/app_ar.arb
@@ -326,5 +326,7 @@
   "no_configuration_parameters_found": "لم يتم العثور على معلمات التكوين",
   "no_configurations_found": "لم يتم العثور على أي تكوين",
   "confirm": "تأكيد",
-  "scan_now": "امسح الآن"
+  "scan_now": "امسح الآن",
+  "enter_additional_info_req_id": "أدخل معرف طلب المعلومات الإضافية",
+  "additional_info_req_id": "معرف طلب المعلومات الإضافية"
 }
\ No newline at end of file
diff --git a/assets/l10n/app_en.arb b/assets/l10n/app_en.arb
index 7a8da0e4f..c5724267a 100644
--- a/assets/l10n/app_en.arb
+++ b/assets/l10n/app_en.arb
@@ -326,5 +326,7 @@
   "no_configuration_parameters_found": "No configuration parameters found",
   "no_configurations_found": "No configurations found",
   "confirm": "CONFIRM",
-  "scan_now": "Scan Now"
+  "scan_now": "Scan Now",
+  "enter_additional_info_req_id": "Enter Additional Info Request ID",
+  "additional_info_req_id": "Additional Info Request ID"
 }
\ No newline at end of file
diff --git a/assets/l10n/app_fr.arb b/assets/l10n/app_fr.arb
index e2b62efdd..7ce39d507 100644
--- a/assets/l10n/app_fr.arb
+++ b/assets/l10n/app_fr.arb
@@ -326,5 +326,7 @@
   "no_configuration_parameters_found": "Aucun paramètre de configuration trouvé",
   "no_configurations_found": "Aucune configuration trouvée",
   "confirm": "Confirmer",
-  "scan_now": "Analyser maintenant"
+  "scan_now": "Analyser maintenant",
+  "enter_additional_info_req_id": "Entrez l'identifiant de la demande d'information supplémentaire",
+  "additional_info_req_id": "Identifiant de la demande d'information supplémentaire"
 }
\ No newline at end of file
diff --git a/assets/l10n/app_hi.arb b/assets/l10n/app_hi.arb
index 5dd313f39..56e70d8ef 100644
--- a/assets/l10n/app_hi.arb
+++ b/assets/l10n/app_hi.arb
@@ -326,5 +326,7 @@
   "no_configuration_parameters_found": "कोई कॉन्फ़िगरेशन पैरामीटर नहीं मिला",
   "no_configurations_found": "कोई कॉन्फ़िगरेशन नहीं मिला",
   "confirm": "पुष्टि करें",
-  "scan_now": "अभी स्कैन करें"
+  "scan_now": "अभी स्कैन करें",
+  "enter_additional_info_req_id": "अतिरिक्त जानकारी अनुरोध आईडी दर्ज करें",
+  "additional_info_req_id": "अतिरिक्त जानकारी अनुरोध आईडी"
 }
\ No newline at end of file
diff --git a/assets/l10n/app_kn.arb b/assets/l10n/app_kn.arb
index 92f0ab57a..8f19e55e8 100644
--- a/assets/l10n/app_kn.arb
+++ b/assets/l10n/app_kn.arb
@@ -326,5 +326,7 @@
   "no_configuration_parameters_found": "ಯಾವುದೇ ಸಂರಚನಾ ನಿಯತಾಂಕಗಳು ಕಂಡುಬರಲಿಲ್ಲ",
   "no_configurations_found": "ಯಾವುದೇ ಸಂರಚನೆಗಳು ಕಂಡುಬರಲಿಲ್ಲ",
   "confirm": "ದೃಢೀಕರಿಸಿ",
-  "scan_now": "ಈಗಸ್ಕ್ಯಾನ್ ಮಾಡಿ"
+  "scan_now": "ಈಗಸ್ಕ್ಯಾನ್ ಮಾಡಿ",
+  "enter_additional_info_req_id": "ಹೆಚ್ಚುವರಿ ಮಾಹಿತಿ ವಿನಂತಿ ಐಡಿ ನಮೂದಿಸಿ",
+  "additional_info_req_id": "ಹೆಚ್ಚುವರಿ ಮಾಹಿತಿ ವಿನಂತಿ ಐಡಿ"
 }
\ No newline at end of file
diff --git a/assets/l10n/app_ta.arb b/assets/l10n/app_ta.arb
index bf417626b..45a99a3b0 100644
--- a/assets/l10n/app_ta.arb
+++ b/assets/l10n/app_ta.arb
@@ -335,5 +335,7 @@
   "no_configuration_parameters_found": "எந்த கட்டமைப்பு அளவுருக்களும் கிடைக்கவில்லை",
   "no_configurations_found": "எந்த கட்டமைப்பும் கிடைக்கவில்லை",
   "confirm": "உறுதிப்படுத்தவும்",
-  "scan_now": "இப்போது ஸ்கேன் செய்யுங்கள்"
+  "scan_now": "இப்போது ஸ்கேன் செய்யுங்கள்",
+  "enter_additional_info_req_id": "கூடுதல் தகவல் கோரிக்கை ஐடியை உள்ளிடவும்",
+  "additional_info_req_id": "கூடுதல் தகவல் கோரிக்கை ஐடி"
 }
\ No newline at end of file
diff --git a/lib/app_router.dart b/lib/app_router.dart
index f75c93e26..9d57ea001 100644
--- a/lib/app_router.dart
+++ b/lib/app_router.dart
@@ -7,6 +7,7 @@
 
 import 'package:flutter/material.dart';
 import 'package:registration_client/ui/process_ui/lost_process.dart';
+import 'package:registration_client/ui/process_ui/correction_process.dart';
 
 import 'package:registration_client/ui/process_ui/new_process.dart';
 
@@ -25,6 +26,7 @@ class AppRouter {
     OnboardLandingPage.route: (context) => const OnboardLandingPage(),
     HomePage.route: (context) => const HomePage(),
     LostProcess.routeName: (context) => const LostProcess(),
+    CorrectionProcess.routeName: (context) => const CorrectionProcess(),
   };
 
   static Route? onUnknownRoute(RouteSettings settings) {
diff --git a/lib/model/registration.dart b/lib/model/registration.dart
index a4009041a..add6962ac 100644
--- a/lib/model/registration.dart
+++ b/lib/model/registration.dart
@@ -36,6 +36,7 @@ class Registration with _$Registration {
   int? crDtime,
   String? updBy,
   int? updDtimes,
+    String? id
   }) = _Registration;
 
   factory Registration.fromJson(Map json) => _$RegistrationFromJson(json);
diff --git a/lib/platform_android/registration_service_impl.dart b/lib/platform_android/registration_service_impl.dart
index 96de4a9f7..6abc6dde2 100644
--- a/lib/platform_android/registration_service_impl.dart
+++ b/lib/platform_android/registration_service_impl.dart
@@ -96,6 +96,17 @@ class RegistrationServiceImpl implements RegistrationService {
       debugPrint('Application ID not added ${e.toString()}');
     }
   }
+
+  @override
+  Future setAdditionalReqId(String additionalReqId) async {
+    try {
+      await RegistrationDataApi().setAdditionalReqId(additionalReqId);
+    } on PlatformException {
+      debugPrint('RegistrationDataApi call failed');
+    } catch (e) {
+      debugPrint('Additional info req ID not added ${e.toString()}');
+    }
+  }
 }
 
 RegistrationService getRegistrationServiceImpl() => RegistrationServiceImpl();
diff --git a/lib/platform_spi/registration_service.dart b/lib/platform_spi/registration_service.dart
index 6eb231190..79f0b61b7 100644
--- a/lib/platform_spi/registration_service.dart
+++ b/lib/platform_spi/registration_service.dart
@@ -17,6 +17,7 @@ abstract class RegistrationService {
       bool isPreview, Map templateValues);
   Future submitRegistrationDto(String makerName);
   Future setApplicationId(String applicationId);
+  Future setAdditionalReqId(String additionalReqId);
 
   factory RegistrationService() => getRegistrationServiceImpl();
 }
diff --git a/lib/provider/global_provider.dart b/lib/provider/global_provider.dart
index 1b00d052d..a3dd231d5 100644
--- a/lib/provider/global_provider.dart
+++ b/lib/provider/global_provider.dart
@@ -40,6 +40,7 @@ class GlobalProvider with ChangeNotifier {
   String _centerName = "";
   String _machineName = "";
   String _preRegId = "";
+  String _additionalInfoReqId = "";
   final formKey = GlobalKey();
   final updateFieldKey = GlobalKey();
   String _updateUINNumber = "";
@@ -168,6 +169,7 @@ class GlobalProvider with ChangeNotifier {
   Map get machineDetails => _machineDetails;
   String get regId => _regId;
   String get preRegId => _preRegId;
+  String get additionalInfoReqId => _additionalInfoReqId;
 
   String get operatorOnboardingAttributes => _operatorOnboardingAttributes;
   set operatorOnboardingAttributes(String value) {
@@ -333,6 +335,11 @@ class GlobalProvider with ChangeNotifier {
     notifyListeners();
   }
 
+  setAdditionalInfoReqId(String value) {
+    _additionalInfoReqId = value;
+    notifyListeners();
+  }
+
   setMachineDetails() async {
     final machine = await machineKeyService.getMachineKeys();
 
diff --git a/lib/provider/registration_task_provider.dart b/lib/provider/registration_task_provider.dart
index d3c9b740d..d73ca4902 100644
--- a/lib/provider/registration_task_provider.dart
+++ b/lib/provider/registration_task_provider.dart
@@ -349,4 +349,8 @@ class RegistrationTaskProvider with ChangeNotifier {
   setApplicationId(String appId) async {
     await registrationService.setApplicationId(appId);
   }
+
+  setAdditionalReqId(String additionalReqId) async {
+    await registrationService.setAdditionalReqId(additionalReqId);
+  }
 }
diff --git a/lib/ui/approve_packet/widget/approve_table.dart b/lib/ui/approve_packet/widget/approve_table.dart
index 5181d90d0..66d7d5e7f 100644
--- a/lib/ui/approve_packet/widget/approve_table.dart
+++ b/lib/ui/approve_packet/widget/approve_table.dart
@@ -181,7 +181,7 @@ class _ApproveTableState extends State {
                         showTemplate();
                         log("show");
                       },
-                      child: Text(regCurrent.packetId,
+                      child: Text(regCurrent.id!,
                           textAlign: TextAlign.center,
                           overflow: TextOverflow.ellipsis,
                           maxLines: 2),
diff --git a/lib/ui/approve_packet/widget/template_bottom_sheet.dart b/lib/ui/approve_packet/widget/template_bottom_sheet.dart
index 73cb706c9..9e6173cc4 100644
--- a/lib/ui/approve_packet/widget/template_bottom_sheet.dart
+++ b/lib/ui/approve_packet/widget/template_bottom_sheet.dart
@@ -67,7 +67,7 @@ class TemplateBottomSheet {
                         context
                             .read()
                             .setWebViewPlusController(controller);
-                        loadHtmlData(controller, regCurrent.packetId);
+                        loadHtmlData(controller, regCurrent.id!);
                       },
                       javascriptMode: JavascriptMode.unrestricted,
                     ),
diff --git a/lib/ui/export_packet/widgets/export_table.dart b/lib/ui/export_packet/widgets/export_table.dart
index 833cc9838..249ca927e 100644
--- a/lib/ui/export_packet/widgets/export_table.dart
+++ b/lib/ui/export_packet/widgets/export_table.dart
@@ -72,7 +72,7 @@ class ExportTable extends StatelessWidget {
               mainAxisAlignment: MainAxisAlignment.spaceEvenly,
               children: [
                 SizedBox(width: tableWidth/35, child:Text("$index.", textAlign: TextAlign.center, )),
-                SizedBox(width: tableWidth/5.5, child: Text(context.watch().matchingPackets[index-1].packetId, textAlign: TextAlign.center,  overflow: TextOverflow.ellipsis,maxLines: 2,)),
+                SizedBox(width: tableWidth/5.5, child: Text(context.watch().matchingPackets[index-1].id!, textAlign: TextAlign.center,  overflow: TextOverflow.ellipsis,maxLines: 2,)),
                 SizedBox(width: tableWidth/9, child: Text(formattedDate,textAlign: TextAlign.center, overflow: TextOverflow.ellipsis, maxLines: 2,)),
                 SizedBox(width: tableWidth/15, child:Text(context.watch().matchingPackets[index-1].regType.toString(), textAlign: TextAlign.center, overflow: TextOverflow.ellipsis,maxLines: 2,)),
                 SizedBox(width: tableWidth/9, child: Text(context.watch().matchingPackets[index-1].clientStatus.toString(),textAlign: TextAlign.center, overflow: TextOverflow.ellipsis,maxLines: 2,)),
diff --git a/lib/ui/onboard/home_page.dart b/lib/ui/onboard/home_page.dart
index f50936ff5..df5c72846 100644
--- a/lib/ui/onboard/home_page.dart
+++ b/lib/ui/onboard/home_page.dart
@@ -116,9 +116,10 @@ class _HomePageState extends State {
   Widget getProcessUI(BuildContext context, Process process) {
     List sortedScreens;
     sortedScreens = process.screens!.toList()..sort((e1, e2) => e1!.order!.compareTo(e2!.order!));
-    if (process.id == "NEW" || process.id == "UPDATE" || process.id == "LOST") {
+    if (process.flow == "NEW" || process.flow == "UPDATE" || process.flow == "LOST" || process.flow == "CORRECTION") {
       globalProvider.clearRegistrationProcessData();
       globalProvider.setPreRegistrationId("");
+      globalProvider.setAdditionalInfoReqId("");
       for (var screen in sortedScreens) {
         for (var field in screen!.fields!) {
           if (field!.controlType == 'dropdown' &&
diff --git a/lib/ui/process_ui/correction_process.dart b/lib/ui/process_ui/correction_process.dart
new file mode 100644
index 000000000..b2f2e7835
--- /dev/null
+++ b/lib/ui/process_ui/correction_process.dart
@@ -0,0 +1,1002 @@
+import 'dart:convert';
+
+import 'package:flutter/material.dart';
+import 'package:flutter/services.dart';
+import 'package:flutter_screenutil/flutter_screenutil.dart';
+import 'package:flutter_svg/svg.dart';
+import 'package:provider/provider.dart';
+import 'package:registration_client/model/process.dart';
+import 'package:registration_client/model/screen.dart';
+import 'package:registration_client/provider/global_provider.dart';
+import 'package:registration_client/provider/registration_task_provider.dart';
+import 'package:registration_client/ui/post_registration/acknowledgement_page.dart';
+import 'package:registration_client/ui/post_registration/preview_page.dart';
+import 'package:registration_client/ui/process_ui/widgets/new_process_screen_content.dart';
+import 'package:registration_client/utils/app_config.dart';
+import 'package:flutter_gen/gen_l10n/app_localizations.dart';
+import 'package:registration_client/utils/app_style.dart';
+
+import '../../model/biometric_attribute_data.dart';
+import '../../pigeon/biometrics_pigeon.dart';
+import '../../pigeon/demographics_data_pigeon.dart';
+import '../../pigeon/registration_data_pigeon.dart';
+import '../../provider/auth_provider.dart';
+
+class CorrectionProcess extends StatefulWidget {
+  const CorrectionProcess({super.key});
+
+  static const routeName = '/correction_process';
+
+  @override
+  State createState() => _CorrectionProcessState();
+}
+
+class _CorrectionProcessState extends State with WidgetsBindingObserver {
+  late GlobalProvider globalProvider;
+  late RegistrationTaskProvider registrationTaskProvider;
+  late AuthProvider authProvider;
+  late AppLocalizations appLocalizations = AppLocalizations.of(context)!;
+  bool isPortrait = true;
+
+  List postRegistrationTabs = [
+    'Preview',
+    'Authentication',
+    'Acknowledgement',
+  ];
+
+  Map? templateTitleMap;
+
+  String username = '';
+  String password = '';
+
+  @override
+  void initState() {
+    globalProvider = Provider.of(context, listen: false);
+    registrationTaskProvider = Provider.of(context, listen: false);
+    authProvider = Provider.of(context, listen: false);
+    super.initState();
+  }
+
+  @override
+  void dispose() {
+    WidgetsBinding.instance.removeObserver(this);
+    super.dispose();
+  }
+
+  _authenticatePacket(BuildContext context) async {
+    if (!_validateUsername(context)) {
+      return false;
+    }
+
+    if (!_validatePassword(context)) {
+      return false;
+    }
+
+    if (authProvider.currentUser.userId != username) {
+      _showInSnackBar(appLocalizations.invalid_user);
+      return false;
+    }
+
+    await authProvider.authenticatePacket(username, password);
+
+    if (!authProvider.isPacketAuthenticated) {
+      _showErrorInSnackbar();
+      return false;
+    }
+    return true;
+  }
+
+  _showErrorInSnackbar() {
+    String errorMsg = authProvider.packetError;
+    String snackbarText = "";
+
+    switch (errorMsg) {
+      case "REG_TRY_AGAIN":
+        snackbarText = appLocalizations.login_failed;
+        break;
+
+      case "REG_INVALID_REQUEST":
+        snackbarText = appLocalizations.password_incorrect;
+        break;
+
+      case "REG_NETWORK_ERROR":
+        snackbarText = appLocalizations.network_error;
+        break;
+
+      case "":
+        return;
+
+      default:
+        snackbarText = errorMsg;
+        break;
+    }
+
+    _showInSnackBar(snackbarText);
+  }
+
+  bool _validateUsername(BuildContext context) {
+    if (username.trim().isEmpty) {
+      _showInSnackBar(appLocalizations.username_required);
+      return false;
+    }
+
+    if (username.trim().length > 50) {
+      _showInSnackBar(appLocalizations.username_exceed);
+      return false;
+    }
+
+    return true;
+  }
+
+  bool _validatePassword(BuildContext context) {
+    if (password.trim().isEmpty) {
+      _showInSnackBar(appLocalizations.password_required);
+      return false;
+    }
+
+    if (password.trim().length > 50) {
+      _showInSnackBar(appLocalizations.password_exceed);
+      return false;
+    }
+
+    return true;
+  }
+
+  _resetValuesOnRegistrationComplete() {
+    Navigator.of(context).pop();
+  }
+
+  _nextButtonClickedAudit() async {
+    await globalProvider.getAudit("REG-EVT-003", "REG-MOD-103");
+  }
+
+  void _showInSnackBar(String value) {
+    ScaffoldMessenger.of(context).showSnackBar(
+      SnackBar(
+        content: Text(value),
+      ),
+    );
+  }
+
+  bool continueButton = false;
+  bool authButton = false;
+  @override
+  Widget build(BuildContext context) {
+    postRegistrationTabs = [
+      AppLocalizations.of(context)!.preview_page,
+      AppLocalizations.of(context)!.packet_auth_page,
+      AppLocalizations.of(context)!.acknowledgement_page,
+    ];
+    isPortrait = MediaQuery.of(context).orientation == Orientation.portrait;
+    bool isMobile = MediaQuery.of(context).size.width < 750;
+    double w = ScreenUtil().screenWidth;
+    Map arguments =
+        ModalRoute.of(context)!.settings.arguments! as Map;
+    final Process process = arguments["process"];
+    int size = process.screens!.length;
+
+    evaluateMVELVisible(String fieldData) async {
+      bool visible =
+      await registrationTaskProvider.evaluateMVELVisible(fieldData);
+      return visible;
+    }
+
+    evaluateMVELRequired(String fieldData) async {
+      bool required =
+      await registrationTaskProvider.evaluateMVELRequired(fieldData);
+      return required;
+    }
+
+    isExceptionPresent(String id) {
+      bool isExceptionPresent = false;
+      for (BiometricAttributeData x in globalProvider.fieldInputValue[id]) {
+        if (x.exceptions.contains(true) || x.title == "Exception") {
+          isExceptionPresent = true;
+          break;
+        }
+      }
+      return isExceptionPresent;
+    }
+
+    returnBiometricListLength(List? list, String id) {
+      int i = 0;
+      if (list!.contains("leftEye") && list.contains("rightEye")) {
+        i++;
+      }
+      if (list.contains("rightIndex") &&
+          list.contains("rightLittle") &&
+          list.contains("rightRing") &&
+          list.contains("rightMiddle")) {
+        i++;
+      }
+      if (list.contains("leftIndex") &&
+          list.contains("leftLittle") &&
+          list.contains("leftRing") &&
+          list.contains("leftMiddle")) {
+        i++;
+      }
+      if (list.contains("rightThumb") && list.contains("rightThumb")) {
+        i++;
+      }
+      if (list.contains("face")) {
+        i++;
+      }
+      if (isExceptionPresent(id) == true) {
+        i++;
+      }
+      return i;
+    }
+
+    customValidation(int currentIndex) async {
+      if (currentIndex == 0) {
+        return true;
+      }
+      bool isValid = true;
+      if (globalProvider.newProcessTabIndex < size) {
+        Screen screen = process.screens!.elementAt(currentIndex)!;
+        for (int i = 0; i < screen.fields!.length; i++) {
+          if (screen.fields!.elementAt(i)!.inputRequired! &&
+              screen.fields!.elementAt(i)!.required!) {
+            if (!(globalProvider.fieldInputValue
+                .containsKey(screen.fields!.elementAt(i)!.id)) &&
+                !(globalProvider.fieldInputValue
+                    .containsKey(screen.fields!.elementAt(i)!.subType)) &&
+                !(globalProvider.fieldInputValue.containsKey(
+                    "${screen.fields!.elementAt(i)!.group}${screen.fields!.elementAt(i)!.subType}"))) {
+              isValid = false;
+
+              break;
+            }
+            if (screen.fields!.elementAt(i)!.conditionalBioAttributes != null &&
+                screen.fields!
+                    .elementAt(i)!
+                    .conditionalBioAttributes!
+                    .isNotEmpty) {
+              String response = await BiometricsApi().getAgeGroup();
+              if (!(response.compareTo(screen.fields!
+                  .elementAt(i)!
+                  .conditionalBioAttributes!
+                  .first!
+                  .ageGroup!) ==
+                  0)) {
+                if (screen.fields!.elementAt(i)!.controlType == "biometrics") {
+                  int count = returnBiometricListLength(
+                      screen.fields!.elementAt(i)!.bioAttributes,
+                      screen.fields!.elementAt(i)!.id!);
+                  if (globalProvider.completeException[
+                  screen.fields!.elementAt(i)!.id!] !=
+                      null) {
+                    int length = globalProvider
+                        .completeException[screen.fields!.elementAt(i)!.id!]
+                        .length;
+                    count = count - length;
+                  }
+
+                  if (globalProvider
+                      .fieldInputValue[screen.fields!.elementAt(i)!.id!]
+                      .length <
+                      count) {
+                    isValid = false;
+
+                    break;
+                  }
+                  if(globalProvider.isValidBiometricCapture){
+                    isValid = false;
+                    break;
+                  }
+                }
+              }
+            }
+          }
+          if (screen.fields!.elementAt(i)!.requiredOn != null &&
+              screen.fields!.elementAt(i)!.requiredOn!.isNotEmpty) {
+            bool visible = await evaluateMVELVisible(
+                jsonEncode(screen.fields!.elementAt(i)!.toJson()));
+            bool required = await evaluateMVELRequired(
+                jsonEncode(screen.fields!.elementAt(i)!.toJson()));
+            if (visible && required) {
+              if (screen.fields!.elementAt(i)!.inputRequired!) {
+                if (!(globalProvider.fieldInputValue
+                    .containsKey(screen.fields!.elementAt(i)!.id)) &&
+                    !(globalProvider.fieldInputValue
+                        .containsKey(screen.fields!.elementAt(i)!.subType)) &&
+                    !(globalProvider.fieldInputValue.containsKey(
+                        "${screen.fields!.elementAt(i)!.group}${screen.fields!.elementAt(i)!.subType}"))) {
+                  isValid = false;
+
+                  break;
+                }
+                if (screen.fields!.elementAt(i)!.conditionalBioAttributes !=
+                    null &&
+                    screen.fields!
+                        .elementAt(i)!
+                        .conditionalBioAttributes!
+                        .isNotEmpty) {
+                  String response = await BiometricsApi().getAgeGroup();
+                  if (!(response.compareTo(screen.fields!
+                      .elementAt(i)!
+                      .conditionalBioAttributes!
+                      .first!
+                      .ageGroup!) ==
+                      0)) {
+                    if (screen.fields!.elementAt(i)!.controlType ==
+                        "biometrics") {
+                      int count = returnBiometricListLength(
+                          screen.fields!.elementAt(i)!.bioAttributes,
+                          screen.fields!.elementAt(i)!.id!);
+                      if (globalProvider.completeException[
+                      screen.fields!.elementAt(i)!.id!] !=
+                          null) {
+                        int length = globalProvider
+                            .completeException[screen.fields!.elementAt(i)!.id!]
+                            .length;
+                        count = count - length;
+                      }
+                      if (globalProvider
+                          .fieldInputValue[screen.fields!.elementAt(i)!.id!]
+                          .length <
+                          count) {
+                        isValid = false;
+
+                        break;
+                      }
+                      if(globalProvider.isValidBiometricCapture){
+                        isValid = false;
+                        break;
+                      }
+                    }
+                  }
+                  if (response.compareTo(screen.fields!
+                      .elementAt(i)!
+                      .conditionalBioAttributes!
+                      .first!
+                      .ageGroup!) ==
+                      0) {
+                    bool valid = await BiometricsApi()
+                        .conditionalBioAttributeValidation(
+                        screen.fields!.elementAt(i)!.id!,
+                        screen.fields!
+                            .elementAt(i)!
+                            .conditionalBioAttributes!
+                            .first!
+                            .validationExpr!);
+                    if (screen.fields!.elementAt(i)!.exceptionPhotoRequired ==
+                        true) {
+                      List biometricAttributeDataList =
+                      globalProvider.fieldInputValue[
+                      screen.fields!.elementAt(i)!.id!];
+                      bool isExceptionPresent = false;
+                      bool isExceptionAttributePresent = false;
+                      for (var biometricAttributeData
+                      in biometricAttributeDataList) {
+                        if (globalProvider.exceptionAttributes
+                            .contains(biometricAttributeData.title)) {
+                          isExceptionPresent = true;
+                        }
+                        if (biometricAttributeData.title == "Exception") {
+                          isExceptionAttributePresent = true;
+                        }
+                      }
+                      if (isExceptionPresent == true &&
+                          isExceptionAttributePresent == false) {
+                        isValid = false;
+                        break;
+                      }
+                    }
+                    if (!valid) {
+                      isValid = false;
+                      break;
+                    }
+                  }
+                }
+              }
+            }
+          }
+        }
+      }
+      return isValid;
+    }
+
+    continueButtonTap(int size, newProcess) async {
+      globalProvider.isPageChanged = true;
+      if (globalProvider.newProcessTabIndex < size) {
+        bool customValidator =
+        await customValidation(globalProvider.newProcessTabIndex);
+        if (customValidator) {
+          if (globalProvider.formKey.currentState!.validate()) {
+            if (globalProvider.newProcessTabIndex ==
+                newProcess.screens!.length - 1) {
+              templateTitleMap = {
+                'demographicInfo': appLocalizations.demographic_information,
+                'documents': appLocalizations.documents,
+                'bioMetrics': appLocalizations.biometrics
+              };
+              registrationTaskProvider.setPreviewTemplate("");
+              registrationTaskProvider.setAcknowledgementTemplate("");
+              await registrationTaskProvider.getPreviewTemplate(
+                  true, templateTitleMap!);
+              await registrationTaskProvider.getAcknowledgementTemplate(
+                false, templateTitleMap!,
+              );
+            }
+
+            globalProvider.newProcessTabIndex =
+                globalProvider.newProcessTabIndex + 1;
+          }
+        }
+
+        _nextButtonClickedAudit();
+      } else {
+        if (globalProvider.newProcessTabIndex == size + 1) {
+          bool isPacketAuthenticated = await _authenticatePacket(context);
+          if (!isPacketAuthenticated) {
+            return;
+          }
+          RegistrationSubmitResponse registrationSubmitResponse =
+          await registrationTaskProvider.submitRegistrationDto(username);
+
+          if (registrationSubmitResponse.errorCode!.isNotEmpty) {
+            _showInSnackBar(registrationSubmitResponse.errorCode!);
+            return;
+          }
+          globalProvider.setRegId(registrationSubmitResponse.rId);
+
+          // Updating key to packetId after success creation of packet
+          registrationTaskProvider
+              .updateTemplateStorageKey(registrationSubmitResponse.rId);
+          registrationTaskProvider.deleteDefaultTemplateStored();
+
+          setState(() {
+            username = '';
+            password = '';
+          });
+        }
+        if (globalProvider.newProcessTabIndex == size + 2) {
+          _resetValuesOnRegistrationComplete();
+          return;
+        }
+        globalProvider.newProcessTabIndex =
+            globalProvider.newProcessTabIndex + 1;
+      }
+    }
+
+    customValidation(globalProvider.newProcessTabIndex).then((value) {
+      setState(() {
+        continueButton = value &&
+            globalProvider.formKey.currentState != null &&
+            globalProvider.formKey.currentState!.validate();
+
+        // Disable continue if Additional Info Req ID is required but not entered
+        if (globalProvider.newProcessTabIndex < size) {
+          final screen = process.screens![globalProvider.newProcessTabIndex]!;
+          if (screen.additionalInfoRequestIdRequired == true &&
+              (globalProvider.additionalInfoReqId == null ||
+                  globalProvider.additionalInfoReqId!.trim().isEmpty)) {
+            continueButton = false;
+          }
+        }
+      });
+      if (globalProvider.newProcessTabIndex >= size) {
+        continueButton = true;
+      }
+    });
+
+    //auth button validation
+    if(username.trim().isNotEmpty && password.trim().isNotEmpty){
+      authButton = true;
+    }
+
+    return WillPopScope(
+      onWillPop: () async => true,
+      child: SafeArea(
+        child: Scaffold(
+          backgroundColor: secondaryColors.elementAt(10),
+          bottomNavigationBar: Container(
+            decoration: BoxDecoration(
+              border: const Border(
+                top: BorderSide(
+                  color: dividerColor,
+                  width: 1,
+                ),
+              ),
+              color: pureWhite,
+            ),
+            padding: EdgeInsets.symmetric(
+              horizontal: isPortrait ? 20.w : 60.w,
+              vertical: 16.h,
+            ),
+            // height: isPortrait ? 94.h : 84.h,
+            child: globalProvider.newProcessTabIndex == 0
+                ? Row(
+              children: [
+                Expanded(
+                  child: OutlinedButton(
+                    child: SizedBox(
+                      height: isPortrait && !isMobileSize ? 68.h : 52.h,
+                      child: Center(
+                        child: Text(
+                          appLocalizations.go_back,
+                          style: TextStyle(
+                            fontSize:
+                            isPortrait && !isMobileSize ? 22 : 14,
+                          ),
+                        ),
+                      ),
+                    ),
+                    onPressed: () {
+                      Navigator.of(context).pop();
+                    },
+                  ),
+                ),
+                SizedBox(
+                  width: 10.w,
+                ),
+                Expanded(
+                  child: ElevatedButton(
+                    child: SizedBox(
+                      height: isPortrait && !isMobileSize ? 68.h : 52.h,
+                      child: Center(
+                        child: Text(
+                          appLocalizations.informed,
+                          style: TextStyle(
+                            fontSize:
+                            isPortrait && !isMobileSize ? 22 : 14,
+                          ),
+                        ),
+                      ),
+                    ),
+                    onPressed: () async {
+                      registrationTaskProvider.addConsentField("Y");
+                      await DemographicsApi()
+                          .addDemographicField("consent", "true");
+                      continueButtonTap(size, process);
+                    },
+                  ),
+                ),
+              ],
+            )
+                : Row(
+              mainAxisAlignment: MainAxisAlignment.start,
+              children: [
+                const Expanded(
+                  child: SizedBox(),
+                ),
+                ElevatedButton(
+                  style: ButtonStyle(
+                    maximumSize: MaterialStateProperty.all(
+                        const Size(209, 52)),
+                    minimumSize: MaterialStateProperty.all(
+                        const Size(209, 52)),
+                    backgroundColor: MaterialStateProperty.all(
+                        (continueButton && context.read().newProcessTabIndex <=
+                            size) ? solidPrimary : authButton ? solidPrimary: Colors.grey),
+                  ),
+                  onPressed: () {
+                    continueButtonTap(size, process);
+                  },
+                  child: Text(
+                    context.read().newProcessTabIndex <=
+                        size
+                        ? appLocalizations.continue_text
+                        : globalProvider.newProcessTabIndex == size + 1
+                        ? appLocalizations.authenticate
+                        : appLocalizations.go_to_home,
+                    style: const TextStyle(color: appWhite),
+                  ),
+                ),
+              ],
+            ),
+          ),
+          body: SingleChildScrollView(
+            child: AnnotatedRegion(
+              value: const SystemUiOverlayStyle(
+                statusBarColor: Colors.transparent,
+              ),
+              child: Column(
+                children: [
+                  Container(
+                    padding: isMobile && !isMobileSize
+                        ? const EdgeInsets.fromLTRB(0, 46, 0, 0)
+                        : const EdgeInsets.fromLTRB(0, 0, 0, 0),
+                    decoration: const BoxDecoration(
+                      gradient: LinearGradient(
+                        begin: Alignment.topCenter,
+                        end: Alignment.bottomCenter,
+                        colors: [Color(0xff214FBF), Color(0xff1C43A1)],
+                      ),
+                    ),
+                    child: Column(
+                      crossAxisAlignment: CrossAxisAlignment.start,
+                      children: [
+                        SizedBox(
+                          width: w,
+                          height: isPortrait ? 21.w : 30.w,
+                        ),
+                        Padding(
+                          padding: isPortrait
+                              ? EdgeInsets.fromLTRB(20.w, 0, 0, 0)
+                              : EdgeInsets.fromLTRB(60.w, 0, 60.w, 0),
+                          child: Text(
+                            process.label![context
+                                .read()
+                                .selectedLanguage]!,
+                            style: Theme.of(context)
+                                .textTheme
+                                .titleMedium
+                                ?.copyWith(
+                                color: pureWhite,
+                                fontWeight: semiBold,
+                                fontSize: isPortrait ? 24 : 21),
+                          ),
+                        ),
+                        SizedBox(
+                          height: 30.h,
+                        ),
+                        Divider(
+                          height: 12.h,
+                          thickness: 1,
+                          color: secondaryColors.elementAt(2),
+                        ),
+                        Padding(
+                          padding: isPortrait
+                              ? const EdgeInsets.all(0)
+                              : EdgeInsets.fromLTRB(60.w, 0, 60.w, 0),
+                          child: Stack(
+                            alignment: FractionalOffset.centerRight,
+                            children: [
+                              Padding(
+                                padding: isPortrait
+                                    ? EdgeInsets.fromLTRB(20.w, 10.h, 0, 0)
+                                    : EdgeInsets.fromLTRB(0, 10.h, 0, 0),
+                                child: SizedBox(
+                                  height: 36.h,
+                                  child: ListView.builder(
+                                      padding: const EdgeInsets.all(0),
+                                      scrollDirection: Axis.horizontal,
+                                      itemCount: process.screens!.length + 3,
+                                      itemBuilder:
+                                          (BuildContext context, int index) {
+                                        return GestureDetector(
+                                          onTap: () {
+                                            if (context
+                                                .read()
+                                                .newProcessTabIndex ==
+                                                size + 2) {
+                                              return;
+                                            }
+
+                                            if (index <
+                                                context
+                                                    .read()
+                                                    .newProcessTabIndex) {
+                                              context
+                                                  .read()
+                                                  .newProcessTabIndex = index;
+                                            }
+                                          },
+                                          child: Row(
+                                            children: [
+                                              Container(
+                                                padding: EdgeInsets.fromLTRB(
+                                                    0, 0, 0, 8.h),
+                                                decoration: BoxDecoration(
+                                                  border: Border(
+                                                    bottom: BorderSide(
+                                                        color: (context
+                                                            .watch<
+                                                            GlobalProvider>()
+                                                            .newProcessTabIndex ==
+                                                            index)
+                                                            ? pureWhite
+                                                            : Colors
+                                                            .transparent,
+                                                        width: 3),
+                                                  ),
+                                                ),
+                                                child: Row(
+                                                  children: [
+                                                    (index <
+                                                        context
+                                                            .watch<
+                                                            GlobalProvider>()
+                                                            .newProcessTabIndex)
+                                                        ? Icon(
+                                                      Icons.check_circle,
+                                                      size: 17,
+                                                      color:
+                                                      secondaryColors
+                                                          .elementAt(
+                                                          11),
+                                                    )
+                                                        : (context
+                                                        .watch<
+                                                        GlobalProvider>()
+                                                        .newProcessTabIndex ==
+                                                        index)
+                                                        ? Icon(
+                                                      Icons.circle,
+                                                      color:
+                                                      pureWhite,
+                                                      size: 17,
+                                                    )
+                                                        : Icon(
+                                                      Icons
+                                                          .circle_outlined,
+                                                      size: 17,
+                                                      color: secondaryColors
+                                                          .elementAt(
+                                                          9),
+                                                    ),
+                                                    SizedBox(
+                                                      width: 6.w,
+                                                    ),
+                                                    Text(
+                                                      index < size
+                                                          ? process
+                                                          .screens![index]!
+                                                          .label![
+                                                      context
+                                                          .read<
+                                                          GlobalProvider>()
+                                                          .selectedLanguage]!
+                                                          : postRegistrationTabs[
+                                                      index - size],
+                                                      style: Theme.of(context)
+                                                          .textTheme
+                                                          .titleSmall
+                                                          ?.copyWith(
+                                                          color: (context
+                                                              .watch<
+                                                              GlobalProvider>()
+                                                              .newProcessTabIndex ==
+                                                              index)
+                                                              ? pureWhite
+                                                              : secondaryColors
+                                                              .elementAt(
+                                                              9),
+                                                          fontWeight:
+                                                          semiBold,
+                                                          fontSize: 14),
+                                                    ),
+                                                  ],
+                                                ),
+                                              ),
+                                              SizedBox(
+                                                width: 35.w,
+                                              ),
+                                            ],
+                                          ),
+                                        );
+                                      }),
+                                ),
+                              ),
+                              Container(
+                                height: 36.h,
+                                width: 25.w,
+                                padding: const EdgeInsets.fromLTRB(0, 0, 0, 0),
+                                color: solidPrimary,
+                                child: Icon(
+                                  Icons.arrow_forward_ios_outlined,
+                                  color: pureWhite,
+                                  size: 17,
+                                ),
+                              ),
+                            ],
+                          ),
+                        ),
+                        const SizedBox(
+                          height: 5,
+                        ),
+                      ],
+                    ),
+                  ),
+                  Padding(
+                    padding: isPortrait
+                        ? const EdgeInsets.all(0)
+                        : EdgeInsets.fromLTRB(60.w, 0, 60.w, 0),
+                    child: context.watch().newProcessTabIndex <
+                        size
+                        ? NewProcessScreenContent(
+                        context: context,
+                        screen: process.screens!.elementAt(context
+                            .watch()
+                            .newProcessTabIndex)!)
+                        : context.watch().newProcessTabIndex ==
+                        size
+                        ? const PreviewPage()
+                        : context
+                        .watch()
+                        .newProcessTabIndex ==
+                        size + 1
+                        ? _getPacketAuthComponent()
+                        : const AcknowledgementPage(),
+                  ),
+                  SizedBox(
+                    height: 20.h,
+                  ),
+                ],
+              ),
+            ),
+          ),
+        ),
+      ),
+    );
+  }
+
+  Widget _getPacketAuthComponent() {
+    return Column(
+      children: [
+        SizedBox(
+          height: 30.h,
+        ),
+        Container(
+          width: isPortrait && !isMobileSize ? 566.w : 376.w,
+          padding: EdgeInsets.only(
+            top: 24.h,
+            bottom: 28.h,
+            left: 20.w,
+            right: 20.w,
+          ),
+          decoration: BoxDecoration(
+            borderRadius: const BorderRadius.all(
+              Radius.circular(6),
+            ),
+            color: pureWhite,
+          ),
+          child: Column(
+            children: [
+              _getAuthIcon(),
+              SizedBox(
+                height: 26.h,
+              ),
+              Text(
+                appLocalizations.authenticate_using_password,
+                style: TextStyle(
+                    fontSize: isPortrait && !isMobileSize ? 24 : 18,
+                    fontWeight: semiBold,
+                    color: appBlack),
+              ),
+              SizedBox(
+                height: 35.h,
+              ),
+              Row(
+                children: [
+                  Text(
+                    appLocalizations.username,
+                    style: isPortrait
+                        ? AppTextStyle.tabletPortraitTextfieldHeader
+                        : AppTextStyle.mobileTextfieldHeader,
+                  ),
+                  const Text(
+                    ' *',
+                    style: TextStyle(
+                      color: mandatoryField,
+                    ),
+                  ),
+                ],
+              ),
+              SizedBox(
+                height: 11.h,
+              ),
+              _getUsernameTextField(),
+              SizedBox(
+                height: 35.h,
+              ),
+              Row(
+                children: [
+                  Text(
+                    appLocalizations.password,
+                    style: isPortrait
+                        ? AppTextStyle.tabletPortraitTextfieldHeader
+                        : AppTextStyle.mobileTextfieldHeader,
+                  ),
+                  const Text(
+                    ' *',
+                    style: TextStyle(color: mandatoryField),
+                  ),
+                ],
+              ),
+              SizedBox(
+                height: 11.h,
+              ),
+              _getPasswordTextField(),
+            ],
+          ),
+        ),
+      ],
+    );
+  }
+
+  _getAuthIcon() {
+    return Container(
+      height: 80.w,
+      width: 80.w,
+      decoration: BoxDecoration(
+        shape: BoxShape.circle,
+        border: Border.all(
+          color: authIconBorder,
+          width: 2,
+        ),
+        color: authIconBackground,
+      ),
+      child: Center(
+        child: SvgPicture.asset('assets/images/AuthenticationIcon.svg'),
+      ),
+    );
+  }
+
+  _getUsernameTextField() {
+    return Container(
+      height: isPortrait && !isMobileSize ? 82.h : 52.h,
+      alignment: Alignment.centerLeft,
+      padding: EdgeInsets.symmetric(
+        horizontal: 12.w,
+      ),
+      decoration: BoxDecoration(
+        border: Border.all(
+          width: 1.h,
+          color: appGreyShade,
+        ),
+        borderRadius: const BorderRadius.all(
+          Radius.circular(6),
+        ),
+      ),
+      child: TextField(
+        decoration: InputDecoration(
+          hintText: appLocalizations.enter_username,
+          hintStyle: isPortrait && !isMobileSize
+              ? AppTextStyle.tabletPortraitTextfieldHintText
+              : AppTextStyle.mobileTextfieldHintText,
+          border: InputBorder.none,
+        ),
+        style: TextStyle(
+          fontSize: isPortrait && !isMobileSize ? 22 : 14,
+          color: appBlack,
+        ),
+        onChanged: (v) {
+          setState(() {
+            username = v;
+          });
+        },
+      ),
+    );
+  }
+
+  _getPasswordTextField() {
+    return Container(
+      height: isPortrait && !isMobileSize ? 82.h : 52.h,
+      alignment: Alignment.centerLeft,
+      padding: EdgeInsets.symmetric(
+        horizontal: 12.w,
+      ),
+      decoration: BoxDecoration(
+        border: Border.all(
+          width: 1.h,
+          color: appGreyShade,
+        ),
+        borderRadius: const BorderRadius.all(
+          Radius.circular(6),
+        ),
+      ),
+      child: TextField(
+        obscureText: true,
+        decoration: InputDecoration(
+          hintText: appLocalizations.enter_password,
+          hintStyle: isPortrait && !isMobileSize
+              ? AppTextStyle.tabletPortraitTextfieldHintText
+              : AppTextStyle.mobileTextfieldHintText,
+          border: InputBorder.none,
+        ),
+        style: TextStyle(
+          fontSize: isPortrait && !isMobileSize ? 22 : 14,
+          color: appBlack,
+        ),
+        onChanged: (v) {
+          setState(() {
+            password = v;
+          });
+        },
+      ),
+    );
+  }
+}
diff --git a/lib/ui/process_ui/widgets/additional_Info_ReqId_control.dart b/lib/ui/process_ui/widgets/additional_Info_ReqId_control.dart
new file mode 100644
index 000000000..f51aed556
--- /dev/null
+++ b/lib/ui/process_ui/widgets/additional_Info_ReqId_control.dart
@@ -0,0 +1,86 @@
+import 'package:flutter/material.dart';
+import 'package:flutter_screenutil/flutter_screenutil.dart';
+import 'package:provider/provider.dart';
+import 'package:registration_client/provider/global_provider.dart';
+import 'package:registration_client/utils/app_config.dart';
+import 'package:flutter_gen/gen_l10n/app_localizations.dart';
+
+import '../../../provider/registration_task_provider.dart';
+
+class AdditionalInfoReqIdControl extends StatefulWidget {
+  final VoidCallback? onFetched;
+  const AdditionalInfoReqIdControl({Key? key, this.onFetched}) : super(key: key);
+
+  @override
+  State createState() => _AdditionalInfoReqIdControlState();
+}
+
+class _AdditionalInfoReqIdControlState extends State {
+  late GlobalProvider globalProvider;
+  late RegistrationTaskProvider registrationTaskProvider;
+  final TextEditingController reqIdController = TextEditingController();
+
+  @override
+  void initState() {
+    globalProvider = Provider.of(context, listen: false);
+    registrationTaskProvider = Provider.of(context, listen: false);
+    if (globalProvider.additionalInfoReqId != null && globalProvider.additionalInfoReqId!.isNotEmpty) {
+      reqIdController.text = globalProvider.additionalInfoReqId!;
+    }
+    super.initState();
+  }
+
+  @override
+  Widget build(BuildContext context) {
+    bool isPortrait = MediaQuery.of(context).orientation == Orientation.portrait;
+    return Card(
+      elevation: 5,
+      color: pureWhite,
+      shape: RoundedRectangleBorder(
+        borderRadius: BorderRadius.circular(6.0),
+      ),
+      margin: EdgeInsets.symmetric(
+          vertical: 20.h, horizontal: isPortrait ? 16.w : 0),
+      child: Padding(
+        padding: EdgeInsets.symmetric(vertical: 24.h, horizontal: 16.w),
+        child: Column(
+          crossAxisAlignment: CrossAxisAlignment.start,
+          children: [
+            Text(
+              AppLocalizations.of(context)!.additional_info_req_id,
+              style: TextStyle(
+                  fontSize: isPortrait ? 18 : 14),
+            ),
+            SizedBox(height: 10.h),
+            Row(
+              children: [
+                Expanded(
+                  flex: 3,
+                  child: TextFormField(
+                    controller: reqIdController,
+                    onChanged: (value) {
+                      globalProvider.setAdditionalInfoReqId(value);
+                      registrationTaskProvider.setAdditionalReqId(value);
+                      registrationTaskProvider.setApplicationId(value.split("-")[0]);
+                    },
+                    textAlign: TextAlign.left,
+                    decoration: InputDecoration(
+                      border: OutlineInputBorder(
+                        borderRadius: BorderRadius.circular(8.0),
+                        borderSide: const BorderSide(color: appGreyShade, width: 1),
+                      ),
+                      contentPadding: const EdgeInsets.symmetric(horizontal: 16, vertical: 14),
+                      hintText: AppLocalizations.of(context)!.enter_additional_info_req_id,
+                      hintStyle: const TextStyle(color: appBlackShade3, fontSize: 14),
+                    ),
+                  ),
+                ),
+                const Spacer(),
+              ],
+            )
+          ],
+        ),
+      ),
+    );
+  }
+}
diff --git a/lib/ui/process_ui/widgets/language_selector.dart b/lib/ui/process_ui/widgets/language_selector.dart
index 16c770571..0be61e049 100644
--- a/lib/ui/process_ui/widgets/language_selector.dart
+++ b/lib/ui/process_ui/widgets/language_selector.dart
@@ -14,6 +14,7 @@ import 'package:registration_client/model/process.dart';
 import 'package:registration_client/provider/global_provider.dart';
 import 'package:registration_client/provider/registration_task_provider.dart';
 import 'package:registration_client/ui/process_ui/lost_process.dart';
+import 'package:registration_client/ui/process_ui/correction_process.dart';
 
 import 'package:registration_client/ui/process_ui/new_process.dart';
 import 'package:registration_client/ui/process_ui/update_process.dart';
@@ -38,20 +39,25 @@ class _LanguageSelectorState extends State {
   late RegistrationTaskProvider registrationTaskProvider;
 
   _triggerNavigation() {
-    if (widget.newProcess.id == "NEW") {
+    if (widget.newProcess.flow == "NEW") {
       Navigator.pushNamed(context, NewProcess.routeName,
           arguments: {"process": widget.newProcess});
     }
 
-    if (widget.newProcess.id == "UPDATE") {
+    if (widget.newProcess.flow == "UPDATE") {
       Navigator.pushNamed(context, UpdateProcess.routeName,
           arguments: {"process": widget.newProcess});
     }
 
-    if (widget.newProcess.id == "LOST") {
+    if (widget.newProcess.flow == "LOST") {
       Navigator.pushNamed(context, LostProcess.routeName,
       arguments: {"process": widget.newProcess});
     }
+
+    if (widget.newProcess.flow == "CORRECTION") {
+      Navigator.pushNamed(context, CorrectionProcess.routeName,
+          arguments: {"process": widget.newProcess});
+    }
   }
 
   _showInSnackBar(String value) {
@@ -86,6 +92,7 @@ class _LanguageSelectorState extends State {
             ? "Update"
             : widget.newProcess.flow!,
         widget.newProcess.id!);
+
     registrationTaskProvider.addDemographicField("preferredLang",
         globalProvider.fieldInputValue["preferredLang"].toString());
     String registrationStartError =
diff --git a/lib/ui/process_ui/widgets/new_process_screen_content.dart b/lib/ui/process_ui/widgets/new_process_screen_content.dart
index 8c3f68be6..b896b322c 100644
--- a/lib/ui/process_ui/widgets/new_process_screen_content.dart
+++ b/lib/ui/process_ui/widgets/new_process_screen_content.dart
@@ -28,6 +28,7 @@ import 'package:registration_client/ui/process_ui/widgets/html_box_control.dart'
 import 'package:registration_client/ui/process_ui/widgets/button_control.dart';
 import 'package:registration_client/ui/process_ui/widgets/terms_and_conditions.dart';
 import 'package:registration_client/ui/process_ui/widgets/pre_reg_data_control.dart';
+import 'package:registration_client/ui/process_ui/widgets/additional_Info_ReqId_control.dart';
 import 'package:registration_client/ui/process_ui/widgets/textbox_control.dart';
 
 import 'radio_button_control.dart';
@@ -175,6 +176,9 @@ class _NewProcessScreenContentState extends State {
                 });
               }),
         ],
+        if (widget.screen.additionalInfoRequestIdRequired == true) ...[
+           const AdditionalInfoReqIdControl(),
+        ],
         (context.watch().preRegControllerRefresh)
             ? const CircularProgressIndicator()
             : Form(
diff --git a/lib/ui/process_ui/widgets_mobile/biometric_capture_scan_block_portrait.dart b/lib/ui/process_ui/widgets_mobile/biometric_capture_scan_block_portrait.dart
index abe9ba2a0..ebda09c44 100644
--- a/lib/ui/process_ui/widgets_mobile/biometric_capture_scan_block_portrait.dart
+++ b/lib/ui/process_ui/widgets_mobile/biometric_capture_scan_block_portrait.dart
@@ -217,28 +217,27 @@ class _BiometricCaptureScanBlockPortraitState
     _showCustomAlert(currentAttemptNo, temp);
   }
 
-  bool validateCaptureException(){
-    return (
-        (context.read().iris.isScanned) &&
-            (context.read().iris.qualityPercentage <=
-                int.parse(context.read().iris.thresholdPercentage)) ||
-
-            (context.read().rightHand.isScanned) &&
-                (context.read().rightHand.qualityPercentage <=
-                    int.parse(context.read().rightHand.thresholdPercentage)) ||
-
-            (context.read().leftHand.isScanned) &&
-                (context.read().leftHand.qualityPercentage <=
-                    int.parse(context.read().leftHand.thresholdPercentage)) ||
-
-            (context.read().thumbs.isScanned) &&
-                (context.read().thumbs.qualityPercentage <=
-                    int.parse(context.read().thumbs.thresholdPercentage)) ||
-
-            (context.read().face.isScanned) &&
-                (context.read().face.qualityPercentage <=
-                    int.parse(context.read().face.thresholdPercentage))
-    );
+  bool validateCaptureException() {
+    final biometricProvider = context.read();
+    return (biometricProvider.iris.isScanned &&
+        biometricProvider.iris.qualityPercentage <= int.parse(biometricProvider.iris.thresholdPercentage) &&
+        biometricProvider.iris.attemptNo < biometricProvider.iris.noOfCapturesAllowed) ||
+
+        (biometricProvider.rightHand.isScanned &&
+            biometricProvider.rightHand.qualityPercentage <= int.parse(biometricProvider.rightHand.thresholdPercentage) &&
+            biometricProvider.rightHand.attemptNo < biometricProvider.rightHand.noOfCapturesAllowed) ||
+
+        (biometricProvider.leftHand.isScanned &&
+            biometricProvider.leftHand.qualityPercentage <= int.parse(biometricProvider.leftHand.thresholdPercentage) &&
+            biometricProvider.leftHand.attemptNo < biometricProvider.leftHand.noOfCapturesAllowed) ||
+
+        (biometricProvider.thumbs.isScanned &&
+            biometricProvider.thumbs.qualityPercentage <= int.parse(biometricProvider.thumbs.thresholdPercentage) &&
+            biometricProvider.thumbs.attemptNo < biometricProvider.thumbs.noOfCapturesAllowed) ||
+
+        (biometricProvider.face.isScanned &&
+            biometricProvider.face.qualityPercentage <= int.parse(biometricProvider.face.thresholdPercentage) &&
+            biometricProvider.face.attemptNo < biometricProvider.face.noOfCapturesAllowed);
   }
 
   noOfTrue(List list) {
@@ -274,6 +273,21 @@ class _BiometricCaptureScanBlockPortraitState
     }
   }
 
+  /// Returns true if the user can proceed to the next step for this biometric.
+  bool canProceedToNext() {
+    final int threshold = int.tryParse(biometricAttributeData.thresholdPercentage) ?? 0;
+    final int quality = biometricAttributeData.qualityPercentage.toInt();
+    final int attempts = biometricAttributeData.attemptNo;
+    final int maxAttempts = biometricAttributeData.noOfCapturesAllowed;
+
+    // If quality is above threshold, allow next
+    if (quality >= threshold) return true;
+    // If all attempts are completed, allow next (even if below threshold)
+    if (attempts >= maxAttempts) return true;
+    // Otherwise, do not allow
+    return false;
+  }
+
   Widget _scanBlock() {
     return Column(
       children: [
@@ -2970,33 +2984,35 @@ class _BiometricCaptureScanBlockPortraitState
                   minimumSize:
                   MaterialStateProperty.all(const Size(200, 68)),
                 ),
-                onPressed: () {
-                  List bioAttributes = (widget
-                      .field.conditionalBioAttributes!.first!.ageGroup!
-                      .compareTo(
-                      context.read().ageGroup) ==
-                      0)
-                      ? _returnBiometricList(
-                      widget.field.conditionalBioAttributes!.first!
-                          .bioAttributes!,
-                      widget.field.id!)
-                      : _returnBiometricList(
-                      widget.field.bioAttributes!, widget.field.id!);
-
-                  var nextElement = _getNextElement(
-                      bioAttributes,
-                      context
-                          .read()
-                          .biometricAttribute);
-                  setState(() {});
-                  if (nextElement != null) {
-                    context
-                        .read()
-                        .biometricAttribute = nextElement;
-                  } else {
-                    Navigator.pop(context);
-                  }
-                },
+                onPressed: canProceedToNext()
+                    ? () {
+                        List bioAttributes = (widget
+                                    .field.conditionalBioAttributes!.first!.ageGroup!
+                                    .compareTo(
+                                        context.read().ageGroup) ==
+                                0)
+                            ? _returnBiometricList(
+                                widget.field.conditionalBioAttributes!.first!
+                                    .bioAttributes!,
+                                widget.field.id!)
+                            : _returnBiometricList(
+                                widget.field.bioAttributes!, widget.field.id!);
+
+                        var nextElement = _getNextElement(
+                            bioAttributes,
+                            context
+                                .read()
+                                .biometricAttribute);
+                        setState(() {});
+                        if (nextElement != null) {
+                          context
+                              .read()
+                              .biometricAttribute = nextElement;
+                        } else {
+                          Navigator.pop(context);
+                        }
+                      }
+                    : null, // Disable if cannot proceed
                 child: Text(AppLocalizations.of(context)!.next_button,
                     style: TextStyle(
                         fontSize: (isMobileSize) ? 20 : 24, fontWeight: bold)),
diff --git a/pigeon/registration_data.dart b/pigeon/registration_data.dart
index 4b541ddc0..49f391bc5 100644
--- a/pigeon/registration_data.dart
+++ b/pigeon/registration_data.dart
@@ -30,4 +30,7 @@ abstract class RegistrationDataApi {
 
   @async
   void setApplicationId(String applicationId);
+
+  @async
+  void setAdditionalReqId(String additionalReqId);
 }
diff --git a/pubspec.yaml b/pubspec.yaml
index 6ce32ba3f..f2ba07cec 100644
--- a/pubspec.yaml
+++ b/pubspec.yaml
@@ -30,7 +30,6 @@ environment:
 dependencies:
   flutter:
     sdk: flutter
-  freezed: ^2.1.0+1
   freezed_annotation: ^2.1.0
   json_annotation: ^4.8.0
   flutter_svg: ^2.0.9
@@ -77,6 +76,7 @@ dev_dependencies:
     sdk: flutter
   flutter_driver:
     sdk: flutter
+  freezed: ^2.1.0+1
   build_runner: ^2.3.3
   json_serializable: ^6.1.5
   flutter_launcher_icons: "^0.13.1"

From c3b64d171569a09cf028de7b18577fc3075c2d11 Mon Sep 17 00:00:00 2001
From: Madhuravas reddy 
Date: Thu, 30 Oct 2025 14:06:13 +0530
Subject: [PATCH 30/44] Resolved application id issue in approval page (#598)

Signed-off-by: Madhuravas Reddy 
---
 .../repository/RegistrationRepository.java             |  3 ++-
 .../clientmanager/service/RegistrationServiceImpl.java |  2 +-
 .../repository/RegistrationRepositoryTest.java         |  2 +-
 .../service/RegistrationServiceImplTest.java           | 10 +++++-----
 lib/ui/approve_packet/widget/approve_table.dart        |  2 +-
 lib/ui/export_packet/widgets/export_table.dart         |  2 +-
 6 files changed, 11 insertions(+), 10 deletions(-)

diff --git a/android/clientmanager/src/main/java/io/mosip/registration/clientmanager/repository/RegistrationRepository.java b/android/clientmanager/src/main/java/io/mosip/registration/clientmanager/repository/RegistrationRepository.java
index f11505b8d..56e445ee2 100644
--- a/android/clientmanager/src/main/java/io/mosip/registration/clientmanager/repository/RegistrationRepository.java
+++ b/android/clientmanager/src/main/java/io/mosip/registration/clientmanager/repository/RegistrationRepository.java
@@ -67,7 +67,7 @@ public void updateStatus(String packetId, String serverStatus, String clientStat
     }
 
     public Registration insertRegistration(String packetId, String containerPath, String centerId,
-                                           String registrationType, JSONObject additionalInfo, String additionalInfoReqId, String rid) throws Exception {
+                                           String registrationType, JSONObject additionalInfo, String additionalInfoReqId, String rid, String applicationId) throws Exception {
         Registration registration = new Registration(packetId);
         registration.setFilePath(containerPath);
         registration.setRegType(registrationType);
@@ -77,6 +77,7 @@ public Registration insertRegistration(String packetId, String containerPath, St
         registration.setCrDtime(System.currentTimeMillis());
         registration.setCrBy("110006");
         registration.setId(rid);
+        registration.setAppId(applicationId);
         //TODO use objectMapper
         registration.setAdditionalInfo(additionalInfo.toString().getBytes(StandardCharsets.UTF_8));
         registration.setAdditionalInfoReqId(additionalInfoReqId);
diff --git a/android/clientmanager/src/main/java/io/mosip/registration/clientmanager/service/RegistrationServiceImpl.java b/android/clientmanager/src/main/java/io/mosip/registration/clientmanager/service/RegistrationServiceImpl.java
index 49cee2254..70943c28e 100644
--- a/android/clientmanager/src/main/java/io/mosip/registration/clientmanager/service/RegistrationServiceImpl.java
+++ b/android/clientmanager/src/main/java/io/mosip/registration/clientmanager/service/RegistrationServiceImpl.java
@@ -292,7 +292,7 @@ public void submitRegistrationDto(String makerName) throws Exception {
             additionalInfo.put("phone", getAdditionalInfo(phoneObj));
 
             registrationRepository.insertRegistration(this.registrationDto.getPacketId(), containerPath,
-                    centerMachineDto.getCenterId(), this.registrationDto.getProcess(), additionalInfo, this.registrationDto.getAdditionalInfoRequestId(), this.registrationDto.getRId());
+                    centerMachineDto.getCenterId(), this.registrationDto.getProcess(), additionalInfo, this.registrationDto.getAdditionalInfoRequestId(), this.registrationDto.getRId(), this.registrationDto.getApplicationId());
 
 //        } finally {
             clearRegistration();
diff --git a/android/clientmanager/src/test/java/io/mosip/registration/clientmanager/repository/RegistrationRepositoryTest.java b/android/clientmanager/src/test/java/io/mosip/registration/clientmanager/repository/RegistrationRepositoryTest.java
index 372e123bc..c505e86d9 100644
--- a/android/clientmanager/src/test/java/io/mosip/registration/clientmanager/repository/RegistrationRepositoryTest.java
+++ b/android/clientmanager/src/test/java/io/mosip/registration/clientmanager/repository/RegistrationRepositoryTest.java
@@ -121,7 +121,7 @@ public void testInsertRegistration() throws Exception {
 
         // Execute method
         Registration result = registrationRepository.insertRegistration("10001155851003120250220055513", "/path/to/container",
-                "10011", "NEW", mockJson, "", "");
+                "10011", "NEW", mockJson, "", "", "34259236291839");
 
         // Capture inserted object
         ArgumentCaptor captor = ArgumentCaptor.forClass(Registration.class);
diff --git a/android/clientmanager/src/test/java/io/mosip/registration/clientmanager/service/RegistrationServiceImplTest.java b/android/clientmanager/src/test/java/io/mosip/registration/clientmanager/service/RegistrationServiceImplTest.java
index 3183af700..27150e25f 100644
--- a/android/clientmanager/src/test/java/io/mosip/registration/clientmanager/service/RegistrationServiceImplTest.java
+++ b/android/clientmanager/src/test/java/io/mosip/registration/clientmanager/service/RegistrationServiceImplTest.java
@@ -686,7 +686,7 @@ public void testSubmitRegistrationDto_UpdateFlow_UINField() throws Exception {
         when(identitySchemaRepository.getSchemaJson(Mockito.any(), Mockito.anyDouble())).thenReturn("{}");
         when(packetWriterService.persistPacket(Mockito.anyString(), Mockito.anyString(), Mockito.anyString(), Mockito.anyString(), Mockito.anyString(), Mockito.anyBoolean(), Mockito.anyString())).thenReturn("containerPath123");
         Registration mockRegistration = mock(Registration.class);
-        when(registrationRepository.insertRegistration(Mockito.anyString(), Mockito.anyString(), Mockito.anyString(), Mockito.anyString(), Mockito.any(), "", "")).thenReturn(mockRegistration);
+        when(registrationRepository.insertRegistration(Mockito.anyString(), Mockito.anyString(), Mockito.anyString(), Mockito.anyString(), Mockito.any(), "", "", "34259236291839")).thenReturn(mockRegistration);
 
         registrationService.submitRegistrationDto("makerName");
         Mockito.verify(packetWriterService).setField("RID456", "UIN", "uinValue");
@@ -727,7 +727,7 @@ public void testSubmitRegistrationDto_NewFlow_AllFields() throws Exception {
         when(identitySchemaRepository.getSchemaJson(Mockito.any(), Mockito.anyDouble())).thenReturn("{}");
         when(packetWriterService.persistPacket(Mockito.anyString(), Mockito.anyString(), Mockito.anyString(), Mockito.anyString(), Mockito.anyString(), Mockito.anyBoolean(), Mockito.anyString())).thenReturn("containerPath123");
         Registration mockRegistration = mock(Registration.class);
-        when(registrationRepository.insertRegistration(Mockito.anyString(), Mockito.anyString(), Mockito.anyString(), Mockito.anyString(), Mockito.any(), "", "")).thenReturn(mockRegistration);
+        when(registrationRepository.insertRegistration(Mockito.anyString(), Mockito.anyString(), Mockito.anyString(), Mockito.anyString(), Mockito.any(), "", "", "34259236291839")).thenReturn(mockRegistration);
 
         registrationService.submitRegistrationDto("makerName");
         Mockito.verify(packetWriterService).setField("RID789", "field1", "value1");
@@ -768,7 +768,7 @@ public void testSubmitRegistrationDto_CorrectionFlow() throws Exception {
         when(identitySchemaRepository.getSchemaJson(Mockito.any(), Mockito.anyDouble())).thenReturn("{}");
         when(packetWriterService.persistPacket(Mockito.anyString(), Mockito.anyString(), Mockito.anyString(), Mockito.anyString(), Mockito.anyString(), Mockito.anyBoolean(), Mockito.anyString())).thenReturn("containerPath123");
         Registration mockRegistration = mock(Registration.class);
-        when(registrationRepository.insertRegistration(Mockito.anyString(), Mockito.anyString(), Mockito.anyString(), Mockito.anyString(), Mockito.any(), "", "")).thenReturn(mockRegistration);
+        when(registrationRepository.insertRegistration(Mockito.anyString(), Mockito.anyString(), Mockito.anyString(), Mockito.anyString(), Mockito.any(), "", "", "34259236291839")).thenReturn(mockRegistration);
 
         registrationService.submitRegistrationDto("makerName");
         Mockito.verify(packetWriterService).setField("RID999", "field2", "value2");
@@ -809,7 +809,7 @@ public void testSubmitRegistrationDto_LostFlow() throws Exception {
         when(identitySchemaRepository.getSchemaJson(Mockito.any(), Mockito.anyDouble())).thenReturn("{}");
         when(packetWriterService.persistPacket(Mockito.anyString(), Mockito.anyString(), Mockito.anyString(), Mockito.anyString(), Mockito.anyString(), Mockito.anyBoolean(), Mockito.anyString())).thenReturn("containerPath123");
         Registration mockRegistration = mock(Registration.class);
-        when(registrationRepository.insertRegistration(Mockito.anyString(), Mockito.anyString(), Mockito.anyString(), Mockito.anyString(), Mockito.any(), "", "")).thenReturn(mockRegistration);
+        when(registrationRepository.insertRegistration(Mockito.anyString(), Mockito.anyString(), Mockito.anyString(), Mockito.anyString(), Mockito.any(), "", "", "34259236291839")).thenReturn(mockRegistration);
 
         registrationService.submitRegistrationDto("makerName");
         Mockito.verify(packetWriterService).setField("RID888", "field3", "value3");
@@ -1073,7 +1073,7 @@ public void testSubmitRegistrationDto_SelectedHandles_UpdateFlow() throws Except
         when(identitySchemaRepository.getSchemaJson(Mockito.any(), Mockito.anyDouble())).thenReturn("{}");
         when(packetWriterService.persistPacket(Mockito.anyString(), Mockito.anyString(), Mockito.anyString(), Mockito.anyString(), Mockito.anyString(), Mockito.anyBoolean(), Mockito.anyString())).thenReturn("containerPath123");
         Registration mockRegistration = mock(Registration.class);
-        when(registrationRepository.insertRegistration(Mockito.anyString(), Mockito.anyString(), Mockito.anyString(), Mockito.anyString(), Mockito.any(), "", "")).thenReturn(mockRegistration);
+        when(registrationRepository.insertRegistration(Mockito.anyString(), Mockito.anyString(), Mockito.anyString(), Mockito.anyString(), Mockito.any(), "", "", "34259236291839")).thenReturn(mockRegistration);
 
         registrationService.submitRegistrationDto("makerName");
         Mockito.verify(packetWriterService).setField("RID123", "UIN", "uinValue");
diff --git a/lib/ui/approve_packet/widget/approve_table.dart b/lib/ui/approve_packet/widget/approve_table.dart
index 66d7d5e7f..523718a45 100644
--- a/lib/ui/approve_packet/widget/approve_table.dart
+++ b/lib/ui/approve_packet/widget/approve_table.dart
@@ -181,7 +181,7 @@ class _ApproveTableState extends State {
                         showTemplate();
                         log("show");
                       },
-                      child: Text(regCurrent.id!,
+                      child: Text(regCurrent.appId ?? regCurrent.id!,
                           textAlign: TextAlign.center,
                           overflow: TextOverflow.ellipsis,
                           maxLines: 2),
diff --git a/lib/ui/export_packet/widgets/export_table.dart b/lib/ui/export_packet/widgets/export_table.dart
index 249ca927e..5eaf7e35e 100644
--- a/lib/ui/export_packet/widgets/export_table.dart
+++ b/lib/ui/export_packet/widgets/export_table.dart
@@ -72,7 +72,7 @@ class ExportTable extends StatelessWidget {
               mainAxisAlignment: MainAxisAlignment.spaceEvenly,
               children: [
                 SizedBox(width: tableWidth/35, child:Text("$index.", textAlign: TextAlign.center, )),
-                SizedBox(width: tableWidth/5.5, child: Text(context.watch().matchingPackets[index-1].id!, textAlign: TextAlign.center,  overflow: TextOverflow.ellipsis,maxLines: 2,)),
+                SizedBox(width: tableWidth/5.5, child: Text(context.watch().matchingPackets[index-1].appId ?? context.watch().matchingPackets[index-1].id!, textAlign: TextAlign.center,  overflow: TextOverflow.ellipsis,maxLines: 2,)),
                 SizedBox(width: tableWidth/9, child: Text(formattedDate,textAlign: TextAlign.center, overflow: TextOverflow.ellipsis, maxLines: 2,)),
                 SizedBox(width: tableWidth/15, child:Text(context.watch().matchingPackets[index-1].regType.toString(), textAlign: TextAlign.center, overflow: TextOverflow.ellipsis,maxLines: 2,)),
                 SizedBox(width: tableWidth/9, child: Text(context.watch().matchingPackets[index-1].clientStatus.toString(),textAlign: TextAlign.center, overflow: TextOverflow.ellipsis,maxLines: 2,)),

From e47c2ad13b6b447bb37c3d5cba004e16c5a2872d Mon Sep 17 00:00:00 2001
From: Sachin S  P <52343650+SachinPremkumar@users.noreply.github.com>
Date: Thu, 30 Oct 2025 19:27:57 +0530
Subject: [PATCH 31/44] RCF-1185 : Implemented GPS feature (#593)

* RCF-1185 : Implemented GPS feature

Signed-off-by: sachin.sp 

* RCF-1185 : Implemented GPS feature

Signed-off-by: sachin.sp 

* RCF-1185 : Implemented GPS feature

Signed-off-by: sachin.sp 

* RCF-1185 : Implemented GPS feature

Signed-off-by: sachin.sp 

* RCF-1185: reverted review changes

Signed-off-by: sachin.sp 

* RCF-1185: reverted review changes

Signed-off-by: sachin.sp 

* RCF-1185: changed the flag name

Signed-off-by: sachin.sp 

---------

Signed-off-by: sachin.sp 
Co-authored-by: sachin.sp 
---
 android/app/src/main/AndroidManifest.xml      |    3 +
 .../registration_client/HostApiModule.java    |    8 +
 .../api_services/GlobalConfigSettingsApi.java |   11 +
 .../api_services/RegistrationApi.java         |    9 +
 .../clientmanager/config/AppModule.java       |    5 +-
 .../constant/RegistrationConstants.java       |    2 +
 .../dto/registration/GeoLocationDto.java      |   11 +
 .../dto/registration/RegistrationDto.java     |    6 +
 .../repository/GlobalParamRepository.java     |    8 +
 .../LocationValidationServiceImpl.java        |   42 +
 .../service/RegistrationServiceImpl.java      |  107 +-
 .../spi/LocationValidationService.java        |   22 +
 .../service/RegistrationServiceImplTest.java  |    9 +-
 assets/l10n/app_ar.arb                        |    2 +
 assets/l10n/app_en.arb                        |    2 +
 assets/l10n/app_fr.arb                        |    2 +
 assets/l10n/app_hi.arb                        |    2 +
 assets/l10n/app_kn.arb                        |    2 +
 assets/l10n/app_ta.arb                        |    2 +
 lib/app_router.dart                           |   15 +-
 .../global_config_service_impl.dart           |   13 +
 .../registration_service_impl.dart            |   11 +
 lib/platform_spi/global_config_service.dart   |    2 +
 lib/platform_spi/registration_service.dart    |    1 +
 lib/provider/connectivity_provider.dart       |   28 +
 lib/provider/global_provider.dart             |   39 +
 lib/provider/registration_task_provider.dart  |    4 +
 lib/ui/onboard/home_page.dart                 |    3 +
 lib/ui/process_ui/correction_process.dart     | 1002 ------------
 lib/ui/process_ui/generic_process.dart        | 1371 +++++++++++++++++
 lib/ui/process_ui/lost_process.dart           | 1241 ---------------
 lib/ui/process_ui/new_process.dart            | 1190 --------------
 lib/ui/process_ui/process_type.dart           |   42 +
 lib/ui/process_ui/update_process.dart         | 1184 --------------
 ...rt => generic_process_screen_content.dart} |   74 +-
 .../process_ui/widgets/language_selector.dart |   15 +-
 .../widgets/lost_process_screen_content.dart  |  196 ---
 .../update_process_screen_content.dart        |  191 ---
 lib/ui/profile/profile.dart                   |   48 +
 pigeon.sh                                     |    5 +-
 pigeon/global_config_settings.dart            |    2 +
 pigeon/registration_data.dart                 |    3 +
 pubspec.yaml                                  |    1 +
 43 files changed, 1891 insertions(+), 5045 deletions(-)
 create mode 100644 android/clientmanager/src/main/java/io/mosip/registration/clientmanager/dto/registration/GeoLocationDto.java
 create mode 100644 android/clientmanager/src/main/java/io/mosip/registration/clientmanager/service/LocationValidationServiceImpl.java
 create mode 100644 android/clientmanager/src/main/java/io/mosip/registration/clientmanager/spi/LocationValidationService.java
 delete mode 100644 lib/ui/process_ui/correction_process.dart
 create mode 100644 lib/ui/process_ui/generic_process.dart
 delete mode 100644 lib/ui/process_ui/lost_process.dart
 delete mode 100644 lib/ui/process_ui/new_process.dart
 create mode 100644 lib/ui/process_ui/process_type.dart
 delete mode 100644 lib/ui/process_ui/update_process.dart
 rename lib/ui/process_ui/widgets/{new_process_screen_content.dart => generic_process_screen_content.dart} (76%)
 delete mode 100644 lib/ui/process_ui/widgets/lost_process_screen_content.dart
 delete mode 100644 lib/ui/process_ui/widgets/update_process_screen_content.dart

diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml
index c7466adc1..85ced5362 100644
--- a/android/app/src/main/AndroidManifest.xml
+++ b/android/app/src/main/AndroidManifest.xml
@@ -8,6 +8,9 @@
     
     
     
+    
+    
+    
     localPreferences,
             result.error(e);
         }
     }
+
+    @Override
+    public void getGpsEnableFlag(@NonNull GlobalConfigSettingsPigeon.Result result) {
+        String gpsFlag = "";
+        try {
+            gpsFlag = globalParamRepository.getCachedStringGpsDeviceEnableFlag();
+        } catch (Exception e) {
+            Log.e(getClass().getSimpleName(), "Error fetching GPS enable flag", e);
+        }
+        result.success(gpsFlag);
+    }
 }
\ No newline at end of file
diff --git a/android/app/src/main/java/io/mosip/registration_client/api_services/RegistrationApi.java b/android/app/src/main/java/io/mosip/registration_client/api_services/RegistrationApi.java
index 7972ecc4e..5fe49881f 100644
--- a/android/app/src/main/java/io/mosip/registration_client/api_services/RegistrationApi.java
+++ b/android/app/src/main/java/io/mosip/registration_client/api_services/RegistrationApi.java
@@ -145,5 +145,14 @@ public void setAdditionalReqId(@NonNull String additionalReqId, @NonNull Registr
             Log.e(getClass().getSimpleName(), "Set additional request ID failed: " + Arrays.toString(e.getStackTrace()));
         }
     }
+
+    @Override
+    public void setMachineLocation(@NonNull Double latitude, @NonNull Double longitude, @NonNull RegistrationDataPigeon.Result result) {
+        try {
+            this.registrationDto.setGeoLocation(longitude, latitude);
+        } catch (Exception e) {
+            Log.e(getClass().getSimpleName(),"Set machine location failed:" + Arrays.toString(e.getStackTrace()));
+        }
+    }
 }
 
diff --git a/android/clientmanager/src/main/java/io/mosip/registration/clientmanager/config/AppModule.java b/android/clientmanager/src/main/java/io/mosip/registration/clientmanager/config/AppModule.java
index 2c2f3571e..da70f3ff1 100644
--- a/android/clientmanager/src/main/java/io/mosip/registration/clientmanager/config/AppModule.java
+++ b/android/clientmanager/src/main/java/io/mosip/registration/clientmanager/config/AppModule.java
@@ -54,6 +54,7 @@
 import io.mosip.registration.clientmanager.spi.AuditManagerService;
 import io.mosip.registration.clientmanager.spi.JobManagerService;
 import io.mosip.registration.clientmanager.spi.JobTransactionService;
+import io.mosip.registration.clientmanager.spi.LocationValidationService;
 import io.mosip.registration.clientmanager.spi.MasterDataService;
 import io.mosip.registration.clientmanager.spi.PacketService;
 import io.mosip.registration.clientmanager.spi.PreRegistrationDataSyncService;
@@ -199,10 +200,12 @@ RegistrationService provideRegistrationService(PacketWriterService packetWriterS
                                                    KeyStoreRepository keyStoreRepository,
                                                    GlobalParamRepository globalParamRepository,
                                                    AuditManagerService auditManagerService,
+                                                   RegistrationCenterRepository registrationCenterRepository,
+                                                   LocationValidationService locationValidationService,
                                                    Biometrics095Service biometricService) {
         return new RegistrationServiceImpl(appContext, packetWriterService, registrationRepository,
                 masterDataService, identitySchemaRepository, clientCryptoManagerService,
-                keyStoreRepository, globalParamRepository, auditManagerService,biometricService);
+                keyStoreRepository, globalParamRepository, auditManagerService,registrationCenterRepository,locationValidationService, biometricService);
     }
 
     @Provides
diff --git a/android/clientmanager/src/main/java/io/mosip/registration/clientmanager/constant/RegistrationConstants.java b/android/clientmanager/src/main/java/io/mosip/registration/clientmanager/constant/RegistrationConstants.java
index a3b07c302..37c1135ad 100644
--- a/android/clientmanager/src/main/java/io/mosip/registration/clientmanager/constant/RegistrationConstants.java
+++ b/android/clientmanager/src/main/java/io/mosip/registration/clientmanager/constant/RegistrationConstants.java
@@ -112,5 +112,7 @@ public class RegistrationConstants {
     public static final String RIGHT = "Right";
     public static final String LEFT = "Left";
     public static final String JOB_TRIGGER_POINT_USER = "User";
+    public static final String GPS_DEVICE_ENABLE_FLAG = "mosip.registration.gps_device_enable_flag";
+    public static final String DIST_FRM_MACHINE_TO_CENTER = "mosip.registration.distance.from.machine.to.center";
 
 }
diff --git a/android/clientmanager/src/main/java/io/mosip/registration/clientmanager/dto/registration/GeoLocationDto.java b/android/clientmanager/src/main/java/io/mosip/registration/clientmanager/dto/registration/GeoLocationDto.java
new file mode 100644
index 000000000..36746f205
--- /dev/null
+++ b/android/clientmanager/src/main/java/io/mosip/registration/clientmanager/dto/registration/GeoLocationDto.java
@@ -0,0 +1,11 @@
+package io.mosip.registration.clientmanager.dto.registration;
+
+import lombok.AllArgsConstructor;
+import lombok.Data;
+
+@Data
+@AllArgsConstructor
+public class GeoLocationDto {
+    private double longitude;
+    private double latitude;
+}
\ No newline at end of file
diff --git a/android/clientmanager/src/main/java/io/mosip/registration/clientmanager/dto/registration/RegistrationDto.java b/android/clientmanager/src/main/java/io/mosip/registration/clientmanager/dto/registration/RegistrationDto.java
index d5745c0c5..7c498d06a 100644
--- a/android/clientmanager/src/main/java/io/mosip/registration/clientmanager/dto/registration/RegistrationDto.java
+++ b/android/clientmanager/src/main/java/io/mosip/registration/clientmanager/dto/registration/RegistrationDto.java
@@ -85,6 +85,8 @@ public class RegistrationDto extends Observable {
     private OperatorDto reviewer;
     public Map SELECTED_CODES = new HashMap<>();
 
+    private GeoLocationDto geoLocationDto;
+
     private String applicationId;
     private String additionalInfoRequestId;
 
@@ -481,4 +483,8 @@ public void addWithoutDocument(String fieldId, String docType, String format,Str
             this.documents.put(fieldId, documentDto);
         }
     }
+
+    public void setGeoLocation(double  longitude, double latitude) {
+        this.geoLocationDto = new GeoLocationDto(longitude, latitude);
+    }
 }
diff --git a/android/clientmanager/src/main/java/io/mosip/registration/clientmanager/repository/GlobalParamRepository.java b/android/clientmanager/src/main/java/io/mosip/registration/clientmanager/repository/GlobalParamRepository.java
index 8fdc67b21..40e617c11 100644
--- a/android/clientmanager/src/main/java/io/mosip/registration/clientmanager/repository/GlobalParamRepository.java
+++ b/android/clientmanager/src/main/java/io/mosip/registration/clientmanager/repository/GlobalParamRepository.java
@@ -149,6 +149,14 @@ public String getCachedStringRefreshedLoginTime() {
         return globalParamMap.get(RegistrationConstants.REFRESHED_LOGIN_TIME);
     }
 
+    public String getCachedStringGpsDeviceEnableFlag() {
+        return globalParamMap.get(RegistrationConstants.GPS_DEVICE_ENABLE_FLAG);
+    }
+
+    public String getCachedStringMachineToCenterDistance() {
+        return globalParamMap.get(RegistrationConstants.DIST_FRM_MACHINE_TO_CENTER);
+    }
+
     /**
      * Refresh configuration cache by merging global params with local preferences
      */
diff --git a/android/clientmanager/src/main/java/io/mosip/registration/clientmanager/service/LocationValidationServiceImpl.java b/android/clientmanager/src/main/java/io/mosip/registration/clientmanager/service/LocationValidationServiceImpl.java
new file mode 100644
index 000000000..a399a4f19
--- /dev/null
+++ b/android/clientmanager/src/main/java/io/mosip/registration/clientmanager/service/LocationValidationServiceImpl.java
@@ -0,0 +1,42 @@
+package io.mosip.registration.clientmanager.service;
+
+import android.util.Log;
+
+import javax.inject.Inject;
+import javax.inject.Singleton;
+
+import io.mosip.registration.clientmanager.spi.LocationValidationService;
+
+/**
+ * Implementation of LocationValidationService for distance calculation
+ * 
+ * @author sachin sp
+ */
+@Singleton
+public class LocationValidationServiceImpl implements LocationValidationService {
+
+    private static final String TAG = LocationValidationServiceImpl.class.getSimpleName();
+
+    @Inject
+    public LocationValidationServiceImpl() {
+    }
+
+    @Override
+    public double getDistance(double machineLongitude, double machineLatitude,
+                             double centerLongitude, double centerLatitude) {
+        double earthRadiusInKM = 6371;
+        double longitudeDiff = Math.toRadians(centerLongitude - machineLongitude);
+        double latitudeDiff = Math.toRadians(centerLatitude - machineLatitude);
+
+        double var = Math.sin(latitudeDiff / 2) * Math.sin(latitudeDiff / 2) +
+                Math.sin(longitudeDiff / 2) * Math.sin(longitudeDiff / 2) * 
+                Math.cos(Math.toRadians(machineLatitude)) * Math.cos(Math.toRadians(centerLatitude));
+        
+        double distance = earthRadiusInKM * (2 * Math.atan2(Math.sqrt(var), Math.sqrt(1 - var)));
+        
+        Log.i(TAG, String.format("Distance calculated: %.2f km", distance));
+        
+        return distance;
+    }
+}
+
diff --git a/android/clientmanager/src/main/java/io/mosip/registration/clientmanager/service/RegistrationServiceImpl.java b/android/clientmanager/src/main/java/io/mosip/registration/clientmanager/service/RegistrationServiceImpl.java
index 70943c28e..0b81f7367 100644
--- a/android/clientmanager/src/main/java/io/mosip/registration/clientmanager/service/RegistrationServiceImpl.java
+++ b/android/clientmanager/src/main/java/io/mosip/registration/clientmanager/service/RegistrationServiceImpl.java
@@ -52,16 +52,20 @@
 import io.mosip.registration.clientmanager.constant.RegistrationConstants;
 import io.mosip.registration.clientmanager.dto.CenterMachineDto;
 import io.mosip.registration.clientmanager.dto.registration.BiometricsDto;
+import io.mosip.registration.clientmanager.dto.registration.GeoLocationDto;
 import io.mosip.registration.clientmanager.dto.registration.RegistrationDto;
 import io.mosip.registration.clientmanager.dto.uispec.FieldSpecDto;
 import io.mosip.registration.clientmanager.entity.Audit;
 import io.mosip.registration.clientmanager.entity.Registration;
+import io.mosip.registration.clientmanager.entity.RegistrationCenter;
 import io.mosip.registration.clientmanager.exception.ClientCheckedException;
 import io.mosip.registration.clientmanager.exception.RegBaseCheckedException;
 import io.mosip.registration.clientmanager.repository.GlobalParamRepository;
 import io.mosip.registration.clientmanager.repository.IdentitySchemaRepository;
+import io.mosip.registration.clientmanager.repository.RegistrationCenterRepository;
 import io.mosip.registration.clientmanager.repository.RegistrationRepository;
 import io.mosip.registration.clientmanager.spi.AuditManagerService;
+import io.mosip.registration.clientmanager.spi.LocationValidationService;
 import io.mosip.registration.clientmanager.spi.MasterDataService;
 import io.mosip.registration.clientmanager.spi.RegistrationService;
 import io.mosip.registration.keymanager.repository.KeyStoreRepository;
@@ -104,6 +108,8 @@ public class RegistrationServiceImpl implements RegistrationService {
     private KeyStoreRepository keyStoreRepository;
     private GlobalParamRepository globalParamRepository;
     private AuditManagerService auditManagerService;
+    private RegistrationCenterRepository registrationCenterRepository;
+    private LocationValidationService locationValidationService;
     public static final String BOOLEAN_FALSE = "false";
 
     private Biometrics095Service biometricService;
@@ -116,7 +122,10 @@ public RegistrationServiceImpl(Context context, PacketWriterService packetWriter
                                    ClientCryptoManagerService clientCryptoManagerService,
                                    KeyStoreRepository keyStoreRepository,
                                    GlobalParamRepository globalParamRepository,
-                                   AuditManagerService auditManagerService, Biometrics095Service biometricService) {
+                                   AuditManagerService auditManagerService,
+                                   RegistrationCenterRepository registrationCenterRepository,
+                                   LocationValidationService locationValidationService,
+                                   Biometrics095Service biometricService) {
         this.context = context;
         this.registrationDto = null;
         this.packetWriterService = packetWriterService;
@@ -127,6 +136,8 @@ public RegistrationServiceImpl(Context context, PacketWriterService packetWriter
         this.keyStoreRepository = keyStoreRepository;
         this.globalParamRepository = globalParamRepository;
         this.auditManagerService = auditManagerService;
+        this.registrationCenterRepository = registrationCenterRepository;
+        this.locationValidationService = locationValidationService;
         this.biometricService = biometricService;
     }
 
@@ -195,6 +206,10 @@ public void submitRegistrationDto(String makerName) throws Exception {
         if (this.registrationDto == null) {
             throw new ClientCheckedException(context, R.string.err_004);
         }
+
+        // Validate location before submission
+        validateLocation();
+
         if (this.registrationDto.getAdditionalInfoRequestId() != null) {
             String newAppId = this.registrationDto.getAdditionalInfoRequestId().split("-")[0];
             this.registrationDto.setApplicationId(newAppId);
@@ -445,8 +460,11 @@ private void addMetaInfoMap(String centerId, String machineId, String makerId) t
         packetWriterService.addMetaInfo(rid, PacketManagerConstant.META_INFO_OPERATIONS_DATA, getLabelValueDTOListString(metaData));
 
         //other metaInfo
-        packetWriterService.addMetaInfo(rid, PacketManagerConstant.META_LATITUDE, "null");
-        packetWriterService.addMetaInfo(rid, PacketManagerConstant.META_LONGITUDE, "null");
+        GeoLocationDto geoLocation = this.registrationDto.getGeoLocationDto();
+        packetWriterService.addMetaInfo(rid, PacketManagerConstant.META_LATITUDE,
+            geoLocation != null ? String.valueOf(geoLocation.getLatitude()) : "null");
+        packetWriterService.addMetaInfo(rid, PacketManagerConstant.META_LONGITUDE,
+            geoLocation != null ? String.valueOf(geoLocation.getLongitude()) : "null");
         packetWriterService.addMetaInfo(rid, "checkSum", "{}");
         packetWriterService.addMetaInfo(rid, PacketManagerConstant.REGISTRATIONID, rid);
 
@@ -476,6 +494,89 @@ private List> getLabelValueDTOListString(Map
         return labelValueMap;
     }
 
+    /**
+     * Validate machine location against registration center
+     * @throws Exception if location is outside allowed distance
+     */
+    private void validateLocation() throws Exception {
+        try {
+
+            String enableFlag = globalParamRepository.getCachedStringGpsDeviceEnableFlag();
+            boolean gpsValidationDisabled = "Y".equalsIgnoreCase(enableFlag);
+            if (gpsValidationDisabled) {
+                Log.w(TAG, "GPS distance validation disabled by config, skipping");
+                return;
+            }
+
+            GeoLocationDto geoLocation = this.registrationDto.getGeoLocationDto();
+            if (geoLocation == null) {
+                Log.w(TAG, "Geo location not available, skipping validation");
+                return;
+            }
+
+            // Get center coordinates
+            CenterMachineDto centerMachineDto = masterDataService.getRegistrationCenterMachineDetails();
+            if (centerMachineDto == null) {
+                Log.w(TAG, "Center details not found, skipping distance validation");
+                return;
+            }
+
+            List centers = registrationCenterRepository.getRegistrationCenter(
+                centerMachineDto.getCenterId());
+
+            if (centers == null || centers.isEmpty()) {
+                Log.w(TAG, "Center not found, skipping distance validation");
+                return;
+            }
+
+            RegistrationCenter center = centers.get(0);
+            String centerLatStr = center.getLatitude();
+            String centerLonStr = center.getLongitude();
+
+            if (centerLatStr == null || centerLonStr == null ||
+                centerLatStr.isEmpty() || centerLonStr.isEmpty()) {
+                Log.e(TAG, "Center coordinates not available");
+                throw new ClientCheckedException(context, R.string.err_004);
+            }
+
+            try {
+                double centerLatitude = Double.parseDouble(centerLatStr);
+                double centerLongitude = Double.parseDouble(centerLonStr);
+
+                // Calculate distance
+                double distance = locationValidationService.getDistance(
+                    geoLocation.getLongitude(), geoLocation.getLatitude(),
+                    centerLongitude, centerLatitude);
+
+                // Get max allowed distance from config
+                String maxDistanceStr = globalParamRepository.getCachedStringMachineToCenterDistance();
+                if (maxDistanceStr == null || maxDistanceStr.isEmpty()) {
+                    Log.e(TAG, "Max allowed distance configuration not found");
+                    throw new ClientCheckedException(context, R.string.err_004);
+                }
+
+                double maxAllowedDistance = Double.parseDouble(maxDistanceStr);
+
+                // Validate distance
+                if (distance > maxAllowedDistance) {
+                    Log.e(TAG, "Distance not matched with allowed range");
+                    throw new ClientCheckedException(context, R.string.err_004);
+                }
+
+                Log.i(TAG, "Location validated successfully");
+
+            } catch (NumberFormatException e) {
+                Log.e(TAG, "Invalid center coordinates format", e);
+                // Continue with submission even if coordinates are invalid
+            }
+        } catch (ClientCheckedException e) {
+            throw e;
+        } catch (Exception e) {
+            Log.e(TAG, "Location validation failed: " + e.getMessage(), e);
+            // Continue with submission even if validation fails
+        }
+    }
+
     public List> getAudits() {
         List> audits = new ArrayList<>();
         String savedPoint = globalParamRepository.getCachedStringGlobalParam(RegistrationConstants.AUDIT_EXPORTED_TILL);
diff --git a/android/clientmanager/src/main/java/io/mosip/registration/clientmanager/spi/LocationValidationService.java b/android/clientmanager/src/main/java/io/mosip/registration/clientmanager/spi/LocationValidationService.java
new file mode 100644
index 000000000..86f937c14
--- /dev/null
+++ b/android/clientmanager/src/main/java/io/mosip/registration/clientmanager/spi/LocationValidationService.java
@@ -0,0 +1,22 @@
+package io.mosip.registration.clientmanager.spi;
+
+/**
+ * Service interface for location validation and distance calculation
+ * 
+ * @author sachin sp
+ */
+public interface LocationValidationService {
+
+    /**
+     * Calculate distance between two GPS coordinates using Haversine formula
+     * 
+     * @param machineLongitude Machine's current longitude
+     * @param machineLatitude Machine's current latitude
+     * @param centerLongitude Registration center's longitude
+     * @param centerLatitude Registration center's latitude
+     * @return Distance in kilometers
+     */
+    double getDistance(double machineLongitude, double machineLatitude,
+                      double centerLongitude, double centerLatitude);
+}
+
diff --git a/android/clientmanager/src/test/java/io/mosip/registration/clientmanager/service/RegistrationServiceImplTest.java b/android/clientmanager/src/test/java/io/mosip/registration/clientmanager/service/RegistrationServiceImplTest.java
index 27150e25f..5c336d0a6 100644
--- a/android/clientmanager/src/test/java/io/mosip/registration/clientmanager/service/RegistrationServiceImplTest.java
+++ b/android/clientmanager/src/test/java/io/mosip/registration/clientmanager/service/RegistrationServiceImplTest.java
@@ -12,8 +12,10 @@
 import io.mosip.registration.clientmanager.exception.ClientCheckedException;
 import io.mosip.registration.clientmanager.repository.GlobalParamRepository;
 import io.mosip.registration.clientmanager.repository.IdentitySchemaRepository;
+import io.mosip.registration.clientmanager.repository.RegistrationCenterRepository;
 import io.mosip.registration.clientmanager.repository.RegistrationRepository;
 import io.mosip.registration.clientmanager.spi.AuditManagerService;
+import io.mosip.registration.clientmanager.spi.LocationValidationService;
 import io.mosip.registration.clientmanager.spi.MasterDataService;
 import io.mosip.registration.clientmanager.spi.RegistrationService;
 import io.mosip.registration.keymanager.repository.KeyStoreRepository;
@@ -74,7 +76,10 @@ public class RegistrationServiceImplTest {
     @Mock
     private ClientCryptoManagerService clientCryptoManagerService;
     private RegistrationService registrationService;
-
+    @Mock
+    private RegistrationCenterRepository registrationCenterRepository;
+    @Mock
+    private LocationValidationService locationValidationService;
     @Mock
     private Biometrics095Service biometricService;
 
@@ -87,7 +92,7 @@ public void setUp() {
         when(mockApplicationContext.getSharedPreferences(anyString(), anyInt())).thenReturn(mockSharedPreferences);
         registrationService = new RegistrationServiceImpl(mockApplicationContext, packetWriterService,
                 registrationRepository, masterDataService, identitySchemaRepository, clientCryptoManagerService,
-                keyStoreRepository, globalParamRepository, auditManagerService, biometricService);
+                keyStoreRepository, globalParamRepository, auditManagerService,registrationCenterRepository,locationValidationService, biometricService);
     }
     
     @Test(expected = ClientCheckedException.class)
diff --git a/assets/l10n/app_ar.arb b/assets/l10n/app_ar.arb
index c89887c53..d7ba2d9cd 100644
--- a/assets/l10n/app_ar.arb
+++ b/assets/l10n/app_ar.arb
@@ -300,6 +300,8 @@
   "supervisor": "مشرف",
   "online": "متصل",
   "offline": "غير متصل على الانترنت",
+  "enabled": "ممكّن",
+  "disabled": "معطل",
   "logout_success": "لقد تم تسجيل بنجاح!",
   "logout_failure": "حدث خطأ ما، يرجى المحاولة مرة أخرى بعد مرور بعض الوقت",
   "go_to_home": "اذهب إلى المنزل",
diff --git a/assets/l10n/app_en.arb b/assets/l10n/app_en.arb
index c5724267a..6c45ecfd7 100644
--- a/assets/l10n/app_en.arb
+++ b/assets/l10n/app_en.arb
@@ -300,6 +300,8 @@
   "supervisor": "Supervisor",
   "online": "Online",
   "offline": "Offline",
+  "enabled": "Enabled",
+  "disabled": "Disabled",
   "logout_success": "You have been successfully logged out!",
   "logout_failure": "Something went wrong, please try again after some time",
   "go_to_home": "Go To Home",
diff --git a/assets/l10n/app_fr.arb b/assets/l10n/app_fr.arb
index 7ce39d507..c477e25ab 100644
--- a/assets/l10n/app_fr.arb
+++ b/assets/l10n/app_fr.arb
@@ -300,6 +300,8 @@
   "supervisor": "Superviseur",
   "online": "En ligne",
   "offline": "Hors ligne",
+  "enabled": "Activé",
+  "disabled": "Désactivé",
   "logout_success": "Vous avez été déconnecté avec succès!",
   "logout_failure": "Quelque chose s'est mal passé, veuillez réessayer après un certain temps",
   "go_to_home": "Aller à la maison",
diff --git a/assets/l10n/app_hi.arb b/assets/l10n/app_hi.arb
index 56e70d8ef..330db7a2f 100644
--- a/assets/l10n/app_hi.arb
+++ b/assets/l10n/app_hi.arb
@@ -300,6 +300,8 @@
   "supervisor": "पर्यवेक्षक",
   "online": "ऑनलाइन",
   "offline": "ऑफलाइन",
+  "enabled": "सक्षम",
+  "disabled": "अक्षम",
   "logout_success": "आप सफलता पूर्वक लॉगआउट कर चुके हैं!",
   "logout_failure": "कुछ गलती हो गई है, कृपया कुछ समय बाद पुनः प्रयास करें",
   "go_to_home": "होम पर जाएं",
diff --git a/assets/l10n/app_kn.arb b/assets/l10n/app_kn.arb
index 8f19e55e8..b22db4346 100644
--- a/assets/l10n/app_kn.arb
+++ b/assets/l10n/app_kn.arb
@@ -300,6 +300,8 @@
   "supervisor": "ಮೇಲ್ವಿಚಾರಕ",
   "online": "ಆನ್ಲೈನ್",
   "offline": "ಆಫ್ಲೈನ್",
+  "enabled": "ಸಕ್ರಿಯಗೊಳಿಸಲಾಗಿದೆ",
+  "disabled": "ನಿಷ್ಕ್ರಿಯಗೊಳಿಸಲಾಗಿದೆ",
   "logout_success": "ನೀವು ಯಶಸ್ವಿಯಾಗಿ ಲಾಗ್ ಔಟ್ ಆಗಿರುವಿರಿ!",
   "logout_failure": "ಏನೋ ತಪ್ಪಾಗಿದೆ, ದಯವಿಟ್ಟು ಸ್ವಲ್ಪ ಸಮಯದ ನಂತರ ಮತ್ತೆ ಪ್ರಯತ್ನಿಸಿ",
   "go_to_home": "ಮನೆಗೆ ಹೋಗು",
diff --git a/assets/l10n/app_ta.arb b/assets/l10n/app_ta.arb
index 45a99a3b0..1fd3ea1a2 100644
--- a/assets/l10n/app_ta.arb
+++ b/assets/l10n/app_ta.arb
@@ -309,6 +309,8 @@
   "supervisor": "மேற்பார்வையாளர்",
   "online": "நிகழ்நிலை",
   "offline": "ஆஃப்லைனில்",
+  "enabled": "இயக்கப்பட்டது",
+  "disabled": "முடக்கப்பட்டது",
   "logout_success": "நீங்கள் வெற்றிகரமாக வெளியேறிவிட்டீர்கள்!",
   "logout_failure": "ஏதோ தவறாகிவிட்டது, சிறிது நேரம் கழித்து மீண்டும் முயற்சிக்கவும்",
   "go_to_home": "வீட்டிற்கு போ",
diff --git a/lib/app_router.dart b/lib/app_router.dart
index 9d57ea001..7a6775c42 100644
--- a/lib/app_router.dart
+++ b/lib/app_router.dart
@@ -6,27 +6,24 @@
 */
 
 import 'package:flutter/material.dart';
-import 'package:registration_client/ui/process_ui/lost_process.dart';
-import 'package:registration_client/ui/process_ui/correction_process.dart';
-
-import 'package:registration_client/ui/process_ui/new_process.dart';
+import 'package:registration_client/ui/process_ui/generic_process.dart';
+import 'package:registration_client/ui/process_ui/process_type.dart';
 
 import 'package:registration_client/ui/login_page.dart';
 import 'package:registration_client/ui/onboard/onboard_landing_page.dart';
 import 'package:registration_client/ui/onboard/home_page.dart';
-import 'package:registration_client/ui/process_ui/update_process.dart';
 
 class AppRouter {
   AppRouter._();
 
   static Map routes = {
     LoginPage.route: (context) => const LoginPage(),
-    NewProcess.routeName: (context) => const NewProcess(),
-    UpdateProcess.routeName: (context) => const UpdateProcess(),
+    '/new_process': (context) => const GenericProcess(processType: ProcessType.newProcess),
+    '/update_process': (context) => const GenericProcess(processType: ProcessType.updateProcess),
+    '/lost_process': (context) => const GenericProcess(processType: ProcessType.lostProcess),
+    '/correction_process': (context) => const GenericProcess(processType: ProcessType.correctionProcess),
     OnboardLandingPage.route: (context) => const OnboardLandingPage(),
     HomePage.route: (context) => const HomePage(),
-    LostProcess.routeName: (context) => const LostProcess(),
-    CorrectionProcess.routeName: (context) => const CorrectionProcess(),
   };
 
   static Route? onUnknownRoute(RouteSettings settings) {
diff --git a/lib/platform_android/global_config_service_impl.dart b/lib/platform_android/global_config_service_impl.dart
index 4f77a0016..b8d472285 100644
--- a/lib/platform_android/global_config_service_impl.dart
+++ b/lib/platform_android/global_config_service_impl.dart
@@ -58,6 +58,19 @@ class GlobalConfigServiceImpl implements GlobalConfigService {
     }
   }
 
+  @override
+  Future getGpsEnableFlag() async {
+    String gpsEnableFlag = "";
+    try {
+      gpsEnableFlag = await GlobalConfigSettingsApi().getGpsEnableFlag();
+    } on PlatformException {
+      debugPrint("Location Api failed!");
+    }  catch (e) {
+      debugPrint("Location fetch error: $e");
+    }
+    return gpsEnableFlag;
+  }
+
 }
 
 GlobalConfigService getGlobalConfigServiceImpl() => GlobalConfigServiceImpl();
\ No newline at end of file
diff --git a/lib/platform_android/registration_service_impl.dart b/lib/platform_android/registration_service_impl.dart
index 6abc6dde2..cbce62dea 100644
--- a/lib/platform_android/registration_service_impl.dart
+++ b/lib/platform_android/registration_service_impl.dart
@@ -107,6 +107,17 @@ class RegistrationServiceImpl implements RegistrationService {
       debugPrint('Additional info req ID not added ${e.toString()}');
     }
   }
+
+  @override
+  Future setMachineLocation(double latitude, double longitude) async {
+    try {
+      await RegistrationDataApi().setMachineLocation(latitude, longitude);
+    } on PlatformException {
+      debugPrint('RegistrationDataApi call failed');
+    } catch (e) {
+      debugPrint('location not added ${e.toString()}');
+    }
+  }
 }
 
 RegistrationService getRegistrationServiceImpl() => RegistrationServiceImpl();
diff --git a/lib/platform_spi/global_config_service.dart b/lib/platform_spi/global_config_service.dart
index 5671b5880..eb481ff4f 100644
--- a/lib/platform_spi/global_config_service.dart
+++ b/lib/platform_spi/global_config_service.dart
@@ -9,5 +9,7 @@ abstract class GlobalConfigService {
 
   Future modifyConfigurations(Map localPreferences);
 
+  Future getGpsEnableFlag();
+
   factory GlobalConfigService() => getGlobalConfigServiceImpl();
 }
\ No newline at end of file
diff --git a/lib/platform_spi/registration_service.dart b/lib/platform_spi/registration_service.dart
index 79f0b61b7..866db15ce 100644
--- a/lib/platform_spi/registration_service.dart
+++ b/lib/platform_spi/registration_service.dart
@@ -18,6 +18,7 @@ abstract class RegistrationService {
   Future submitRegistrationDto(String makerName);
   Future setApplicationId(String applicationId);
   Future setAdditionalReqId(String additionalReqId);
+  Future setMachineLocation(double latitude, double longitude);
 
   factory RegistrationService() => getRegistrationServiceImpl();
 }
diff --git a/lib/provider/connectivity_provider.dart b/lib/provider/connectivity_provider.dart
index 3851aef02..6272a1b77 100644
--- a/lib/provider/connectivity_provider.dart
+++ b/lib/provider/connectivity_provider.dart
@@ -7,15 +7,18 @@
 
 import 'package:connectivity_plus/connectivity_plus.dart';
 import 'package:flutter/material.dart';
+import 'package:geolocator/geolocator.dart';
 import 'package:registration_client/platform_spi/network_service.dart';
 
 class ConnectivityProvider extends ChangeNotifier {
   NetworkService networkService = NetworkService();
   late ConnectivityResult _connectivityResult;
   bool _isConnected = false;
+  bool _isGPSEnabled = false;
 
   ConnectivityResult get connectivityResult => _connectivityResult;
   bool get isConnected => _isConnected;
+  bool get isGPSEnabled => _isGPSEnabled;
 
   checkNetworkConnection() async {
     String response = await networkService.checkInternetConnection();
@@ -26,4 +29,29 @@ class ConnectivityProvider extends ChangeNotifier {
     }
     notifyListeners();
   }
+
+  Future checkGPSStatus() async {
+    try {
+      bool serviceEnabled = await Geolocator.isLocationServiceEnabled();
+      
+      if (!serviceEnabled) {
+        _isGPSEnabled = false;
+        notifyListeners();
+        return;
+      }
+
+      LocationPermission permission = await Geolocator.checkPermission();
+      
+      if (permission == LocationPermission.denied || 
+          permission == LocationPermission.deniedForever ||
+          permission == LocationPermission.unableToDetermine) {
+        _isGPSEnabled = false;
+      } else {
+        _isGPSEnabled = true;
+      }
+    } catch (e) {
+      _isGPSEnabled = false;
+    }
+    notifyListeners();
+  }
 }
diff --git a/lib/provider/global_provider.dart b/lib/provider/global_provider.dart
index a3dd231d5..deac515f7 100644
--- a/lib/provider/global_provider.dart
+++ b/lib/provider/global_provider.dart
@@ -9,6 +9,7 @@ import 'dart:developer';
 
 import 'package:flutter/services.dart';
 import 'package:flutter/widgets.dart';
+import 'package:geolocator/geolocator.dart';
 import 'package:registration_client/model/field.dart';
 import 'package:registration_client/model/process.dart';
 import 'package:registration_client/pigeon/biometrics_pigeon.dart';
@@ -16,6 +17,7 @@ import 'package:registration_client/pigeon/common_details_pigeon.dart';
 import 'package:registration_client/pigeon/dynamic_response_pigeon.dart';
 import 'package:registration_client/platform_spi/audit_service.dart';
 import 'package:registration_client/platform_spi/dynamic_response_service.dart';
+import 'package:registration_client/platform_spi/global_config_service.dart';
 
 import 'package:registration_client/platform_spi/machine_key_service.dart';
 import 'package:registration_client/platform_spi/network_service.dart';
@@ -32,6 +34,7 @@ class GlobalProvider with ChangeNotifier {
       DynamicResponseService();
   final Audit audit = Audit();
   final NetworkService networkService = NetworkService();
+  final GlobalConfigService globalConfigService = GlobalConfigService();
 
   //Variables
   int _currentIndex = 0;
@@ -836,4 +839,40 @@ class GlobalProvider with ChangeNotifier {
     selectedUpdateFields = {};
     updateUINNumber = "";
   }
+
+  // Fetch current GPS location
+  // Returns Position if successful, null if GPS disabled or permission denied
+  Future fetchLocation() async {
+    // Check if GPS is enabled in configuration
+    String gpsFlag = await globalConfigService.getGpsEnableFlag();
+
+    if (gpsFlag.isEmpty || gpsFlag != "Y") {
+      return null;
+    }
+
+    // Check if location service is enabled on device
+    bool serviceEnabled = await Geolocator.isLocationServiceEnabled();
+    if (!serviceEnabled) {
+      return null;
+    }
+
+    // Check and request permission
+    LocationPermission permission = await Geolocator.checkPermission();
+    if (permission == LocationPermission.denied) {
+      permission = await Geolocator.requestPermission();
+      if (permission == LocationPermission.denied) {
+        // Permissions still denied
+        return null;
+      }
+    }
+
+    if (permission == LocationPermission.deniedForever) {
+      return null;
+    }
+
+    // Fetch location if permission is granted
+    return await Geolocator.getCurrentPosition(
+      desiredAccuracy: LocationAccuracy.high,
+    );
+  }
 }
diff --git a/lib/provider/registration_task_provider.dart b/lib/provider/registration_task_provider.dart
index d73ca4902..2eee264cc 100644
--- a/lib/provider/registration_task_provider.dart
+++ b/lib/provider/registration_task_provider.dart
@@ -353,4 +353,8 @@ class RegistrationTaskProvider with ChangeNotifier {
   setAdditionalReqId(String additionalReqId) async {
     await registrationService.setAdditionalReqId(additionalReqId);
   }
+
+  setCurrentLocation(double latitude, double longitude) async {
+    await registrationService.setMachineLocation(latitude, longitude);
+  }
 }
diff --git a/lib/ui/onboard/home_page.dart b/lib/ui/onboard/home_page.dart
index df5c72846..e68ef9335 100644
--- a/lib/ui/onboard/home_page.dart
+++ b/lib/ui/onboard/home_page.dart
@@ -63,6 +63,9 @@ class _HomePageState extends State {
     connectivityProvider =
         Provider.of(context, listen: false);
     _fetchProcessSpec();
+    WidgetsBinding.instance.addPostFrameCallback((_) async {
+      await globalProvider.fetchLocation();
+    });
     super.initState();
   }
 
diff --git a/lib/ui/process_ui/correction_process.dart b/lib/ui/process_ui/correction_process.dart
deleted file mode 100644
index b2f2e7835..000000000
--- a/lib/ui/process_ui/correction_process.dart
+++ /dev/null
@@ -1,1002 +0,0 @@
-import 'dart:convert';
-
-import 'package:flutter/material.dart';
-import 'package:flutter/services.dart';
-import 'package:flutter_screenutil/flutter_screenutil.dart';
-import 'package:flutter_svg/svg.dart';
-import 'package:provider/provider.dart';
-import 'package:registration_client/model/process.dart';
-import 'package:registration_client/model/screen.dart';
-import 'package:registration_client/provider/global_provider.dart';
-import 'package:registration_client/provider/registration_task_provider.dart';
-import 'package:registration_client/ui/post_registration/acknowledgement_page.dart';
-import 'package:registration_client/ui/post_registration/preview_page.dart';
-import 'package:registration_client/ui/process_ui/widgets/new_process_screen_content.dart';
-import 'package:registration_client/utils/app_config.dart';
-import 'package:flutter_gen/gen_l10n/app_localizations.dart';
-import 'package:registration_client/utils/app_style.dart';
-
-import '../../model/biometric_attribute_data.dart';
-import '../../pigeon/biometrics_pigeon.dart';
-import '../../pigeon/demographics_data_pigeon.dart';
-import '../../pigeon/registration_data_pigeon.dart';
-import '../../provider/auth_provider.dart';
-
-class CorrectionProcess extends StatefulWidget {
-  const CorrectionProcess({super.key});
-
-  static const routeName = '/correction_process';
-
-  @override
-  State createState() => _CorrectionProcessState();
-}
-
-class _CorrectionProcessState extends State with WidgetsBindingObserver {
-  late GlobalProvider globalProvider;
-  late RegistrationTaskProvider registrationTaskProvider;
-  late AuthProvider authProvider;
-  late AppLocalizations appLocalizations = AppLocalizations.of(context)!;
-  bool isPortrait = true;
-
-  List postRegistrationTabs = [
-    'Preview',
-    'Authentication',
-    'Acknowledgement',
-  ];
-
-  Map? templateTitleMap;
-
-  String username = '';
-  String password = '';
-
-  @override
-  void initState() {
-    globalProvider = Provider.of(context, listen: false);
-    registrationTaskProvider = Provider.of(context, listen: false);
-    authProvider = Provider.of(context, listen: false);
-    super.initState();
-  }
-
-  @override
-  void dispose() {
-    WidgetsBinding.instance.removeObserver(this);
-    super.dispose();
-  }
-
-  _authenticatePacket(BuildContext context) async {
-    if (!_validateUsername(context)) {
-      return false;
-    }
-
-    if (!_validatePassword(context)) {
-      return false;
-    }
-
-    if (authProvider.currentUser.userId != username) {
-      _showInSnackBar(appLocalizations.invalid_user);
-      return false;
-    }
-
-    await authProvider.authenticatePacket(username, password);
-
-    if (!authProvider.isPacketAuthenticated) {
-      _showErrorInSnackbar();
-      return false;
-    }
-    return true;
-  }
-
-  _showErrorInSnackbar() {
-    String errorMsg = authProvider.packetError;
-    String snackbarText = "";
-
-    switch (errorMsg) {
-      case "REG_TRY_AGAIN":
-        snackbarText = appLocalizations.login_failed;
-        break;
-
-      case "REG_INVALID_REQUEST":
-        snackbarText = appLocalizations.password_incorrect;
-        break;
-
-      case "REG_NETWORK_ERROR":
-        snackbarText = appLocalizations.network_error;
-        break;
-
-      case "":
-        return;
-
-      default:
-        snackbarText = errorMsg;
-        break;
-    }
-
-    _showInSnackBar(snackbarText);
-  }
-
-  bool _validateUsername(BuildContext context) {
-    if (username.trim().isEmpty) {
-      _showInSnackBar(appLocalizations.username_required);
-      return false;
-    }
-
-    if (username.trim().length > 50) {
-      _showInSnackBar(appLocalizations.username_exceed);
-      return false;
-    }
-
-    return true;
-  }
-
-  bool _validatePassword(BuildContext context) {
-    if (password.trim().isEmpty) {
-      _showInSnackBar(appLocalizations.password_required);
-      return false;
-    }
-
-    if (password.trim().length > 50) {
-      _showInSnackBar(appLocalizations.password_exceed);
-      return false;
-    }
-
-    return true;
-  }
-
-  _resetValuesOnRegistrationComplete() {
-    Navigator.of(context).pop();
-  }
-
-  _nextButtonClickedAudit() async {
-    await globalProvider.getAudit("REG-EVT-003", "REG-MOD-103");
-  }
-
-  void _showInSnackBar(String value) {
-    ScaffoldMessenger.of(context).showSnackBar(
-      SnackBar(
-        content: Text(value),
-      ),
-    );
-  }
-
-  bool continueButton = false;
-  bool authButton = false;
-  @override
-  Widget build(BuildContext context) {
-    postRegistrationTabs = [
-      AppLocalizations.of(context)!.preview_page,
-      AppLocalizations.of(context)!.packet_auth_page,
-      AppLocalizations.of(context)!.acknowledgement_page,
-    ];
-    isPortrait = MediaQuery.of(context).orientation == Orientation.portrait;
-    bool isMobile = MediaQuery.of(context).size.width < 750;
-    double w = ScreenUtil().screenWidth;
-    Map arguments =
-        ModalRoute.of(context)!.settings.arguments! as Map;
-    final Process process = arguments["process"];
-    int size = process.screens!.length;
-
-    evaluateMVELVisible(String fieldData) async {
-      bool visible =
-      await registrationTaskProvider.evaluateMVELVisible(fieldData);
-      return visible;
-    }
-
-    evaluateMVELRequired(String fieldData) async {
-      bool required =
-      await registrationTaskProvider.evaluateMVELRequired(fieldData);
-      return required;
-    }
-
-    isExceptionPresent(String id) {
-      bool isExceptionPresent = false;
-      for (BiometricAttributeData x in globalProvider.fieldInputValue[id]) {
-        if (x.exceptions.contains(true) || x.title == "Exception") {
-          isExceptionPresent = true;
-          break;
-        }
-      }
-      return isExceptionPresent;
-    }
-
-    returnBiometricListLength(List? list, String id) {
-      int i = 0;
-      if (list!.contains("leftEye") && list.contains("rightEye")) {
-        i++;
-      }
-      if (list.contains("rightIndex") &&
-          list.contains("rightLittle") &&
-          list.contains("rightRing") &&
-          list.contains("rightMiddle")) {
-        i++;
-      }
-      if (list.contains("leftIndex") &&
-          list.contains("leftLittle") &&
-          list.contains("leftRing") &&
-          list.contains("leftMiddle")) {
-        i++;
-      }
-      if (list.contains("rightThumb") && list.contains("rightThumb")) {
-        i++;
-      }
-      if (list.contains("face")) {
-        i++;
-      }
-      if (isExceptionPresent(id) == true) {
-        i++;
-      }
-      return i;
-    }
-
-    customValidation(int currentIndex) async {
-      if (currentIndex == 0) {
-        return true;
-      }
-      bool isValid = true;
-      if (globalProvider.newProcessTabIndex < size) {
-        Screen screen = process.screens!.elementAt(currentIndex)!;
-        for (int i = 0; i < screen.fields!.length; i++) {
-          if (screen.fields!.elementAt(i)!.inputRequired! &&
-              screen.fields!.elementAt(i)!.required!) {
-            if (!(globalProvider.fieldInputValue
-                .containsKey(screen.fields!.elementAt(i)!.id)) &&
-                !(globalProvider.fieldInputValue
-                    .containsKey(screen.fields!.elementAt(i)!.subType)) &&
-                !(globalProvider.fieldInputValue.containsKey(
-                    "${screen.fields!.elementAt(i)!.group}${screen.fields!.elementAt(i)!.subType}"))) {
-              isValid = false;
-
-              break;
-            }
-            if (screen.fields!.elementAt(i)!.conditionalBioAttributes != null &&
-                screen.fields!
-                    .elementAt(i)!
-                    .conditionalBioAttributes!
-                    .isNotEmpty) {
-              String response = await BiometricsApi().getAgeGroup();
-              if (!(response.compareTo(screen.fields!
-                  .elementAt(i)!
-                  .conditionalBioAttributes!
-                  .first!
-                  .ageGroup!) ==
-                  0)) {
-                if (screen.fields!.elementAt(i)!.controlType == "biometrics") {
-                  int count = returnBiometricListLength(
-                      screen.fields!.elementAt(i)!.bioAttributes,
-                      screen.fields!.elementAt(i)!.id!);
-                  if (globalProvider.completeException[
-                  screen.fields!.elementAt(i)!.id!] !=
-                      null) {
-                    int length = globalProvider
-                        .completeException[screen.fields!.elementAt(i)!.id!]
-                        .length;
-                    count = count - length;
-                  }
-
-                  if (globalProvider
-                      .fieldInputValue[screen.fields!.elementAt(i)!.id!]
-                      .length <
-                      count) {
-                    isValid = false;
-
-                    break;
-                  }
-                  if(globalProvider.isValidBiometricCapture){
-                    isValid = false;
-                    break;
-                  }
-                }
-              }
-            }
-          }
-          if (screen.fields!.elementAt(i)!.requiredOn != null &&
-              screen.fields!.elementAt(i)!.requiredOn!.isNotEmpty) {
-            bool visible = await evaluateMVELVisible(
-                jsonEncode(screen.fields!.elementAt(i)!.toJson()));
-            bool required = await evaluateMVELRequired(
-                jsonEncode(screen.fields!.elementAt(i)!.toJson()));
-            if (visible && required) {
-              if (screen.fields!.elementAt(i)!.inputRequired!) {
-                if (!(globalProvider.fieldInputValue
-                    .containsKey(screen.fields!.elementAt(i)!.id)) &&
-                    !(globalProvider.fieldInputValue
-                        .containsKey(screen.fields!.elementAt(i)!.subType)) &&
-                    !(globalProvider.fieldInputValue.containsKey(
-                        "${screen.fields!.elementAt(i)!.group}${screen.fields!.elementAt(i)!.subType}"))) {
-                  isValid = false;
-
-                  break;
-                }
-                if (screen.fields!.elementAt(i)!.conditionalBioAttributes !=
-                    null &&
-                    screen.fields!
-                        .elementAt(i)!
-                        .conditionalBioAttributes!
-                        .isNotEmpty) {
-                  String response = await BiometricsApi().getAgeGroup();
-                  if (!(response.compareTo(screen.fields!
-                      .elementAt(i)!
-                      .conditionalBioAttributes!
-                      .first!
-                      .ageGroup!) ==
-                      0)) {
-                    if (screen.fields!.elementAt(i)!.controlType ==
-                        "biometrics") {
-                      int count = returnBiometricListLength(
-                          screen.fields!.elementAt(i)!.bioAttributes,
-                          screen.fields!.elementAt(i)!.id!);
-                      if (globalProvider.completeException[
-                      screen.fields!.elementAt(i)!.id!] !=
-                          null) {
-                        int length = globalProvider
-                            .completeException[screen.fields!.elementAt(i)!.id!]
-                            .length;
-                        count = count - length;
-                      }
-                      if (globalProvider
-                          .fieldInputValue[screen.fields!.elementAt(i)!.id!]
-                          .length <
-                          count) {
-                        isValid = false;
-
-                        break;
-                      }
-                      if(globalProvider.isValidBiometricCapture){
-                        isValid = false;
-                        break;
-                      }
-                    }
-                  }
-                  if (response.compareTo(screen.fields!
-                      .elementAt(i)!
-                      .conditionalBioAttributes!
-                      .first!
-                      .ageGroup!) ==
-                      0) {
-                    bool valid = await BiometricsApi()
-                        .conditionalBioAttributeValidation(
-                        screen.fields!.elementAt(i)!.id!,
-                        screen.fields!
-                            .elementAt(i)!
-                            .conditionalBioAttributes!
-                            .first!
-                            .validationExpr!);
-                    if (screen.fields!.elementAt(i)!.exceptionPhotoRequired ==
-                        true) {
-                      List biometricAttributeDataList =
-                      globalProvider.fieldInputValue[
-                      screen.fields!.elementAt(i)!.id!];
-                      bool isExceptionPresent = false;
-                      bool isExceptionAttributePresent = false;
-                      for (var biometricAttributeData
-                      in biometricAttributeDataList) {
-                        if (globalProvider.exceptionAttributes
-                            .contains(biometricAttributeData.title)) {
-                          isExceptionPresent = true;
-                        }
-                        if (biometricAttributeData.title == "Exception") {
-                          isExceptionAttributePresent = true;
-                        }
-                      }
-                      if (isExceptionPresent == true &&
-                          isExceptionAttributePresent == false) {
-                        isValid = false;
-                        break;
-                      }
-                    }
-                    if (!valid) {
-                      isValid = false;
-                      break;
-                    }
-                  }
-                }
-              }
-            }
-          }
-        }
-      }
-      return isValid;
-    }
-
-    continueButtonTap(int size, newProcess) async {
-      globalProvider.isPageChanged = true;
-      if (globalProvider.newProcessTabIndex < size) {
-        bool customValidator =
-        await customValidation(globalProvider.newProcessTabIndex);
-        if (customValidator) {
-          if (globalProvider.formKey.currentState!.validate()) {
-            if (globalProvider.newProcessTabIndex ==
-                newProcess.screens!.length - 1) {
-              templateTitleMap = {
-                'demographicInfo': appLocalizations.demographic_information,
-                'documents': appLocalizations.documents,
-                'bioMetrics': appLocalizations.biometrics
-              };
-              registrationTaskProvider.setPreviewTemplate("");
-              registrationTaskProvider.setAcknowledgementTemplate("");
-              await registrationTaskProvider.getPreviewTemplate(
-                  true, templateTitleMap!);
-              await registrationTaskProvider.getAcknowledgementTemplate(
-                false, templateTitleMap!,
-              );
-            }
-
-            globalProvider.newProcessTabIndex =
-                globalProvider.newProcessTabIndex + 1;
-          }
-        }
-
-        _nextButtonClickedAudit();
-      } else {
-        if (globalProvider.newProcessTabIndex == size + 1) {
-          bool isPacketAuthenticated = await _authenticatePacket(context);
-          if (!isPacketAuthenticated) {
-            return;
-          }
-          RegistrationSubmitResponse registrationSubmitResponse =
-          await registrationTaskProvider.submitRegistrationDto(username);
-
-          if (registrationSubmitResponse.errorCode!.isNotEmpty) {
-            _showInSnackBar(registrationSubmitResponse.errorCode!);
-            return;
-          }
-          globalProvider.setRegId(registrationSubmitResponse.rId);
-
-          // Updating key to packetId after success creation of packet
-          registrationTaskProvider
-              .updateTemplateStorageKey(registrationSubmitResponse.rId);
-          registrationTaskProvider.deleteDefaultTemplateStored();
-
-          setState(() {
-            username = '';
-            password = '';
-          });
-        }
-        if (globalProvider.newProcessTabIndex == size + 2) {
-          _resetValuesOnRegistrationComplete();
-          return;
-        }
-        globalProvider.newProcessTabIndex =
-            globalProvider.newProcessTabIndex + 1;
-      }
-    }
-
-    customValidation(globalProvider.newProcessTabIndex).then((value) {
-      setState(() {
-        continueButton = value &&
-            globalProvider.formKey.currentState != null &&
-            globalProvider.formKey.currentState!.validate();
-
-        // Disable continue if Additional Info Req ID is required but not entered
-        if (globalProvider.newProcessTabIndex < size) {
-          final screen = process.screens![globalProvider.newProcessTabIndex]!;
-          if (screen.additionalInfoRequestIdRequired == true &&
-              (globalProvider.additionalInfoReqId == null ||
-                  globalProvider.additionalInfoReqId!.trim().isEmpty)) {
-            continueButton = false;
-          }
-        }
-      });
-      if (globalProvider.newProcessTabIndex >= size) {
-        continueButton = true;
-      }
-    });
-
-    //auth button validation
-    if(username.trim().isNotEmpty && password.trim().isNotEmpty){
-      authButton = true;
-    }
-
-    return WillPopScope(
-      onWillPop: () async => true,
-      child: SafeArea(
-        child: Scaffold(
-          backgroundColor: secondaryColors.elementAt(10),
-          bottomNavigationBar: Container(
-            decoration: BoxDecoration(
-              border: const Border(
-                top: BorderSide(
-                  color: dividerColor,
-                  width: 1,
-                ),
-              ),
-              color: pureWhite,
-            ),
-            padding: EdgeInsets.symmetric(
-              horizontal: isPortrait ? 20.w : 60.w,
-              vertical: 16.h,
-            ),
-            // height: isPortrait ? 94.h : 84.h,
-            child: globalProvider.newProcessTabIndex == 0
-                ? Row(
-              children: [
-                Expanded(
-                  child: OutlinedButton(
-                    child: SizedBox(
-                      height: isPortrait && !isMobileSize ? 68.h : 52.h,
-                      child: Center(
-                        child: Text(
-                          appLocalizations.go_back,
-                          style: TextStyle(
-                            fontSize:
-                            isPortrait && !isMobileSize ? 22 : 14,
-                          ),
-                        ),
-                      ),
-                    ),
-                    onPressed: () {
-                      Navigator.of(context).pop();
-                    },
-                  ),
-                ),
-                SizedBox(
-                  width: 10.w,
-                ),
-                Expanded(
-                  child: ElevatedButton(
-                    child: SizedBox(
-                      height: isPortrait && !isMobileSize ? 68.h : 52.h,
-                      child: Center(
-                        child: Text(
-                          appLocalizations.informed,
-                          style: TextStyle(
-                            fontSize:
-                            isPortrait && !isMobileSize ? 22 : 14,
-                          ),
-                        ),
-                      ),
-                    ),
-                    onPressed: () async {
-                      registrationTaskProvider.addConsentField("Y");
-                      await DemographicsApi()
-                          .addDemographicField("consent", "true");
-                      continueButtonTap(size, process);
-                    },
-                  ),
-                ),
-              ],
-            )
-                : Row(
-              mainAxisAlignment: MainAxisAlignment.start,
-              children: [
-                const Expanded(
-                  child: SizedBox(),
-                ),
-                ElevatedButton(
-                  style: ButtonStyle(
-                    maximumSize: MaterialStateProperty.all(
-                        const Size(209, 52)),
-                    minimumSize: MaterialStateProperty.all(
-                        const Size(209, 52)),
-                    backgroundColor: MaterialStateProperty.all(
-                        (continueButton && context.read().newProcessTabIndex <=
-                            size) ? solidPrimary : authButton ? solidPrimary: Colors.grey),
-                  ),
-                  onPressed: () {
-                    continueButtonTap(size, process);
-                  },
-                  child: Text(
-                    context.read().newProcessTabIndex <=
-                        size
-                        ? appLocalizations.continue_text
-                        : globalProvider.newProcessTabIndex == size + 1
-                        ? appLocalizations.authenticate
-                        : appLocalizations.go_to_home,
-                    style: const TextStyle(color: appWhite),
-                  ),
-                ),
-              ],
-            ),
-          ),
-          body: SingleChildScrollView(
-            child: AnnotatedRegion(
-              value: const SystemUiOverlayStyle(
-                statusBarColor: Colors.transparent,
-              ),
-              child: Column(
-                children: [
-                  Container(
-                    padding: isMobile && !isMobileSize
-                        ? const EdgeInsets.fromLTRB(0, 46, 0, 0)
-                        : const EdgeInsets.fromLTRB(0, 0, 0, 0),
-                    decoration: const BoxDecoration(
-                      gradient: LinearGradient(
-                        begin: Alignment.topCenter,
-                        end: Alignment.bottomCenter,
-                        colors: [Color(0xff214FBF), Color(0xff1C43A1)],
-                      ),
-                    ),
-                    child: Column(
-                      crossAxisAlignment: CrossAxisAlignment.start,
-                      children: [
-                        SizedBox(
-                          width: w,
-                          height: isPortrait ? 21.w : 30.w,
-                        ),
-                        Padding(
-                          padding: isPortrait
-                              ? EdgeInsets.fromLTRB(20.w, 0, 0, 0)
-                              : EdgeInsets.fromLTRB(60.w, 0, 60.w, 0),
-                          child: Text(
-                            process.label![context
-                                .read()
-                                .selectedLanguage]!,
-                            style: Theme.of(context)
-                                .textTheme
-                                .titleMedium
-                                ?.copyWith(
-                                color: pureWhite,
-                                fontWeight: semiBold,
-                                fontSize: isPortrait ? 24 : 21),
-                          ),
-                        ),
-                        SizedBox(
-                          height: 30.h,
-                        ),
-                        Divider(
-                          height: 12.h,
-                          thickness: 1,
-                          color: secondaryColors.elementAt(2),
-                        ),
-                        Padding(
-                          padding: isPortrait
-                              ? const EdgeInsets.all(0)
-                              : EdgeInsets.fromLTRB(60.w, 0, 60.w, 0),
-                          child: Stack(
-                            alignment: FractionalOffset.centerRight,
-                            children: [
-                              Padding(
-                                padding: isPortrait
-                                    ? EdgeInsets.fromLTRB(20.w, 10.h, 0, 0)
-                                    : EdgeInsets.fromLTRB(0, 10.h, 0, 0),
-                                child: SizedBox(
-                                  height: 36.h,
-                                  child: ListView.builder(
-                                      padding: const EdgeInsets.all(0),
-                                      scrollDirection: Axis.horizontal,
-                                      itemCount: process.screens!.length + 3,
-                                      itemBuilder:
-                                          (BuildContext context, int index) {
-                                        return GestureDetector(
-                                          onTap: () {
-                                            if (context
-                                                .read()
-                                                .newProcessTabIndex ==
-                                                size + 2) {
-                                              return;
-                                            }
-
-                                            if (index <
-                                                context
-                                                    .read()
-                                                    .newProcessTabIndex) {
-                                              context
-                                                  .read()
-                                                  .newProcessTabIndex = index;
-                                            }
-                                          },
-                                          child: Row(
-                                            children: [
-                                              Container(
-                                                padding: EdgeInsets.fromLTRB(
-                                                    0, 0, 0, 8.h),
-                                                decoration: BoxDecoration(
-                                                  border: Border(
-                                                    bottom: BorderSide(
-                                                        color: (context
-                                                            .watch<
-                                                            GlobalProvider>()
-                                                            .newProcessTabIndex ==
-                                                            index)
-                                                            ? pureWhite
-                                                            : Colors
-                                                            .transparent,
-                                                        width: 3),
-                                                  ),
-                                                ),
-                                                child: Row(
-                                                  children: [
-                                                    (index <
-                                                        context
-                                                            .watch<
-                                                            GlobalProvider>()
-                                                            .newProcessTabIndex)
-                                                        ? Icon(
-                                                      Icons.check_circle,
-                                                      size: 17,
-                                                      color:
-                                                      secondaryColors
-                                                          .elementAt(
-                                                          11),
-                                                    )
-                                                        : (context
-                                                        .watch<
-                                                        GlobalProvider>()
-                                                        .newProcessTabIndex ==
-                                                        index)
-                                                        ? Icon(
-                                                      Icons.circle,
-                                                      color:
-                                                      pureWhite,
-                                                      size: 17,
-                                                    )
-                                                        : Icon(
-                                                      Icons
-                                                          .circle_outlined,
-                                                      size: 17,
-                                                      color: secondaryColors
-                                                          .elementAt(
-                                                          9),
-                                                    ),
-                                                    SizedBox(
-                                                      width: 6.w,
-                                                    ),
-                                                    Text(
-                                                      index < size
-                                                          ? process
-                                                          .screens![index]!
-                                                          .label![
-                                                      context
-                                                          .read<
-                                                          GlobalProvider>()
-                                                          .selectedLanguage]!
-                                                          : postRegistrationTabs[
-                                                      index - size],
-                                                      style: Theme.of(context)
-                                                          .textTheme
-                                                          .titleSmall
-                                                          ?.copyWith(
-                                                          color: (context
-                                                              .watch<
-                                                              GlobalProvider>()
-                                                              .newProcessTabIndex ==
-                                                              index)
-                                                              ? pureWhite
-                                                              : secondaryColors
-                                                              .elementAt(
-                                                              9),
-                                                          fontWeight:
-                                                          semiBold,
-                                                          fontSize: 14),
-                                                    ),
-                                                  ],
-                                                ),
-                                              ),
-                                              SizedBox(
-                                                width: 35.w,
-                                              ),
-                                            ],
-                                          ),
-                                        );
-                                      }),
-                                ),
-                              ),
-                              Container(
-                                height: 36.h,
-                                width: 25.w,
-                                padding: const EdgeInsets.fromLTRB(0, 0, 0, 0),
-                                color: solidPrimary,
-                                child: Icon(
-                                  Icons.arrow_forward_ios_outlined,
-                                  color: pureWhite,
-                                  size: 17,
-                                ),
-                              ),
-                            ],
-                          ),
-                        ),
-                        const SizedBox(
-                          height: 5,
-                        ),
-                      ],
-                    ),
-                  ),
-                  Padding(
-                    padding: isPortrait
-                        ? const EdgeInsets.all(0)
-                        : EdgeInsets.fromLTRB(60.w, 0, 60.w, 0),
-                    child: context.watch().newProcessTabIndex <
-                        size
-                        ? NewProcessScreenContent(
-                        context: context,
-                        screen: process.screens!.elementAt(context
-                            .watch()
-                            .newProcessTabIndex)!)
-                        : context.watch().newProcessTabIndex ==
-                        size
-                        ? const PreviewPage()
-                        : context
-                        .watch()
-                        .newProcessTabIndex ==
-                        size + 1
-                        ? _getPacketAuthComponent()
-                        : const AcknowledgementPage(),
-                  ),
-                  SizedBox(
-                    height: 20.h,
-                  ),
-                ],
-              ),
-            ),
-          ),
-        ),
-      ),
-    );
-  }
-
-  Widget _getPacketAuthComponent() {
-    return Column(
-      children: [
-        SizedBox(
-          height: 30.h,
-        ),
-        Container(
-          width: isPortrait && !isMobileSize ? 566.w : 376.w,
-          padding: EdgeInsets.only(
-            top: 24.h,
-            bottom: 28.h,
-            left: 20.w,
-            right: 20.w,
-          ),
-          decoration: BoxDecoration(
-            borderRadius: const BorderRadius.all(
-              Radius.circular(6),
-            ),
-            color: pureWhite,
-          ),
-          child: Column(
-            children: [
-              _getAuthIcon(),
-              SizedBox(
-                height: 26.h,
-              ),
-              Text(
-                appLocalizations.authenticate_using_password,
-                style: TextStyle(
-                    fontSize: isPortrait && !isMobileSize ? 24 : 18,
-                    fontWeight: semiBold,
-                    color: appBlack),
-              ),
-              SizedBox(
-                height: 35.h,
-              ),
-              Row(
-                children: [
-                  Text(
-                    appLocalizations.username,
-                    style: isPortrait
-                        ? AppTextStyle.tabletPortraitTextfieldHeader
-                        : AppTextStyle.mobileTextfieldHeader,
-                  ),
-                  const Text(
-                    ' *',
-                    style: TextStyle(
-                      color: mandatoryField,
-                    ),
-                  ),
-                ],
-              ),
-              SizedBox(
-                height: 11.h,
-              ),
-              _getUsernameTextField(),
-              SizedBox(
-                height: 35.h,
-              ),
-              Row(
-                children: [
-                  Text(
-                    appLocalizations.password,
-                    style: isPortrait
-                        ? AppTextStyle.tabletPortraitTextfieldHeader
-                        : AppTextStyle.mobileTextfieldHeader,
-                  ),
-                  const Text(
-                    ' *',
-                    style: TextStyle(color: mandatoryField),
-                  ),
-                ],
-              ),
-              SizedBox(
-                height: 11.h,
-              ),
-              _getPasswordTextField(),
-            ],
-          ),
-        ),
-      ],
-    );
-  }
-
-  _getAuthIcon() {
-    return Container(
-      height: 80.w,
-      width: 80.w,
-      decoration: BoxDecoration(
-        shape: BoxShape.circle,
-        border: Border.all(
-          color: authIconBorder,
-          width: 2,
-        ),
-        color: authIconBackground,
-      ),
-      child: Center(
-        child: SvgPicture.asset('assets/images/AuthenticationIcon.svg'),
-      ),
-    );
-  }
-
-  _getUsernameTextField() {
-    return Container(
-      height: isPortrait && !isMobileSize ? 82.h : 52.h,
-      alignment: Alignment.centerLeft,
-      padding: EdgeInsets.symmetric(
-        horizontal: 12.w,
-      ),
-      decoration: BoxDecoration(
-        border: Border.all(
-          width: 1.h,
-          color: appGreyShade,
-        ),
-        borderRadius: const BorderRadius.all(
-          Radius.circular(6),
-        ),
-      ),
-      child: TextField(
-        decoration: InputDecoration(
-          hintText: appLocalizations.enter_username,
-          hintStyle: isPortrait && !isMobileSize
-              ? AppTextStyle.tabletPortraitTextfieldHintText
-              : AppTextStyle.mobileTextfieldHintText,
-          border: InputBorder.none,
-        ),
-        style: TextStyle(
-          fontSize: isPortrait && !isMobileSize ? 22 : 14,
-          color: appBlack,
-        ),
-        onChanged: (v) {
-          setState(() {
-            username = v;
-          });
-        },
-      ),
-    );
-  }
-
-  _getPasswordTextField() {
-    return Container(
-      height: isPortrait && !isMobileSize ? 82.h : 52.h,
-      alignment: Alignment.centerLeft,
-      padding: EdgeInsets.symmetric(
-        horizontal: 12.w,
-      ),
-      decoration: BoxDecoration(
-        border: Border.all(
-          width: 1.h,
-          color: appGreyShade,
-        ),
-        borderRadius: const BorderRadius.all(
-          Radius.circular(6),
-        ),
-      ),
-      child: TextField(
-        obscureText: true,
-        decoration: InputDecoration(
-          hintText: appLocalizations.enter_password,
-          hintStyle: isPortrait && !isMobileSize
-              ? AppTextStyle.tabletPortraitTextfieldHintText
-              : AppTextStyle.mobileTextfieldHintText,
-          border: InputBorder.none,
-        ),
-        style: TextStyle(
-          fontSize: isPortrait && !isMobileSize ? 22 : 14,
-          color: appBlack,
-        ),
-        onChanged: (v) {
-          setState(() {
-            password = v;
-          });
-        },
-      ),
-    );
-  }
-}
diff --git a/lib/ui/process_ui/generic_process.dart b/lib/ui/process_ui/generic_process.dart
new file mode 100644
index 000000000..13e1a93e4
--- /dev/null
+++ b/lib/ui/process_ui/generic_process.dart
@@ -0,0 +1,1371 @@
+/*
+ * Copyright (c) Modular Open Source Identity Platform
+ * This source code is licensed under the MIT license found in the
+ * LICENSE file in the root directory of this source tree.
+ *
+*/
+
+import 'dart:convert';
+
+import 'package:flutter/material.dart';
+import 'package:flutter/services.dart';
+
+import 'package:flutter_screenutil/flutter_screenutil.dart';
+import 'package:flutter_svg/flutter_svg.dart';
+import 'package:provider/provider.dart';
+import 'package:geolocator/geolocator.dart';
+import 'package:registration_client/model/biometric_attribute_data.dart';
+import 'package:registration_client/model/field.dart';
+import 'package:registration_client/model/process.dart';
+import 'package:registration_client/model/screen.dart';
+import 'package:registration_client/ui/process_ui/process_type.dart';
+import 'package:registration_client/pigeon/biometrics_pigeon.dart';
+import 'package:registration_client/pigeon/demographics_data_pigeon.dart';
+import 'package:registration_client/pigeon/registration_data_pigeon.dart';
+
+import 'package:registration_client/provider/auth_provider.dart';
+import 'package:registration_client/provider/connectivity_provider.dart';
+import 'package:registration_client/provider/global_provider.dart';
+import 'package:registration_client/provider/registration_task_provider.dart';
+
+import 'package:registration_client/ui/post_registration/acknowledgement_page.dart';
+import 'package:registration_client/ui/post_registration/preview_page.dart';
+import 'package:registration_client/ui/process_ui/widgets/generic_process_screen_content.dart';
+import 'package:registration_client/ui/process_ui/widgets/update_field_selector.dart';
+
+import 'package:registration_client/utils/app_config.dart';
+import 'package:flutter_gen/gen_l10n/app_localizations.dart';
+import 'package:registration_client/utils/app_style.dart';
+
+import '../../utils/life_cycle_event_handler.dart';
+
+class GenericProcess extends StatefulWidget {
+  final ProcessType processType;
+
+  const GenericProcess({
+    super.key,
+    required this.processType,
+  });
+
+  @override
+  State createState() => _GenericProcessState();
+}
+
+class _GenericProcessState extends State
+    with WidgetsBindingObserver {
+  late GlobalProvider globalProvider;
+  late RegistrationTaskProvider registrationTaskProvider;
+  late AuthProvider authProvider;
+  late ConnectivityProvider connectivityProvider;
+  late AppLocalizations appLocalizations = AppLocalizations.of(context)!;
+  bool isPortrait = true;
+  ScrollController scrollController = ScrollController();
+  bool _isContinueProcessing = false;
+  bool fieldSelectionCompleted = false;
+
+  List postRegistrationTabs = [
+    'Preview',
+    'Authentication',
+    'Acknowledgement',
+  ];
+
+  Map? templateTitleMap;
+
+  String username = '';
+  String password = '';
+
+  @override
+  void initState() {
+    globalProvider = Provider.of(context, listen: false);
+    registrationTaskProvider =
+        Provider.of(context, listen: false);
+    authProvider = Provider.of(context, listen: false);
+    connectivityProvider =
+        Provider.of(context, listen: false);
+    super.initState();
+    WidgetsBinding.instance.addObserver(LifecycleEventHandler(
+      resumeCallBack: () async {
+        if (mounted) {
+          setState(() {
+            closeKeyboard();
+          });
+        }
+      },
+      suspendingCallBack: () async {
+        if (mounted) {
+          setState(() {
+            closeKeyboard();
+          });
+        }
+      },
+    ));
+    _registrationScreenLoadedAudit();
+    WidgetsBinding.instance.addPostFrameCallback((_) async {
+      await _fetchLocation();
+    });
+  }
+
+  bool _locationFetched = false;
+
+  Future _fetchLocation() async {
+    if (_locationFetched) return;
+    _locationFetched = true;
+
+    Position? position = await globalProvider.fetchLocation();
+    if (position != null) {
+      registrationTaskProvider.setCurrentLocation(position.latitude, position.longitude);
+    } else {
+      debugPrint("Location unavailable — permission denied or service off.");
+    }
+  }
+
+  @override
+  void dispose() {
+    WidgetsBinding.instance.removeObserver(this);
+    super.dispose();
+  }
+
+  void closeKeyboard() {
+    FocusScope.of(context).unfocus();
+  }
+
+  void _showInSnackBar(String value) {
+    ScaffoldMessenger.of(context).showSnackBar(
+      SnackBar(
+        content: Text(value),
+      ),
+    );
+  }
+
+  _authenticatePacket(BuildContext context) async {
+    if (!_validateUsername(context)) {
+      return false;
+    }
+
+    if (!_validatePassword(context)) {
+      return false;
+    }
+
+    if (authProvider.currentUser.userId != username) {
+      _showInSnackBar(appLocalizations.invalid_user);
+      return false;
+    }
+
+    await authProvider.authenticatePacket(username, password);
+
+    if (!authProvider.isPacketAuthenticated) {
+      _showErrorInSnackbar();
+      return false;
+    }
+    return true;
+  }
+
+  _showErrorInSnackbar() {
+    String errorMsg = authProvider.packetError;
+    String snackbarText = "";
+
+    switch (errorMsg) {
+      case "REG_TRY_AGAIN":
+        snackbarText = appLocalizations.login_failed;
+        break;
+
+      case "REG_INVALID_REQUEST":
+        snackbarText = appLocalizations.password_incorrect;
+        break;
+
+      case "REG_NETWORK_ERROR":
+        snackbarText = appLocalizations.network_error;
+        break;
+
+      case "":
+        return;
+
+      default:
+        snackbarText = errorMsg;
+        break;
+    }
+
+    _showInSnackBar(snackbarText);
+  }
+
+  bool _validateUsername(BuildContext context) {
+    if (username.trim().isEmpty) {
+      _showInSnackBar(appLocalizations.username_required);
+      return false;
+    }
+
+    if (username.trim().length > 50) {
+      _showInSnackBar(appLocalizations.username_exceed);
+      return false;
+    }
+
+    return true;
+  }
+
+  bool _validatePassword(BuildContext context) {
+    if (password.trim().isEmpty) {
+      _showInSnackBar(appLocalizations.password_required);
+      return false;
+    }
+
+    if (password.trim().length > 50) {
+      _showInSnackBar(appLocalizations.password_exceed);
+      return false;
+    }
+
+    return true;
+  }
+
+  _resetValuesOnRegistrationComplete() {
+    Navigator.of(context).pop();
+  }
+
+  void _registrationScreenLoadedAudit() async {
+    await globalProvider.getAudit("REG-EVT-002", "REG-MOD-103");
+  }
+
+  _nextButtonClickedAudit() async {
+    await globalProvider.getAudit("REG-EVT-003", "REG-MOD-103");
+  }
+
+  setScrollToTop() {
+    scrollController.animateTo(
+      scrollController.position.minScrollExtent,
+      duration: const Duration(milliseconds: 500),
+      curve: Curves.easeOut,
+    );
+    globalProvider.isPageChanged = false;
+  }
+
+  Future onWillPop(Process process) async {
+    if (globalProvider.newProcessTabIndex > 0 &&
+        globalProvider.newProcessTabIndex <
+            process.screens!.length + postRegistrationTabs.length - 1) {
+      globalProvider.newProcessTabIndex =
+          globalProvider.newProcessTabIndex - 1;
+    } else if (globalProvider.newProcessTabIndex == 0 &&
+        fieldSelectionCompleted) {
+      setState(() {
+        fieldSelectionCompleted = false;
+      });
+    } else {
+      return true;
+    }
+    return false;
+  }
+
+  bool isExceptionPresent(String id) {
+    bool isExceptionPresent = false;
+    for (BiometricAttributeData x in globalProvider.fieldInputValue[id]) {
+      if (x.exceptions.contains(true) || x.title == "Exception") {
+        isExceptionPresent = true;
+        break;
+      }
+    }
+    return isExceptionPresent;
+  }
+
+  int returnBiometricListLength(List? list, String id) {
+    int i = 0;
+    if (list!.contains("leftEye") && list.contains("rightEye")) {
+      i++;
+    }
+    if (list.contains("rightIndex") &&
+        list.contains("rightLittle") &&
+        list.contains("rightRing") &&
+        list.contains("rightMiddle")) {
+      i++;
+    }
+    if (list.contains("leftIndex") &&
+        list.contains("leftLittle") &&
+        list.contains("leftRing") &&
+        list.contains("leftMiddle")) {
+      i++;
+    }
+    if (list.contains("rightThumb") && list.contains("rightThumb")) {
+      i++;
+    }
+    if (list.contains("face")) {
+      i++;
+    }
+    if (isExceptionPresent(id) == true) {
+      i++;
+    }
+    return i;
+  }
+
+  Future ageDateChangeValidation(int currentIndex, Process process, int size) async {
+    if (globalProvider.newProcessTabIndex < size) {
+      Screen screen = process.screens!.elementAt(currentIndex)!;
+      for (int i = 0; i < screen.fields!.length; i++) {
+        if (screen.fields!.elementAt(i)!.controlType == "ageDate") {
+          if (globalProvider.checkAgeGroupChange == "") {
+            globalProvider.checkAgeGroupChange = globalProvider.ageGroup;
+          } else {
+            if (globalProvider.checkAgeGroupChange
+                    .compareTo(globalProvider.ageGroup) ==
+                0) {
+            } else {
+              List screens = [];
+              for (int i = 0;
+                  i < registrationTaskProvider.listOfProcesses.length;
+                  i++) {
+                Process tempProcess = Process.fromJson(
+                  jsonDecode(
+                    context
+                        .read()
+                        .listOfProcesses
+                        .elementAt(i)
+                        .toString(),
+                  ),
+                );
+                if (tempProcess.id == widget.processType.id ||
+                    (widget.processType == ProcessType.updateProcess &&
+                        tempProcess.id == "NEW")) {
+                  screens = tempProcess.screens!;
+                }
+              }
+              for (Screen? screen in screens) {
+                if (screen!.name! == "Documents" ||
+                    screen.name! == "BiometricDetails") {
+                  for (Field? field in screen.fields!) {
+                    if (globalProvider.fieldInputValue
+                        .containsKey(field!.id!)) {
+                      globalProvider.fieldInputValue.remove(field.id);
+                    }
+                  }
+                }
+              }
+              await BiometricsApi().clearBiometricAndDocumentHashmap();
+              globalProvider.clearExceptions();
+              globalProvider.checkAgeGroupChange = globalProvider.ageGroup;
+            }
+          }
+        }
+      }
+    }
+  }
+
+  Future biometricRequiredFieldValidation(Field field) async {
+    if (field.controlType == "biometrics") {
+      int count = returnBiometricListLength(field.bioAttributes, field.id!);
+      if (globalProvider.completeException[field.id!] != null) {
+        int length = globalProvider.completeException[field.id!].length;
+        count = count - length;
+      }
+
+      if (globalProvider.fieldInputValue[field.id!].length < count) {
+        return false;
+      }
+    }
+
+    return true;
+  }
+
+  Future biometricConditionalFieldValidation(Field field) async {
+    bool valid = await BiometricsApi().conditionalBioAttributeValidation(
+        field.id!, field.conditionalBioAttributes!.first!.validationExpr!);
+    if (field.exceptionPhotoRequired == true) {
+      List biometricAttributeDataList =
+          globalProvider.fieldInputValue[field.id!];
+      bool isExceptionPresent = false;
+      bool isExceptionAttributePresent = false;
+      for (var biometricAttributeData in biometricAttributeDataList) {
+        if (globalProvider.exceptionAttributes
+            .contains(biometricAttributeData.title)) {
+          isExceptionPresent = true;
+        }
+        if (biometricAttributeData.title == "Exception") {
+          isExceptionAttributePresent = true;
+        }
+      }
+
+      if (isExceptionPresent == true &&
+          isExceptionAttributePresent == false) {
+        return false;
+      }
+    }
+    if (!valid) {
+      return false;
+    }
+    return true;
+  }
+
+  Future biometricValidation(Field field) async {
+    if (field.conditionalBioAttributes != null &&
+        field.conditionalBioAttributes!.isNotEmpty) {
+      String response = await BiometricsApi().getAgeGroup();
+      if (response
+              .compareTo(field.conditionalBioAttributes!.first!.ageGroup!) !=
+          0) {
+        bool isValid = true;
+        if (field.conditionalBioAttributes!.first!.ageGroup! == "ALL") {
+          isValid = await biometricConditionalFieldValidation(field);
+        } else {
+          isValid = await biometricRequiredFieldValidation(field);
+        }
+
+        if (!isValid) {
+          return false;
+        }
+      }
+
+      if (response
+              .compareTo(field.conditionalBioAttributes!.first!.ageGroup!) ==
+          0) {
+        bool isValid = await biometricConditionalFieldValidation(field);
+        if (!isValid) {
+          return false;
+        }
+      }
+    }
+
+    return true;
+  }
+
+  Future evaluateMVELVisible(String fieldData) async {
+    bool visible =
+        await registrationTaskProvider.evaluateMVELVisible(fieldData);
+    return visible;
+  }
+
+  Future evaluateMVELRequired(String fieldData) async {
+    bool required =
+        await registrationTaskProvider.evaluateMVELRequired(fieldData);
+    return required;
+  }
+
+  Future customValidation(int currentIndex, Process process, int size) async {
+    // First screen validation
+    if (currentIndex == 0) {
+      if (widget.processType == ProcessType.updateProcess) {
+        if (globalProvider.updateUINNumber.isEmpty) {
+          return false;
+        }
+      }
+      return true;
+    }
+
+    bool isValid = true;
+    if (globalProvider.newProcessTabIndex < size) {
+      Screen screen = process.screens!.elementAt(currentIndex)!;
+      for (int i = 0; i < screen.fields!.length; i++) {
+        Field field = screen.fields!.elementAt(i)!;
+
+        // Update process specific validation
+        if (widget.processType == ProcessType.updateProcess) {
+          String group = field.group!;
+          String fieldId = field.id!;
+          if (globalProvider.selectedUpdateFields[group] != null) {
+            if (field.required! ||
+                (globalProvider.mvelRequiredFields[fieldId] ?? false)) {
+              if (!(globalProvider.fieldInputValue.containsKey(field.id)) &&
+                  !(globalProvider.fieldInputValue.containsKey(field.subType)) &&
+                  !(globalProvider.fieldInputValue
+                      .containsKey("${field.group}${field.subType}"))) {
+                return false;
+              }
+
+              bool isValid = await biometricValidation(field);
+              if (!isValid) {
+                return false;
+              }
+            }
+          } else if (process.autoSelectedGroups!.contains(group)) {
+            if (globalProvider.mvelRequiredFields[fieldId] ?? false) {
+              if (!(globalProvider.fieldInputValue.containsKey(field.id)) &&
+                  !(globalProvider.fieldInputValue
+                      .containsKey(field.subType)) &&
+                  !(globalProvider.fieldInputValue
+                      .containsKey("${field.group}${field.subType}"))) {
+                return false;
+              }
+
+              if (field.conditionalBioAttributes != null &&
+                  field.conditionalBioAttributes!.isNotEmpty) {
+                bool isValid =
+                    await biometricConditionalFieldValidation(field);
+                if (!isValid) {
+                  return false;
+                }
+              }
+            }
+          }
+          continue;
+        }
+
+        // Common validation for other processes
+        if (field.inputRequired! && field.required!) {
+          if (!(globalProvider.fieldInputValue.containsKey(field.id)) &&
+              !(globalProvider.fieldInputValue.containsKey(field.subType)) &&
+              !(globalProvider.fieldInputValue
+                  .containsKey("${field.group}${field.subType}"))) {
+            isValid = false;
+            break;
+          }
+          if (field.conditionalBioAttributes != null &&
+              field.conditionalBioAttributes!.isNotEmpty) {
+            String response = await BiometricsApi().getAgeGroup();
+            if (!(response.compareTo(
+                    field.conditionalBioAttributes!.first!.ageGroup!) ==
+                0)) {
+              if (field.controlType == "biometrics") {
+                int count =
+                    returnBiometricListLength(field.bioAttributes, field.id!);
+                if (globalProvider.completeException[field.id!] != null) {
+                  int length =
+                      globalProvider.completeException[field.id!].length;
+                  count = count - length;
+                }
+
+                if (globalProvider.fieldInputValue[field.id!].length < count) {
+                  isValid = false;
+                  break;
+                }
+                if (globalProvider.isValidBiometricCapture) {
+                  isValid = false;
+                  break;
+                }
+              }
+            }
+          }
+        }
+        if (field.requiredOn != null && field.requiredOn!.isNotEmpty) {
+          bool visible =
+              await evaluateMVELVisible(jsonEncode(field.toJson()));
+          bool required =
+              await evaluateMVELRequired(jsonEncode(field.toJson()));
+          if (visible && required) {
+            if (field.inputRequired!) {
+              if (!(globalProvider.fieldInputValue.containsKey(field.id)) &&
+                  !(globalProvider.fieldInputValue
+                      .containsKey(field.subType)) &&
+                  !(globalProvider.fieldInputValue
+                      .containsKey("${field.group}${field.subType}"))) {
+                isValid = false;
+                break;
+              }
+              if (field.conditionalBioAttributes != null &&
+                  field.conditionalBioAttributes!.isNotEmpty) {
+                String response = await BiometricsApi().getAgeGroup();
+                if (!(response.compareTo(
+                        field.conditionalBioAttributes!.first!.ageGroup!) ==
+                    0)) {
+                  if (field.controlType == "biometrics") {
+                    int count = returnBiometricListLength(
+                        field.bioAttributes, field.id!);
+                    if (globalProvider.completeException[field.id!] != null) {
+                      int length =
+                          globalProvider.completeException[field.id!].length;
+                      count = count - length;
+                    }
+                    if (globalProvider.fieldInputValue[field.id!].length <
+                        count) {
+                      isValid = false;
+                      break;
+                    }
+                    if (globalProvider.isValidBiometricCapture) {
+                      isValid = false;
+                      break;
+                    }
+                  }
+                }
+                if (response.compareTo(
+                        field.conditionalBioAttributes!.first!.ageGroup!) ==
+                    0) {
+                  bool valid = await BiometricsApi()
+                      .conditionalBioAttributeValidation(field.id!,
+                          field.conditionalBioAttributes!.first!.validationExpr!);
+                  if (field.exceptionPhotoRequired == true) {
+                    List biometricAttributeDataList =
+                        globalProvider.fieldInputValue[field.id!];
+                    bool isExceptionPresent = false;
+                    bool isExceptionAttributePresent = false;
+                    for (var biometricAttributeData
+                        in biometricAttributeDataList) {
+                      if (globalProvider.exceptionAttributes
+                          .contains(biometricAttributeData.title)) {
+                        isExceptionPresent = true;
+                      }
+                      if (biometricAttributeData.title == "Exception") {
+                        isExceptionAttributePresent = true;
+                      }
+                    }
+                    if (isExceptionPresent == true &&
+                        isExceptionAttributePresent == false) {
+                      isValid = false;
+                      break;
+                    }
+                  }
+                  if (!valid) {
+                    isValid = false;
+                    break;
+                  }
+                }
+              }
+            }
+          }
+        }
+      }
+    }
+    return isValid;
+  }
+
+  Future continueButtonTap(int size, Process process) async {
+    setState(() {
+      _isContinueProcessing = true;
+    });
+
+    try {
+      // Field selection validation (UPDATE process only)
+      if (globalProvider.newProcessTabIndex == 0 &&
+          !fieldSelectionCompleted &&
+          process.id == "UPDATE") {
+        if (globalProvider.selectedUpdateFields.isEmpty ||
+            globalProvider.updateFieldKey.currentState == null ||
+            !globalProvider.updateFieldKey.currentState!.validate()) {
+          return;
+        }
+      }
+
+      // Field selection completion (UPDATE process only)
+      if (!fieldSelectionCompleted &&
+          process.id == "UPDATE" &&
+          globalProvider.selectedUpdateFields.isNotEmpty) {
+        globalProvider.clearMap();
+        globalProvider.clearScannedPages();
+        globalProvider.clearExceptions();
+        await registrationTaskProvider.changeUpdatableFieldGroups();
+        globalProvider.ageGroup = "";
+        await BiometricsApi().clearBiometricAndDocumentHashmap();
+        setState(() {
+          fieldSelectionCompleted = true;
+        });
+        return;
+      }
+
+      // Page change tracking for new process
+      if (widget.processType == ProcessType.newProcess) {
+        globalProvider.isPageChanged = true;
+      }
+
+      if (globalProvider.newProcessTabIndex < size) {
+        await ageDateChangeValidation(globalProvider.newProcessTabIndex, process, size);
+        bool customValidator =
+            await customValidation(globalProvider.newProcessTabIndex, process, size);
+        if (customValidator) {
+          if (globalProvider.formKey.currentState!.validate()) {
+            // Additional info validation - prevent navigation if required but not filled
+            final screen = process.screens![globalProvider.newProcessTabIndex]!;
+            if (screen.additionalInfoRequestIdRequired == true &&
+                (globalProvider.additionalInfoReqId == null ||
+                    globalProvider.additionalInfoReqId!.trim().isEmpty)) {
+              _showInSnackBar(appLocalizations.enter_additional_info_req_id);
+              return;
+            }
+
+            if (globalProvider.newProcessTabIndex ==
+                process.screens!.length - 1) {
+              templateTitleMap = {
+                'demographicInfo': appLocalizations.demographic_information,
+                'documents': appLocalizations.documents,
+                'bioMetrics': appLocalizations.biometrics
+              };
+              registrationTaskProvider.setPreviewTemplate("");
+              registrationTaskProvider.setAcknowledgementTemplate("");
+              await registrationTaskProvider.getPreviewTemplate(
+                  true, templateTitleMap!);
+              await registrationTaskProvider.getAcknowledgementTemplate(
+                false,
+                templateTitleMap!,
+              );
+            }
+
+            globalProvider.newProcessTabIndex =
+                globalProvider.newProcessTabIndex + 1;
+          }
+        }
+
+        _nextButtonClickedAudit();
+      } else {
+        if (globalProvider.newProcessTabIndex == size + 1) {
+          bool isPacketAuthenticated = await _authenticatePacket(context);
+          if (!isPacketAuthenticated) {
+            return;
+          }
+          RegistrationSubmitResponse registrationSubmitResponse =
+              await registrationTaskProvider.submitRegistrationDto(username);
+          if (registrationSubmitResponse.errorCode!.isNotEmpty) {
+            _showInSnackBar(registrationSubmitResponse.errorCode!);
+            return;
+          }
+          globalProvider.setRegId(registrationSubmitResponse.rId);
+
+          // Updating key to packetId after success creation of packet
+          registrationTaskProvider
+              .updateTemplateStorageKey(registrationSubmitResponse.rId);
+          registrationTaskProvider.deleteDefaultTemplateStored();
+
+          setState(() {
+            username = '';
+            password = '';
+          });
+        }
+        if (globalProvider.newProcessTabIndex == size + 2) {
+          _resetValuesOnRegistrationComplete();
+          return;
+        }
+        globalProvider.newProcessTabIndex =
+            globalProvider.newProcessTabIndex + 1;
+      }
+    } finally {
+      setState(() {
+        _isContinueProcessing = false;
+      });
+    }
+  }
+
+  bool continueButton = false;
+  bool authButton = false;
+
+  @override
+  Widget build(BuildContext context) {
+    // Scroll to top when page changes
+    WidgetsBinding.instance.addPostFrameCallback((timeStamp) {
+      if (globalProvider.isPageChanged) {
+        setScrollToTop();
+      }
+    });
+
+    postRegistrationTabs = [
+      appLocalizations.preview_page,
+      appLocalizations.packet_auth_page,
+      appLocalizations.acknowledgement_page,
+    ];
+    isPortrait = MediaQuery.of(context).orientation == Orientation.portrait;
+    bool isMobile = MediaQuery.of(context).size.width < 750;
+    double w = ScreenUtil().screenWidth;
+    Map arguments =
+        ModalRoute.of(context)!.settings.arguments! as Map;
+    final Process process = arguments["process"];
+    int size = process.screens!.length;
+
+    customValidation(globalProvider.newProcessTabIndex, process, size).then((value) {
+      setState(() {
+        // Field selection screen validation (UPDATE process before consent)
+        if (globalProvider.newProcessTabIndex == 0 && !fieldSelectionCompleted) {
+          continueButton = value &&
+              globalProvider.updateFieldKey.currentState != null &&
+              globalProvider.updateFieldKey.currentState!.validate();
+        } 
+        // Consent screen after field selection
+        else if (globalProvider.newProcessTabIndex == 0 && fieldSelectionCompleted) {
+          continueButton = true;
+        } 
+        // Regular screen validation
+        else {
+          continueButton = value &&
+              globalProvider.formKey.currentState != null &&
+              globalProvider.formKey.currentState!.validate();
+
+          // Additional info validation
+          if (globalProvider.newProcessTabIndex < size) {
+            final screen = process.screens![globalProvider.newProcessTabIndex]!;
+            if (screen.additionalInfoRequestIdRequired == true &&
+                (globalProvider.additionalInfoReqId == null ||
+                    globalProvider.additionalInfoReqId!.trim().isEmpty)) {
+              continueButton = false;
+            }
+          }
+        }
+      });
+      if (globalProvider.newProcessTabIndex >= size) {
+        continueButton = true;
+      }
+    });
+
+    // Auth button validation for all processes
+    if (username.trim().isNotEmpty && password.trim().isNotEmpty) {
+      authButton = true;
+    }
+
+    return WillPopScope(
+      onWillPop: () => onWillPop(process),
+      child: SafeArea(
+        child: Scaffold(
+          backgroundColor: secondaryColors.elementAt(10),
+          bottomNavigationBar: _buildBottomNavigationBar(size, process, isPortrait, isMobile),
+          body: _buildBody(size, process, isPortrait, isMobile, w),
+        ),
+      ),
+    );
+  }
+
+  Widget _buildBottomNavigationBar(int size, Process process, bool isPortrait, bool isMobile) {
+    return Container(
+      decoration: BoxDecoration(
+        border: const Border(
+          top: BorderSide(
+            color: dividerColor,
+            width: 1,
+          ),
+        ),
+        color: pureWhite,
+      ),
+      padding: EdgeInsets.symmetric(
+        horizontal: isPortrait ? 20.w : 60.w,
+        vertical: 16.h,
+      ),
+      child: globalProvider.newProcessTabIndex == 0
+          ? _buildFirstScreenButtons(size, process, isPortrait, isMobile)
+          : _buildOtherScreenButtons(size, process, isPortrait, isMobile),
+    );
+  }
+
+  Widget _buildFirstScreenButtons(int size, Process process, bool isPortrait, bool isMobile) {
+    final bool isUpdate = process.id == "UPDATE";
+    return Row(
+      children: [
+        Expanded(
+          child: (isUpdate && fieldSelectionCompleted)
+              ? OutlinedButton(
+                  child: SizedBox(
+                    height: isPortrait && !isMobileSize ? 68.h : 52.h,
+                    child: Center(
+                      child: Text(
+                        appLocalizations.go_back,
+                        style: TextStyle(
+                          fontSize: isPortrait && !isMobileSize ? 22 : 14,
+                        ),
+                      ),
+                    ),
+                  ),
+                  onPressed: () {
+                    setState(() {
+                      fieldSelectionCompleted = false;
+                    });
+                  },
+                )
+              : (!isUpdate
+                  ? OutlinedButton(
+                      child: SizedBox(
+                        height: isPortrait && !isMobileSize ? 68.h : 52.h,
+                        child: Center(
+                          child: Text(
+                            appLocalizations.go_back,
+                            style: TextStyle(
+                              fontSize: isPortrait && !isMobileSize ? 22 : 14,
+                            ),
+                          ),
+                        ),
+                      ),
+                      onPressed: () {
+                        Navigator.of(context).pop();
+                      },
+                    )
+                  : const SizedBox()),
+        ),
+        SizedBox(
+          width: 10.w,
+        ),
+        Expanded(
+          child: ElevatedButton(
+            style: isUpdate
+                ? ButtonStyle(
+                    maximumSize: MaterialStateProperty.all(
+                        const Size(209, 52)),
+                    minimumSize: MaterialStateProperty.all(
+                        const Size(209, 52)),
+                    backgroundColor: MaterialStateProperty.all(
+                        !fieldSelectionCompleted
+                            ? (continueButton)
+                                ? solidPrimary
+                                : Colors.grey
+                            : solidPrimary),
+                  )
+                : null,
+            onPressed: _isContinueProcessing
+                ? null
+                : () async {
+                    if (isUpdate && fieldSelectionCompleted) {
+                      registrationTaskProvider.addConsentField("Y");
+                      await DemographicsApi().addDemographicField(
+                          "UIN", globalProvider.updateUINNumber);
+                      await DemographicsApi()
+                          .addDemographicField("consent", "true");
+                    } else {
+                      registrationTaskProvider.addConsentField("Y");
+                      await DemographicsApi()
+                          .addDemographicField("consent", "true");
+                    }
+                    continueButtonTap(size, process);
+                  },
+            child: SizedBox(
+              height: isPortrait && !isMobileSize ? 68.h : 52.h,
+              child: Center(
+                child: Text(
+                  isUpdate && fieldSelectionCompleted
+                      ? appLocalizations.informed
+                      : (isUpdate
+                          ? appLocalizations.continue_text
+                          : appLocalizations.informed),
+                  style: TextStyle(
+                    fontSize: isPortrait && !isMobileSize ? 22 : 14,
+                  ),
+                ),
+              ),
+            ),
+          ),
+        ),
+      ],
+    );
+  }
+
+  Widget _buildOtherScreenButtons(int size, Process process, bool isPortrait, bool isMobile) {
+    return Row(
+      mainAxisAlignment: MainAxisAlignment.start,
+      children: [
+        const Expanded(
+          child: SizedBox(),
+        ),
+        ElevatedButton(
+          style: ButtonStyle(
+            maximumSize: MaterialStateProperty.all(const Size(209, 52)),
+            minimumSize: MaterialStateProperty.all(const Size(209, 52)),
+            backgroundColor: MaterialStateProperty.all(
+                (continueButton &&
+                        context.read().newProcessTabIndex <= size)
+                    ? solidPrimary
+                    : authButton
+                        ? solidPrimary
+                        : Colors.grey),
+          ),
+          onPressed: _isContinueProcessing
+              ? null
+              : () async {
+                  await continueButtonTap(size, process);
+                },
+          child: Text(
+            context.read().newProcessTabIndex <= size
+                ? appLocalizations.continue_text
+                : globalProvider.newProcessTabIndex == size + 1
+                    ? appLocalizations.authenticate
+                    : appLocalizations.go_to_home,
+            style: const TextStyle(color: appWhite),
+          ),
+        ),
+      ],
+    );
+  }
+
+  Widget _buildBody(int size, Process process, bool isPortrait, bool isMobile, double w) {
+    return SingleChildScrollView(
+      controller: scrollController,
+      child: AnnotatedRegion(
+        value: const SystemUiOverlayStyle(
+          statusBarColor: Colors.transparent,
+        ),
+        child: Column(
+          children: [
+            Container(
+              padding: isMobile && !isMobileSize
+                  ? const EdgeInsets.fromLTRB(0, 46, 0, 0)
+                  : const EdgeInsets.fromLTRB(0, 0, 0, 0),
+              decoration: const BoxDecoration(
+                gradient: LinearGradient(
+                  begin: Alignment.topCenter,
+                  end: Alignment.bottomCenter,
+                  colors: [Color(0xff214FBF), Color(0xff1C43A1)],
+                ),
+              ),
+              child: Column(
+                crossAxisAlignment: CrossAxisAlignment.start,
+                children: [
+                  SizedBox(
+                    width: w,
+                    height: isPortrait ? 21.w : 30.w,
+                  ),
+                  Padding(
+                    padding: isPortrait
+                        ? EdgeInsets.fromLTRB(20.w, 0, 0, 0)
+                        : EdgeInsets.fromLTRB(60.w, 0, 60.w, 0),
+                    child: Text(
+                      process.label![context
+                          .read()
+                          .selectedLanguage]!,
+                      style: Theme.of(context).textTheme.titleMedium?.copyWith(
+                          color: pureWhite,
+                          fontWeight: semiBold,
+                          fontSize: isPortrait ? 24 : 21),
+                    ),
+                  ),
+                  SizedBox(
+                    height: 30.h,
+                  ),
+                  if (process.id != "UPDATE" ||
+                      fieldSelectionCompleted)
+                    Divider(
+                      height: 12.h,
+                      thickness: 1,
+                      color: secondaryColors.elementAt(2),
+                    ),
+                  if (process.id != "UPDATE" ||
+                      fieldSelectionCompleted)
+                    _buildTabBar(size, process, isPortrait),
+                  const SizedBox(
+                    height: 5,
+                  ),
+                ],
+              ),
+            ),
+            Padding(
+              padding: isPortrait
+                  ? const EdgeInsets.all(0)
+                  : EdgeInsets.fromLTRB(60.w, 0, 60.w, 0),
+              child: _buildMainContent(size, process),
+            ),
+            SizedBox(
+              height: 20.h,
+            ),
+          ],
+        ),
+      ),
+    );
+  }
+
+  Widget _buildTabBar(int size, Process process, bool isPortrait) {
+    return Padding(
+      padding: isPortrait
+          ? const EdgeInsets.all(0)
+          : EdgeInsets.fromLTRB(60.w, 0, 60.w, 0),
+      child: Stack(
+        alignment: FractionalOffset.centerRight,
+        children: [
+          Padding(
+            padding: isPortrait
+                ? EdgeInsets.fromLTRB(20.w, 10.h, 0, 0)
+                : EdgeInsets.fromLTRB(0, 10.h, 0, 0),
+            child: SizedBox(
+              height: 36.h,
+              child: ListView.builder(
+                  padding: const EdgeInsets.all(0),
+                  scrollDirection: Axis.horizontal,
+                  itemCount: process.screens!.length + 3,
+                  itemBuilder: (BuildContext context, int index) {
+                    return GestureDetector(
+                      onTap: () {
+                        if (context.read().newProcessTabIndex ==
+                            size + 2) {
+                          return;
+                        }
+
+                        if (index <
+                            context
+                                .read()
+                                .newProcessTabIndex) {
+                          context.read().newProcessTabIndex =
+                              index;
+                        }
+                      },
+                      child: Row(
+                        children: [
+                          Container(
+                            padding: EdgeInsets.fromLTRB(0, 0, 0, 8.h),
+                            decoration: BoxDecoration(
+                              border: Border(
+                                bottom: BorderSide(
+                                    color: (context
+                                                .watch()
+                                                .newProcessTabIndex ==
+                                            index)
+                                        ? pureWhite
+                                        : Colors.transparent,
+                                    width: 3),
+                              ),
+                            ),
+                            child: Row(
+                              children: [
+                                (index <
+                                        context
+                                            .watch()
+                                            .newProcessTabIndex)
+                                    ? Icon(
+                                        Icons.check_circle,
+                                        size: 17,
+                                        color: secondaryColors.elementAt(11),
+                                      )
+                                    : (context
+                                                .watch()
+                                                .newProcessTabIndex ==
+                                            index)
+                                        ? Icon(
+                                            Icons.circle,
+                                            color: pureWhite,
+                                            size: 17,
+                                          )
+                                        : Icon(
+                                            Icons.circle_outlined,
+                                            size: 17,
+                                            color: secondaryColors.elementAt(9),
+                                          ),
+                                SizedBox(
+                                  width: 6.w,
+                                ),
+                                Text(
+                                  index < size
+                                      ? process.screens![index]!.label![context
+                                          .read()
+                                          .selectedLanguage]!
+                                      : postRegistrationTabs[index - size],
+                                  style: Theme.of(context)
+                                      .textTheme
+                                      .titleSmall
+                                      ?.copyWith(
+                                          color: (context
+                                                      .watch()
+                                                      .newProcessTabIndex ==
+                                                  index)
+                                              ? pureWhite
+                                              : secondaryColors.elementAt(9),
+                                          fontWeight: semiBold,
+                                          fontSize: 14),
+                                ),
+                              ],
+                            ),
+                          ),
+                          SizedBox(
+                            width: 35.w,
+                          ),
+                        ],
+                      ),
+                    );
+                  }),
+            ),
+          ),
+          if (context.watch().newProcessTabIndex < size + 2)
+            Container(
+              height: 36.h,
+              width: 25.w,
+              padding: const EdgeInsets.fromLTRB(0, 0, 0, 0),
+              color: solidPrimary,
+              child: Icon(
+                Icons.arrow_forward_ios_outlined,
+                color: pureWhite,
+                size: 17,
+              ),
+            ),
+        ],
+      ),
+    );
+  }
+
+  Widget _buildMainContent(int size, Process process) {
+    // Show field selector for UPDATE process before consent
+    if (!fieldSelectionCompleted && process.id == "UPDATE") {
+      return UpdateFieldSelector(process: process);
+    }
+
+    if (context.watch().newProcessTabIndex < size) {
+      return GenericProcessScreenContent(
+        context: context,
+        screen: process.screens!.elementAt(
+            context.watch().newProcessTabIndex)!,
+        processType: widget.processType,
+        process: process,
+      );
+    }
+
+    if (context.watch().newProcessTabIndex == size) {
+      return const PreviewPage();
+    }
+
+    if (context.watch().newProcessTabIndex == size + 1) {
+      return _getPacketAuthComponent();
+    }
+
+    return const AcknowledgementPage();
+  }
+
+  Widget _getPacketAuthComponent() {
+    return Column(
+      children: [
+        SizedBox(
+          height: 30.h,
+        ),
+        Container(
+          width: isPortrait && !isMobileSize ? 566.w : 376.w,
+          padding: EdgeInsets.only(
+            top: 24.h,
+            bottom: 28.h,
+            left: 20.w,
+            right: 20.w,
+          ),
+          decoration: BoxDecoration(
+            borderRadius: const BorderRadius.all(
+              Radius.circular(6),
+            ),
+            color: pureWhite,
+          ),
+          child: Column(
+            children: [
+              _getAuthIcon(),
+              SizedBox(
+                height: 26.h,
+              ),
+              Text(
+                appLocalizations.authenticate_using_password,
+                style: TextStyle(
+                    fontSize: isPortrait && !isMobileSize ? 24 : 18,
+                    fontWeight: semiBold,
+                    color: appBlack),
+              ),
+              SizedBox(
+                height: 35.h,
+              ),
+              Row(
+                children: [
+                  Text(
+                    appLocalizations.username,
+                    style: isPortrait
+                        ? AppTextStyle.tabletPortraitTextfieldHeader
+                        : AppTextStyle.mobileTextfieldHeader,
+                  ),
+                  const Text(
+                    ' *',
+                    style: TextStyle(
+                      color: mandatoryField,
+                    ),
+                  ),
+                ],
+              ),
+              SizedBox(
+                height: 11.h,
+              ),
+              _getUsernameTextField(),
+              SizedBox(
+                height: 35.h,
+              ),
+              Row(
+                children: [
+                  Text(
+                    appLocalizations.password,
+                    style: isPortrait
+                        ? AppTextStyle.tabletPortraitTextfieldHeader
+                        : AppTextStyle.mobileTextfieldHeader,
+                  ),
+                  const Text(
+                    ' *',
+                    style: TextStyle(color: mandatoryField),
+                  ),
+                ],
+              ),
+              SizedBox(
+                height: 11.h,
+              ),
+              _getPasswordTextField(),
+            ],
+          ),
+        ),
+      ],
+    );
+  }
+
+  _getAuthIcon() {
+    bool useImage = widget.processType == ProcessType.lostProcess ||
+        widget.processType == ProcessType.updateProcess;
+
+    return Container(
+      height: 80.w,
+      width: 80.w,
+      decoration: BoxDecoration(
+        shape: BoxShape.circle,
+        border: Border.all(
+          color: authIconBorder,
+          width: 2,
+        ),
+        color: authIconBackground,
+      ),
+      child: Center(
+        child: useImage
+            ? Image.asset('assets/images/Registering an Individual@2x.png')
+            : SvgPicture.asset('assets/images/AuthenticationIcon.svg'),
+      ),
+    );
+  }
+
+  _getUsernameTextField() {
+    return Container(
+      height: isPortrait && !isMobileSize ? 82.h : 52.h,
+      alignment: Alignment.centerLeft,
+      padding: EdgeInsets.symmetric(
+        horizontal: 12.w,
+      ),
+      decoration: BoxDecoration(
+        border: Border.all(
+          width: 1.h,
+          color: appGreyShade,
+        ),
+        borderRadius: const BorderRadius.all(
+          Radius.circular(6),
+        ),
+      ),
+      child: TextField(
+        decoration: InputDecoration(
+          hintText: appLocalizations.enter_username,
+          hintStyle: isPortrait && !isMobileSize
+              ? AppTextStyle.tabletPortraitTextfieldHintText
+              : AppTextStyle.mobileTextfieldHintText,
+          border: InputBorder.none,
+        ),
+        style: TextStyle(
+          fontSize: isPortrait && !isMobileSize ? 22 : 14,
+          color: appBlack,
+        ),
+        onChanged: (v) {
+          setState(() {
+            username = v;
+          });
+        },
+      ),
+    );
+  }
+
+  _getPasswordTextField() {
+    return Container(
+      height: isPortrait && !isMobileSize ? 82.h : 52.h,
+      alignment: Alignment.centerLeft,
+      padding: EdgeInsets.symmetric(
+        horizontal: 12.w,
+      ),
+      decoration: BoxDecoration(
+        border: Border.all(
+          width: 1.h,
+          color: appGreyShade,
+        ),
+        borderRadius: const BorderRadius.all(
+          Radius.circular(6),
+        ),
+      ),
+      child: TextField(
+        obscureText: true,
+        decoration: InputDecoration(
+          hintText: appLocalizations.enter_password,
+          hintStyle: isPortrait && !isMobileSize
+              ? AppTextStyle.tabletPortraitTextfieldHintText
+              : AppTextStyle.mobileTextfieldHintText,
+          border: InputBorder.none,
+        ),
+        style: TextStyle(
+          fontSize: isPortrait && !isMobileSize ? 22 : 14,
+          color: appBlack,
+        ),
+        onChanged: (v) {
+          setState(() {
+            password = v;
+          });
+        },
+      ),
+    );
+  }
+}
+
diff --git a/lib/ui/process_ui/lost_process.dart b/lib/ui/process_ui/lost_process.dart
deleted file mode 100644
index e35904b10..000000000
--- a/lib/ui/process_ui/lost_process.dart
+++ /dev/null
@@ -1,1241 +0,0 @@
-/*
- * Copyright (c) Modular Open Source Identity Platform
- * This source code is licensed under the MIT license found in the
- * LICENSE file in the root directory of this source tree.
- *
-*/
-
-import 'dart:convert';
-
-import 'package:flutter/material.dart';
-import 'package:flutter/services.dart';
-
-import 'package:flutter_screenutil/flutter_screenutil.dart';
-import 'package:provider/provider.dart';
-import 'package:registration_client/model/biometric_attribute_data.dart';
-import 'package:registration_client/model/field.dart';
-import 'package:registration_client/model/process.dart';
-import 'package:registration_client/model/screen.dart';
-import 'package:registration_client/pigeon/biometrics_pigeon.dart';
-import 'package:registration_client/pigeon/demographics_data_pigeon.dart';
-import 'package:registration_client/pigeon/registration_data_pigeon.dart';
-
-import 'package:registration_client/provider/auth_provider.dart';
-import 'package:registration_client/provider/connectivity_provider.dart';
-import 'package:registration_client/provider/global_provider.dart';
-import 'package:registration_client/provider/registration_task_provider.dart';
-
-import 'package:registration_client/ui/post_registration/acknowledgement_page.dart';
-
-import 'package:registration_client/ui/post_registration/preview_page.dart';
-import 'package:registration_client/ui/process_ui/widgets/lost_process_screen_content.dart';
-import 'package:registration_client/utils/app_config.dart';
-import 'package:flutter_gen/gen_l10n/app_localizations.dart';
-import 'package:registration_client/utils/app_style.dart';
-
-import '../../utils/life_cycle_event_handler.dart';
-
-class LostProcess extends StatefulWidget {
-  const LostProcess({
-    super.key,
-  });
-
-  static const routeName = '/lost_process';
-
-  @override
-  State createState() => _LostProcessState();
-}
-
-class _LostProcessState extends State
-    with WidgetsBindingObserver {
-  late GlobalProvider globalProvider;
-  late RegistrationTaskProvider registrationTaskProvider;
-  late AuthProvider authProvider;
-  late ConnectivityProvider connectivityProvider;
-  late AppLocalizations appLocalizations = AppLocalizations.of(context)!;
-  bool isPortrait = true;
-  bool _isLostUinContinue = false;
-
-  List postRegistrationTabs = [
-    'Preview',
-    'Authentication',
-    'Acknowledgement',
-  ];
-
-  Map? templateTitleMap;
-
-  String username = '';
-  String password = '';
-
-  @override
-  void initState() {
-    globalProvider = Provider.of(context, listen: false);
-    registrationTaskProvider =
-        Provider.of(context, listen: false);
-    authProvider = Provider.of(context, listen: false);
-    connectivityProvider =
-        Provider.of(context, listen: false);
-    super.initState();
-    WidgetsBinding.instance.addObserver(LifecycleEventHandler(
-      resumeCallBack: () async {
-        if (mounted) {
-          setState(() {
-            closeKeyboard();
-          });
-        }
-      },
-      suspendingCallBack: () async {
-        if (mounted) {
-          setState(() {
-            closeKeyboard();
-          });
-        }
-      },
-    ));
-    _registrationScreenLoadedAudit();
-  }
-
-  @override
-  void dispose() {
-    WidgetsBinding.instance.removeObserver(this);
-    super.dispose();
-  }
-
-  void closeKeyboard() {
-    FocusScope.of(context).unfocus();
-  }
-
-  void _showInSnackBar(String value) {
-    ScaffoldMessenger.of(context).showSnackBar(
-      SnackBar(
-        content: Text(value),
-      ),
-    );
-  }
-
-  _authenticatePacket(BuildContext context) async {
-    if (!_validateUsername(context)) {
-      return false;
-    }
-
-    if (!_validatePassword(context)) {
-      return false;
-    }
-
-    if (authProvider.currentUser.userId != username) {
-      _showInSnackBar(appLocalizations.invalid_user);
-      return false;
-    }
-
-    await authProvider.authenticatePacket(username, password);
-
-    if (!authProvider.isPacketAuthenticated) {
-      _showErrorInSnackbar();
-      return false;
-    }
-    return true;
-  }
-
-  _showErrorInSnackbar() {
-    String errorMsg = authProvider.packetError;
-    String snackbarText = "";
-
-    switch (errorMsg) {
-      case "REG_TRY_AGAIN":
-        snackbarText = appLocalizations.login_failed;
-        break;
-
-      case "REG_INVALID_REQUEST":
-        snackbarText = appLocalizations.password_incorrect;
-        break;
-
-      case "REG_NETWORK_ERROR":
-        snackbarText = appLocalizations.network_error;
-        break;
-
-      case "":
-        return;
-
-      default:
-        snackbarText = errorMsg;
-        break;
-    }
-
-    _showInSnackBar(snackbarText);
-  }
-
-  bool _validateUsername(BuildContext context) {
-    if (username.trim().isEmpty) {
-      _showInSnackBar(appLocalizations.username_required);
-      return false;
-    }
-
-    if (username.trim().length > 50) {
-      _showInSnackBar(appLocalizations.username_exceed);
-      return false;
-    }
-
-    return true;
-  }
-
-  bool _validatePassword(BuildContext context) {
-    if (password.trim().isEmpty) {
-      _showInSnackBar(appLocalizations.password_required);
-      return false;
-    }
-
-    if (password.trim().length > 50) {
-      _showInSnackBar(appLocalizations.password_exceed);
-      return false;
-    }
-
-    return true;
-  }
-
-  _resetValuesOnRegistrationComplete() {
-    Navigator.of(context).pop();
-  }
-
-  void _registrationScreenLoadedAudit() async {
-    await globalProvider.getAudit("REG-EVT-002", "REG-MOD-103");
-  }
-
-  _nextButtonClickedAudit() async {
-    await globalProvider.getAudit("REG-EVT-003", "REG-MOD-103");
-  }
-
-  bool continueButton = false;
-
-  @override
-  Widget build(BuildContext context) {
-    postRegistrationTabs = [
-      appLocalizations.preview_page,
-      appLocalizations.packet_auth_page,
-      appLocalizations.acknowledgement_page,
-    ];
-    isPortrait = MediaQuery.of(context).orientation == Orientation.portrait;
-    bool isMobile = MediaQuery.of(context).size.width < 750;
-    double w = ScreenUtil().screenWidth;
-    Map arguments =
-    ModalRoute.of(context)!.settings.arguments! as Map;
-    final Process newProcess = arguments["process"];
-    int size = newProcess.screens!.length;
-
-    evaluateMVELVisible(String fieldData) async {
-      bool visible =
-      await registrationTaskProvider.evaluateMVELVisible(fieldData);
-      return visible;
-    }
-
-    evaluateMVELRequired(String fieldData) async {
-      bool required =
-      await registrationTaskProvider.evaluateMVELRequired(fieldData);
-      return required;
-    }
-
-    Future onWillPop() async {
-      if (globalProvider.newProcessTabIndex > 0 &&
-          globalProvider.newProcessTabIndex <
-              newProcess.screens!.length + postRegistrationTabs.length - 1) {
-        globalProvider.newProcessTabIndex =
-            globalProvider.newProcessTabIndex - 1;
-      } else {
-        return true;
-      }
-      return false;
-    }
-
-    isExceptionPresent(String id) {
-      bool isExceptionPresent = false;
-      for (BiometricAttributeData x in globalProvider.fieldInputValue[id]) {
-        if (x.exceptions.contains(true) || x.title == "Exception") {
-          isExceptionPresent = true;
-          break;
-        }
-      }
-      return isExceptionPresent;
-    }
-
-    returnBiometricListLength(List? list, String id) {
-      int i = 0;
-      if (list!.contains("leftEye") && list.contains("rightEye")) {
-        i++;
-      }
-      if (list.contains("rightIndex") &&
-          list.contains("rightLittle") &&
-          list.contains("rightRing") &&
-          list.contains("rightMiddle")) {
-        i++;
-      }
-      if (list.contains("leftIndex") &&
-          list.contains("leftLittle") &&
-          list.contains("leftRing") &&
-          list.contains("leftMiddle")) {
-        i++;
-      }
-      if (list.contains("rightThumb") && list.contains("rightThumb")) {
-        i++;
-      }
-      if (list.contains("face")) {
-        i++;
-      }
-      if (isExceptionPresent(id) == true) {
-        i++;
-      }
-      return i;
-    }
-
-    biometricRequiredFieldValidation(Field field) async {
-      if (field.controlType == "biometrics") {
-        int count = returnBiometricListLength(field.bioAttributes, field.id!);
-        if (globalProvider.completeException[field.id!] != null) {
-          int length = globalProvider.completeException[field.id!].length;
-          count = count - length;
-        }
-
-        if (globalProvider.fieldInputValue[field.id!].length < count) {
-          return false;
-        }
-      }
-
-      return true;
-    }
-
-    biometricConditionalFieldValidation(Field field) async {
-      bool valid = await BiometricsApi().conditionalBioAttributeValidation(
-          field.id!, field.conditionalBioAttributes!.first!.validationExpr!);
-      if (field.exceptionPhotoRequired == true) {
-        List biometricAttributeDataList =
-        globalProvider.fieldInputValue[field.id!];
-        bool isExceptionPresent = false;
-        bool isExceptionAttributePresent = false;
-        for (var biometricAttributeData in biometricAttributeDataList) {
-          if (globalProvider.exceptionAttributes
-              .contains(biometricAttributeData.title)) {
-            isExceptionPresent = true;
-          }
-          if (biometricAttributeData.title == "Exception") {
-            isExceptionAttributePresent = true;
-          }
-        }
-
-        if (isExceptionPresent == true &&
-            isExceptionAttributePresent == false) {
-          return false;
-        }
-      }
-      if (!valid) {
-        return false;
-      }
-      return true;
-    }
-
-    biometricValidation(Field field) async {
-      if (field.conditionalBioAttributes != null &&
-          field.conditionalBioAttributes!.isNotEmpty) {
-        String response = await BiometricsApi().getAgeGroup();
-        if (response
-            .compareTo(field.conditionalBioAttributes!.first!.ageGroup!) !=
-            0) {
-          bool isValid = true;
-          if (field.conditionalBioAttributes!.first!.ageGroup! == "ALL") {
-            isValid = await biometricConditionalFieldValidation(field);
-          } else {
-            isValid = await biometricRequiredFieldValidation(field);
-          }
-
-          if (!isValid) {
-            return false;
-          }
-        }
-
-        if (response
-            .compareTo(field.conditionalBioAttributes!.first!.ageGroup!) ==
-            0) {
-          bool isValid = await biometricConditionalFieldValidation(field);
-          if (!isValid) {
-            return false;
-          }
-        }
-      }
-
-      return true;
-    }
-
-    ageDateChangeValidation(int currentIndex) async {
-      if (globalProvider.newProcessTabIndex < size) {
-        Screen screen = newProcess.screens!.elementAt(currentIndex)!;
-        for (int i = 0; i < screen.fields!.length; i++) {
-          if (screen.fields!.elementAt(i)!.controlType == "ageDate") {
-            if (globalProvider.checkAgeGroupChange == "") {
-              globalProvider.checkAgeGroupChange = globalProvider.ageGroup;
-            } else {
-              if (globalProvider.checkAgeGroupChange
-                  .compareTo(globalProvider.ageGroup) ==
-                  0) {
-              } else {
-                List screens = [];
-                for (int i = 0;
-                i < registrationTaskProvider.listOfProcesses.length;
-                i++) {
-                  Process process = Process.fromJson(
-                    jsonDecode(
-                      context
-                          .read()
-                          .listOfProcesses
-                          .elementAt(i)
-                          .toString(),
-                    ),
-                  );
-                  if (process.id == "LOST") {
-                    screens = process.screens!;
-                  }
-                }
-                for (Screen? screen in screens) {
-                  if (screen!.name! == "Documents" ||
-                      screen.name! == "BiometricDetails") {
-                    for (Field? field in screen.fields!) {
-                      globalProvider.fieldInputValue.remove(field!.id);
-                    }
-                  }
-                }
-                await BiometricsApi().clearBiometricAndDocumentHashmap();
-                globalProvider.clearExceptions();
-                globalProvider.checkAgeGroupChange = globalProvider.ageGroup;
-              }
-            }
-          }
-        }
-      }
-    }
-
-    customValidation(int currentIndex) async {
-      if (currentIndex == 0) {
-        return true;
-      }
-      bool isValid = true;
-      if (globalProvider.newProcessTabIndex < size) {
-        Screen screen = newProcess.screens!.elementAt(currentIndex)!;
-        for (int i = 0; i < screen.fields!.length; i++) {
-          if (screen.fields!.elementAt(i)!.inputRequired! &&
-              screen.fields!.elementAt(i)!.required!) {
-            if (!(globalProvider.fieldInputValue
-                .containsKey(screen.fields!.elementAt(i)!.id)) &&
-                !(globalProvider.fieldInputValue
-                    .containsKey(screen.fields!.elementAt(i)!.subType)) &&
-                !(globalProvider.fieldInputValue.containsKey(
-                    "${screen.fields!.elementAt(i)!.group}${screen.fields!.elementAt(i)!.subType}"))) {
-              isValid = false;
-
-              break;
-            }
-            if (screen.fields!.elementAt(i)!.conditionalBioAttributes != null &&
-                screen.fields!
-                    .elementAt(i)!
-                    .conditionalBioAttributes!
-                    .isNotEmpty) {
-              String response = await BiometricsApi().getAgeGroup();
-              if (!(response.compareTo(screen.fields!
-                  .elementAt(i)!
-                  .conditionalBioAttributes!
-                  .first!
-                  .ageGroup!) ==
-                  0)) {
-                if (screen.fields!.elementAt(i)!.controlType == "biometrics") {
-                  int count = returnBiometricListLength(
-                      screen.fields!.elementAt(i)!.bioAttributes,
-                      screen.fields!.elementAt(i)!.id!);
-                  if (globalProvider.completeException[
-                  screen.fields!.elementAt(i)!.id!] !=
-                      null) {
-                    int length = globalProvider
-                        .completeException[screen.fields!.elementAt(i)!.id!]
-                        .length;
-                    count = count - length;
-                  }
-
-                  if (globalProvider
-                      .fieldInputValue[screen.fields!.elementAt(i)!.id!]
-                      .length <
-                      count) {
-                    isValid = false;
-
-                    break;
-                  }
-                  if(globalProvider.isValidBiometricCapture){
-                    isValid = false;
-                    break;
-                  }
-                }
-              }
-            }
-          }
-          if (screen.fields!.elementAt(i)!.requiredOn != null &&
-              screen.fields!.elementAt(i)!.requiredOn!.isNotEmpty) {
-            bool visible = await evaluateMVELVisible(
-                jsonEncode(screen.fields!.elementAt(i)!.toJson()));
-            bool required = await evaluateMVELRequired(
-                jsonEncode(screen.fields!.elementAt(i)!.toJson()));
-            if (visible && required) {
-              if (screen.fields!.elementAt(i)!.inputRequired!) {
-                if (!(globalProvider.fieldInputValue
-                    .containsKey(screen.fields!.elementAt(i)!.id)) &&
-                    !(globalProvider.fieldInputValue
-                        .containsKey(screen.fields!.elementAt(i)!.subType)) &&
-                    !(globalProvider.fieldInputValue.containsKey(
-                        "${screen.fields!.elementAt(i)!.group}${screen.fields!.elementAt(i)!.subType}"))) {
-                  isValid = false;
-
-                  break;
-                }
-                if (screen.fields!.elementAt(i)!.conditionalBioAttributes !=
-                    null &&
-                    screen.fields!
-                        .elementAt(i)!
-                        .conditionalBioAttributes!
-                        .isNotEmpty) {
-                  String response = await BiometricsApi().getAgeGroup();
-                  if (!(response.compareTo(screen.fields!
-                      .elementAt(i)!
-                      .conditionalBioAttributes!
-                      .first!
-                      .ageGroup!) ==
-                      0)) {
-                    if (screen.fields!.elementAt(i)!.controlType ==
-                        "biometrics") {
-                      int count = returnBiometricListLength(
-                          screen.fields!.elementAt(i)!.bioAttributes,
-                          screen.fields!.elementAt(i)!.id!);
-                      if (globalProvider.completeException[
-                      screen.fields!.elementAt(i)!.id!] !=
-                          null) {
-                        int length = globalProvider
-                            .completeException[screen.fields!.elementAt(i)!.id!]
-                            .length;
-                        count = count - length;
-                      }
-                      if (globalProvider
-                          .fieldInputValue[screen.fields!.elementAt(i)!.id!]
-                          .length <
-                          count) {
-                        isValid = false;
-
-                        break;
-                      }
-                      if(globalProvider.isValidBiometricCapture){
-                        isValid = false;
-                        break;
-                      }
-                    }
-                  }
-                  if (response.compareTo(screen.fields!
-                      .elementAt(i)!
-                      .conditionalBioAttributes!
-                      .first!
-                      .ageGroup!) ==
-                      0) {
-                    bool valid = await BiometricsApi()
-                        .conditionalBioAttributeValidation(
-                        screen.fields!.elementAt(i)!.id!,
-                        screen.fields!
-                            .elementAt(i)!
-                            .conditionalBioAttributes!
-                            .first!
-                            .validationExpr!);
-                    if (screen.fields!.elementAt(i)!.exceptionPhotoRequired ==
-                        true) {
-                      List biometricAttributeDataList =
-                      globalProvider.fieldInputValue[
-                      screen.fields!.elementAt(i)!.id!];
-                      bool isExceptionPresent = false;
-                      bool isExceptionAttributePresent = false;
-                      for (var biometricAttributeData
-                      in biometricAttributeDataList) {
-                        if (globalProvider.exceptionAttributes
-                            .contains(biometricAttributeData.title)) {
-                          isExceptionPresent = true;
-                        }
-                        if (biometricAttributeData.title == "Exception") {
-                          isExceptionAttributePresent = true;
-                        }
-                      }
-                      if (isExceptionPresent == true &&
-                          isExceptionAttributePresent == false) {
-                        isValid = false;
-                        break;
-                      }
-                    }
-                    if (!valid) {
-                      isValid = false;
-                      break;
-                    }
-                  }
-                }
-              }
-            }
-          }
-        }
-      }
-      return isValid;
-    }
-
-    const debounceDuration = Duration(milliseconds: 500);
-    DateTime? lastClickTime;
-
-    continueButtonTap(int size, newProcess) async {
-
-      final now = DateTime.now();
-      if (lastClickTime != null &&
-          now.difference(lastClickTime!) < debounceDuration) {
-        return;
-      }
-      lastClickTime = now;
-
-      setState(() {
-        _isLostUinContinue = true;
-      });
-
-      try {
-        if (globalProvider.newProcessTabIndex < size) {
-          ageDateChangeValidation(globalProvider.newProcessTabIndex);
-          bool customValidator =
-          await customValidation(globalProvider.newProcessTabIndex);
-          if (customValidator) {
-            if (globalProvider.formKey.currentState!.validate()) {
-              if (globalProvider.newProcessTabIndex ==
-                  newProcess.screens!.length - 1) {
-                templateTitleMap = {
-                  'demographicInfo': appLocalizations.demographic_information,
-                  'documents': appLocalizations.documents,
-                  'bioMetrics': appLocalizations.biometrics,
-                };
-                registrationTaskProvider.setPreviewTemplate("");
-                registrationTaskProvider.setAcknowledgementTemplate("");
-                await registrationTaskProvider.getPreviewTemplate(
-                    true, templateTitleMap!);
-                await registrationTaskProvider.getAcknowledgementTemplate(
-                    false, templateTitleMap!);
-              }
-
-              globalProvider.newProcessTabIndex =
-                  globalProvider.newProcessTabIndex + 1;
-            }
-          }
-
-          _nextButtonClickedAudit();
-        } else {
-          if (globalProvider.newProcessTabIndex == size + 1) {
-            bool isPacketAuthenticated = await _authenticatePacket(context);
-            if (!isPacketAuthenticated) {
-              return;
-            }
-            RegistrationSubmitResponse registrationSubmitResponse =
-            await registrationTaskProvider.submitRegistrationDto(username);
-            if (registrationSubmitResponse.errorCode!.isNotEmpty) {
-              _showInSnackBar(registrationSubmitResponse.errorCode!);
-              return;
-            }
-            globalProvider.setRegId(registrationSubmitResponse.rId);
-
-            // Updating key to packetId after success creation of packet
-            registrationTaskProvider
-                .updateTemplateStorageKey(registrationSubmitResponse.rId);
-            registrationTaskProvider.deleteDefaultTemplateStored();
-
-            setState(() {
-              username = '';
-              password = '';
-            });
-          }
-          if (globalProvider.newProcessTabIndex == size + 2) {
-            _resetValuesOnRegistrationComplete();
-            return;
-          }
-          globalProvider.newProcessTabIndex =
-              globalProvider.newProcessTabIndex + 1;
-        }
-      } finally {
-        setState(() {
-          _isLostUinContinue = false;
-        });
-      }
-    }
-
-    customValidation(globalProvider.newProcessTabIndex).then((value) {
-      setState(() {
-        continueButton = value &&
-            globalProvider.formKey.currentState != null &&
-            globalProvider.formKey.currentState!.validate();
-      });
-      if (globalProvider.newProcessTabIndex >= size) {
-        continueButton = true;
-      }
-    });
-
-    return WillPopScope(
-      onWillPop: onWillPop,
-      child: SafeArea(
-        child: Scaffold(
-          backgroundColor: secondaryColors.elementAt(10),
-          bottomNavigationBar: Container(
-            decoration: BoxDecoration(
-              border: const Border(
-                top: BorderSide(
-                  color: dividerColor,
-                  width: 1,
-                ),
-              ),
-              color: pureWhite,
-            ),
-            padding: EdgeInsets.symmetric(
-              horizontal: isPortrait ? 20.w : 60.w,
-              vertical: 16.h,
-            ),
-            // height: isPortrait ? 94.h : 84.h,
-            child: context.watch().newProcessTabIndex == 0
-                ? Row(
-              children: [
-                Expanded(
-                    child: OutlinedButton(
-                      child: SizedBox(
-                        height:
-                        isPortrait && !isMobileSize ? 68.h : 52.h,
-                        child: Center(
-                          child: Text(
-                            appLocalizations.go_back,
-                            style: TextStyle(
-                              fontSize: isPortrait && !isMobileSize
-                                  ? 22
-                                  : 14,
-                            ),
-                          ),
-                        ),
-                      ),
-                      onPressed: () {
-                        Navigator.of(context).pop();
-                      },
-                    )
-                ),
-                SizedBox(
-                  width: 10.w,
-                ),
-                Expanded(
-                  child: ElevatedButton(
-                    onPressed:  _isLostUinContinue ? null : () async {
-                      registrationTaskProvider.addConsentField("Y");
-                      await DemographicsApi()
-                          .addDemographicField("consent", "true");
-                      continueButtonTap(size, newProcess);
-                    },
-                    child: SizedBox(
-                      height: isPortrait && !isMobileSize ? 68.h : 52.h,
-                      child: Center(
-                        child: Text(
-                          appLocalizations.informed,
-                          style: TextStyle(
-                            fontSize:
-                            isPortrait && !isMobileSize ? 22 : 14,
-                          ),
-                        ),
-                      ),
-                    ),
-                  ),
-                ),
-              ],
-            )
-                : Row(
-              mainAxisAlignment: MainAxisAlignment.start,
-              children: [
-                // globalProvider.newProcessTabIndex == size + 2
-                //     ? ElevatedButton(
-                //         onPressed: () async {
-                //           await connectivityProvider
-                //               .checkNetworkConnection();
-                //           bool isConnected =
-                //               connectivityProvider.isConnected;
-                //           if (!isConnected) {
-                //             _showInSnackBar(
-                //                 appLocalizations.network_error);
-                //             return;
-                //           }
-                //           globalProvider.syncPacket(globalProvider.regId);
-                //         },
-                //         child: Text(appLocalizations.sync_packet),
-                //       )
-                //     : const SizedBox.shrink(),
-                // SizedBox(
-                //   width: 10.w,
-                // ),
-                // globalProvider.newProcessTabIndex == size + 2
-                //     ? ElevatedButton(
-                //         onPressed: () async {
-                //           await connectivityProvider
-                //               .checkNetworkConnection();
-                //           bool isConnected =
-                //               connectivityProvider.isConnected;
-                //           if (!isConnected) {
-                //             _showInSnackBar(
-                //                 appLocalizations.network_error);
-                //             return;
-                //           }
-                //           globalProvider
-                //               .uploadPacket(globalProvider.regId);
-                //         },
-                //         child: Text(appLocalizations.upload_packet),
-                //       )
-                //     : const SizedBox.shrink(),
-                const Expanded(
-                  child: SizedBox(),
-                ),
-                ElevatedButton(
-                  style: ButtonStyle(
-                    maximumSize: MaterialStateProperty.all(
-                        const Size(209, 52)),
-                    minimumSize: MaterialStateProperty.all(
-                        const Size(209, 52)),
-                    backgroundColor: MaterialStateProperty.all(
-                        continueButton ? solidPrimary : Colors.grey),
-                  ),
-                  onPressed: _isLostUinContinue ? null : () async {
-                    await continueButtonTap(size, newProcess);
-                  },
-                  child: Text(
-                    context.read().newProcessTabIndex <=
-                        size
-                        ? appLocalizations.continue_text
-                        : globalProvider.newProcessTabIndex == size + 1
-                        ? appLocalizations.authenticate
-                        : appLocalizations.go_to_home,
-                    style: const TextStyle(color: appWhite),
-                  ),
-                ),
-              ],
-            ),
-          ),
-          body: SingleChildScrollView(
-            child: AnnotatedRegion(
-              value: const SystemUiOverlayStyle(
-                statusBarColor: Colors.transparent,
-              ),
-              child: Column(
-                children: [
-                  // isPortrait
-                  //     ? const SizedBox()
-                  //     : const Column(
-                  //         children: [
-                  //          // TabletHeader(),
-                  //           TabletNavbar(),
-                  //         ],
-                  //       ),
-                  Container(
-                    padding: isMobile && !isMobileSize
-                        ? const EdgeInsets.fromLTRB(0, 46, 0, 0)
-                        : const EdgeInsets.fromLTRB(0, 0, 0, 0),
-                    decoration: const BoxDecoration(
-                      gradient: LinearGradient(
-                        begin: Alignment.topCenter,
-                        end: Alignment.bottomCenter,
-                        colors: [Color(0xff214FBF), Color(0xff1C43A1)],
-                      ),
-                    ),
-                    child: Column(
-                      crossAxisAlignment: CrossAxisAlignment.start,
-                      children: [
-                        SizedBox(
-                          width: w,
-                          height: isPortrait ? 21.w : 30.w,
-                        ),
-                        Padding(
-                          padding: isPortrait
-                              ? EdgeInsets.fromLTRB(20.w, 0, 0, 0)
-                              : EdgeInsets.fromLTRB(60.w, 0, 60.w, 0),
-                          child: Text(
-                            newProcess.label![globalProvider.selectedLanguage]!,
-                            style: Theme.of(context)
-                                .textTheme
-                                .titleMedium
-                                ?.copyWith(
-                                color: pureWhite,
-                                fontWeight: semiBold,
-                                fontSize: isPortrait ? 24 : 21),
-                          ),
-                        ),
-                        SizedBox(
-                          height: 30.h,
-                        ),
-                        Divider(
-                          height: 12.h,
-                          thickness: 1,
-                          color: secondaryColors.elementAt(2),
-                        ),
-                        Padding(
-                          padding: isPortrait
-                              ? const EdgeInsets.all(0)
-                              : EdgeInsets.fromLTRB(60.w, 0, 60.w, 0),
-                          child: Stack(
-                            alignment: FractionalOffset.centerRight,
-                            children: [
-                              Padding(
-                                padding: isPortrait
-                                    ? EdgeInsets.fromLTRB(
-                                    20.w, 10.h, 0, 0)
-                                    : EdgeInsets.fromLTRB(0, 10.h, 0, 0),
-                                child: SizedBox(
-                                  height: 36.h,
-                                  child: ListView.builder(
-                                      padding: const EdgeInsets.all(0),
-                                      scrollDirection: Axis.horizontal,
-                                      itemCount:
-                                      newProcess.screens!.length + 3,
-                                      itemBuilder: (BuildContext context,
-                                          int index) {
-                                        return GestureDetector(
-                                          onTap: () {
-                                            if (globalProvider
-                                                .newProcessTabIndex ==
-                                                size + 2) {
-                                              return;
-                                            }
-
-                                            if (index <
-                                                globalProvider
-                                                    .newProcessTabIndex) {
-                                              globalProvider
-                                                  .newProcessTabIndex =
-                                                  index;
-                                            }
-                                          },
-                                          child: Row(
-                                            children: [
-                                              Container(
-                                                padding:
-                                                EdgeInsets.fromLTRB(
-                                                    0, 0, 0, 8.h),
-                                                decoration: BoxDecoration(
-                                                  border: Border(
-                                                    bottom: BorderSide(
-                                                        color: (context
-                                                            .watch<
-                                                            GlobalProvider>()
-                                                            .newProcessTabIndex ==
-                                                            index)
-                                                            ? pureWhite
-                                                            : Colors
-                                                            .transparent,
-                                                        width: 3),
-                                                  ),
-                                                ),
-                                                child: Row(
-                                                  children: [
-                                                    (index <
-                                                        context
-                                                            .watch<
-                                                            GlobalProvider>()
-                                                            .newProcessTabIndex)
-                                                        ? Icon(
-                                                      Icons
-                                                          .check_circle,
-                                                      size: 17,
-                                                      color: secondaryColors
-                                                          .elementAt(
-                                                          11),
-                                                    )
-                                                        : (context
-                                                        .watch<
-                                                        GlobalProvider>()
-                                                        .newProcessTabIndex ==
-                                                        index)
-                                                        ? Icon(
-                                                      Icons
-                                                          .circle,
-                                                      color:
-                                                      pureWhite,
-                                                      size: 17,
-                                                    )
-                                                        : Icon(
-                                                      Icons
-                                                          .circle_outlined,
-                                                      size: 17,
-                                                      color: secondaryColors
-                                                          .elementAt(
-                                                          9),
-                                                    ),
-                                                    SizedBox(
-                                                      width: 6.w,
-                                                    ),
-                                                    Text(
-                                                      index < size
-                                                          ? newProcess
-                                                          .screens![
-                                                      index]!
-                                                          .label![
-                                                      context
-                                                          .read<
-                                                          GlobalProvider>()
-                                                          .selectedLanguage]!
-                                                          : postRegistrationTabs[
-                                                      index -
-                                                          size],
-                                                      style: Theme.of(
-                                                          context)
-                                                          .textTheme
-                                                          .titleSmall
-                                                          ?.copyWith(
-                                                          color: (context.watch().newProcessTabIndex ==
-                                                              index)
-                                                              ? pureWhite
-                                                              : secondaryColors
-                                                              .elementAt(
-                                                              9),
-                                                          fontWeight:
-                                                          semiBold,
-                                                          fontSize:
-                                                          14),
-                                                    ),
-                                                  ],
-                                                ),
-                                              ),
-                                              SizedBox(
-                                                width: 35.w,
-                                              ),
-                                            ],
-                                          ),
-                                        );
-                                      }),
-                                ),
-                              ),
-                              if (context.watch().newProcessTabIndex < size + 2)
-                              Container(
-                                height: 36.h,
-                                width: 25.w,
-                                padding:
-                                const EdgeInsets.fromLTRB(0, 0, 0, 0),
-                                color: solidPrimary,
-                                child: Icon(
-                                  Icons.arrow_forward_ios_outlined,
-                                  color: pureWhite,
-                                  size: 17,
-                                ),
-                              ),
-                            ],
-                          ),
-                        ),
-                        const SizedBox(
-                          height: 5,
-                        ),
-                      ],
-                    ),
-                  ),
-                  Padding(
-                    padding: isPortrait
-                        ? const EdgeInsets.all(0)
-                        : EdgeInsets.fromLTRB(60.w, 0, 60.w, 0),
-                    child: context.watch().newProcessTabIndex <
-                        size
-                        ? LostProcessScreenContent(
-                        context: context,
-                        //process: newProcess,
-                        screen: newProcess.screens!.elementAt(context
-                            .watch()
-                            .newProcessTabIndex)!)
-                        : context
-                        .watch()
-                        .newProcessTabIndex ==
-                        size
-                        ? const PreviewPage()
-                        : context
-                        .watch()
-                        .newProcessTabIndex ==
-                        size + 1
-                        ? _getPacketAuthComponent()
-                        : const AcknowledgementPage(),
-                  ),
-                  SizedBox(
-                    height: 20.h,
-                  ),
-                ],
-              ),
-            ),
-          ),
-        ),
-      ),
-    );
-  }
-
-  Widget _getPacketAuthComponent() {
-    return Column(
-      children: [
-        SizedBox(
-          height: 30.h,
-        ),
-        Container(
-          width: isPortrait && !isMobileSize ? 566.w : 376.w,
-          padding: EdgeInsets.only(
-            top: 24.h,
-            bottom: 28.h,
-            left: 20.w,
-            right: 20.w,
-          ),
-          decoration: BoxDecoration(
-            borderRadius: const BorderRadius.all(
-              Radius.circular(6),
-            ),
-            color: pureWhite,
-          ),
-          child: Column(
-            children: [
-              _getAuthIcon(),
-              SizedBox(
-                height: 26.h,
-              ),
-              Text(
-                appLocalizations.authenticate_using_password,
-                style: TextStyle(
-                    fontSize: isPortrait && !isMobileSize ? 24 : 18,
-                    fontWeight: semiBold,
-                    color: appBlack),
-              ),
-              SizedBox(
-                height: 35.h,
-              ),
-              Row(
-                children: [
-                  Text(
-                    appLocalizations.username,
-                    style: isPortrait
-                        ? AppTextStyle.tabletPortraitTextfieldHeader
-                        : AppTextStyle.mobileTextfieldHeader,
-                  ),
-                  const Text(
-                    ' *',
-                    style: TextStyle(
-                      color: mandatoryField,
-                    ),
-                  ),
-                ],
-              ),
-              SizedBox(
-                height: 11.h,
-              ),
-              _getUsernameTextField(),
-              SizedBox(
-                height: 35.h,
-              ),
-              Row(
-                children: [
-                  Text(
-                    appLocalizations.password,
-                    style: isPortrait
-                        ? AppTextStyle.tabletPortraitTextfieldHeader
-                        : AppTextStyle.mobileTextfieldHeader,
-                  ),
-                  const Text(
-                    ' *',
-                    style: TextStyle(color: mandatoryField),
-                  ),
-                ],
-              ),
-              SizedBox(
-                height: 11.h,
-              ),
-              _getPasswordTextField(),
-            ],
-          ),
-        ),
-      ],
-    );
-  }
-
-  _getAuthIcon() {
-    return Container(
-      height: 80.w,
-      width: 80.w,
-      decoration: BoxDecoration(
-        shape: BoxShape.circle,
-        border: Border.all(
-          color: authIconBorder,
-          width: 2,
-        ),
-        color: authIconBackground,
-      ),
-      child: Center(
-        child: Image.asset('assets/images/Registering an Individual@2x.png'),
-      ),
-    );
-  }
-
-  _getUsernameTextField() {
-    return Container(
-      height: isPortrait && !isMobileSize ? 82.h : 52.h,
-      alignment: Alignment.centerLeft,
-      padding: EdgeInsets.symmetric(
-        horizontal: 12.w,
-      ),
-      decoration: BoxDecoration(
-        border: Border.all(
-          width: 1.h,
-          color: appGreyShade,
-        ),
-        borderRadius: const BorderRadius.all(
-          Radius.circular(6),
-        ),
-      ),
-      child: TextField(
-        decoration: InputDecoration(
-          hintText: appLocalizations.enter_username,
-          hintStyle: isPortrait && !isMobileSize
-              ? AppTextStyle.tabletPortraitTextfieldHintText
-              : AppTextStyle.mobileTextfieldHintText,
-          border: InputBorder.none,
-        ),
-        style: TextStyle(
-          fontSize: isPortrait && !isMobileSize ? 22 : 14,
-          color: appBlack,
-        ),
-        onChanged: (v) {
-          setState(() {
-            username = v;
-          });
-        },
-      ),
-    );
-  }
-
-  _getPasswordTextField() {
-    return Container(
-      height: isPortrait && !isMobileSize ? 82.h : 52.h,
-      alignment: Alignment.centerLeft,
-      padding: EdgeInsets.symmetric(
-        horizontal: 12.w,
-      ),
-      decoration: BoxDecoration(
-        border: Border.all(
-          width: 1.h,
-          color: appGreyShade,
-        ),
-        borderRadius: const BorderRadius.all(
-          Radius.circular(6),
-        ),
-      ),
-      child: TextField(
-        obscureText: true,
-        decoration: InputDecoration(
-          hintText: appLocalizations.enter_password,
-          hintStyle: isPortrait && !isMobileSize
-              ? AppTextStyle.tabletPortraitTextfieldHintText
-              : AppTextStyle.mobileTextfieldHintText,
-          border: InputBorder.none,
-        ),
-        style: TextStyle(
-          fontSize: isPortrait && !isMobileSize ? 22 : 14,
-          color: appBlack,
-        ),
-        onChanged: (v) {
-          setState(() {
-            password = v;
-          });
-        },
-      ),
-    );
-  }
-}
diff --git a/lib/ui/process_ui/new_process.dart b/lib/ui/process_ui/new_process.dart
deleted file mode 100644
index 93cb7433a..000000000
--- a/lib/ui/process_ui/new_process.dart
+++ /dev/null
@@ -1,1190 +0,0 @@
-/*
- * Copyright (c) Modular Open Source Identity Platform
- * This source code is licensed under the MIT license found in the
- * LICENSE file in the root directory of this source tree.
- *
-*/
-
-import 'dart:convert';
-
-import 'package:flutter/material.dart';
-import 'package:flutter/services.dart';
-
-import 'package:flutter_screenutil/flutter_screenutil.dart';
-import 'package:flutter_svg/flutter_svg.dart';
-import 'package:provider/provider.dart';
-import 'package:registration_client/model/biometric_attribute_data.dart';
-import 'package:registration_client/model/field.dart';
-import 'package:registration_client/model/process.dart';
-import 'package:registration_client/model/screen.dart';
-import 'package:registration_client/pigeon/biometrics_pigeon.dart';
-import 'package:registration_client/pigeon/demographics_data_pigeon.dart';
-import 'package:registration_client/pigeon/registration_data_pigeon.dart';
-
-import 'package:registration_client/provider/auth_provider.dart';
-import 'package:registration_client/provider/connectivity_provider.dart';
-import 'package:registration_client/provider/global_provider.dart';
-import 'package:registration_client/provider/registration_task_provider.dart';
-
-import 'package:registration_client/ui/common/tablet_header.dart';
-import 'package:registration_client/ui/common/tablet_navbar.dart';
-import 'package:registration_client/ui/post_registration/acknowledgement_page.dart';
-
-import 'package:registration_client/ui/post_registration/preview_page.dart';
-import 'package:registration_client/ui/process_ui/widgets/language_selector.dart';
-
-import 'package:registration_client/ui/process_ui/widgets/new_process_screen_content.dart';
-
-import 'package:registration_client/utils/app_config.dart';
-import 'package:flutter_gen/gen_l10n/app_localizations.dart';
-import 'package:registration_client/utils/app_style.dart';
-
-import '../../utils/life_cycle_event_handler.dart';
-
-class NewProcess extends StatefulWidget {
-  const NewProcess({super.key});
-
-  static const routeName = '/new_process';
-
-  @override
-  State createState() => _NewProcessState();
-}
-
-class _NewProcessState extends State with WidgetsBindingObserver {
-  late GlobalProvider globalProvider;
-  late RegistrationTaskProvider registrationTaskProvider;
-  late AuthProvider authProvider;
-  late ConnectivityProvider connectivityProvider;
-  late AppLocalizations appLocalizations = AppLocalizations.of(context)!;
-  bool isPortrait = true;
-  ScrollController scrollController = ScrollController();
-  bool _isContinueProcessing = false;
-
-  List postRegistrationTabs = [
-    'Preview',
-    'Authentication',
-    'Acknowledgement',
-  ];
-
-  Map? templateTitleMap;
-
-  String username = '';
-  String password = '';
-
-  @override
-  void initState() {
-    globalProvider = Provider.of(context, listen: false);
-    registrationTaskProvider =
-        Provider.of(context, listen: false);
-    authProvider = Provider.of(context, listen: false);
-    connectivityProvider =
-        Provider.of(context, listen: false);
-    super.initState();
-    WidgetsBinding.instance.addObserver(LifecycleEventHandler(
-      resumeCallBack: () async {
-        if (mounted) {
-          setState(() {
-            closeKeyboard();
-          });
-        }
-      },
-      suspendingCallBack: () async {
-        if (mounted) {
-          setState(() {
-            closeKeyboard();
-          });
-        }
-      },
-    ));
-    _registrationScreenLoadedAudit();
-  }
-
-  @override
-  void dispose() {
-    WidgetsBinding.instance.removeObserver(this);
-    super.dispose();
-  }
-
-  void closeKeyboard() {
-    FocusScope.of(context).unfocus();
-  }
-
-  void _showInSnackBar(String value) {
-    ScaffoldMessenger.of(context).showSnackBar(
-      SnackBar(
-        content: Text(value),
-      ),
-    );
-  }
-
-  _authenticatePacket(BuildContext context) async {
-    if (!_validateUsername(context)) {
-      return false;
-    }
-
-    if (!_validatePassword(context)) {
-      return false;
-    }
-
-    if (authProvider.currentUser.userId != username) {
-      _showInSnackBar(appLocalizations.invalid_user);
-      return false;
-    }
-
-    await authProvider.authenticatePacket(username, password);
-
-    if (!authProvider.isPacketAuthenticated) {
-      _showErrorInSnackbar();
-      return false;
-    }
-    return true;
-  }
-
-  _showErrorInSnackbar() {
-    String errorMsg = authProvider.packetError;
-    String snackbarText = "";
-
-    switch (errorMsg) {
-      case "REG_TRY_AGAIN":
-        snackbarText = appLocalizations.login_failed;
-        break;
-
-      case "REG_INVALID_REQUEST":
-        snackbarText = appLocalizations.password_incorrect;
-        break;
-
-      case "REG_NETWORK_ERROR":
-        snackbarText = appLocalizations.network_error;
-        break;
-
-      case "":
-        return;
-
-      default:
-        snackbarText = errorMsg;
-        break;
-    }
-
-    _showInSnackBar(snackbarText);
-  }
-
-  bool _validateUsername(BuildContext context) {
-    if (username.trim().isEmpty) {
-      _showInSnackBar(appLocalizations.username_required);
-      return false;
-    }
-
-    if (username.trim().length > 50) {
-      _showInSnackBar(appLocalizations.username_exceed);
-      return false;
-    }
-
-    return true;
-  }
-
-  bool _validatePassword(BuildContext context) {
-    if (password.trim().isEmpty) {
-      _showInSnackBar(appLocalizations.password_required);
-      return false;
-    }
-
-    if (password.trim().length > 50) {
-      _showInSnackBar(appLocalizations.password_exceed);
-      return false;
-    }
-
-    return true;
-  }
-
-  _resetValuesOnRegistrationComplete() {
-    Navigator.of(context).pop();
-  }
-
-  void _registrationScreenLoadedAudit() async {
-    await globalProvider.getAudit("REG-EVT-002", "REG-MOD-103");
-  }
-
-  _nextButtonClickedAudit() async {
-    await globalProvider.getAudit("REG-EVT-003", "REG-MOD-103");
-  }
-
-  setScrollToTop() {
-    scrollController.animateTo(
-      scrollController.position.minScrollExtent,
-      duration: const Duration(milliseconds: 500),
-      curve: Curves.easeOut,
-    );
-    globalProvider.isPageChanged = false;
-  }
-
-  bool continueButton = false;
-  bool authButton = false;
-  @override
-  Widget build(BuildContext context) {
-    WidgetsBinding.instance.addPostFrameCallback((timeStamp) {
-      if (globalProvider.isPageChanged) {
-        setScrollToTop();
-      }
-    });
-    postRegistrationTabs = [
-      appLocalizations.preview_page,
-      appLocalizations.packet_auth_page,
-      appLocalizations.acknowledgement_page,
-    ];
-    isPortrait = MediaQuery.of(context).orientation == Orientation.portrait;
-    bool isMobile = MediaQuery.of(context).size.width < 750;
-    double w = ScreenUtil().screenWidth;
-    Map arguments =
-        ModalRoute.of(context)!.settings.arguments! as Map;
-    final Process newProcess = arguments["process"];
-    int size = newProcess.screens!.length;
-
-    evaluateMVELVisible(String fieldData) async {
-      bool visible =
-          await registrationTaskProvider.evaluateMVELVisible(fieldData);
-      return visible;
-    }
-
-    evaluateMVELRequired(String fieldData) async {
-      bool required =
-          await registrationTaskProvider.evaluateMVELRequired(fieldData);
-      return required;
-    }
-
-    Future onWillPop() async {
-      if (globalProvider.newProcessTabIndex > 0 &&
-          globalProvider.newProcessTabIndex <
-              newProcess.screens!.length + postRegistrationTabs.length - 1) {
-        globalProvider.newProcessTabIndex =
-            globalProvider.newProcessTabIndex - 1;
-      } else {
-        return true;
-      }
-      return false;
-    }
-
-    isExceptionPresent(String id) {
-      bool isExceptionPresent = false;
-      for (BiometricAttributeData x in globalProvider.fieldInputValue[id]) {
-        if (x.exceptions.contains(true) || x.title == "Exception") {
-          isExceptionPresent = true;
-          break;
-        }
-      }
-      return isExceptionPresent;
-    }
-
-    returnBiometricListLength(List? list, String id) {
-      int i = 0;
-      if (list!.contains("leftEye") && list.contains("rightEye")) {
-        i++;
-      }
-      if (list.contains("rightIndex") &&
-          list.contains("rightLittle") &&
-          list.contains("rightRing") &&
-          list.contains("rightMiddle")) {
-        i++;
-      }
-      if (list.contains("leftIndex") &&
-          list.contains("leftLittle") &&
-          list.contains("leftRing") &&
-          list.contains("leftMiddle")) {
-        i++;
-      }
-      if (list.contains("rightThumb") && list.contains("rightThumb")) {
-        i++;
-      }
-      if (list.contains("face")) {
-        i++;
-      }
-      if (isExceptionPresent(id) == true) {
-        i++;
-      }
-      return i;
-    }
-
-    ageDateChangeValidation(int currentIndex) async {
-      if (globalProvider.newProcessTabIndex < size) {
-        Screen screen = newProcess.screens!.elementAt(currentIndex)!;
-        for (int i = 0; i < screen.fields!.length; i++) {
-          if (screen.fields!.elementAt(i)!.controlType == "ageDate") {
-            if (globalProvider.checkAgeGroupChange == "") {
-              globalProvider.checkAgeGroupChange = globalProvider.ageGroup;
-            } else {
-              if (globalProvider.checkAgeGroupChange
-                      .compareTo(globalProvider.ageGroup) ==
-                  0) {
-              } else {
-                List screens = [];
-                for (int i = 0;
-                    i < registrationTaskProvider.listOfProcesses.length;
-                    i++) {
-                  Process process = Process.fromJson(
-                    jsonDecode(
-                      context
-                          .read()
-                          .listOfProcesses
-                          .elementAt(i)
-                          .toString(),
-                    ),
-                  );
-                  if (process.id == "NEW") {
-                    screens = process.screens!;
-                  }
-                }
-                for (Screen? screen in screens) {
-                  if (screen!.name! == "Documents" ||
-                      screen.name! == "BiometricDetails") {
-                    for (Field? field in screen.fields!) {
-                      if (globalProvider.fieldInputValue
-                          .containsKey(field!.id!)) {
-                        globalProvider.fieldInputValue.remove(field.id);
-                      }
-                    }
-                  }
-                }
-                await BiometricsApi().clearBiometricAndDocumentHashmap();
-                globalProvider.clearExceptions();
-                globalProvider.checkAgeGroupChange = globalProvider.ageGroup;
-              }
-            }
-          }
-        }
-      }
-    }
-
-    customValidation(int currentIndex) async {
-      if (currentIndex == 0) {
-        return true;
-      }
-      bool isValid = true;
-      if (globalProvider.newProcessTabIndex < size) {
-        Screen screen = newProcess.screens!.elementAt(currentIndex)!;
-        for (int i = 0; i < screen.fields!.length; i++) {
-          if (screen.fields!.elementAt(i)!.inputRequired! &&
-              screen.fields!.elementAt(i)!.required!) {
-            if (!(globalProvider.fieldInputValue
-                    .containsKey(screen.fields!.elementAt(i)!.id)) &&
-                !(globalProvider.fieldInputValue
-                    .containsKey(screen.fields!.elementAt(i)!.subType)) &&
-                !(globalProvider.fieldInputValue.containsKey(
-                    "${screen.fields!.elementAt(i)!.group}${screen.fields!.elementAt(i)!.subType}"))) {
-              // log("field: ${screen.fields!.elementAt(i)!.group}${screen.fields!.elementAt(i)!.subType}");
-
-              // if (screen.fields!.elementAt(i)!.controlType == "fileupload") {
-              //   _showInSnackBar(appLocalizations.upload_document);
-              // }
-              isValid = false;
-
-              break;
-            }
-            if (screen.fields!.elementAt(i)!.conditionalBioAttributes != null &&
-                screen.fields!
-                    .elementAt(i)!
-                    .conditionalBioAttributes!
-                    .isNotEmpty) {
-              String response = await BiometricsApi().getAgeGroup();
-              if (!(response.compareTo(screen.fields!
-                      .elementAt(i)!
-                      .conditionalBioAttributes!
-                      .first!
-                      .ageGroup!) ==
-                  0)) {
-                if (screen.fields!.elementAt(i)!.controlType == "biometrics") {
-                  int count = returnBiometricListLength(
-                      screen.fields!.elementAt(i)!.bioAttributes,
-                      screen.fields!.elementAt(i)!.id!);
-                  if (globalProvider.completeException[
-                          screen.fields!.elementAt(i)!.id!] !=
-                      null) {
-                    int length = globalProvider
-                        .completeException[screen.fields!.elementAt(i)!.id!]
-                        .length;
-                    count = count - length;
-                  }
-
-                  if (globalProvider
-                          .fieldInputValue[screen.fields!.elementAt(i)!.id!]
-                          .length <
-                      count) {
-                    isValid = false;
-
-                    break;
-                  }
-                  if(globalProvider.isValidBiometricCapture){
-                    isValid = false;
-                    break;
-                  }
-                }
-              }
-            }
-          }
-          if (screen.fields!.elementAt(i)!.requiredOn != null &&
-              screen.fields!.elementAt(i)!.requiredOn!.isNotEmpty) {
-            bool visible = await evaluateMVELVisible(
-                jsonEncode(screen.fields!.elementAt(i)!.toJson()));
-            bool required = await evaluateMVELRequired(
-                jsonEncode(screen.fields!.elementAt(i)!.toJson()));
-            if (visible && required) {
-              if (screen.fields!.elementAt(i)!.inputRequired!) {
-                if (!(globalProvider.fieldInputValue
-                        .containsKey(screen.fields!.elementAt(i)!.id)) &&
-                    !(globalProvider.fieldInputValue
-                        .containsKey(screen.fields!.elementAt(i)!.subType)) &&
-                    !(globalProvider.fieldInputValue.containsKey(
-                        "${screen.fields!.elementAt(i)!.group}${screen.fields!.elementAt(i)!.subType}"))) {
-                  isValid = false;
-
-                  break;
-                }
-                if (screen.fields!.elementAt(i)!.conditionalBioAttributes !=
-                        null &&
-                    screen.fields!
-                        .elementAt(i)!
-                        .conditionalBioAttributes!
-                        .isNotEmpty) {
-                  String response = await BiometricsApi().getAgeGroup();
-                  if (!(response.compareTo(screen.fields!
-                          .elementAt(i)!
-                          .conditionalBioAttributes!
-                          .first!
-                          .ageGroup!) ==
-                      0)) {
-                    if (screen.fields!.elementAt(i)!.controlType ==
-                        "biometrics") {
-                      int count = returnBiometricListLength(
-                          screen.fields!.elementAt(i)!.bioAttributes,
-                          screen.fields!.elementAt(i)!.id!);
-                      if (globalProvider.completeException[
-                              screen.fields!.elementAt(i)!.id!] !=
-                          null) {
-                        int length = globalProvider
-                            .completeException[screen.fields!.elementAt(i)!.id!]
-                            .length;
-                        count = count - length;
-                      }
-                      if (globalProvider
-                              .fieldInputValue[screen.fields!.elementAt(i)!.id!]
-                              .length <
-                          count) {
-                        isValid = false;
-
-                        break;
-                      }
-                      if(globalProvider.isValidBiometricCapture){
-                        isValid = false;
-                        break;
-                      }
-                    }
-                  }
-                  if (response.compareTo(screen.fields!
-                          .elementAt(i)!
-                          .conditionalBioAttributes!
-                          .first!
-                          .ageGroup!) ==
-                      0) {
-                    bool valid = await BiometricsApi()
-                        .conditionalBioAttributeValidation(
-                            screen.fields!.elementAt(i)!.id!,
-                            screen.fields!
-                                .elementAt(i)!
-                                .conditionalBioAttributes!
-                                .first!
-                                .validationExpr!);
-                    if (screen.fields!.elementAt(i)!.exceptionPhotoRequired ==
-                        true) {
-                      List biometricAttributeDataList =
-                          globalProvider.fieldInputValue[
-                              screen.fields!.elementAt(i)!.id!];
-                      bool isExceptionPresent = false;
-                      bool isExceptionAttributePresent = false;
-                      for (var biometricAttributeData
-                          in biometricAttributeDataList) {
-                        if (globalProvider.exceptionAttributes
-                            .contains(biometricAttributeData.title)) {
-                          isExceptionPresent = true;
-                        }
-                        if (biometricAttributeData.title == "Exception") {
-                          isExceptionAttributePresent = true;
-                        }
-                      }
-                      if (isExceptionPresent == true &&
-                          isExceptionAttributePresent == false) {
-                        isValid = false;
-                        break;
-                      }
-                    }
-                    if (!valid) {
-                      isValid = false;
-                      break;
-                    }
-                  }
-                }
-              }
-            }
-          }
-        }
-      }
-      return isValid;
-    }
-
-    continueButtonTap(int size, newProcess) async {
-      globalProvider.isPageChanged = true;
-      if (globalProvider.newProcessTabIndex < size) {
-        ageDateChangeValidation(globalProvider.newProcessTabIndex);
-        bool customValidator =
-            await customValidation(globalProvider.newProcessTabIndex);
-        if (customValidator) {
-          if (globalProvider.formKey.currentState!.validate()) {
-            if (globalProvider.newProcessTabIndex ==
-                newProcess.screens!.length - 1) {
-              templateTitleMap = {
-                'demographicInfo': appLocalizations.demographic_information,
-                'documents': appLocalizations.documents,
-                'bioMetrics': appLocalizations.biometrics
-              };
-              registrationTaskProvider.setPreviewTemplate("");
-              registrationTaskProvider.setAcknowledgementTemplate("");
-              await registrationTaskProvider.getPreviewTemplate(
-                  true, templateTitleMap!);
-              await registrationTaskProvider.getAcknowledgementTemplate(
-                  false, templateTitleMap!,
-              );
-            }
-
-            globalProvider.newProcessTabIndex =
-                globalProvider.newProcessTabIndex + 1;
-          }
-        }
-
-        _nextButtonClickedAudit();
-      } else {
-        if (globalProvider.newProcessTabIndex == size + 1) {
-          bool isPacketAuthenticated = await _authenticatePacket(context);
-          if (!isPacketAuthenticated) {
-            return;
-          }
-          RegistrationSubmitResponse registrationSubmitResponse =
-              await registrationTaskProvider.submitRegistrationDto(username);
-          if (registrationSubmitResponse.errorCode!.isNotEmpty) {
-            _showInSnackBar(registrationSubmitResponse.errorCode!);
-            return;
-          }
-          globalProvider.setRegId(registrationSubmitResponse.rId);
-
-          // Updating key to packetId after success creation of packet
-          registrationTaskProvider
-              .updateTemplateStorageKey(registrationSubmitResponse.rId);
-          registrationTaskProvider.deleteDefaultTemplateStored();
-
-          setState(() {
-            username = '';
-            password = '';
-          });
-        }
-        if (globalProvider.newProcessTabIndex == size + 2) {
-          _resetValuesOnRegistrationComplete();
-          return;
-        }
-        globalProvider.newProcessTabIndex =
-            globalProvider.newProcessTabIndex + 1;
-      }
-    }
-
-    customValidation(globalProvider.newProcessTabIndex).then((value) {
-      setState(() {
-        continueButton = value &&
-            globalProvider.formKey.currentState != null &&
-            globalProvider.formKey.currentState!.validate();
-      });
-      if (globalProvider.newProcessTabIndex >= size) {
-        continueButton = true;
-      }
-    });
-
-    //auth button validation
-    if(username.trim().isNotEmpty && password.trim().isNotEmpty){
-      authButton = true;
-    }
-
-    return WillPopScope(
-      onWillPop: onWillPop,
-      child: SafeArea(
-        child: Scaffold(
-          backgroundColor: secondaryColors.elementAt(10),
-          bottomNavigationBar: Container(
-            decoration: BoxDecoration(
-              border: const Border(
-                top: BorderSide(
-                  color: dividerColor,
-                  width: 1,
-                ),
-              ),
-              color: pureWhite,
-            ),
-            padding: EdgeInsets.symmetric(
-              horizontal: isPortrait ? 20.w : 60.w,
-              vertical: 16.h,
-            ),
-            // height: isPortrait ? 94.h : 84.h,
-            child: globalProvider.newProcessTabIndex == 0
-                ? Row(
-              children: [
-                Expanded(
-                  child: OutlinedButton(
-                    child: SizedBox(
-                      height: isPortrait && !isMobileSize ? 68.h : 52.h,
-                      child: Center(
-                        child: Text(
-                          appLocalizations.go_back,
-                          style: TextStyle(
-                            fontSize:
-                            isPortrait && !isMobileSize ? 22 : 14,
-                          ),
-                        ),
-                      ),
-                    ),
-                    onPressed: () {
-                      Navigator.of(context).pop();
-                    },
-                  ),
-                ),
-                SizedBox(
-                  width: 10.w,
-                ),
-                Expanded(
-                  child: ElevatedButton(
-                    onPressed: _isContinueProcessing ? null : () async {
-                      setState(() {
-                        _isContinueProcessing = true;
-                      });
-                      try {
-                        registrationTaskProvider.addConsentField("Y");
-                        await DemographicsApi()
-                            .addDemographicField("consent", "true");
-                        continueButtonTap(size, newProcess);
-                      } finally {
-                        setState(() {
-                          _isContinueProcessing = false;
-                        });
-                      }
-                    },
-                    child: SizedBox(
-                      height: isPortrait && !isMobileSize ? 68.h : 52.h,
-                      child: Center(
-                        child: Text(
-                          appLocalizations.informed,
-                          style: TextStyle(
-                            fontSize:
-                            isPortrait && !isMobileSize ? 22 : 14,
-                          ),
-                        ),
-                      ),
-                    ),
-                  ),
-                ),
-              ],
-            )
-                : Row(
-                    mainAxisAlignment: MainAxisAlignment.start,
-                    children: [
-                      /*globalProvider.newProcessTabIndex == size + 2
-                          ? ElevatedButton(
-                              onPressed: () async {
-                                await connectivityProvider
-                                    .checkNetworkConnection();
-                                bool isConnected =
-                                    connectivityProvider.isConnected;
-                                if (!isConnected) {
-                                  _showInSnackBar(
-                                      appLocalizations.network_error);
-                                  return;
-                                }
-                                globalProvider.syncPacket(globalProvider.regId);
-                              },
-                              child: Text(appLocalizations.sync_packet),
-                            )
-                          : const SizedBox.shrink(),
-                      SizedBox(
-                        width: 10.w,
-                      ),
-                      globalProvider.newProcessTabIndex == size + 2
-                          ? ElevatedButton(
-                              onPressed: () async {
-                                await connectivityProvider
-                                    .checkNetworkConnection();
-                                bool isConnected =
-                                    connectivityProvider.isConnected;
-                                if (!isConnected) {
-                                  _showInSnackBar(
-                                      appLocalizations.network_error);
-                                  return;
-                                }
-                                globalProvider
-                                    .uploadPacket(globalProvider.regId);
-                              },
-                              child: Text(appLocalizations.upload_packet),
-                            )
-                          : const SizedBox.shrink(),*/
-                const Expanded(
-                  child: SizedBox(),
-                ),
-                ElevatedButton(
-                  style: ButtonStyle(
-                    maximumSize: MaterialStateProperty.all(
-                        const Size(209, 52)),
-                    minimumSize: MaterialStateProperty.all(
-                        const Size(209, 52)),
-                    backgroundColor: MaterialStateProperty.all(
-                        (continueButton && context.read().newProcessTabIndex <=
-                            size) ? solidPrimary : authButton ? solidPrimary: Colors.grey),
-                  ),
-                  onPressed: _isContinueProcessing ? null : () async {
-                    if (_isContinueProcessing) return;
-                    setState(() {
-                      _isContinueProcessing = true;
-                    });
-                    try {
-                      await continueButtonTap(size, newProcess);
-                    } finally {
-                      setState(() {
-                        _isContinueProcessing = false;
-                      });
-                    }
-                  },
-                  child: Text(
-                    context.read().newProcessTabIndex <=
-                        size
-                        ? appLocalizations.continue_text
-                        : globalProvider.newProcessTabIndex == size + 1
-                        ? appLocalizations.authenticate
-                        : appLocalizations.go_to_home,
-                    style: const TextStyle(color: appWhite),
-                  ),
-                ),
-              ],
-            ),
-          ),
-          body: SingleChildScrollView(
-            controller: scrollController,
-            child: AnnotatedRegion(
-              value: const SystemUiOverlayStyle(
-                statusBarColor: Colors.transparent,
-              ),
-              child: Column(
-                children: [
-                  // isPortrait
-                  //     ? const SizedBox()
-                  //     : const Column(
-                  //         children: [
-                  //           TabletHeader(),
-                  //           TabletNavbar(),
-                  //         ],
-                  //       ),
-                  Container(
-                    padding: isMobile && !isMobileSize
-                        ? const EdgeInsets.fromLTRB(0, 46, 0, 0)
-                        : const EdgeInsets.fromLTRB(0, 0, 0, 0),
-                    decoration: const BoxDecoration(
-                      gradient: LinearGradient(
-                        begin: Alignment.topCenter,
-                        end: Alignment.bottomCenter,
-                        colors: [Color(0xff214FBF), Color(0xff1C43A1)],
-                      ),
-                    ),
-                    child: Column(
-                      crossAxisAlignment: CrossAxisAlignment.start,
-                      children: [
-                        SizedBox(
-                          width: w,
-                          height: isPortrait ? 21.w : 30.w,
-                        ),
-                        Padding(
-                          padding: isPortrait
-                              ? EdgeInsets.fromLTRB(20.w, 0, 0, 0)
-                              : EdgeInsets.fromLTRB(60.w, 0, 60.w, 0),
-                          child: Text(
-                            newProcess.label![context
-                                .read()
-                                .selectedLanguage]!,
-                            style: Theme.of(context)
-                                .textTheme
-                                .titleMedium
-                                ?.copyWith(
-                                    color: pureWhite,
-                                    fontWeight: semiBold,
-                                    fontSize: isPortrait ? 24 : 21),
-                          ),
-                        ),
-                        SizedBox(
-                          height: 30.h,
-                        ),
-                        Divider(
-                          height: 12.h,
-                          thickness: 1,
-                          color: secondaryColors.elementAt(2),
-                        ),
-                        Padding(
-                          padding: isPortrait
-                              ? const EdgeInsets.all(0)
-                              : EdgeInsets.fromLTRB(60.w, 0, 60.w, 0),
-                          child: Stack(
-                            alignment: FractionalOffset.centerRight,
-                            children: [
-                              Padding(
-                                padding: isPortrait
-                                    ? EdgeInsets.fromLTRB(20.w, 10.h, 0, 0)
-                                    : EdgeInsets.fromLTRB(0, 10.h, 0, 0),
-                                child: SizedBox(
-                                  height: 36.h,
-                                  child: ListView.builder(
-                                      padding: const EdgeInsets.all(0),
-                                      scrollDirection: Axis.horizontal,
-                                      itemCount: newProcess.screens!.length + 3,
-                                      itemBuilder:
-                                          (BuildContext context, int index) {
-                                        return GestureDetector(
-                                          onTap: () {
-                                            if (context
-                                                    .read()
-                                                    .newProcessTabIndex ==
-                                                size + 2) {
-                                              return;
-                                            }
-
-                                            if (index <
-                                                context
-                                                    .read()
-                                                    .newProcessTabIndex) {
-                                              context
-                                                  .read()
-                                                  .newProcessTabIndex = index;
-                                            }
-                                          },
-                                          child: Row(
-                                            children: [
-                                              Container(
-                                                padding: EdgeInsets.fromLTRB(
-                                                    0, 0, 0, 8.h),
-                                                decoration: BoxDecoration(
-                                                  border: Border(
-                                                    bottom: BorderSide(
-                                                        color: (context
-                                                                    .watch<
-                                                                        GlobalProvider>()
-                                                                    .newProcessTabIndex ==
-                                                                index)
-                                                            ? pureWhite
-                                                            : Colors
-                                                                .transparent,
-                                                        width: 3),
-                                                  ),
-                                                ),
-                                                child: Row(
-                                                  children: [
-                                                    (index <
-                                                            context
-                                                                .watch<
-                                                                    GlobalProvider>()
-                                                                .newProcessTabIndex)
-                                                        ? Icon(
-                                                            Icons.check_circle,
-                                                            size: 17,
-                                                            color:
-                                                                secondaryColors
-                                                                    .elementAt(
-                                                                        11),
-                                                          )
-                                                        : (context
-                                                                    .watch<
-                                                                        GlobalProvider>()
-                                                                    .newProcessTabIndex ==
-                                                                index)
-                                                            ? Icon(
-                                                                Icons.circle,
-                                                                color:
-                                                                    pureWhite,
-                                                                size: 17,
-                                                              )
-                                                            : Icon(
-                                                                Icons
-                                                                    .circle_outlined,
-                                                                size: 17,
-                                                                color: secondaryColors
-                                                                    .elementAt(
-                                                                        9),
-                                                              ),
-                                                    SizedBox(
-                                                      width: 6.w,
-                                                    ),
-                                                    Text(
-                                                      index < size
-                                                          ? newProcess
-                                                                  .screens![index]!
-                                                                  .label![
-                                                              context
-                                                                  .read<
-                                                                      GlobalProvider>()
-                                                                  .selectedLanguage]!
-                                                          : postRegistrationTabs[
-                                                              index - size],
-                                                      style: Theme.of(context)
-                                                          .textTheme
-                                                          .titleSmall
-                                                          ?.copyWith(
-                                                              color: (context
-                                                                          .watch<
-                                                                              GlobalProvider>()
-                                                                          .newProcessTabIndex ==
-                                                                      index)
-                                                                  ? pureWhite
-                                                                  : secondaryColors
-                                                                      .elementAt(
-                                                                          9),
-                                                              fontWeight:
-                                                                  semiBold,
-                                                              fontSize: 14),
-                                                    ),
-                                                  ],
-                                                ),
-                                              ),
-                                              SizedBox(
-                                                width: 35.w,
-                                              ),
-                                            ],
-                                          ),
-                                        );
-                                      }),
-                                ),
-                              ),
-                              if (context.watch().newProcessTabIndex < size + 2)
-                              Container(
-                                height: 36.h,
-                                width: 25.w,
-                                padding: const EdgeInsets.fromLTRB(0, 0, 0, 0),
-                                color: solidPrimary,
-                                child: Icon(
-                                  Icons.arrow_forward_ios_outlined,
-                                  color: pureWhite,
-                                  size: 17,
-                                ),
-                              ),
-                            ],
-                          ),
-                        ),
-                        const SizedBox(
-                          height: 5,
-                        ),
-                      ],
-                    ),
-                  ),
-                  Padding(
-                    padding: isPortrait
-                        ? const EdgeInsets.all(0)
-                        : EdgeInsets.fromLTRB(60.w, 0, 60.w, 0),
-                    child: context.watch().newProcessTabIndex <
-                            size
-                        ? NewProcessScreenContent(
-                            context: context,
-                            screen: newProcess.screens!.elementAt(context
-                                .watch()
-                                .newProcessTabIndex)!)
-                        : context.watch().newProcessTabIndex ==
-                                size
-                            ? const PreviewPage()
-                            : context
-                                        .watch()
-                                        .newProcessTabIndex ==
-                                    size + 1
-                                ? _getPacketAuthComponent()
-                                : const AcknowledgementPage(),
-                  ),
-                  SizedBox(
-                    height: 20.h,
-                  ),
-                ],
-              ),
-            ),
-          ),
-        ),
-      ),
-    );
-  }
-
-  Widget _getPacketAuthComponent() {
-    return Column(
-      children: [
-        SizedBox(
-          height: 30.h,
-        ),
-        Container(
-          width: isPortrait && !isMobileSize ? 566.w : 376.w,
-          padding: EdgeInsets.only(
-            top: 24.h,
-            bottom: 28.h,
-            left: 20.w,
-            right: 20.w,
-          ),
-          decoration: BoxDecoration(
-            borderRadius: const BorderRadius.all(
-              Radius.circular(6),
-            ),
-            color: pureWhite,
-          ),
-          child: Column(
-            children: [
-              _getAuthIcon(),
-              SizedBox(
-                height: 26.h,
-              ),
-              Text(
-                appLocalizations.authenticate_using_password,
-                style: TextStyle(
-                    fontSize: isPortrait && !isMobileSize ? 24 : 18,
-                    fontWeight: semiBold,
-                    color: appBlack),
-              ),
-              SizedBox(
-                height: 35.h,
-              ),
-              Row(
-                children: [
-                  Text(
-                    appLocalizations.username,
-                    style: isPortrait
-                        ? AppTextStyle.tabletPortraitTextfieldHeader
-                        : AppTextStyle.mobileTextfieldHeader,
-                  ),
-                  const Text(
-                    ' *',
-                    style: TextStyle(
-                      color: mandatoryField,
-                    ),
-                  ),
-                ],
-              ),
-              SizedBox(
-                height: 11.h,
-              ),
-              _getUsernameTextField(),
-              SizedBox(
-                height: 35.h,
-              ),
-              Row(
-                children: [
-                  Text(
-                    appLocalizations.password,
-                    style: isPortrait
-                        ? AppTextStyle.tabletPortraitTextfieldHeader
-                        : AppTextStyle.mobileTextfieldHeader,
-                  ),
-                  const Text(
-                    ' *',
-                    style: TextStyle(color: mandatoryField),
-                  ),
-                ],
-              ),
-              SizedBox(
-                height: 11.h,
-              ),
-              _getPasswordTextField(),
-            ],
-          ),
-        ),
-      ],
-    );
-  }
-
-  _getAuthIcon() {
-    return Container(
-      height: 80.w,
-      width: 80.w,
-      decoration: BoxDecoration(
-        shape: BoxShape.circle,
-        border: Border.all(
-          color: authIconBorder,
-          width: 2,
-        ),
-        color: authIconBackground,
-      ),
-      child: Center(
-        child: SvgPicture.asset('assets/images/AuthenticationIcon.svg'),
-      ),
-    );
-  }
-
-  _getUsernameTextField() {
-    return Container(
-      height: isPortrait && !isMobileSize ? 82.h : 52.h,
-      alignment: Alignment.centerLeft,
-      padding: EdgeInsets.symmetric(
-        horizontal: 12.w,
-      ),
-      decoration: BoxDecoration(
-        border: Border.all(
-          width: 1.h,
-          color: appGreyShade,
-        ),
-        borderRadius: const BorderRadius.all(
-          Radius.circular(6),
-        ),
-      ),
-      child: TextField(
-        decoration: InputDecoration(
-          hintText: appLocalizations.enter_username,
-          hintStyle: isPortrait && !isMobileSize
-              ? AppTextStyle.tabletPortraitTextfieldHintText
-              : AppTextStyle.mobileTextfieldHintText,
-          border: InputBorder.none,
-        ),
-        style: TextStyle(
-          fontSize: isPortrait && !isMobileSize ? 22 : 14,
-          color: appBlack,
-        ),
-        onChanged: (v) {
-          setState(() {
-            username = v;
-          });
-        },
-      ),
-    );
-  }
-
-  _getPasswordTextField() {
-    return Container(
-      height: isPortrait && !isMobileSize ? 82.h : 52.h,
-      alignment: Alignment.centerLeft,
-      padding: EdgeInsets.symmetric(
-        horizontal: 12.w,
-      ),
-      decoration: BoxDecoration(
-        border: Border.all(
-          width: 1.h,
-          color: appGreyShade,
-        ),
-        borderRadius: const BorderRadius.all(
-          Radius.circular(6),
-        ),
-      ),
-      child: TextField(
-        obscureText: true,
-        decoration: InputDecoration(
-          hintText: appLocalizations.enter_password,
-          hintStyle: isPortrait && !isMobileSize
-              ? AppTextStyle.tabletPortraitTextfieldHintText
-              : AppTextStyle.mobileTextfieldHintText,
-          border: InputBorder.none,
-        ),
-        style: TextStyle(
-          fontSize: isPortrait && !isMobileSize ? 22 : 14,
-          color: appBlack,
-        ),
-        onChanged: (v) {
-          setState(() {
-            password = v;
-          });
-        },
-      ),
-    );
-  }
-}
diff --git a/lib/ui/process_ui/process_type.dart b/lib/ui/process_ui/process_type.dart
new file mode 100644
index 000000000..15fa1f18f
--- /dev/null
+++ b/lib/ui/process_ui/process_type.dart
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) Modular Open Source Identity Platform
+ * This source code is licensed under the MIT license found in the
+ * LICENSE file in the root directory of this source tree.
+ *
+*/
+
+enum ProcessType {
+  newProcess,
+  lostProcess,
+  updateProcess,
+  correctionProcess,
+}
+
+extension ProcessTypeExtension on ProcessType {
+  String get id {
+    switch (this) {
+      case ProcessType.newProcess:
+        return 'NEW';
+      case ProcessType.lostProcess:
+        return 'LOST';
+      case ProcessType.updateProcess:
+        return 'UPDATE';
+      case ProcessType.correctionProcess:
+        return 'CORRECTION';
+    }
+  }
+
+  String get routeName {
+    switch (this) {
+      case ProcessType.newProcess:
+        return '/new_process';
+      case ProcessType.lostProcess:
+        return '/lost_process';
+      case ProcessType.updateProcess:
+        return '/update_process';
+      case ProcessType.correctionProcess:
+        return '/correction_process';
+    }
+  }
+}
+
diff --git a/lib/ui/process_ui/update_process.dart b/lib/ui/process_ui/update_process.dart
deleted file mode 100644
index 7b6704ee1..000000000
--- a/lib/ui/process_ui/update_process.dart
+++ /dev/null
@@ -1,1184 +0,0 @@
-/*
- * Copyright (c) Modular Open Source Identity Platform
- * This source code is licensed under the MIT license found in the
- * LICENSE file in the root directory of this source tree.
- *
-*/
-
-import 'dart:convert';
-
-import 'package:flutter/material.dart';
-import 'package:flutter/services.dart';
-
-import 'package:flutter_screenutil/flutter_screenutil.dart';
-import 'package:provider/provider.dart';
-import 'package:registration_client/model/biometric_attribute_data.dart';
-import 'package:registration_client/model/field.dart';
-import 'package:registration_client/model/process.dart';
-import 'package:registration_client/model/screen.dart';
-import 'package:registration_client/pigeon/biometrics_pigeon.dart';
-import 'package:registration_client/pigeon/demographics_data_pigeon.dart';
-import 'package:registration_client/pigeon/registration_data_pigeon.dart';
-
-import 'package:registration_client/provider/auth_provider.dart';
-import 'package:registration_client/provider/connectivity_provider.dart';
-import 'package:registration_client/provider/global_provider.dart';
-import 'package:registration_client/provider/registration_task_provider.dart';
-
-import 'package:registration_client/ui/post_registration/acknowledgement_page.dart';
-
-import 'package:registration_client/ui/post_registration/preview_page.dart';
-import 'package:registration_client/ui/process_ui/widgets/update_field_selector.dart';
-
-import 'package:registration_client/ui/process_ui/widgets/update_process_screen_content.dart';
-
-import 'package:registration_client/utils/app_config.dart';
-import 'package:flutter_gen/gen_l10n/app_localizations.dart';
-import 'package:registration_client/utils/app_style.dart';
-
-import '../../utils/life_cycle_event_handler.dart';
-
-class UpdateProcess extends StatefulWidget {
-  const UpdateProcess({
-    super.key,
-  });
-
-  static const routeName = '/update_process';
-
-  @override
-  State createState() => _UpdateProcessState();
-}
-
-class _UpdateProcessState extends State
-    with WidgetsBindingObserver {
-  late GlobalProvider globalProvider;
-  late RegistrationTaskProvider registrationTaskProvider;
-  late AuthProvider authProvider;
-  late ConnectivityProvider connectivityProvider;
-  late AppLocalizations appLocalizations = AppLocalizations.of(context)!;
-  bool isPortrait = true;
-  bool fieldSelectionCompleted = false;
-  bool _isContinueProcessing = false;
-
-  List postRegistrationTabs = [
-    'Preview',
-    'Authentication',
-    'Acknowledgement',
-  ];
-
-  Map? templateTitleMap;
-
-  String username = '';
-  String password = '';
-
-  @override
-  void initState() {
-    globalProvider = Provider.of(context, listen: false);
-    registrationTaskProvider =
-        Provider.of(context, listen: false);
-    authProvider = Provider.of(context, listen: false);
-    connectivityProvider =
-        Provider.of(context, listen: false);
-    super.initState();
-    WidgetsBinding.instance.addObserver(LifecycleEventHandler(
-      resumeCallBack: () async {
-        if (mounted) {
-          setState(() {
-            closeKeyboard();
-          });
-        }
-      },
-      suspendingCallBack: () async {
-        if (mounted) {
-          setState(() {
-            closeKeyboard();
-          });
-        }
-      },
-    ));
-    _registrationScreenLoadedAudit();
-  }
-
-  @override
-  void dispose() {
-    WidgetsBinding.instance.removeObserver(this);
-    super.dispose();
-  }
-
-  void closeKeyboard() {
-    FocusScope.of(context).unfocus();
-  }
-
-  void _showInSnackBar(String value) {
-    ScaffoldMessenger.of(context).showSnackBar(
-      SnackBar(
-        content: Text(value),
-      ),
-    );
-  }
-
-  _authenticatePacket(BuildContext context) async {
-    if (!_validateUsername(context)) {
-      return false;
-    }
-
-    if (!_validatePassword(context)) {
-      return false;
-    }
-
-    if (authProvider.currentUser.userId != username) {
-      _showInSnackBar(appLocalizations.invalid_user);
-      return false;
-    }
-
-    await authProvider.authenticatePacket(username, password);
-
-    if (!authProvider.isPacketAuthenticated) {
-      _showErrorInSnackbar();
-      return false;
-    }
-    return true;
-  }
-
-  _showErrorInSnackbar() {
-    String errorMsg = authProvider.packetError;
-    String snackbarText = "";
-
-    switch (errorMsg) {
-      case "REG_TRY_AGAIN":
-        snackbarText = appLocalizations.login_failed;
-        break;
-
-      case "REG_INVALID_REQUEST":
-        snackbarText = appLocalizations.password_incorrect;
-        break;
-
-      case "REG_NETWORK_ERROR":
-        snackbarText = appLocalizations.network_error;
-        break;
-
-      case "":
-        return;
-
-      default:
-        snackbarText = errorMsg;
-        break;
-    }
-
-    _showInSnackBar(snackbarText);
-  }
-
-  bool _validateUsername(BuildContext context) {
-    if (username.trim().isEmpty) {
-      _showInSnackBar(appLocalizations.username_required);
-      return false;
-    }
-
-    if (username.trim().length > 50) {
-      _showInSnackBar(appLocalizations.username_exceed);
-      return false;
-    }
-
-    return true;
-  }
-
-  bool _validatePassword(BuildContext context) {
-    if (password.trim().isEmpty) {
-      _showInSnackBar(appLocalizations.password_required);
-      return false;
-    }
-
-    if (password.trim().length > 50) {
-      _showInSnackBar(appLocalizations.password_exceed);
-      return false;
-    }
-
-    return true;
-  }
-
-  _resetValuesOnRegistrationComplete() {
-    Navigator.of(context).pop();
-  }
-
-  void _registrationScreenLoadedAudit() async {
-    await globalProvider.getAudit("REG-EVT-002", "REG-MOD-103");
-  }
-
-  _nextButtonClickedAudit() async {
-    await globalProvider.getAudit("REG-EVT-003", "REG-MOD-103");
-  }
-
-  bool continueButton = false;
-
-  @override
-  Widget build(BuildContext context) {
-    postRegistrationTabs = [
-      appLocalizations.preview_page,
-      appLocalizations.packet_auth_page,
-      appLocalizations.acknowledgement_page,
-    ];
-    isPortrait = MediaQuery.of(context).orientation == Orientation.portrait;
-    bool isMobile = MediaQuery.of(context).size.width < 750;
-    double w = ScreenUtil().screenWidth;
-    Map arguments =
-        ModalRoute.of(context)!.settings.arguments! as Map;
-    final Process newProcess = arguments["process"];
-    int size = newProcess.screens!.length;
-
-    Future onWillPop() async {
-      if (globalProvider.newProcessTabIndex > 0 &&
-          globalProvider.newProcessTabIndex <
-              newProcess.screens!.length + postRegistrationTabs.length - 1) {
-        globalProvider.newProcessTabIndex =
-            globalProvider.newProcessTabIndex - 1;
-      } else if (globalProvider.newProcessTabIndex == 0 &&
-          fieldSelectionCompleted) {
-        setState(() {
-          fieldSelectionCompleted = false;
-        });
-      } else {
-        return true;
-      }
-      return false;
-    }
-
-    isExceptionPresent(String id) {
-      bool isExceptionPresent = false;
-      for (BiometricAttributeData x in globalProvider.fieldInputValue[id]) {
-        if (x.exceptions.contains(true) || x.title == "Exception") {
-          isExceptionPresent = true;
-          break;
-        }
-      }
-      return isExceptionPresent;
-    }
-
-    returnBiometricListLength(List? list, String id) {
-      int i = 0;
-      if (list!.contains("leftEye") && list.contains("rightEye")) {
-        i++;
-      }
-      if (list.contains("rightIndex") &&
-          list.contains("rightLittle") &&
-          list.contains("rightRing") &&
-          list.contains("rightMiddle")) {
-        i++;
-      }
-      if (list.contains("leftIndex") &&
-          list.contains("leftLittle") &&
-          list.contains("leftRing") &&
-          list.contains("leftMiddle")) {
-        i++;
-      }
-      if (list.contains("rightThumb") && list.contains("rightThumb")) {
-        i++;
-      }
-      if (list.contains("face")) {
-        i++;
-      }
-      if (isExceptionPresent(id) == true) {
-        i++;
-      }
-      return i;
-    }
-
-    biometricRequiredFieldValidation(Field field) async {
-      if (field.controlType == "biometrics") {
-        int count = returnBiometricListLength(field.bioAttributes, field.id!);
-        if (globalProvider.completeException[field.id!] != null) {
-          int length = globalProvider.completeException[field.id!].length;
-          count = count - length;
-        }
-
-        if (globalProvider.fieldInputValue[field.id!].length < count) {
-          return false;
-        }
-      }
-
-      return true;
-    }
-
-    biometricConditionalFieldValidation(Field field) async {
-      bool valid = await BiometricsApi().conditionalBioAttributeValidation(
-          field.id!, field.conditionalBioAttributes!.first!.validationExpr!);
-      if (field.exceptionPhotoRequired == true) {
-        List biometricAttributeDataList =
-            globalProvider.fieldInputValue[field.id!];
-        bool isExceptionPresent = false;
-        bool isExceptionAttributePresent = false;
-        for (var biometricAttributeData in biometricAttributeDataList) {
-          if (globalProvider.exceptionAttributes
-              .contains(biometricAttributeData.title)) {
-            isExceptionPresent = true;
-          }
-          if (biometricAttributeData.title == "Exception") {
-            isExceptionAttributePresent = true;
-          }
-        }
-
-        if (isExceptionPresent == true &&
-            isExceptionAttributePresent == false) {
-          return false;
-        }
-      }
-      if (!valid) {
-        return false;
-      }
-      return true;
-    }
-
-    biometricValidation(Field field) async {
-      if (field.conditionalBioAttributes != null &&
-          field.conditionalBioAttributes!.isNotEmpty) {
-        String response = await BiometricsApi().getAgeGroup();
-        if (response
-                .compareTo(field.conditionalBioAttributes!.first!.ageGroup!) !=
-            0) {
-          bool isValid = true;
-          if (field.conditionalBioAttributes!.first!.ageGroup! == "ALL") {
-            isValid = await biometricConditionalFieldValidation(field);
-          } else {
-            isValid = await biometricRequiredFieldValidation(field);
-          }
-
-          if (!isValid) {
-            return false;
-          }
-        }
-
-        if (response
-                .compareTo(field.conditionalBioAttributes!.first!.ageGroup!) ==
-            0) {
-          bool isValid = await biometricConditionalFieldValidation(field);
-          if (!isValid) {
-            return false;
-          }
-        }
-      }
-
-      return true;
-    }
-
-    ageDateChangeValidation(int currentIndex) async {
-      if (globalProvider.newProcessTabIndex < size) {
-        Screen screen = newProcess.screens!.elementAt(currentIndex)!;
-        for (int i = 0; i < screen.fields!.length; i++) {
-          if (screen.fields!.elementAt(i)!.controlType == "ageDate") {
-            if (globalProvider.checkAgeGroupChange == "") {
-              globalProvider.checkAgeGroupChange = globalProvider.ageGroup;
-            } else {
-              if (globalProvider.checkAgeGroupChange
-                      .compareTo(globalProvider.ageGroup) ==
-                  0) {
-              } else {
-                List screens = [];
-                for (int i = 0;
-                    i < registrationTaskProvider.listOfProcesses.length;
-                    i++) {
-                  Process process = Process.fromJson(
-                    jsonDecode(
-                      context
-                          .read()
-                          .listOfProcesses
-                          .elementAt(i)
-                          .toString(),
-                    ),
-                  );
-                  if (process.id == "NEW" || process.id == "UPDATE") {
-                    screens = process.screens!;
-                  }
-                }
-                for (Screen? screen in screens) {
-                  if (screen!.name! == "Documents" ||
-                      screen.name! == "BiometricDetails") {
-                    for (Field? field in screen.fields!) {
-                      globalProvider.fieldInputValue.remove(field!.id);
-                    }
-                  }
-                }
-                await BiometricsApi().clearBiometricAndDocumentHashmap();
-                globalProvider.clearExceptions();
-                globalProvider.checkAgeGroupChange = globalProvider.ageGroup;
-              }
-            }
-          }
-        }
-      }
-    }
-
-    customValidation(int currentIndex) async {
-      if (currentIndex == 0) {
-        if (globalProvider.updateUINNumber.isEmpty) {
-          return false;
-        }
-        return true;
-      }
-      if (globalProvider.newProcessTabIndex < size) {
-        Screen screen = newProcess.screens!.elementAt(currentIndex)!;
-        for (int i = 0; i < screen.fields!.length; i++) {
-          Field field = screen.fields!.elementAt(i)!;
-          String group = field.group!;
-          String fieldId = field.id!;
-          if (globalProvider.selectedUpdateFields[group] != null) {
-            if (field.required! ||
-                (globalProvider.mvelRequiredFields[fieldId] ?? false)) {
-              if (!(globalProvider.fieldInputValue.containsKey(field.id)) &&
-                  !(globalProvider.fieldInputValue
-                      .containsKey(field.subType)) &&
-                  !(globalProvider.fieldInputValue
-                      .containsKey("${field.group}${field.subType}"))) {
-                return false;
-              }
-
-              bool isValid = await biometricValidation(field);
-              if (!isValid) {
-                return false;
-              }
-            }
-          } else if (newProcess.autoSelectedGroups!.contains(group)) {
-            if (globalProvider.mvelRequiredFields[fieldId] ?? false) {
-              if (!(globalProvider.fieldInputValue.containsKey(field.id)) &&
-                  !(globalProvider.fieldInputValue
-                      .containsKey(field.subType)) &&
-                  !(globalProvider.fieldInputValue
-                      .containsKey("${field.group}${field.subType}"))) {
-                return false;
-              }
-
-              if (field.conditionalBioAttributes != null &&
-                  field.conditionalBioAttributes!.isNotEmpty) {
-                bool isValid = await biometricConditionalFieldValidation(field);
-                if (!isValid) {
-                  return false;
-                }
-              }
-            }
-          }
-        }
-      }
-      return true;
-    }
-
-    const debounceDuration = Duration(milliseconds: 500);
-    DateTime? lastClickTime;
-
-    continueButtonTap(int size, newProcess) async {
-      final now = DateTime.now();
-      if (lastClickTime != null &&
-          now.difference(lastClickTime!) < debounceDuration) {
-        return;
-      }
-      lastClickTime = now;
-
-      setState(() {
-        _isContinueProcessing = true;
-      });
-
-      try {
-        if (globalProvider.newProcessTabIndex == 0 && !fieldSelectionCompleted) {
-          if (globalProvider.selectedUpdateFields.isEmpty ||
-              globalProvider.updateFieldKey.currentState == null ||
-              !globalProvider.updateFieldKey.currentState!.validate()) {
-            return;
-          }
-        }
-        if (!fieldSelectionCompleted) {
-          globalProvider.clearMap();
-          globalProvider.clearScannedPages();
-          globalProvider.clearExceptions();
-          await registrationTaskProvider.changeUpdatableFieldGroups();
-          globalProvider.ageGroup = "";
-          await BiometricsApi().clearBiometricAndDocumentHashmap();
-          setState(() {
-            fieldSelectionCompleted = true;
-          });
-          return;
-        }
-        if (globalProvider.newProcessTabIndex < size) {
-          ageDateChangeValidation(globalProvider.newProcessTabIndex);
-          bool customValidator =
-          await customValidation(globalProvider.newProcessTabIndex);
-          if (customValidator) {
-            if (globalProvider.formKey.currentState!.validate()) {
-              if (globalProvider.newProcessTabIndex ==
-                  newProcess.screens!.length - 1) {
-                templateTitleMap = {
-                  'demographicInfo': appLocalizations.demographic_information,
-                  'documents': appLocalizations.documents,
-                  'bioMetrics': appLocalizations.biometrics,
-                };
-                registrationTaskProvider.setPreviewTemplate("");
-                registrationTaskProvider.setAcknowledgementTemplate("");
-                await registrationTaskProvider.getPreviewTemplate(
-                    true, templateTitleMap!);
-                await registrationTaskProvider.getAcknowledgementTemplate(
-                    false, templateTitleMap!);
-              }
-
-              globalProvider.newProcessTabIndex =
-                  globalProvider.newProcessTabIndex + 1;
-            }
-          }
-
-          _nextButtonClickedAudit();
-        } else {
-          if (globalProvider.newProcessTabIndex == size + 1) {
-            bool isPacketAuthenticated = await _authenticatePacket(context);
-            if (!isPacketAuthenticated) {
-              return;
-            }
-            RegistrationSubmitResponse registrationSubmitResponse =
-            await registrationTaskProvider.submitRegistrationDto(username);
-            if (registrationSubmitResponse.errorCode!.isNotEmpty) {
-              _showInSnackBar(registrationSubmitResponse.errorCode!);
-              return;
-            }
-            globalProvider.setRegId(registrationSubmitResponse.rId);
-
-            // Updating key to packetId after success creation of packet
-            registrationTaskProvider
-                .updateTemplateStorageKey(registrationSubmitResponse.rId);
-            registrationTaskProvider.deleteDefaultTemplateStored();
-
-            setState(() {
-              username = '';
-              password = '';
-            });
-          }
-          if (globalProvider.newProcessTabIndex == size + 2) {
-            _resetValuesOnRegistrationComplete();
-            return;
-          }
-          globalProvider.newProcessTabIndex =
-              globalProvider.newProcessTabIndex + 1;
-        }
-      } finally {
-        setState(() {
-          _isContinueProcessing = false;
-        });
-      }
-    }
-
-    customValidation(globalProvider.newProcessTabIndex).then((value) {
-      if (globalProvider.newProcessTabIndex == 0) {
-        if (!fieldSelectionCompleted) {
-          continueButton = value &&
-              globalProvider.updateFieldKey.currentState != null &&
-              globalProvider.updateFieldKey.currentState!.validate();
-        } else {
-          continueButton = true;
-        }
-      } else {
-        continueButton = value &&
-            globalProvider.formKey.currentState != null &&
-            globalProvider.formKey.currentState!.validate();
-      }
-
-      if (globalProvider.newProcessTabIndex >= size) {
-        continueButton = true;
-      }
-    });
-
-    return WillPopScope(
-      onWillPop: onWillPop,
-      child: SafeArea(
-        child: Scaffold(
-          backgroundColor: secondaryColors.elementAt(10),
-          bottomNavigationBar: Container(
-            decoration: BoxDecoration(
-              border: const Border(
-                top: BorderSide(
-                  color: dividerColor,
-                  width: 1,
-                ),
-              ),
-              color: pureWhite,
-            ),
-            padding: EdgeInsets.symmetric(
-              horizontal: isPortrait ? 20.w : 60.w,
-              vertical: 16.h,
-            ),
-            // height: isPortrait ? 94.h : 84.h,
-            child: context.watch().newProcessTabIndex == 0
-                ? Row(
-              children: [
-                Expanded(
-                  child: fieldSelectionCompleted
-                      ? OutlinedButton(
-                    child: SizedBox(
-                      height:
-                      isPortrait && !isMobileSize ? 68.h : 52.h,
-                      child: Center(
-                        child: Text(
-                          appLocalizations.go_back,
-                          style: TextStyle(
-                            fontSize: isPortrait && !isMobileSize
-                                ? 22
-                                : 14,
-                          ),
-                        ),
-                      ),
-                    ),
-                    onPressed: () {
-                      if (!fieldSelectionCompleted) {
-                        Navigator.of(context).pop();
-                      } else {
-                        setState(() {
-                          fieldSelectionCompleted = false;
-                        });
-                      }
-                    },
-                  )
-                      : const SizedBox(),
-                ),
-                SizedBox(
-                  width: 10.w,
-                ),
-                Expanded(
-                  child: ElevatedButton(
-                    style: ButtonStyle(
-                      maximumSize: MaterialStateProperty.all(
-                          const Size(209, 52)),
-                      minimumSize: MaterialStateProperty.all(
-                          const Size(209, 52)),
-                      backgroundColor: MaterialStateProperty.all(
-                          !fieldSelectionCompleted
-                              ? (context
-                              .watch()
-                              .selectedUpdateFields
-                              .isNotEmpty &&
-                              continueButton)
-                              ? solidPrimary
-                              : Colors.grey
-                              : solidPrimary),
-                    ),
-                    onPressed: _isContinueProcessing ? null : () async {
-                      if (fieldSelectionCompleted) {
-                        registrationTaskProvider.addConsentField("Y");
-                        await DemographicsApi().addDemographicField(
-                            "UIN", globalProvider.updateUINNumber);
-                        await DemographicsApi()
-                            .addDemographicField("consent", "true");
-                      }
-                      continueButtonTap(size, newProcess);
-                    },
-                    child: SizedBox(
-                      height: isPortrait && !isMobileSize ? 68.h : 52.h,
-                      child: Center(
-                        child: Text(
-                          fieldSelectionCompleted
-                              ? appLocalizations.informed
-                              : appLocalizations.continue_text,
-                          style: TextStyle(
-                            fontSize:
-                            isPortrait && !isMobileSize ? 22 : 14,
-                          ),
-                        ),
-                      ),
-                    ),
-                  ),
-                ),
-              ],
-            )
-                : Row(
-              mainAxisAlignment: MainAxisAlignment.start,
-              children: [
-                // globalProvider.newProcessTabIndex == size + 2
-                //     ? ElevatedButton(
-                //         onPressed: () async {
-                //           await connectivityProvider
-                //               .checkNetworkConnection();
-                //           bool isConnected =
-                //               connectivityProvider.isConnected;
-                //           if (!isConnected) {
-                //             _showInSnackBar(
-                //                 appLocalizations.network_error);
-                //             return;
-                //           }
-                //           globalProvider.syncPacket(globalProvider.regId);
-                //         },
-                //         child: Text(appLocalizations.sync_packet),
-                //       )
-                //     : const SizedBox.shrink(),
-                // SizedBox(
-                //   width: 10.w,
-                // ),
-                // globalProvider.newProcessTabIndex == size + 2
-                //     ? ElevatedButton(
-                //         onPressed: () async {
-                //           await connectivityProvider
-                //               .checkNetworkConnection();
-                //           bool isConnected =
-                //               connectivityProvider.isConnected;
-                //           if (!isConnected) {
-                //             _showInSnackBar(
-                //                 appLocalizations.network_error);
-                //             return;
-                //           }
-                //           globalProvider
-                //               .uploadPacket(globalProvider.regId);
-                //         },
-                //         child: Text(appLocalizations.upload_packet),
-                //       )
-                //     : const SizedBox.shrink(),
-                const Expanded(
-                  child: SizedBox(),
-                ),
-                ElevatedButton(
-                  style: ButtonStyle(
-                    maximumSize: MaterialStateProperty.all(
-                        const Size(209, 52)),
-                    minimumSize: MaterialStateProperty.all(
-                        const Size(209, 52)),
-                    backgroundColor: MaterialStateProperty.all(
-                        continueButton ? solidPrimary : Colors.grey),
-                  ),
-                  onPressed: _isContinueProcessing ? null : () async {
-                    await continueButtonTap(size, newProcess);
-                  },
-                  child: Text(
-                    context.read().newProcessTabIndex <=
-                        size
-                        ? appLocalizations.continue_text
-                        : globalProvider.newProcessTabIndex == size + 1
-                        ? appLocalizations.authenticate
-                        : appLocalizations.go_to_home,
-                    style: const TextStyle(color: appWhite),
-                  ),
-                ),
-              ],
-            ),
-          ),
-          body: SingleChildScrollView(
-            child: AnnotatedRegion(
-              value: const SystemUiOverlayStyle(
-                statusBarColor: Colors.transparent,
-              ),
-              child: Column(
-                children: [
-                  // isPortrait
-                  //     ? const SizedBox()
-                  //     : const Column(
-                  //         children: [
-                  //          // TabletHeader(),
-                  //           TabletNavbar(),
-                  //         ],
-                  //       ),
-                  Container(
-                    padding: isMobile && !isMobileSize
-                        ? const EdgeInsets.fromLTRB(0, 46, 0, 0)
-                        : const EdgeInsets.fromLTRB(0, 0, 0, 0),
-                    decoration: const BoxDecoration(
-                      gradient: LinearGradient(
-                        begin: Alignment.topCenter,
-                        end: Alignment.bottomCenter,
-                        colors: [Color(0xff214FBF), Color(0xff1C43A1)],
-                      ),
-                    ),
-                    child: Column(
-                      crossAxisAlignment: CrossAxisAlignment.start,
-                      children: [
-                        SizedBox(
-                          width: w,
-                          height: isPortrait ? 21.w : 30.w,
-                        ),
-                        Padding(
-                          padding: isPortrait
-                              ? EdgeInsets.fromLTRB(20.w, 0, 0, 0)
-                              : EdgeInsets.fromLTRB(60.w, 0, 60.w, 0),
-                          child: Text(
-                            newProcess.label![globalProvider.selectedLanguage]!,
-                            style: Theme.of(context)
-                                .textTheme
-                                .titleMedium
-                                ?.copyWith(
-                                    color: pureWhite,
-                                    fontWeight: semiBold,
-                                    fontSize: isPortrait ? 24 : 21),
-                          ),
-                        ),
-                        SizedBox(
-                          height: 30.h,
-                        ),
-                        fieldSelectionCompleted
-                            ? Divider(
-                                height: 12.h,
-                                thickness: 1,
-                                color: secondaryColors.elementAt(2),
-                              )
-                            : const SizedBox(),
-                        fieldSelectionCompleted
-                            ? Padding(
-                                padding: isPortrait
-                                    ? const EdgeInsets.all(0)
-                                    : EdgeInsets.fromLTRB(60.w, 0, 60.w, 0),
-                                child: Stack(
-                                  alignment: FractionalOffset.centerRight,
-                                  children: [
-                                    Padding(
-                                      padding: isPortrait
-                                          ? EdgeInsets.fromLTRB(
-                                              20.w, 10.h, 0, 0)
-                                          : EdgeInsets.fromLTRB(0, 10.h, 0, 0),
-                                      child: SizedBox(
-                                        height: 36.h,
-                                        child: ListView.builder(
-                                            padding: const EdgeInsets.all(0),
-                                            scrollDirection: Axis.horizontal,
-                                            itemCount:
-                                                newProcess.screens!.length + 3,
-                                            itemBuilder: (BuildContext context,
-                                                int index) {
-                                              return GestureDetector(
-                                                onTap: () {
-                                                  if (globalProvider
-                                                          .newProcessTabIndex ==
-                                                      size + 2) {
-                                                    return;
-                                                  }
-
-                                                  if (index <
-                                                      globalProvider
-                                                          .newProcessTabIndex) {
-                                                    globalProvider
-                                                            .newProcessTabIndex =
-                                                        index;
-                                                  }
-                                                },
-                                                child: Row(
-                                                  children: [
-                                                    Container(
-                                                      padding:
-                                                          EdgeInsets.fromLTRB(
-                                                              0, 0, 0, 8.h),
-                                                      decoration: BoxDecoration(
-                                                        border: Border(
-                                                          bottom: BorderSide(
-                                                              color: (context
-                                                                          .watch<
-                                                                              GlobalProvider>()
-                                                                          .newProcessTabIndex ==
-                                                                      index)
-                                                                  ? pureWhite
-                                                                  : Colors
-                                                                      .transparent,
-                                                              width: 3),
-                                                        ),
-                                                      ),
-                                                      child: Row(
-                                                        children: [
-                                                          (index <
-                                                                  context
-                                                                      .watch<
-                                                                          GlobalProvider>()
-                                                                      .newProcessTabIndex)
-                                                              ? Icon(
-                                                                  Icons
-                                                                      .check_circle,
-                                                                  size: 17,
-                                                                  color: secondaryColors
-                                                                      .elementAt(
-                                                                          11),
-                                                                )
-                                                              : (context
-                                                                          .watch<
-                                                                              GlobalProvider>()
-                                                                          .newProcessTabIndex ==
-                                                                      index)
-                                                                  ? Icon(
-                                                                      Icons
-                                                                          .circle,
-                                                                      color:
-                                                                          pureWhite,
-                                                                      size: 17,
-                                                                    )
-                                                                  : Icon(
-                                                                      Icons
-                                                                          .circle_outlined,
-                                                                      size: 17,
-                                                                      color: secondaryColors
-                                                                          .elementAt(
-                                                                              9),
-                                                                    ),
-                                                          SizedBox(
-                                                            width: 6.w,
-                                                          ),
-                                                          Text(
-                                                            index < size
-                                                                ? newProcess
-                                                                        .screens![
-                                                                            index]!
-                                                                        .label![
-                                                                    context
-                                                                        .read<
-                                                                            GlobalProvider>()
-                                                                        .selectedLanguage]!
-                                                                : postRegistrationTabs[
-                                                                    index -
-                                                                        size],
-                                                            style: Theme.of(
-                                                                    context)
-                                                                .textTheme
-                                                                .titleSmall
-                                                                ?.copyWith(
-                                                                    color: (context.watch().newProcessTabIndex ==
-                                                                            index)
-                                                                        ? pureWhite
-                                                                        : secondaryColors
-                                                                            .elementAt(
-                                                                                9),
-                                                                    fontWeight:
-                                                                        semiBold,
-                                                                    fontSize:
-                                                                        14),
-                                                          ),
-                                                        ],
-                                                      ),
-                                                    ),
-                                                    SizedBox(
-                                                      width: 35.w,
-                                                    ),
-                                                  ],
-                                                ),
-                                              );
-                                            }),
-                                      ),
-                                    ),
-                                    if (context.watch().newProcessTabIndex < size + 2)
-                                    Container(
-                                      height: 36.h,
-                                      width: 25.w,
-                                      padding:
-                                          const EdgeInsets.fromLTRB(0, 0, 0, 0),
-                                      color: solidPrimary,
-                                      child: Icon(
-                                        Icons.arrow_forward_ios_outlined,
-                                        color: pureWhite,
-                                        size: 17,
-                                      ),
-                                    ),
-                                  ],
-                                ),
-                              )
-                            : const SizedBox.shrink(),
-                        const SizedBox(
-                          height: 5,
-                        ),
-                      ],
-                    ),
-                  ),
-                  Padding(
-                    padding: isPortrait
-                        ? const EdgeInsets.all(0)
-                        : EdgeInsets.fromLTRB(60.w, 0, 60.w, 0),
-                    child: !fieldSelectionCompleted
-                        ? UpdateFieldSelector(process: newProcess)
-                        : context.watch().newProcessTabIndex <
-                                size
-                            ? UpdateProcessScreenContent(
-                                context: context,
-                                process: newProcess,
-                                screen: newProcess.screens!.elementAt(context
-                                    .watch()
-                                    .newProcessTabIndex)!)
-                            : context
-                                        .watch()
-                                        .newProcessTabIndex ==
-                                    size
-                                ? const PreviewPage()
-                                : context
-                                            .watch()
-                                            .newProcessTabIndex ==
-                                        size + 1
-                                    ? _getPacketAuthComponent()
-                                    : const AcknowledgementPage(),
-                  ),
-                  SizedBox(
-                    height: 20.h,
-                  ),
-                ],
-              ),
-            ),
-          ),
-        ),
-      ),
-    );
-  }
-
-  Widget _getPacketAuthComponent() {
-    return Column(
-      children: [
-        SizedBox(
-          height: 30.h,
-        ),
-        Container(
-          width: isPortrait && !isMobileSize ? 566.w : 376.w,
-          padding: EdgeInsets.only(
-            top: 24.h,
-            bottom: 28.h,
-            left: 20.w,
-            right: 20.w,
-          ),
-          decoration: BoxDecoration(
-            borderRadius: const BorderRadius.all(
-              Radius.circular(6),
-            ),
-            color: pureWhite,
-          ),
-          child: Column(
-            children: [
-              _getAuthIcon(),
-              SizedBox(
-                height: 26.h,
-              ),
-              Text(
-                appLocalizations.authenticate_using_password,
-                style: TextStyle(
-                    fontSize: isPortrait && !isMobileSize ? 24 : 18,
-                    fontWeight: semiBold,
-                    color: appBlack),
-              ),
-              SizedBox(
-                height: 35.h,
-              ),
-              Row(
-                children: [
-                  Text(
-                    appLocalizations.username,
-                    style: isPortrait
-                        ? AppTextStyle.tabletPortraitTextfieldHeader
-                        : AppTextStyle.mobileTextfieldHeader,
-                  ),
-                  const Text(
-                    ' *',
-                    style: TextStyle(
-                      color: mandatoryField,
-                    ),
-                  ),
-                ],
-              ),
-              SizedBox(
-                height: 11.h,
-              ),
-              _getUsernameTextField(),
-              SizedBox(
-                height: 35.h,
-              ),
-              Row(
-                children: [
-                  Text(
-                    appLocalizations.password,
-                    style: isPortrait
-                        ? AppTextStyle.tabletPortraitTextfieldHeader
-                        : AppTextStyle.mobileTextfieldHeader,
-                  ),
-                  const Text(
-                    ' *',
-                    style: TextStyle(color: mandatoryField),
-                  ),
-                ],
-              ),
-              SizedBox(
-                height: 11.h,
-              ),
-              _getPasswordTextField(),
-            ],
-          ),
-        ),
-      ],
-    );
-  }
-
-  _getAuthIcon() {
-    return Container(
-      height: 80.w,
-      width: 80.w,
-      decoration: BoxDecoration(
-        shape: BoxShape.circle,
-        border: Border.all(
-          color: authIconBorder,
-          width: 2,
-        ),
-        color: authIconBackground,
-      ),
-      child: Center(
-        child: Image.asset('assets/images/Registering an Individual@2x.png'),
-      ),
-    );
-  }
-
-  _getUsernameTextField() {
-    return Container(
-      height: isPortrait && !isMobileSize ? 82.h : 52.h,
-      alignment: Alignment.centerLeft,
-      padding: EdgeInsets.symmetric(
-        horizontal: 12.w,
-      ),
-      decoration: BoxDecoration(
-        border: Border.all(
-          width: 1.h,
-          color: appGreyShade,
-        ),
-        borderRadius: const BorderRadius.all(
-          Radius.circular(6),
-        ),
-      ),
-      child: TextField(
-        decoration: InputDecoration(
-          hintText: appLocalizations.enter_username,
-          hintStyle: isPortrait && !isMobileSize
-              ? AppTextStyle.tabletPortraitTextfieldHintText
-              : AppTextStyle.mobileTextfieldHintText,
-          border: InputBorder.none,
-        ),
-        style: TextStyle(
-          fontSize: isPortrait && !isMobileSize ? 22 : 14,
-          color: appBlack,
-        ),
-        onChanged: (v) {
-          setState(() {
-            username = v;
-          });
-        },
-      ),
-    );
-  }
-
-  _getPasswordTextField() {
-    return Container(
-      height: isPortrait && !isMobileSize ? 82.h : 52.h,
-      alignment: Alignment.centerLeft,
-      padding: EdgeInsets.symmetric(
-        horizontal: 12.w,
-      ),
-      decoration: BoxDecoration(
-        border: Border.all(
-          width: 1.h,
-          color: appGreyShade,
-        ),
-        borderRadius: const BorderRadius.all(
-          Radius.circular(6),
-        ),
-      ),
-      child: TextField(
-        obscureText: true,
-        decoration: InputDecoration(
-          hintText: appLocalizations.enter_password,
-          hintStyle: isPortrait && !isMobileSize
-              ? AppTextStyle.tabletPortraitTextfieldHintText
-              : AppTextStyle.mobileTextfieldHintText,
-          border: InputBorder.none,
-        ),
-        style: TextStyle(
-          fontSize: isPortrait && !isMobileSize ? 22 : 14,
-          color: appBlack,
-        ),
-        onChanged: (v) {
-          setState(() {
-            password = v;
-          });
-        },
-      ),
-    );
-  }
-}
diff --git a/lib/ui/process_ui/widgets/new_process_screen_content.dart b/lib/ui/process_ui/widgets/generic_process_screen_content.dart
similarity index 76%
rename from lib/ui/process_ui/widgets/new_process_screen_content.dart
rename to lib/ui/process_ui/widgets/generic_process_screen_content.dart
index b896b322c..4c9bdea5d 100644
--- a/lib/ui/process_ui/widgets/new_process_screen_content.dart
+++ b/lib/ui/process_ui/widgets/generic_process_screen_content.dart
@@ -11,9 +11,11 @@ import 'package:flutter/material.dart';
 
 import 'package:provider/provider.dart';
 import 'package:registration_client/model/field.dart';
+import 'package:registration_client/model/process.dart';
 import 'package:registration_client/model/screen.dart';
 import 'package:registration_client/provider/global_provider.dart';
 import 'package:registration_client/provider/registration_task_provider.dart';
+import 'package:registration_client/ui/process_ui/process_type.dart';
 import 'package:registration_client/ui/process_ui/widgets/age_date_control.dart';
 import 'package:registration_client/ui/process_ui/widgets/biometric_capture_control.dart';
 
@@ -33,18 +35,26 @@ import 'package:registration_client/ui/process_ui/widgets/textbox_control.dart';
 
 import 'radio_button_control.dart';
 
-class NewProcessScreenContent extends StatefulWidget {
-  const NewProcessScreenContent(
-      {super.key, required this.context, required this.screen});
+class GenericProcessScreenContent extends StatefulWidget {
+  const GenericProcessScreenContent({
+    super.key,
+    required this.context,
+    required this.screen,
+    required this.processType,
+    required this.process,
+  });
+  
   final BuildContext context;
   final Screen screen;
+  final ProcessType processType;
+  final Process process;
 
   @override
-  State createState() =>
-      _NewProcessScreenContentState();
+  State createState() =>
+      _GenericProcessScreenContentState();
 }
 
-class _NewProcessScreenContentState extends State {
+class _GenericProcessScreenContentState extends State {
   late GlobalProvider globalProvider;
   late RegistrationTaskProvider registrationTaskProvider;
   int refreshValue = 0;
@@ -70,8 +80,9 @@ class _NewProcessScreenContentState extends State {
     if (e.id == "preferredLang") {
       return const SizedBox.shrink();
     }
-
-    if (e.inputRequired == false) {
+    if ((widget.processType == ProcessType.newProcess ||
+            widget.processType == ProcessType.correctionProcess) &&
+        e.inputRequired == false) {
       return const SizedBox.shrink();
     }
 
@@ -87,7 +98,7 @@ class _NewProcessScreenContentState extends State {
       case "html":
         return HtmlBoxControl(field: e);
       case "biometrics":
-        if (context.watch().mvelRequiredFields[e.id] ?? true) {
+        if (context.watch().mvelRequiredFields[e.id] ?? _getDefaultBiometricVisibility()) {
           return BiometricCaptureControl(e: e);
         }
         return Container();
@@ -133,8 +144,15 @@ class _NewProcessScreenContentState extends State {
           validation: regexPattern,
         );
       default:
-        return (e.controlType!=null)? Text("${e.controlType}"): const SizedBox.shrink();
+        return (e.controlType != null) ? Text("${e.controlType}") : const SizedBox.shrink();
+    }
+  }
+
+  bool _getDefaultBiometricVisibility() {
+    if (widget.processType == ProcessType.updateProcess) {
+      return false;
     }
+    return true;
   }
 
   evaluateMVELVisible(String fieldData, Field e) async {
@@ -155,14 +173,39 @@ class _NewProcessScreenContentState extends State {
   }
 
   _checkMvelVisible(Field e) async {
-    if (e.required == false) {
+    if (widget.processType == ProcessType.updateProcess) {
       if (e.requiredOn != null && e.requiredOn!.isNotEmpty) {
         await evaluateMVELVisible(jsonEncode(e.toJson()), e);
         await evaluateMVELRequired(jsonEncode(e.toJson()), e);
       }
+    } else {
+      if (e.required == false) {
+        if (e.requiredOn != null && e.requiredOn!.isNotEmpty) {
+          await evaluateMVELVisible(jsonEncode(e.toJson()), e);
+          await evaluateMVELRequired(jsonEncode(e.toJson()), e);
+        }
+      }
     }
   }
 
+  bool _shouldShowField(Field e) {
+
+    if (widget.processType == ProcessType.updateProcess) {
+      if (widget.process.autoSelectedGroups!.contains(e.group)) {
+        return true;
+      } else if (globalProvider.selectedUpdateFields[e.group] != null) {
+        return true;
+      }
+      return false;
+    }
+
+    if (context.watch().mvelVisibleFields[e.id] ?? true) {
+      return true;
+    }
+
+    return false;
+  }
+
   @override
   Widget build(BuildContext context) {
     return Column(
@@ -176,9 +219,11 @@ class _NewProcessScreenContentState extends State {
                 });
               }),
         ],
+
         if (widget.screen.additionalInfoRequestIdRequired == true) ...[
-           const AdditionalInfoReqIdControl(),
+          const AdditionalInfoReqIdControl(),
         ],
+        
         (context.watch().preRegControllerRefresh)
             ? const CircularProgressIndicator()
             : Form(
@@ -187,10 +232,7 @@ class _NewProcessScreenContentState extends State {
                   children: [
                     ...widget.screen.fields!.map((e) {
                       _checkMvelVisible(e!);
-                      if (context
-                              .watch()
-                              .mvelVisibleFields[e.id] ??
-                          true) {
+                      if (_shouldShowField(e)) {
                         return widgetType(e);
                       }
                       return Container();
diff --git a/lib/ui/process_ui/widgets/language_selector.dart b/lib/ui/process_ui/widgets/language_selector.dart
index 0be61e049..ba8222693 100644
--- a/lib/ui/process_ui/widgets/language_selector.dart
+++ b/lib/ui/process_ui/widgets/language_selector.dart
@@ -13,11 +13,8 @@ import 'package:registration_client/model/process.dart';
 
 import 'package:registration_client/provider/global_provider.dart';
 import 'package:registration_client/provider/registration_task_provider.dart';
-import 'package:registration_client/ui/process_ui/lost_process.dart';
-import 'package:registration_client/ui/process_ui/correction_process.dart';
+import 'package:registration_client/ui/process_ui/process_type.dart';
 
-import 'package:registration_client/ui/process_ui/new_process.dart';
-import 'package:registration_client/ui/process_ui/update_process.dart';
 import 'package:registration_client/ui/widgets/language_component.dart';
 import 'package:registration_client/utils/app_config.dart';
 import 'package:flutter_gen/gen_l10n/app_localizations.dart';
@@ -40,22 +37,22 @@ class _LanguageSelectorState extends State {
 
   _triggerNavigation() {
     if (widget.newProcess.flow == "NEW") {
-      Navigator.pushNamed(context, NewProcess.routeName,
+      Navigator.pushNamed(context, ProcessType.newProcess.routeName,
           arguments: {"process": widget.newProcess});
     }
 
     if (widget.newProcess.flow == "UPDATE") {
-      Navigator.pushNamed(context, UpdateProcess.routeName,
+      Navigator.pushNamed(context, ProcessType.updateProcess.routeName,
           arguments: {"process": widget.newProcess});
     }
 
     if (widget.newProcess.flow == "LOST") {
-      Navigator.pushNamed(context, LostProcess.routeName,
-      arguments: {"process": widget.newProcess});
+      Navigator.pushNamed(context, ProcessType.lostProcess.routeName,
+          arguments: {"process": widget.newProcess});
     }
 
     if (widget.newProcess.flow == "CORRECTION") {
-      Navigator.pushNamed(context, CorrectionProcess.routeName,
+      Navigator.pushNamed(context, ProcessType.correctionProcess.routeName,
           arguments: {"process": widget.newProcess});
     }
   }
diff --git a/lib/ui/process_ui/widgets/lost_process_screen_content.dart b/lib/ui/process_ui/widgets/lost_process_screen_content.dart
deleted file mode 100644
index ec86e5872..000000000
--- a/lib/ui/process_ui/widgets/lost_process_screen_content.dart
+++ /dev/null
@@ -1,196 +0,0 @@
-/*
- * Copyright (c) Modular Open Source Identity Platform
- * This source code is licensed under the MIT license found in the
- * LICENSE file in the root directory of this source tree.
- *
-*/
-
-import 'dart:convert';
-
-import 'package:flutter/material.dart';
-
-import 'package:provider/provider.dart';
-import 'package:registration_client/model/field.dart';
-import 'package:registration_client/model/screen.dart';
-import 'package:registration_client/provider/global_provider.dart';
-import 'package:registration_client/provider/registration_task_provider.dart';
-import 'package:registration_client/ui/process_ui/widgets/age_date_control.dart';
-import 'package:registration_client/ui/process_ui/widgets/biometric_capture_control.dart';
-
-import 'package:registration_client/ui/process_ui/widgets/checkbox_control.dart';
-import 'package:registration_client/ui/process_ui/widgets/date_control.dart';
-import 'package:registration_client/ui/process_ui/widgets/document_upload_control.dart';
-import 'package:registration_client/ui/process_ui/widgets/dropdown_control.dart';
-import 'package:registration_client/ui/process_ui/widgets/dynamic_dropdown_control.dart';
-import 'package:registration_client/ui/process_ui/widgets/gender_control.dart';
-import 'package:registration_client/ui/process_ui/widgets/html_box_control.dart';
-
-import 'package:registration_client/ui/process_ui/widgets/button_control.dart';
-import 'package:registration_client/ui/process_ui/widgets/terms_and_conditions.dart';
-import 'package:registration_client/ui/process_ui/widgets/pre_reg_data_control.dart';
-import 'package:registration_client/ui/process_ui/widgets/textbox_control.dart';
-
-import 'radio_button_control.dart';
-
-class LostProcessScreenContent extends StatefulWidget {
-  const LostProcessScreenContent(
-      {super.key, required this.context, required this.screen});
-  final BuildContext context;
-  final Screen screen;
-
-  @override
-  State createState() =>
-      _LostProcessScreenContentState();
-}
-
-class _LostProcessScreenContentState extends State {
-  late GlobalProvider globalProvider;
-  late RegistrationTaskProvider registrationTaskProvider;
-  int refreshValue = 0;
-
-  @override
-  void initState() {
-    globalProvider = Provider.of(context, listen: false);
-    registrationTaskProvider =
-        Provider.of(context, listen: false);
-    super.initState();
-  }
-
-  Widget widgetType(Field e) {
-    RegExp regexPattern = RegExp(r'^.*$');
-
-    if (e.validators != null && e.validators!.isNotEmpty) {
-      final validation = e.validators?.first?.validator;
-      if (validation != null) {
-        regexPattern = RegExp(validation);
-      }
-    }
-
-    if (e.id == "preferredLang") {
-      return const SizedBox.shrink();
-    }
-
-    switch (e.controlType) {
-      case "checkbox":
-        if (e.subType == "gender") {
-          return RadioButtonControl(field: e);
-        }
-        if (e.group!.toLowerCase() == "consent") {
-          return TermsAndConditions(field: e);
-        }
-        return CheckboxControl(field: e);
-      case "html":
-        return HtmlBoxControl(field: e);
-      case "biometrics":
-        if (context.watch().mvelRequiredFields[e.id] ?? true) {
-          return BiometricCaptureControl(e: e);
-        }
-        return Container();
-      case "button":
-        if (e.subType == "preferredLang") {
-          return ButtonControl(field: e);
-        }
-        if (e.subType == "gender" || e.subType == "residenceStatus") {
-          return RadioButtonControl(field: e);
-        }
-        //feature will implement
-        if (e.subType == "selectedHandles") {
-          return const SizedBox.shrink();
-        }
-        return Text("${e.controlType}");
-      case "textbox":
-        return TextBoxControl(e: e, validation: regexPattern);
-      case "dropdown":
-        if (e.id == "gender") {
-          return GenderControl(field: e, validation: regexPattern);
-        }
-        if (e.fieldType == "dynamic") {
-          return DynamicDropDownControl(field: e, validation: regexPattern);
-        }
-        return DropDownControl(
-          validation: regexPattern,
-          field: e,
-        );
-
-      case "ageDate":
-        return AgeDateControl(
-          field: e,
-          validation: regexPattern,
-        );
-      case "date":
-        return DateControl(
-          validation: regexPattern,
-          field: e,
-        );
-      case "fileupload":
-        return DocumentUploadControl(
-          field: e,
-          validation: regexPattern,
-        );
-      default:
-        return (e.controlType!=null)? Text("${e.controlType}"): const SizedBox.shrink();
-    }
-  }
-
-  evaluateMVELVisible(String fieldData, Field e) async {
-    registrationTaskProvider.evaluateMVELVisible(fieldData).then((value) {
-      if (!value) {
-        globalProvider.removeFieldFromMap(
-            e.id!, globalProvider.fieldInputValue);
-        registrationTaskProvider.removeDemographicField(e.id!);
-      }
-      globalProvider.setMvelVisibleFields(e.id!, value);
-    });
-  }
-
-  evaluateMVELRequired(String fieldData, Field e) async {
-    registrationTaskProvider.evaluateMVELRequired(fieldData).then((value) {
-      globalProvider.setMvelRequiredFields(e.id!, value);
-    });
-  }
-
-  _checkMvelVisible(Field e) async {
-    if (e.required == false) {
-      if (e.requiredOn != null && e.requiredOn!.isNotEmpty) {
-        await evaluateMVELVisible(jsonEncode(e.toJson()), e);
-        await evaluateMVELRequired(jsonEncode(e.toJson()), e);
-      }
-    }
-  }
-
-  @override
-  Widget build(BuildContext context) {
-    return Column(
-      children: [
-        if (widget.screen.preRegFetchRequired == true) ...[
-          PreRegDataControl(
-              screen: widget.screen,
-              onFetched: () {
-                setState(() {
-                  refreshValue = 1;
-                });
-              }),
-        ],
-        (context.watch().preRegControllerRefresh)
-            ? const CircularProgressIndicator()
-            : Form(
-          key: context.watch().formKey,
-          child: Column(
-            children: [
-              ...widget.screen.fields!.map((e) {
-                _checkMvelVisible(e!);
-                if (context
-                    .watch()
-                    .mvelVisibleFields[e.id] ??
-                    true) {
-                  return widgetType(e);
-                }
-                return Container();
-              }).toList(),
-            ],
-          ),
-        ),
-      ],
-    );
-  }
-}
diff --git a/lib/ui/process_ui/widgets/update_process_screen_content.dart b/lib/ui/process_ui/widgets/update_process_screen_content.dart
deleted file mode 100644
index 9ea1d7a73..000000000
--- a/lib/ui/process_ui/widgets/update_process_screen_content.dart
+++ /dev/null
@@ -1,191 +0,0 @@
-/*
- * Copyright (c) Modular Open Source Identity Platform
- * This source code is licensed under the MIT license found in the
- * LICENSE file in the root directory of this source tree.
- *
-*/
-
-import 'dart:convert';
-
-import 'package:flutter/material.dart';
-
-import 'package:provider/provider.dart';
-import 'package:registration_client/model/field.dart';
-import 'package:registration_client/model/process.dart';
-import 'package:registration_client/model/screen.dart';
-import 'package:registration_client/provider/global_provider.dart';
-import 'package:registration_client/provider/registration_task_provider.dart';
-import 'package:registration_client/ui/process_ui/widgets/age_date_control.dart';
-import 'package:registration_client/ui/process_ui/widgets/biometric_capture_control.dart';
-
-import 'package:registration_client/ui/process_ui/widgets/checkbox_control.dart';
-import 'package:registration_client/ui/process_ui/widgets/date_control.dart';
-import 'package:registration_client/ui/process_ui/widgets/document_upload_control.dart';
-import 'package:registration_client/ui/process_ui/widgets/dropdown_control.dart';
-import 'package:registration_client/ui/process_ui/widgets/dynamic_dropdown_control.dart';
-import 'package:registration_client/ui/process_ui/widgets/gender_control.dart';
-import 'package:registration_client/ui/process_ui/widgets/html_box_control.dart';
-
-import 'package:registration_client/ui/process_ui/widgets/button_control.dart';
-import 'package:registration_client/ui/process_ui/widgets/terms_and_conditions.dart';
-import 'package:registration_client/ui/process_ui/widgets/textbox_control.dart';
-
-import 'radio_button_control.dart';
-
-class UpdateProcessScreenContent extends StatefulWidget {
-  const UpdateProcessScreenContent({
-    super.key,
-    required this.context,
-    required this.screen,
-    required this.process,
-  });
-  final BuildContext context;
-  final Screen screen;
-  final Process process;
-
-  @override
-  State createState() =>
-      _UpdateProcessScreenContentState();
-}
-
-class _UpdateProcessScreenContentState
-    extends State {
-  late GlobalProvider globalProvider;
-  late RegistrationTaskProvider registrationTaskProvider;
-
-  @override
-  void initState() {
-    globalProvider = Provider.of(context, listen: false);
-    registrationTaskProvider =
-        Provider.of(context, listen: false);
-
-    super.initState();
-  }
-
-  Widget widgetType(Field e) {
-    RegExp regexPattern = RegExp(r'^.*$');
-
-    if (e.validators != null && e.validators!.isNotEmpty) {
-      final validation = e.validators?.first?.validator;
-      if (validation != null) {
-        regexPattern = RegExp(validation);
-      }
-    }
-
-    if (e.id == "preferredLang") {
-      return const SizedBox.shrink();
-    }
-
-    switch (e.controlType) {
-      case "checkbox":
-        if (e.subType == "gender") {
-          return RadioButtonControl(field: e);
-        }
-        if (e.group!.toLowerCase() == "consent") {
-          return TermsAndConditions(field: e);
-        }
-        return CheckboxControl(field: e);
-      case "html":
-        return HtmlBoxControl(field: e);
-      case "biometrics":
-        if (globalProvider.mvelRequiredFields[e.id] ?? false) {
-          return BiometricCaptureControl(e: e);
-        }
-        return Container();
-      case "button":
-        if (e.subType == "preferredLang") {
-          return ButtonControl(field: e);
-        }
-        if (e.subType == "gender" || e.subType == "residenceStatus") {
-          return RadioButtonControl(field: e);
-        }
-        return Text("${e.controlType}");
-      case "textbox":
-        return TextBoxControl(e: e, validation: regexPattern);
-      case "dropdown":
-        if (e.id == "gender") {
-          return GenderControl(field: e, validation: regexPattern);
-        }
-        if (e.fieldType == "dynamic") {
-          return DynamicDropDownControl(field: e, validation: regexPattern);
-        }
-        return DropDownControl(
-          validation: regexPattern,
-          field: e,
-        );
-
-      case "ageDate":
-        return AgeDateControl(
-          field: e,
-          validation: regexPattern,
-        );
-      case "date":
-        return DateControl(
-          validation: regexPattern,
-          field: e,
-        );
-      case "fileupload":
-        return DocumentUploadControl(
-          field: e,
-          validation: regexPattern,
-        );
-      default:
-        return Text("${e.controlType}");
-    }
-  }
-
-  evaluateMVELVisible(String fieldData, Field e) async {
-    registrationTaskProvider.evaluateMVELVisible(fieldData).then((value) {
-      if (!value) {
-        globalProvider.removeFieldFromMap(
-            e.id!, globalProvider.fieldInputValue);
-        registrationTaskProvider.removeDemographicField(e.id!);
-      }
-      globalProvider.setMvelVisibleFields(e.id!, value);
-    });
-  }
-
-  evaluateMVELRequired(String fieldData, Field e) async {
-    registrationTaskProvider.evaluateMVELRequired(fieldData).then((value) {
-      // if (!value && globalProvider.selectedUpdateFields[e.group] == null) {
-      //   globalProvider.removeFieldFromMap(
-      //       e.id!, globalProvider.fieldInputValue);
-      //   registrationTaskProvider.removeDemographicField(e.id!);
-      // }
-      globalProvider.setMvelRequiredFields(e.id!, value);
-    });
-  }
-
-  checkMvelVisible(Field e) async {
-    if (e.requiredOn != null && e.requiredOn!.isNotEmpty) {
-      await evaluateMVELVisible(jsonEncode(e.toJson()), e);
-      await evaluateMVELRequired(jsonEncode(e.toJson()), e);
-    }
-  }
-
-  @override
-  Widget build(BuildContext context) {
-    return Form(
-      key: context.watch().formKey,
-      child: Column(
-        children: [
-          ...widget.screen.fields!.map((e) {
-            checkMvelVisible(e!);
-            if (widget.process.autoSelectedGroups!.contains(e.group)) {
-              return widgetType(e);
-            } else if (globalProvider.selectedUpdateFields[e.group] != null) {
-              return widgetType(e);
-            }
-            // else if (context
-            //         .watch()
-            //         .mvelRequiredFields[e.id] ??
-            //     false) {
-            //   return widgetType(e);
-            // }
-            return Container();
-          }).toList(),
-        ],
-      ),
-    );
-  }
-}
diff --git a/lib/ui/profile/profile.dart b/lib/ui/profile/profile.dart
index 79e8e5ce0..f18ef8b34 100644
--- a/lib/ui/profile/profile.dart
+++ b/lib/ui/profile/profile.dart
@@ -30,6 +30,10 @@ class _ProfilePageState extends State {
     syncProvider = Provider.of(context, listen: false);
     connectivityProvider =  Provider.of(context, listen: false);
     super.initState();
+    // Check GPS status when profile page loads
+    WidgetsBinding.instance.addPostFrameCallback((_) {
+      connectivityProvider.checkGPSStatus();
+    });
   }
 
   goToUrl(String url) async {
@@ -153,6 +157,50 @@ class _ProfilePageState extends State {
               ],
             ),
           ),
+          const Divider(color: Color(0xFFF5F8FF), height: 4),
+          const SizedBox(height: 15),
+          Padding(
+            padding: const EdgeInsets.only(left: 16, right: 16),
+            child: Row(
+              mainAxisAlignment: MainAxisAlignment.spaceBetween,
+              children: [
+                Row(
+                  children: [
+                    Icon(
+                      Icons.location_on_outlined,
+                      color: solidPrimary,
+                      size: 16,
+                    ),
+                    const SizedBox(width: 10),
+                    Text(
+                      "GPS",
+                      style: Theme.of(context).textTheme.titleSmall?.copyWith(
+                          color: const Color(0xff333333), fontWeight: semiBold),
+                    ),
+                  ],
+                ),
+                Row(
+                  children: [
+                    Icon(
+                      Icons.circle,
+                      color: context.watch().isGPSEnabled
+                          ? const Color(0xff1A9B42)
+                          : Colors.red,
+                      size: 12,
+                    ),
+                    const SizedBox(width: 10),
+                    Text(
+                      context.watch().isGPSEnabled
+                          ? appLocalizations.enabled
+                          : appLocalizations.disabled,
+                      style: Theme.of(context).textTheme.titleSmall?.copyWith(
+                          color: const Color(0xff333333), fontWeight: semiBold),
+                    ),
+                  ],
+                ),
+              ],
+            ),
+          ),
           const SizedBox(height: 15),
           const Divider(color: Color(0xFFF5F8FF), height: 4),
           const SizedBox(height: 15),
diff --git a/pigeon.sh b/pigeon.sh
index 3d9033560..167072bdc 100644
--- a/pigeon.sh
+++ b/pigeon.sh
@@ -59,4 +59,7 @@ dart run pigeon --input pigeon/document_category.dart --dart_out lib/pigeon/docu
 dart run pigeon --input pigeon/dash_board.dart --dart_out lib/pigeon/dash_board_pigeon.dart --objc_header_out ios/Runner/pigeon.h --objc_source_out ios/Runner/pigeon.m --java_out ./android/app/src/main/java/io/mosip/registration_client/model/DashBoardPigeon.java --java_package "io.mosip.registration_client.model"
 
 # Generate global config settings files
-dart run pigeon --input pigeon/global_config_settings.dart --dart_out lib/pigeon/global_config_settings_pigeon.dart --objc_header_out ios/Runner/pigeon.h --objc_source_out ios/Runner/pigeon.m --java_out ./android/app/src/main/java/io/mosip/registration_client/model/GlobalConfigSettingsPigeon.java --java_package "io.mosip.registration_client.model"
\ No newline at end of file
+dart run pigeon --input pigeon/global_config_settings.dart --dart_out lib/pigeon/global_config_settings_pigeon.dart --objc_header_out ios/Runner/pigeon.h --objc_source_out ios/Runner/pigeon.m --java_out ./android/app/src/main/java/io/mosip/registration_client/model/GlobalConfigSettingsPigeon.java --java_package "io.mosip.registration_client.model"
+
+# Generate location pigeon files
+dart run pigeon --input pigeon/location.dart --dart_out lib/pigeon/location_pigeon.dart --objc_header_out ios/Runner/pigeon.h --objc_source_out ios/Runner/pigeon.m --java_out ./android/app/src/main/java/io/mosip/registration_client/model/LocationPigeon.java --java_package "io.mosip.registration_client.model"
\ No newline at end of file
diff --git a/pigeon/global_config_settings.dart b/pigeon/global_config_settings.dart
index b0386176a..0c2e8f379 100644
--- a/pigeon/global_config_settings.dart
+++ b/pigeon/global_config_settings.dart
@@ -10,4 +10,6 @@ abstract class GlobalConfigSettingsApi {
   List getPermittedConfigurationNames();
   @async
   void modifyConfigurations(Map localPreferences);
+  @async
+  String getGpsEnableFlag();
 }
\ No newline at end of file
diff --git a/pigeon/registration_data.dart b/pigeon/registration_data.dart
index 49f391bc5..0632b3379 100644
--- a/pigeon/registration_data.dart
+++ b/pigeon/registration_data.dart
@@ -33,4 +33,7 @@ abstract class RegistrationDataApi {
 
   @async
   void setAdditionalReqId(String additionalReqId);
+
+  @async
+  void setMachineLocation(double latitude, double longitude);
 }
diff --git a/pubspec.yaml b/pubspec.yaml
index f2ba07cec..66a428ffc 100644
--- a/pubspec.yaml
+++ b/pubspec.yaml
@@ -70,6 +70,7 @@ dependencies:
   native_image_cropper: ^0.6.0
   qr_code_scanner: ^1.0.1
   restart_app: ^1.2.1
+  geolocator: ^10.1.0
 
 dev_dependencies:
   flutter_test:

From 387135f48b7fcaa01115321c320b4982157252cb Mon Sep 17 00:00:00 2001
From: Sachin S  P <52343650+SachinPremkumar@users.noreply.github.com>
Date: Thu, 30 Oct 2025 21:21:01 +0530
Subject: [PATCH 32/44] RCF-1224: for operator role not able to login getting
 some error  (#595)

* RCF-1224: for operator role not able to login

Signed-off-by: sachin.sp 

* RCF-1224: added localization

Signed-off-by: sachin.sp 

---------

Signed-off-by: sachin.sp 
Co-authored-by: sachin.sp 
---
 .../clientmanager/config/SessionManager.java         |  2 +-
 assets/l10n/app_ar.arb                               |  3 ++-
 assets/l10n/app_en.arb                               |  3 ++-
 assets/l10n/app_fr.arb                               |  3 ++-
 assets/l10n/app_hi.arb                               |  3 ++-
 assets/l10n/app_kn.arb                               |  3 ++-
 assets/l10n/app_ta.arb                               |  3 ++-
 lib/ui/settings/settings_screen.dart                 | 12 ++++++++----
 8 files changed, 21 insertions(+), 11 deletions(-)

diff --git a/android/clientmanager/src/main/java/io/mosip/registration/clientmanager/config/SessionManager.java b/android/clientmanager/src/main/java/io/mosip/registration/clientmanager/config/SessionManager.java
index b9122920b..7f9c5a0d3 100644
--- a/android/clientmanager/src/main/java/io/mosip/registration/clientmanager/config/SessionManager.java
+++ b/android/clientmanager/src/main/java/io/mosip/registration/clientmanager/config/SessionManager.java
@@ -61,7 +61,7 @@ public List saveAuthToken(@NonNull String token) throws Exception {
         if(roles.isEmpty())
             throw new Exception("Unauthorized access, No roles");
 
-        if(!roles.contains("REGISTRATION_SUPERVISOR") && !roles.contains("REGISTRATION_OFFICER"))
+        if(!roles.contains("REGISTRATION_SUPERVISOR") && !roles.contains("REGISTRATION_OFFICER") && !roles.contains("REGISTRATION_OPERATOR"))
             throw new Exception("Unauthorized access, Required roles not found");
 
         SharedPreferences.Editor editor = this.context.getSharedPreferences(this.context.getString(R.string.app_name),
diff --git a/assets/l10n/app_ar.arb b/assets/l10n/app_ar.arb
index d7ba2d9cd..518dfe9fe 100644
--- a/assets/l10n/app_ar.arb
+++ b/assets/l10n/app_ar.arb
@@ -330,5 +330,6 @@
   "confirm": "تأكيد",
   "scan_now": "امسح الآن",
   "enter_additional_info_req_id": "أدخل معرف طلب المعلومات الإضافية",
-  "additional_info_req_id": "معرف طلب المعلومات الإضافية"
+  "additional_info_req_id": "معرف طلب المعلومات الإضافية",
+  "no_access_to_this_page": "ليست لديك صلاحية الوصول إلى هذه الصفحة"
 }
\ No newline at end of file
diff --git a/assets/l10n/app_en.arb b/assets/l10n/app_en.arb
index 6c45ecfd7..633e8562c 100644
--- a/assets/l10n/app_en.arb
+++ b/assets/l10n/app_en.arb
@@ -330,5 +330,6 @@
   "confirm": "CONFIRM",
   "scan_now": "Scan Now",
   "enter_additional_info_req_id": "Enter Additional Info Request ID",
-  "additional_info_req_id": "Additional Info Request ID"
+  "additional_info_req_id": "Additional Info Request ID",
+  "no_access_to_this_page": "You don't have access to this page"
 }
\ No newline at end of file
diff --git a/assets/l10n/app_fr.arb b/assets/l10n/app_fr.arb
index c477e25ab..4d629a53f 100644
--- a/assets/l10n/app_fr.arb
+++ b/assets/l10n/app_fr.arb
@@ -330,5 +330,6 @@
   "confirm": "Confirmer",
   "scan_now": "Analyser maintenant",
   "enter_additional_info_req_id": "Entrez l'identifiant de la demande d'information supplémentaire",
-  "additional_info_req_id": "Identifiant de la demande d'information supplémentaire"
+  "additional_info_req_id": "Identifiant de la demande d'information supplémentaire",
+  "no_access_to_this_page": "Vous n'avez pas accès à cette page"
 }
\ No newline at end of file
diff --git a/assets/l10n/app_hi.arb b/assets/l10n/app_hi.arb
index 330db7a2f..a2888414f 100644
--- a/assets/l10n/app_hi.arb
+++ b/assets/l10n/app_hi.arb
@@ -330,5 +330,6 @@
   "confirm": "पुष्टि करें",
   "scan_now": "अभी स्कैन करें",
   "enter_additional_info_req_id": "अतिरिक्त जानकारी अनुरोध आईडी दर्ज करें",
-  "additional_info_req_id": "अतिरिक्त जानकारी अनुरोध आईडी"
+  "additional_info_req_id": "अतिरिक्त जानकारी अनुरोध आईडी",
+  "no_access_to_this_page": "आपको इस पृष्ठ तक पहुँच नहीं है"
 }
\ No newline at end of file
diff --git a/assets/l10n/app_kn.arb b/assets/l10n/app_kn.arb
index b22db4346..3ceacb39b 100644
--- a/assets/l10n/app_kn.arb
+++ b/assets/l10n/app_kn.arb
@@ -330,5 +330,6 @@
   "confirm": "ದೃಢೀಕರಿಸಿ",
   "scan_now": "ಈಗಸ್ಕ್ಯಾನ್ ಮಾಡಿ",
   "enter_additional_info_req_id": "ಹೆಚ್ಚುವರಿ ಮಾಹಿತಿ ವಿನಂತಿ ಐಡಿ ನಮೂದಿಸಿ",
-  "additional_info_req_id": "ಹೆಚ್ಚುವರಿ ಮಾಹಿತಿ ವಿನಂತಿ ಐಡಿ"
+  "additional_info_req_id": "ಹೆಚ್ಚುವರಿ ಮಾಹಿತಿ ವಿನಂತಿ ಐಡಿ",
+  "no_access_to_this_page": "ನಿಮಗೆ ಈ ಪುಟಕ್ಕೆ ಪ್ರವೇಶವಿಲ್ಲ"
 }
\ No newline at end of file
diff --git a/assets/l10n/app_ta.arb b/assets/l10n/app_ta.arb
index 1fd3ea1a2..135770fc0 100644
--- a/assets/l10n/app_ta.arb
+++ b/assets/l10n/app_ta.arb
@@ -339,5 +339,6 @@
   "confirm": "உறுதிப்படுத்தவும்",
   "scan_now": "இப்போது ஸ்கேன் செய்யுங்கள்",
   "enter_additional_info_req_id": "கூடுதல் தகவல் கோரிக்கை ஐடியை உள்ளிடவும்",
-  "additional_info_req_id": "கூடுதல் தகவல் கோரிக்கை ஐடி"
+  "additional_info_req_id": "கூடுதல் தகவல் கோரிக்கை ஐடி",
+  "no_access_to_this_page": "இந்தப் பக்கத்தை அணுக உங்களுக்கு அனுமதி இல்லை"
 }
\ No newline at end of file
diff --git a/lib/ui/settings/settings_screen.dart b/lib/ui/settings/settings_screen.dart
index 81b1c4179..020eda4e0 100644
--- a/lib/ui/settings/settings_screen.dart
+++ b/lib/ui/settings/settings_screen.dart
@@ -64,10 +64,14 @@ class _SettingsScreenState extends State {
 
 
     if (settingUiByRole.isEmpty) {
-      return const Center(
-        child: Text(
-          "You don't have access to this page.",
-          style: TextStyle(fontSize: 18, color: Colors.black),
+      return SizedBox(
+        width: MediaQuery.of(context).size.width,
+        height: MediaQuery.of(context).size.height,
+        child: Center(
+          child: Text(
+            AppLocalizations.of(context)!.no_access_to_this_page,
+            style: TextStyle(fontSize: 18, color: Colors.black),
+          ),
         ),
       );
     }

From e141f481770f8d9bc0334bb5ee28630e7dc78d2e Mon Sep 17 00:00:00 2001
From: Rakshithasai123 
Date: Thu, 30 Oct 2025 21:21:59 +0530
Subject: [PATCH 33/44] Using setAccessible(true) issue (#594)

* Using setAccessible(true) issue

Signed-off-by: Rakshithasai123 

* Comment out objectToMap method in BiometricsDetailsApi

Comment out the objectToMap method and its implementation.

Signed-off-by: Rakshithasai123 

---------

Signed-off-by: Rakshithasai123 
---
 .../api_services/BiometricsDetailsApi.java    | 44 +++++++++----------
 1 file changed, 22 insertions(+), 22 deletions(-)

diff --git a/android/app/src/main/java/io/mosip/registration_client/api_services/BiometricsDetailsApi.java b/android/app/src/main/java/io/mosip/registration_client/api_services/BiometricsDetailsApi.java
index 467b30178..0306ecfc0 100644
--- a/android/app/src/main/java/io/mosip/registration_client/api_services/BiometricsDetailsApi.java
+++ b/android/app/src/main/java/io/mosip/registration_client/api_services/BiometricsDetailsApi.java
@@ -783,28 +783,28 @@ public static Boolean customMatcher(String str1, String str2) {
         return result;
     }
 
-    public static Map objectToMap(Object object) {
-        Map map = new HashMap<>();
-
-        // Get all fields of the object using reflection
-        Field[] fields = object.getClass().getDeclaredFields();
-
-        for (Field field : fields) {
-            field.setAccessible(true); // Make the private fields accessible
-
-            try {
-                Object fieldValue = field.get(object);
-                if (fieldValue != null) {
-                    // Convert field value to String and add it to the map
-                    map.put(field.getName(), fieldValue.toString());
-                }
-            } catch (IllegalAccessException e) {
-                e.printStackTrace();
-            }
-        }
-
-        return map;
-    }
+    // public static Map objectToMap(Object object) {
+    //     Map map = new HashMap<>();
+
+    //     // Get all fields of the object using reflection
+    //     Field[] fields = object.getClass().getDeclaredFields();
+
+    //     for (Field field : fields) {
+    //        // field.setAccessible(true); // Make the private fields accessible
+
+    //         try {
+    //             Object fieldValue = field.get(object);
+    //             if (fieldValue != null) {
+    //                 // Convert field value to String and add it to the map
+    //                 map.put(field.getName(), fieldValue.toString());
+    //             }
+    //         } catch (IllegalAccessException e) {
+    //             e.printStackTrace();
+    //         }
+    //     }
+
+    //     return map;
+    // }
 
     private void queryPackage(Intent intent) throws ClientCheckedException {
         List activities = activity.getPackageManager().queryIntentActivities(intent, PackageManager.MATCH_ALL);

From badca22dd7f31ff504f0ee4c95ff356eb67a6aa4 Mon Sep 17 00:00:00 2001
From: Rakshithasai123 
Date: Fri, 31 Oct 2025 08:43:50 +0530
Subject: [PATCH 34/44] operator permission is not mandated (#596)

* operator permission is not mandated

Signed-off-by: Rakshithasai123 

* Removed skip to home button

Signed-off-by: Rakshithasai123 

---------

Signed-off-by: Rakshithasai123 
---
 lib/ui/onboard/onboarding_page.dart | 14 --------------
 1 file changed, 14 deletions(-)

diff --git a/lib/ui/onboard/onboarding_page.dart b/lib/ui/onboard/onboarding_page.dart
index 2cb790038..a8f451fb4 100644
--- a/lib/ui/onboard/onboarding_page.dart
+++ b/lib/ui/onboard/onboarding_page.dart
@@ -115,20 +115,6 @@ class OnboardingPage extends StatelessWidget {
                       color: appWhite,
                       fontColor: appSolidPrimary,
                     ),
-                    SizedBox(
-                      height: 40.h,
-                    ),
-                    _getButton(
-                      title: appLocalizations.skip_to_home,
-                      onTap: () {
-                        globalProvider.setCurrentIndex(1);
-                      },
-                      color: Colors.transparent,
-                      fontColor: appWhite,
-                    ),
-                    SizedBox(
-                      height: 40.h,
-                    ),
                   ],
                 ),
               ),

From 3a7ef490d1e790d49c6552e070ede3cf19d45b67 Mon Sep 17 00:00:00 2001
From: Madhuravas reddy 
Date: Fri, 31 Oct 2025 09:24:09 +0530
Subject: [PATCH 35/44] Implemented scheduled jobs in the settings page (#586)

* Created Scheduled jobs feature

Signed-off-by: Madhuravas reddy 

* Created audit logs deletion

Signed-off-by: Madhuravas reddy 

* Removed debug logs

Signed-off-by: Madhuravas reddy 

* implemented pre-reg deletion

Signed-off-by: Madhuravas Reddy 

* Added last sync and next sync timings

Signed-off-by: Madhuravas Reddy 

* calling _getJobIdFinder after masterdata sync

Signed-off-by: Madhuravas Reddy 

* Added corn job timer for next run

Signed-off-by: Madhuravas Reddy 

* Resolved review comments

Signed-off-by: Madhuravas Reddy 

* Changed naming convention

Signed-off-by: Madhuravas Reddy 

* Removed testing code

Signed-off-by: Madhuravas Reddy 

* removed dulicate code

Signed-off-by: Madhuravas Reddy 

* changed local DB name

Signed-off-by: Madhuravas Reddy 

* changed local DB name

Signed-off-by: Madhuravas Reddy 

* Added auto sync method

Signed-off-by: Madhuravas Reddy 

* Resolved review comments

Signed-off-by: Madhuravas Reddy 

---------

Signed-off-by: Madhuravas reddy 
Signed-off-by: Madhuravas Reddy 
---
 .../registration_client/MainActivity.java     | 156 ++++++++---
 .../UploadBackgroundService.java              |  12 +-
 .../api_services/MasterDataSyncApi.java       | 189 +++++++++++--
 android/clientmanager/build.gradle            |   2 +
 .../clientmanager/config/AppModule.java       |  11 +-
 .../constant/RegistrationConstants.java       |   3 +
 .../dao/PreRegistrationDataSyncDao.java       |  29 +-
 .../PreRegistrationDataSyncRepositoryDao.java |   4 +
 .../clientmanager/jobs/ConfigDataSyncJob.java |   2 +-
 .../jobs/DeleteAuditLogsJob.java              |  50 ++++
 .../repository/GlobalParamRepository.java     |   1 +
 .../repository/SyncJobDefRepository.java      |   7 +
 .../service/AuditManagerServiceImpl.java      |  21 +-
 .../service/JobManagerServiceImpl.java        |  64 +++--
 .../service/MasterDataServiceImpl.java        |  57 +++-
 .../PreRegistrationDataSyncDaoImpl.java       |  32 ++-
 .../PreRegistrationDataSyncServiceImpl.java   | 155 ++++++++++-
 .../service/RegistrationServiceImpl.java      | 149 ++++++-----
 .../external/PreRegZipHandlingService.java    |   2 +-
 .../clientmanager/spi/MasterDataService.java  |  13 +-
 .../spi/PreRegistrationDataSyncService.java   |  12 +-
 .../util/CronExpressionParser.java            |  65 +++++
 .../clientmanager/util/DateUtil.java          |  13 +-
 .../clientmanager/config/AppModuleTest.java   |  16 +-
 .../jobs/ConfigDataSyncJobTest.java           |  12 +-
 .../service/MasterDataServiceImplTest.java    |  28 +-
 ...reRegistrationDataSyncServiceImplTest.java |  19 +-
 .../service/RegistrationServiceImplTest.java  |  35 +--
 .../service/SyncDataServiceImplTest.java      |  21 +-
 assets/l10n/app_ar.arb                        |   3 +-
 assets/l10n/app_en.arb                        |   1 +
 assets/l10n/app_fr.arb                        |   3 +-
 assets/l10n/app_hi.arb                        |   3 +-
 assets/l10n/app_kn.arb                        |   3 +-
 assets/l10n/app_ta.arb                        |   3 +-
 .../sync_response_service_impl.dart           | 106 ++++++--
 lib/platform_spi/sync_response_service.dart   |  20 +-
 lib/provider/sync_provider.dart               |  91 +++++--
 lib/ui/settings/settings_screen.dart          |  23 +-
 .../widgets/Scheduled_jobs_settings.dart      | 252 ++++++++++++++++++
 lib/utils/sync_job_def.dart                   |  45 ++++
 pigeon/master_data_sync.dart                  |  24 +-
 42 files changed, 1435 insertions(+), 322 deletions(-)
 create mode 100644 android/clientmanager/src/main/java/io/mosip/registration/clientmanager/jobs/DeleteAuditLogsJob.java
 create mode 100644 android/clientmanager/src/main/java/io/mosip/registration/clientmanager/util/CronExpressionParser.java
 create mode 100644 lib/ui/settings/widgets/Scheduled_jobs_settings.dart
 create mode 100644 lib/utils/sync_job_def.dart

diff --git a/android/app/src/main/java/io/mosip/registration_client/MainActivity.java b/android/app/src/main/java/io/mosip/registration_client/MainActivity.java
index 5a51b1257..25598da76 100644
--- a/android/app/src/main/java/io/mosip/registration_client/MainActivity.java
+++ b/android/app/src/main/java/io/mosip/registration_client/MainActivity.java
@@ -24,6 +24,8 @@
 
 import com.fasterxml.jackson.databind.ObjectWriter;
 
+import java.util.List;
+import java.util.Objects;
 import java.util.concurrent.Executors;
 import java.util.concurrent.ScheduledExecutorService;
 import java.util.concurrent.TimeUnit;
@@ -36,13 +38,22 @@
 import io.mosip.registration.clientmanager.config.AppModule;
 import io.mosip.registration.clientmanager.config.NetworkModule;
 import io.mosip.registration.clientmanager.config.RoomModule;
+import io.mosip.registration.clientmanager.constant.AuditEvent;
+import io.mosip.registration.clientmanager.constant.Components;
+import io.mosip.registration.clientmanager.constant.PacketClientStatus;
+import io.mosip.registration.clientmanager.constant.PacketTaskStatus;
 import io.mosip.registration.clientmanager.dao.GlobalParamDao;
+import io.mosip.registration.clientmanager.dto.CenterMachineDto;
+import io.mosip.registration.clientmanager.entity.GlobalParam;
+import io.mosip.registration.clientmanager.entity.Registration;
+import io.mosip.registration.clientmanager.entity.SyncJobDef;
 import io.mosip.registration.clientmanager.repository.GlobalParamRepository;
 import io.mosip.registration.clientmanager.repository.IdentitySchemaRepository;
 import io.mosip.registration.clientmanager.repository.RegistrationCenterRepository;
 import io.mosip.registration.clientmanager.repository.SyncJobDefRepository;
 import io.mosip.registration.clientmanager.repository.UserDetailRepository;
 import io.mosip.registration.clientmanager.service.LoginService;
+import io.mosip.registration.clientmanager.spi.AsyncPacketTaskCallBack;
 import io.mosip.registration.clientmanager.spi.AuditManagerService;
 import io.mosip.registration.clientmanager.spi.JobManagerService;
 import io.mosip.registration.clientmanager.spi.JobTransactionService;
@@ -89,6 +100,7 @@
 import io.mosip.registration_client.model.UserPigeon;
 import io.mosip.registration_client.model.DocumentDataPigeon;
 import io.mosip.registration_client.utils.BatchJob;
+import io.mosip.registration_client.utils.CustomToast;
 
 import android.net.Uri;
 
@@ -187,68 +199,127 @@ public class MainActivity extends FlutterActivity {
     private BroadcastReceiver broadcastReceiver = new BroadcastReceiver() {
         @Override
         public void onReceive(Context context, Intent intent) {
-        if (intent.getAction().equals("REGISTRATION_PACKET_UPLOAD")) {
-            batchJob.syncRegistrationPackets(context);
+            String jobApiName = intent.getStringExtra(UploadBackgroundService.EXTRA_JOB_API_NAME);
+            if (jobApiName == null) jobApiName = "registrationPacketUploadJob"; // Backward compatibility
+
+            // Execute the job based on API name
+            masterDataSyncApi.executeJobByApiName(jobApiName, context);
+
+            // Reschedule next execution
+            String finalJobApiName = jobApiName;
             ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);
             scheduler.schedule(()-> {
-                createBackgroundTask("registrationPacketUploadJob");
+                createBackgroundTask(finalJobApiName);
             }, 1, TimeUnit.MINUTES);
         }
-        }
     };
 
     @Override
     protected void onCreate(@Nullable Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
-        createBackgroundTask("registrationPacketUploadJob");
-        IntentFilter intentFilterUpload = new IntentFilter("REGISTRATION_PACKET_UPLOAD");
+//        createBackgroundTask("registrationPacketUploadJob");
+        IntentFilter intentFilterUpload = new IntentFilter("SYNC_JOB_TRIGGER");
         registerReceiver(broadcastReceiver, intentFilterUpload);
     }
 
+    private void initializeAutoSync() {
+        try {
+            CenterMachineDto dto = masterDataService.getRegistrationCenterMachineDetails();
+            if (dto != null && dto.getMachineRefId() != null) {
+                Log.d(getClass().getSimpleName(), "Machine configured - initializing auto sync");
+                scheduleAllActiveJobs();
+            } else {
+                Log.w(getClass().getSimpleName(), "Machine not configured yet - skipping auto sync initialization");
+            }
+        } catch (Exception e) {
+            Log.e(getClass().getSimpleName(), "Error initializing auto sync", e);
+        }
+    }
+
+    // Schedule all active jobs from database
+    void scheduleAllActiveJobs() {
+        new Thread(() -> {
+            try {
+                List activeJobs = syncJobDefRepository.getAllSyncJobDefList();
+                int scheduledCount = 0;
+
+                for (SyncJobDef job : activeJobs) {
+                    if (job.getIsActive() != null && job.getIsActive() && job.getApiName() != null) {
+                        Log.d(getClass().getSimpleName(), "Scheduling job: " + job.getApiName() +
+                                " (ID: " + job.getId() + ", Cron: " + job.getSyncFreq() + ")");
+
+                        runOnUiThread(() -> createBackgroundTask(job.getApiName()));
+                        scheduledCount++;
+                    }
+                }
+
+                Log.d(getClass().getSimpleName(), "Scheduled " + scheduledCount + " active jobs");
+            } catch (Exception e) {
+                Log.e(getClass().getSimpleName(), "Error scheduling jobs", e);
+            }
+        }).start();
+    }
+
     @Override
     protected void onDestroy() {
         super.onDestroy();
         unregisterReceiver(broadcastReceiver);
     }
 
-    void createBackgroundTask(String api){
-        Intent intent = new Intent(this, UploadBackgroundService.class);
-        PendingIntent pendingIntent;
-        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
-            pendingIntent = PendingIntent.getForegroundService(
-                    this,
-                    0,  // Request code
-                    intent,
-                    PendingIntent.FLAG_IMMUTABLE
-            );
-        } else {
-            pendingIntent = PendingIntent.getService(
-                    this,
-                    0,  // Request code
-                    intent,
-                    PendingIntent.FLAG_UPDATE_CURRENT
-            );
-        }
-        AlarmManager alarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
-        if (alarmManager != null) {
-            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S && !alarmManager.canScheduleExactAlarms()) {
-                Intent permissionIntent = new Intent(android.provider.Settings.ACTION_REQUEST_SCHEDULE_EXACT_ALARM);
-                permissionIntent.setData(Uri.fromParts("package", getPackageName(), null));
-                startActivity(permissionIntent);
-            }
-            long alarmTime = batchJob.getIntervalMillis(api);
-            long currentTime = System.currentTimeMillis();
-            long delay = alarmTime > currentTime ? alarmTime - currentTime : alarmTime - currentTime;
-            Log.d(getClass().getSimpleName(), String.valueOf(delay)+ " Next Execution");
-
-//            alarmManager.setInexactRepeating(AlarmManager.RTC_WAKEUP,System.currentTimeMillis(), 30000, pendingIntent);
-            if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.M) {
-                alarmManager.setExactAndAllowWhileIdle(AlarmManager.ELAPSED_REALTIME_WAKEUP, SystemClock.elapsedRealtime() + delay, pendingIntent);
-            } else if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.KITKAT) {
-                alarmManager.setExact(AlarmManager.ELAPSED_REALTIME_WAKEUP, SystemClock.elapsedRealtime() + delay, pendingIntent);
+    public void createBackgroundTask(String api){
+        try {
+            Intent intent = new Intent(this, UploadBackgroundService.class);
+            intent.putExtra(UploadBackgroundService.EXTRA_JOB_API_NAME, api); // Pass job API name
+
+            // Use unique request code per job to prevent conflicts
+            int requestCode = Math.abs(api.hashCode() % 10000);
+
+            PendingIntent pendingIntent;
+            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
+                pendingIntent = PendingIntent.getForegroundService(this, requestCode, intent, PendingIntent.FLAG_IMMUTABLE);
             } else {
-                alarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, SystemClock.elapsedRealtime() + delay, pendingIntent);
+                pendingIntent = PendingIntent.getService(this, requestCode, intent, PendingIntent.FLAG_UPDATE_CURRENT);
+            }
+
+            AlarmManager alarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
+            if (alarmManager != null) {
+                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S && !alarmManager.canScheduleExactAlarms()) {
+                    Intent permissionIntent = new Intent(android.provider.Settings.ACTION_REQUEST_SCHEDULE_EXACT_ALARM);
+                    permissionIntent.setData(Uri.fromParts("package", getPackageName(), null));
+                    startActivity(permissionIntent);
+                    return;
+                }
+
+                // Get next execution time from cron expression
+                long alarmTime = batchJob.getIntervalMillis(api);
+                long currentTime = System.currentTimeMillis();
+                long delay = alarmTime - currentTime;
+
+                // Ensure delay is positive (prevent immediate execution)
+                if (delay < 0 || delay < 60000) {
+                    Log.w(getClass().getSimpleName(), api + " - Calculated delay is too small (" + delay + "ms), using 1 minute minimum");
+                    delay = 60000; // Minimum 1 minute
+                }
+
+                Log.d(getClass().getSimpleName(), api + " - Request code: " + requestCode +
+                        ", Next execution in: " + (delay / 1000) + " seconds");
+
+                // Cancel old alarm before scheduling new one
+                alarmManager.cancel(pendingIntent);
+
+                // Schedule alarm
+                if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.M) {
+                    alarmManager.setExactAndAllowWhileIdle(AlarmManager.ELAPSED_REALTIME_WAKEUP, SystemClock.elapsedRealtime() + delay, pendingIntent);
+                } else if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.KITKAT) {
+                    alarmManager.setExact(AlarmManager.ELAPSED_REALTIME_WAKEUP, SystemClock.elapsedRealtime() + delay, pendingIntent);
+                } else {
+                    alarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, SystemClock.elapsedRealtime() + delay, pendingIntent);
+                }
+
+                Log.d(getClass().getSimpleName(), api + " - Alarm scheduled successfully");
             }
+        } catch (Exception e) {
+            Log.e(getClass().getSimpleName(), "Error scheduling job: " + api, e);
         }
     }
 
@@ -261,6 +332,7 @@ public void initializeAppComponent() {
                 .hostApiModule(new HostApiModule(getApplication()))
                 .build();
         appComponent.inject(this);
+        initializeAutoSync();
     }
 
     @Override
diff --git a/android/app/src/main/java/io/mosip/registration_client/UploadBackgroundService.java b/android/app/src/main/java/io/mosip/registration_client/UploadBackgroundService.java
index ee3159bf2..43ff484ac 100644
--- a/android/app/src/main/java/io/mosip/registration_client/UploadBackgroundService.java
+++ b/android/app/src/main/java/io/mosip/registration_client/UploadBackgroundService.java
@@ -22,6 +22,8 @@ public class UploadBackgroundService extends Service {
     private static final int NOTIFICATION_ID = 1;
     private static final String CHANNEL_ID = "ForegroundServiceChannel";
 
+    public static final String EXTRA_JOB_API_NAME = "job_api_name";
+
     @Override
     public void onCreate() {
         super.onCreate();
@@ -29,11 +31,17 @@ public void onCreate() {
 
     @Override
     public int onStartCommand(Intent intent, int flags, int startId) {
+        // Get job API name from intent, default to packet upload
+        String jobApiName = intent != null ? intent.getStringExtra(EXTRA_JOB_API_NAME) : "registrationPacketUploadJob";
+
         createNotificationChannel();
         Notification notification = createNotification();
         startForeground(NOTIFICATION_ID, notification);
-        Log.d(getClass().getSimpleName(), "Sync & Upload Packets in background activity");
-        Intent broadcastIntent = new Intent("REGISTRATION_PACKET_UPLOAD");
+        Log.d(getClass().getSimpleName(), "Sync job triggered: " + jobApiName);
+
+        // Send broadcast with job API name
+        Intent broadcastIntent = new Intent("SYNC_JOB_TRIGGER");
+        broadcastIntent.putExtra(EXTRA_JOB_API_NAME, jobApiName);
         sendBroadcast(broadcastIntent);
         return START_STICKY;
     }
diff --git a/android/app/src/main/java/io/mosip/registration_client/api_services/MasterDataSyncApi.java b/android/app/src/main/java/io/mosip/registration_client/api_services/MasterDataSyncApi.java
index f154ff620..1f6f1a4c5 100644
--- a/android/app/src/main/java/io/mosip/registration_client/api_services/MasterDataSyncApi.java
+++ b/android/app/src/main/java/io/mosip/registration_client/api_services/MasterDataSyncApi.java
@@ -20,6 +20,7 @@
 import android.os.Build;
 import android.os.SystemClock;
 import android.util.Log;
+import android.widget.Toast;
 
 import androidx.annotation.NonNull;
 
@@ -54,6 +55,8 @@
 import io.mosip.registration.clientmanager.repository.SyncJobDefRepository;
 import io.mosip.registration.clientmanager.repository.TemplateRepository;
 import io.mosip.registration.clientmanager.repository.UserDetailRepository;
+import io.mosip.registration.clientmanager.constant.RegistrationConstants;
+import io.mosip.registration.clientmanager.service.JobManagerServiceImpl;
 import io.mosip.registration.clientmanager.spi.AuditManagerService;
 import io.mosip.registration.clientmanager.spi.JobManagerService;
 import io.mosip.registration.clientmanager.spi.MasterDataService;
@@ -165,9 +168,8 @@ public void getLastSyncTime(@NonNull MasterDataSyncPigeon.Result result) {
+    public void getPolicyKeySync(@NonNull Boolean isManualSync, @NonNull String jobId, @NonNull MasterDataSyncPigeon.Result result) {
         CenterMachineDto centerMachineDto = masterDataService.getRegistrationCenterMachineDetails();
-
         if (centerMachineDto == null) {
             result.success(syncResult("PolicyKeySync", 5, "policy_key_sync_failed"));
             return;
@@ -175,33 +177,33 @@ public void getPolicyKeySync(@NonNull Boolean isManualSync, @NonNull MasterDataS
 
         try {
             masterDataService.syncCertificate(() -> {
-                Log.i(TAG, "Policy Key Sync Completed");
+
                 result.success(syncResult("PolicyKeySync", 5, masterDataService.onResponseComplete()));
-            }, REG_APP_ID, centerMachineDto.getMachineRefId(), REG_APP_ID, centerMachineDto.getMachineRefId(), isManualSync);
+            }, REG_APP_ID, centerMachineDto.getMachineRefId(), REG_APP_ID, centerMachineDto.getMachineRefId(), isManualSync, jobId);
         } catch (Exception e) {
             e.printStackTrace();
         }
     }
 
     @Override
-    public void getGlobalParamsSync(@NonNull Boolean isManualSync, @NonNull MasterDataSyncPigeon.Result result) {
+    public void getGlobalParamsSync(@NonNull Boolean isManualSync, @NonNull String jobId, @NonNull MasterDataSyncPigeon.Result result) {
         try {
             masterDataService.syncGlobalParamsData(() -> {
                 Log.i(TAG, "Sync Global Params Completed.");
                 result.success(syncResult("GlobalParamsSync", 1, masterDataService.onResponseComplete()));
-            }, isManualSync);
+            }, isManualSync, jobId);
         } catch (Exception e) {
             e.printStackTrace();
         }
     }
 
     @Override
-    public void getUserDetailsSync(@NonNull Boolean isManualSync, @NonNull MasterDataSyncPigeon.Result result) {
+    public void getUserDetailsSync(@NonNull Boolean isManualSync, @NonNull String jobId, @NonNull MasterDataSyncPigeon.Result result) {
         try {
             masterDataService.syncUserDetails(() -> {
                 Log.i(TAG, "User details sync Completed.");
                 result.success(syncResult("UserDetailsSync", 3, masterDataService.onResponseComplete()));
-            }, isManualSync);
+            }, isManualSync, jobId);
         } catch (Exception e) {
             e.printStackTrace();
         }
@@ -221,12 +223,12 @@ public void getIDSchemaSync(@NonNull Boolean isManualSync, @NonNull MasterDataSy
     }
 
     @Override
-    public void getMasterDataSync(@NonNull Boolean isManualSync, @NonNull MasterDataSyncPigeon.Result result) {
+    public void getMasterDataSync(@NonNull Boolean isManualSync, @NonNull String jobId, @NonNull MasterDataSyncPigeon.Result result) {
         try {
             masterDataService.syncMasterData(() -> {
                 Log.i(TAG, "Master Data Sync Completed.");
                 result.success(syncResult("MasterDataSync", 2, masterDataService.onResponseComplete()));
-            }, 0, isManualSync);
+            }, 0, isManualSync, jobId);
         } catch (Exception e) {
             Log.e(TAG, "Master Data Sync Failed.", e);
             e.printStackTrace();
@@ -243,12 +245,12 @@ private MasterDataSyncPigeon.Sync syncResult(String syncType, int progress, Stri
     }
 
     @Override
-    public void getCaCertsSync(@NonNull Boolean isManualSync, @NonNull MasterDataSyncPigeon.Result result) {
+    public void getCaCertsSync(@NonNull Boolean isManualSync, @NonNull String jobId, @NonNull MasterDataSyncPigeon.Result result) {
         masterDataService.syncCACertificates(() -> {
             Log.i(TAG, "CA Certificate Sync Completed");
             resetAlarm("registrationPacketUploadJob");
             result.success(syncResult("CACertificatesSync", 6, masterDataService.onResponseComplete()));
-        }, isManualSync);
+        }, isManualSync, jobId);
     }
 
     @Override
@@ -268,13 +270,13 @@ public void getReasonList(@NonNull String langCode, @NonNull MasterDataSyncPigeo
     }
 
     @Override
-    public void getPreRegIds(@NonNull MasterDataSyncPigeon.Result result) {
+    public void getPreRegIds(@NonNull String jobId, @NonNull MasterDataSyncPigeon.Result result) {
         if (NetworkUtils.isNetworkConnected(this.context)) {
             try {
                 preRegistrationDataSyncService.fetchPreRegistrationIds(() -> {
                     Log.i(TAG, "Application Id's Sync Completed");
                     result.success("Application Id's Sync Completed.");
-                });
+                }, jobId);
             } catch (Exception e) {
                 e.printStackTrace();
             }
@@ -283,12 +285,12 @@ public void getPreRegIds(@NonNull MasterDataSyncPigeon.Result result) {
 
 
     @Override
-    public void getKernelCertsSync(@NonNull Boolean isManualSync, @NonNull MasterDataSyncPigeon.Result result) {
+    public void getKernelCertsSync(@NonNull Boolean isManualSync, @NonNull String jobId, @NonNull MasterDataSyncPigeon.Result result) {
         try {
             masterDataService.syncCertificate(() -> {
                 Log.i(TAG, "Policy Key Sync Completed");
                 result.success(syncResult("KernelCertsSync", 7, masterDataService.onResponseComplete()));
-            }, KERNEL_APP_ID, "SIGN", "SERVER-RESPONSE", "SIGN-VERIFY", isManualSync);
+            }, KERNEL_APP_ID, "SIGN", "SERVER-RESPONSE", "SIGN-VERIFY", isManualSync, jobId);
         } catch (Exception e) {
             e.printStackTrace();
         }
@@ -339,4 +341,159 @@ void resetAlarm(String api) {
             }
         }
     }
+
+    @Override
+    public void deleteAuditLogs(@NonNull String jobId, @NonNull MasterDataSyncPigeon.Result result) {
+        try {
+            boolean deletedRes = auditManagerService.deleteAuditLogs();
+            // Also persist timestamps so UI can show Last/Next immediately when triggered manually
+            try {
+                if(deletedRes){
+                    masterDataService.logLastSyncCompletionDateTime(jobId);
+                    Toast.makeText(context, "Deleted Audit logs", Toast.LENGTH_LONG).show();
+                }
+            } catch (Exception e) {
+                Log.e(TAG, "Failed to store CA certificates sync last sync time", e);
+                Toast.makeText(context, "Failed to Deleted Audit logs", Toast.LENGTH_LONG).show();
+            }
+            result.success(deletedRes);
+        } catch (Exception e) {
+            result.error(e);
+            Toast.makeText(context, "Failed to deleted Audit logs", Toast.LENGTH_LONG).show();
+        }
+    }
+
+    @Override
+    public void deletePreRegRecords(@NonNull String jobId, @NonNull MasterDataSyncPigeon.Result result) {
+        try {
+            // Call fetchAndDeleteRecords from PreRegistrationDataSyncService
+            preRegistrationDataSyncService.fetchAndDeleteRecords();
+            masterDataService.logLastSyncCompletionDateTime(jobId);
+            Toast.makeText(context, "Deleted Pre-reg records", Toast.LENGTH_LONG).show();
+            result.success(true);
+        } catch (Exception e) {
+            result.error(e);
+            Toast.makeText(context, "Failed to deleted Pre-reg records", Toast.LENGTH_LONG).show();
+        }
+    }
+
+    @Override
+    public void getLastSyncTimeByJobId(@NonNull String jobId, @NonNull MasterDataSyncPigeon.Result result) {
+        int syncJobId = jobManagerService.generateJobServiceId(jobId);
+        String lastSyncTime = jobManagerService.getLastSyncTime(syncJobId);
+        result.success(lastSyncTime);
+    }
+
+    @Override
+    public void getNextSyncTimeByJobId(@NonNull String jobId, @NonNull MasterDataSyncPigeon.Result result) {
+        int syncJobId = jobManagerService.generateJobServiceId(jobId);
+        String nextSyncTime = jobManagerService.getNextSyncTime(syncJobId);
+        result.success(nextSyncTime);
+    }
+
+    @Override
+    public void getActiveSyncJobs(@NonNull MasterDataSyncPigeon.Result> result) {
+        List list = syncJobDefRepository.getActiveSyncJobs();
+        List value = new ArrayList<>();
+        try {
+            for (SyncJobDef job : list) {
+                value.add(objectMapper.writeValueAsString(job));
+            }
+        } catch (Exception e) {
+            Log.e(TAG, "Failed to serialize active sync jobs", e);
+        }
+        result.success(value);
+    }
+
+    // Execute job based on API name
+    public void executeJobByApiName(String jobApiName, Context context) {
+        new Thread(() -> {
+            try {
+
+                // Get job ID from database for tracking last/next sync
+                String jobId = getJobIdByApiName(jobApiName);
+
+                // Execute appropriate sync job
+                switch (jobApiName) {
+                    case "registrationPacketUploadJob":
+                        batchJob.syncRegistrationPackets(context);
+                        break;
+                    case "packetSyncStatusJob":
+                        packetService.syncAllPacketStatus();
+                        break;
+                    case "masterSyncJob":
+                        masterDataService.syncMasterData(() -> {
+                            Log.d(getClass().getSimpleName(), "Master data sync callback");
+                        }, 0, true, jobId);
+                        break;
+                    case "synchConfigDataJob":
+                        masterDataService.syncGlobalParamsData(() -> {
+                            Log.d(getClass().getSimpleName(), "Config data sync callback");
+                        }, true, jobId);
+                        break;
+                    case "userDetailServiceJob":
+                        masterDataService.syncUserDetails(() -> {
+                            Log.d(getClass().getSimpleName(), "User details sync callback");
+                        }, true, jobId);
+                        break;
+                    case "keyPolicySyncJob":
+                        CenterMachineDto centerMachineDto = masterDataService.getRegistrationCenterMachineDetails();
+                        if (centerMachineDto != null && centerMachineDto.getMachineRefId() != null) {
+                            masterDataService.syncCertificate(() -> {
+                                Log.d(getClass().getSimpleName(), "Policy key sync callback");
+                            }, REG_APP_ID, centerMachineDto.getMachineRefId(), REG_APP_ID, centerMachineDto.getMachineRefId(), true, jobId);
+                        } else {
+                            Log.w(getClass().getSimpleName(), "Skipping keyPolicySyncJob - machine details not available");
+                        }
+                        break;
+                    case "publicKeySyncJob":
+                        // Public key sync for KERNEL app (SIGN certificates)
+                        masterDataService.syncCertificate(() -> {
+                            Log.d(getClass().getSimpleName(), "Public key sync callback");
+                        }, KERNEL_APP_ID, "SIGN", "SERVER-RESPONSE", "SIGN-VERIFY", true, jobId);
+                        break;
+                    case "syncCertificateJob":
+                        // CA certificate sync
+                        masterDataService.syncCACertificates(() -> {
+                            Log.d(getClass().getSimpleName(), "CA cert sync callback");
+                        }, true, jobId);
+                        break;
+                    case "preRegistrationDataSyncJob":
+                        preRegistrationDataSyncService.fetchPreRegistrationIds(() -> {
+                            Log.i(TAG, "Application Id's Sync Completed");
+                        }, jobId);
+                        break;
+
+                    case "deleteAuditLogsJob":
+                        auditManagerService.deleteAuditLogs();
+                        masterDataService.logLastSyncCompletionDateTime(jobId);
+                        break;
+
+                    case "preRegistrationPacketDeletionJob":
+                        preRegistrationDataSyncService.fetchAndDeleteRecords();
+                        masterDataService.logLastSyncCompletionDateTime(jobId);
+                        break;
+                    default:
+                        Log.w(getClass().getSimpleName(), "Unknown job: " + jobApiName);
+                }
+                Log.d(getClass().getSimpleName(), "Completed: " + jobApiName);
+            } catch (Exception e) {
+                Log.e(getClass().getSimpleName(), "Job failed: " + jobApiName, e);
+            }
+        }).start();
+    }
+
+    private String getJobIdByApiName(String apiName) {
+        try {
+            List jobs = syncJobDefRepository.getAllSyncJobDefList();
+            for (SyncJobDef job : jobs) {
+                if (apiName.equals(job.getApiName())) {
+                    return job.getId();
+                }
+            }
+        } catch (Exception e) {
+            Log.e(getClass().getSimpleName(), "Error getting job ID for: " + apiName, e);
+        }
+        return ""; // Return empty string if not found
+    }
 }
diff --git a/android/clientmanager/build.gradle b/android/clientmanager/build.gradle
index 61b5191dc..001ca3f2a 100644
--- a/android/clientmanager/build.gradle
+++ b/android/clientmanager/build.gradle
@@ -67,6 +67,8 @@ dependencies {
 
     implementation 'javax.validation:validation-api:2.0.1.Final'
 
+    implementation 'com.cronutils:cron-utils:9.2.0'
+
     //AspectJ
     implementation 'org.aspectj:aspectjrt:1.9.7'
 
diff --git a/android/clientmanager/src/main/java/io/mosip/registration/clientmanager/config/AppModule.java b/android/clientmanager/src/main/java/io/mosip/registration/clientmanager/config/AppModule.java
index da70f3ff1..9aeaf7c57 100644
--- a/android/clientmanager/src/main/java/io/mosip/registration/clientmanager/config/AppModule.java
+++ b/android/clientmanager/src/main/java/io/mosip/registration/clientmanager/config/AppModule.java
@@ -7,6 +7,7 @@
 
 import com.fasterxml.jackson.databind.ObjectMapper;
 
+import javax.inject.Provider;
 import javax.inject.Singleton;
 
 import dagger.Module;
@@ -167,14 +168,15 @@ public MasterDataService provideMasterDataService(ObjectMapper objectMapper, Syn
                                                       CertificateManagerService certificateManagerService,
                                                       LanguageRepository languageRepository,
                                                       JobManagerService jobManagerService,
-                                                      FileSignatureDao fileSignatureDao,
-                                                      PermittedLocalConfigRepository permittedLocalConfigRepository,
+                                                      FileSignatureDao fileSignatureDao, JobTransactionService jobTransactionService, PermittedLocalConfigRepository permittedLocalConfigRepository,
                                                       LocalConfigDAO localConfigDAO) {
+
         return new MasterDataServiceImpl(appContext, objectMapper, syncRestService, clientCryptoManagerService,
                 machineRepository, reasonListRepository, registrationCenterRepository, documentTypeRepository, applicantValidDocRepository,
                 templateRepository, dynamicFieldRepository, locationRepository,
                 globalParamRepository, identitySchemaRepository, blocklistedWordRepository, syncJobDefRepository, userDetailRepository,
-                certificateManagerService, languageRepository, jobManagerService, fileSignatureDao, permittedLocalConfigRepository, localConfigDAO);
+                certificateManagerService, languageRepository, jobManagerService, fileSignatureDao, jobTransactionService, permittedLocalConfigRepository, localConfigDAO);
+
     }
 
 
@@ -202,10 +204,11 @@ RegistrationService provideRegistrationService(PacketWriterService packetWriterS
                                                    AuditManagerService auditManagerService,
                                                    RegistrationCenterRepository registrationCenterRepository,
                                                    LocationValidationService locationValidationService,
+                                                   Provider preRegistrationDataSyncServiceProvider,
                                                    Biometrics095Service biometricService) {
         return new RegistrationServiceImpl(appContext, packetWriterService, registrationRepository,
                 masterDataService, identitySchemaRepository, clientCryptoManagerService,
-                keyStoreRepository, globalParamRepository, auditManagerService,registrationCenterRepository,locationValidationService, biometricService);
+                keyStoreRepository, globalParamRepository, auditManagerService, registrationCenterRepository,locationValidationService, preRegistrationDataSyncServiceProvider, biometricService);
     }
 
     @Provides
diff --git a/android/clientmanager/src/main/java/io/mosip/registration/clientmanager/constant/RegistrationConstants.java b/android/clientmanager/src/main/java/io/mosip/registration/clientmanager/constant/RegistrationConstants.java
index 37c1135ad..bf441c0e1 100644
--- a/android/clientmanager/src/main/java/io/mosip/registration/clientmanager/constant/RegistrationConstants.java
+++ b/android/clientmanager/src/main/java/io/mosip/registration/clientmanager/constant/RegistrationConstants.java
@@ -111,6 +111,9 @@ public class RegistrationConstants {
     public static final String RIGHT_THUMB = "Right Thumb";
     public static final String RIGHT = "Right";
     public static final String LEFT = "Left";
+    public static final String PRE_REG_DELETION_CONFIGURED_DAYS = "mosip.registration.pre_reg_deletion_configured_days";
+    public static final String PRE_REG_DELETE_SUCCESS = "PRE_REG_DELETE_SUCCESS";
+    public static final String PRE_REG_DELETE_FAILURE = "PRE_REG_DELETE_FAILURE";
     public static final String JOB_TRIGGER_POINT_USER = "User";
     public static final String GPS_DEVICE_ENABLE_FLAG = "mosip.registration.gps_device_enable_flag";
     public static final String DIST_FRM_MACHINE_TO_CENTER = "mosip.registration.distance.from.machine.to.center";
diff --git a/android/clientmanager/src/main/java/io/mosip/registration/clientmanager/dao/PreRegistrationDataSyncDao.java b/android/clientmanager/src/main/java/io/mosip/registration/clientmanager/dao/PreRegistrationDataSyncDao.java
index 0ad3583db..ff0bdd738 100644
--- a/android/clientmanager/src/main/java/io/mosip/registration/clientmanager/dao/PreRegistrationDataSyncDao.java
+++ b/android/clientmanager/src/main/java/io/mosip/registration/clientmanager/dao/PreRegistrationDataSyncDao.java
@@ -1,8 +1,11 @@
 package io.mosip.registration.clientmanager.dao;
 
-import io.mosip.registration.clientmanager.entity.PreRegistrationList;
+import java.sql.Timestamp;
+import java.util.Date;
 import java.util.List;
 
+import io.mosip.registration.clientmanager.entity.PreRegistrationList;
+
 
 /**
  * This class is used to fetch the specific pre registration by passing pre registration id as parameter,
@@ -17,26 +20,28 @@
  */
 public interface PreRegistrationDataSyncDao {
 
-  
+
     public PreRegistrationList get(String preRegId);
 
-    
+
     public void save(PreRegistrationList preRegistration);
 
-   
-    public List fetchRecordsToBeDeleted(String startDate);
 
-   
+    public List fetchRecordsToBeDeleted(Date startDate);
+
+
     public long update(String id,String updatedBy,String updatedTime);
 
-    
-    //public void deleteAll(List preRegistrationList);
 
-    
-   // List getAllPreRegPackets();
+    public void deleteAll(List preRegistrationList);
+
+
+    // List getAllPreRegPackets();
+
 
-   
     public String getLastPreRegPacketDownloadedTime();
 
     public PreRegistrationList getById(String id);
-}
+
+    public Timestamp getLastPreRegPacketDownloadedTimeAsTimestamp();
+}
\ No newline at end of file
diff --git a/android/clientmanager/src/main/java/io/mosip/registration/clientmanager/dao/PreRegistrationDataSyncRepositoryDao.java b/android/clientmanager/src/main/java/io/mosip/registration/clientmanager/dao/PreRegistrationDataSyncRepositoryDao.java
index b25dcbb8d..fd9b8774e 100644
--- a/android/clientmanager/src/main/java/io/mosip/registration/clientmanager/dao/PreRegistrationDataSyncRepositoryDao.java
+++ b/android/clientmanager/src/main/java/io/mosip/registration/clientmanager/dao/PreRegistrationDataSyncRepositoryDao.java
@@ -2,6 +2,7 @@
 package io.mosip.registration.clientmanager.dao;
 
 import androidx.room.Dao;
+import androidx.room.Delete;
 import androidx.room.Insert;
 import androidx.room.OnConflictStrategy;
 import androidx.room.Query;
@@ -46,4 +47,7 @@ public interface PreRegistrationDataSyncRepositoryDao {
     @Query("SELECT * FROM pre_registration_list WHERE id = :id LIMIT 1")
     PreRegistrationList getById(String id);
 
+    @Delete
+    void deleteAll(List preRegistrationList);
+
 }
\ No newline at end of file
diff --git a/android/clientmanager/src/main/java/io/mosip/registration/clientmanager/jobs/ConfigDataSyncJob.java b/android/clientmanager/src/main/java/io/mosip/registration/clientmanager/jobs/ConfigDataSyncJob.java
index 9674a908a..ff7e02b1e 100644
--- a/android/clientmanager/src/main/java/io/mosip/registration/clientmanager/jobs/ConfigDataSyncJob.java
+++ b/android/clientmanager/src/main/java/io/mosip/registration/clientmanager/jobs/ConfigDataSyncJob.java
@@ -39,7 +39,7 @@ public void onCreate() {
     public boolean triggerJob(int jobId) {
         Log.d(TAG, TAG + " Started");
         try {
-            masterDataService.syncGlobalParamsData(() -> {}, true);
+            masterDataService.syncGlobalParamsData(() -> {}, true, "");
             long timeStampInSeconds = TimeUnit.MILLISECONDS.toSeconds(System.currentTimeMillis());
             logJobTransaction(jobId, timeStampInSeconds);
             return true;
diff --git a/android/clientmanager/src/main/java/io/mosip/registration/clientmanager/jobs/DeleteAuditLogsJob.java b/android/clientmanager/src/main/java/io/mosip/registration/clientmanager/jobs/DeleteAuditLogsJob.java
new file mode 100644
index 000000000..ff61fc5f8
--- /dev/null
+++ b/android/clientmanager/src/main/java/io/mosip/registration/clientmanager/jobs/DeleteAuditLogsJob.java
@@ -0,0 +1,50 @@
+package io.mosip.registration.clientmanager.jobs;
+
+import android.annotation.SuppressLint;
+import android.util.Log;
+
+import java.util.concurrent.TimeUnit;
+
+import javax.inject.Inject;
+
+import dagger.android.AndroidInjection;
+import io.mosip.registration.clientmanager.spi.AuditManagerService;
+
+@SuppressLint("SpecifyJobSchedulerIdRange")
+public class DeleteAuditLogsJob extends SyncJobServiceBase {
+
+    private static final String TAG = DeleteAuditLogsJob.class.getSimpleName();
+
+    @Inject
+    AuditManagerService auditManagerService;
+
+    
+
+    public DeleteAuditLogsJob() {
+        configureBuilder();
+    }
+
+    @Override
+    public void onCreate() {
+        super.onCreate();
+        AndroidInjection.inject(this);
+    }
+
+    @Override
+    public boolean triggerJob(int jobId) {
+        Log.d(TAG, TAG + " Started");
+        try {
+            // Do not modify AUDIT_EXPORTED_TILL here; rely on existing configured value
+            boolean ok = auditManagerService.deleteAuditLogs();
+            long nowMs = System.currentTimeMillis();
+            long timeStampInSeconds = TimeUnit.MILLISECONDS.toSeconds(nowMs);
+            logJobTransaction(jobId, timeStampInSeconds);
+            return ok;
+        } catch (Exception e) {
+            Log.e(TAG, TAG + " failed", e);
+        }
+        return false;
+    }
+}
+
+
diff --git a/android/clientmanager/src/main/java/io/mosip/registration/clientmanager/repository/GlobalParamRepository.java b/android/clientmanager/src/main/java/io/mosip/registration/clientmanager/repository/GlobalParamRepository.java
index 40e617c11..12c4d5885 100644
--- a/android/clientmanager/src/main/java/io/mosip/registration/clientmanager/repository/GlobalParamRepository.java
+++ b/android/clientmanager/src/main/java/io/mosip/registration/clientmanager/repository/GlobalParamRepository.java
@@ -15,6 +15,7 @@
 import javax.inject.Inject;
 
 import java.util.Arrays;
+import java.util.List;
 import java.util.stream.Collectors;
 
 public class GlobalParamRepository {
diff --git a/android/clientmanager/src/main/java/io/mosip/registration/clientmanager/repository/SyncJobDefRepository.java b/android/clientmanager/src/main/java/io/mosip/registration/clientmanager/repository/SyncJobDefRepository.java
index 24fc52499..ce561fa2b 100644
--- a/android/clientmanager/src/main/java/io/mosip/registration/clientmanager/repository/SyncJobDefRepository.java
+++ b/android/clientmanager/src/main/java/io/mosip/registration/clientmanager/repository/SyncJobDefRepository.java
@@ -1,5 +1,7 @@
 package io.mosip.registration.clientmanager.repository;
 
+import android.util.Log;
+
 import java.util.List;
 
 import javax.inject.Inject;
@@ -29,4 +31,9 @@ public void saveSyncJobDef(SyncJobDef syncJobDef) {
     public List getAllSyncJobDefList() {
         return this.syncJobDefDao.findAll();
     }
+
+    public List getActiveSyncJobs() {
+        List activeJobs = this.syncJobDefDao.findAllByActiveStatus(true);
+        return activeJobs;
+    }
 }
diff --git a/android/clientmanager/src/main/java/io/mosip/registration/clientmanager/service/AuditManagerServiceImpl.java b/android/clientmanager/src/main/java/io/mosip/registration/clientmanager/service/AuditManagerServiceImpl.java
index dd7e77912..2366975d1 100644
--- a/android/clientmanager/src/main/java/io/mosip/registration/clientmanager/service/AuditManagerServiceImpl.java
+++ b/android/clientmanager/src/main/java/io/mosip/registration/clientmanager/service/AuditManagerServiceImpl.java
@@ -93,23 +93,16 @@ public void audit(AuditEvent auditEventEnum, String appModuleId, String appModul
 
     @Override
     public boolean deleteAuditLogs() {
-        Log.i(TAG, "Deletion of Audit Logs Started");
 
         String tillDate = globalParamRepository.getGlobalParamValue(RegistrationConstants.AUDIT_EXPORTED_TILL);
 
-        if (tillDate != null && !tillDate.isEmpty()) {
-            try {
-                /* Delete Audits before given Time */
-                long tillDateLong = Long.parseLong(tillDate);
-                auditRepository.deleteAllAuditsTillDate(tillDateLong);
-                Log.i(TAG, "deleteAuditLogs: Deletion of Audit Logs Completed for datetime before : {}" + tillDateLong);
-                return true;
-            } catch (RuntimeException runtimeException) {
-                Log.e(TAG, "deleteAuditLogs: Deletion of Audit Logs failed", runtimeException);
-                return false;
-            }
-        } else {
-            Log.e(TAG, "deleteAuditLogs: Deletion of Audit Logs failed, tillDate missing");
+        try {
+            long tillDateLong = (tillDate != null) ? Long.parseLong(tillDate) : System.currentTimeMillis();
+            auditRepository.deleteAllAuditsTillDate(tillDateLong);
+            globalParamRepository.saveGlobalParam(RegistrationConstants.AUDIT_EXPORTED_TILL, null);
+            return true;
+        } catch (RuntimeException runtimeException) {
+            Log.e(TAG, "Error in deleting audit logs", runtimeException);
             return false;
         }
     }
diff --git a/android/clientmanager/src/main/java/io/mosip/registration/clientmanager/service/JobManagerServiceImpl.java b/android/clientmanager/src/main/java/io/mosip/registration/clientmanager/service/JobManagerServiceImpl.java
index 630ef282b..3c90c3182 100644
--- a/android/clientmanager/src/main/java/io/mosip/registration/clientmanager/service/JobManagerServiceImpl.java
+++ b/android/clientmanager/src/main/java/io/mosip/registration/clientmanager/service/JobManagerServiceImpl.java
@@ -11,6 +11,7 @@
 import org.apache.commons.lang3.NotImplementedException;
 
 import java.text.DateFormat;
+import java.time.Instant;
 import java.util.Date;
 import java.util.List;
 import java.util.concurrent.TimeUnit;
@@ -18,10 +19,12 @@
 import io.mosip.registration.clientmanager.R;
 import io.mosip.registration.clientmanager.entity.SyncJobDef;
 import io.mosip.registration.clientmanager.jobs.ConfigDataSyncJob;
+import io.mosip.registration.clientmanager.jobs.DeleteAuditLogsJob;
 import io.mosip.registration.clientmanager.jobs.PacketStatusSyncJob;
 import io.mosip.registration.clientmanager.repository.SyncJobDefRepository;
 import io.mosip.registration.clientmanager.spi.JobManagerService;
 import io.mosip.registration.clientmanager.spi.JobTransactionService;
+import io.mosip.registration.clientmanager.util.CronExpressionParser;
 import io.mosip.registration.clientmanager.util.DateUtil;
 
 /**
@@ -32,7 +35,7 @@
 public class JobManagerServiceImpl implements JobManagerService {
 
     private static final String TAG = JobManagerServiceImpl.class.getSimpleName();
-    private static final int JOB_PERIODIC_SECONDS = 15 * 60;
+    private static final int JOB_PERIODIC_SECONDS = (15 * 60) * 1000;
     private static final int NUM_LENGTH_LIMIT = 5;
 
     Context context;
@@ -96,22 +99,13 @@ public int scheduleJob(int jobId, String apiName, String syncFreq) {
 
         ComponentName componentName = new ComponentName(context, clientJobService);
         JobInfo info;
-        if (syncFreq == null || syncFreq.trim().isEmpty()) {
-            //To schedule only once
-            info = new JobInfo.Builder(jobId, componentName)
-                    .setRequiresCharging(false)
-                    .setPersisted(false)
-                    .build();
-
-        } else {
-            //To schedule periodically
-            //TODO set cron wise
-            info = new JobInfo.Builder(jobId, componentName)
-                    .setRequiresCharging(false)
-                    .setPersisted(true)
-                    .setPeriodic(JOB_PERIODIC_SECONDS * 1000)
-                    .build();
-        }
+        //To schedule periodically
+        long periodMillis = JOB_PERIODIC_SECONDS * 1000L;
+        info = new JobInfo.Builder(jobId, componentName)
+                .setRequiresCharging(false)
+                .setPersisted(true)
+                .setPeriodic(periodMillis)
+                .build();
         return jobScheduler.schedule(info);
     }
 
@@ -167,15 +161,27 @@ public String getLastSyncTime(int jobId) {
 
     @Override
     public String getNextSyncTime(int jobId) {
-        //TODO implementation using CRON job
-        long lastSyncTimeSeconds = jobTransactionService.getLastSyncTime(jobId);
-        String nextSync = context.getString(R.string.NA);
+        SyncJobDef jobDef = getJobDefByJobId(jobId);
+        if (jobDef == null) {
+            return "NA";
+        }
+
+        String cronExpression = jobDef.getSyncFreq();
+        // Try cron-based calculation first
+        if (CronExpressionParser.isValidCronExpression(cronExpression)) {
+            Instant nextExecution = CronExpressionParser.getNextExecutionTime(cronExpression);
+            if (nextExecution != null) {
+                return dateUtil.getDateTime(nextExecution.toEpochMilli());
+            }
+        }
 
+        // Fallback: use last sync time + interval
+        long lastSyncTimeSeconds = jobTransactionService.getLastSyncTime(jobId);
         if (lastSyncTimeSeconds > 0) {
-            long nextSyncTimeSeconds = lastSyncTimeSeconds + JOB_PERIODIC_SECONDS;
-            nextSync = dateUtil.getDateTime(nextSyncTimeSeconds);
+            return dateUtil.getDateTime(lastSyncTimeSeconds + JOB_PERIODIC_SECONDS);
         }
-        return nextSync;
+
+        return "NA";
     }
 
     @Override
@@ -196,8 +202,20 @@ private Class getJobServiceImplClass(String jobAPIName) {
                 return PacketStatusSyncJob.class;
             case "synchConfigDataJob":
                 return ConfigDataSyncJob.class;
+            case "deleteAuditLogsJob":
+                return DeleteAuditLogsJob.class;
             default:
                 return null;
         }
     }
+
+    private SyncJobDef getJobDefByJobId(int jobId) {
+        List allJobs = syncJobDefRepository.getAllSyncJobDefList();
+        for (SyncJobDef jobDef : allJobs) {
+            if (jobId == generateJobServiceId(jobDef.getId())) {
+                return jobDef;
+            }
+        }
+        return null;
+    }
 }
diff --git a/android/clientmanager/src/main/java/io/mosip/registration/clientmanager/service/MasterDataServiceImpl.java b/android/clientmanager/src/main/java/io/mosip/registration/clientmanager/service/MasterDataServiceImpl.java
index b2acb77da..73de638fe 100644
--- a/android/clientmanager/src/main/java/io/mosip/registration/clientmanager/service/MasterDataServiceImpl.java
+++ b/android/clientmanager/src/main/java/io/mosip/registration/clientmanager/service/MasterDataServiceImpl.java
@@ -30,6 +30,7 @@
 import io.mosip.registration.clientmanager.entity.SyncJobDef;
 import io.mosip.registration.clientmanager.repository.*;
 import io.mosip.registration.clientmanager.spi.JobManagerService;
+import io.mosip.registration.clientmanager.spi.JobTransactionService;
 import io.mosip.registration.clientmanager.spi.MasterDataService;
 import io.mosip.registration.clientmanager.spi.SyncRestService;
 import io.mosip.registration.clientmanager.util.SyncRestUtil;
@@ -64,6 +65,7 @@
 import java.time.LocalDateTime;
 import java.time.ZoneOffset;
 import java.util.*;
+import java.util.concurrent.TimeUnit;
 import java.util.concurrent.atomic.AtomicReference;
 import java.util.stream.Collectors;
 
@@ -112,6 +114,7 @@ public class MasterDataServiceImpl implements MasterDataService {
     private String regCenterId;
     private String result = "";
     SharedPreferences sharedPreferences;
+    private JobTransactionService jobTransactionService;
 
     @Inject
     public MasterDataServiceImpl(Context context, ObjectMapper objectMapper, SyncRestService syncRestService,
@@ -133,6 +136,7 @@ public MasterDataServiceImpl(Context context, ObjectMapper objectMapper, SyncRes
                                  LanguageRepository languageRepository,
                                  JobManagerService jobManagerService,
                                  FileSignatureDao fileSignatureDao,
+                                 JobTransactionService jobTransactionService,
                                  PermittedLocalConfigRepository permittedLocalConfigRepository,
                                  LocalConfigDAO localConfigDAO) {
         this.context = context;
@@ -156,6 +160,7 @@ public MasterDataServiceImpl(Context context, ObjectMapper objectMapper, SyncRes
         this.languageRepository = languageRepository;
         this.jobManagerService = jobManagerService;
         this.fileSignatureDao = fileSignatureDao;
+        this.jobTransactionService = jobTransactionService;
         this.permittedLocalConfigRepository = permittedLocalConfigRepository;
         this.localConfigDAO = localConfigDAO;
         sharedPreferences = this.context.getSharedPreferences(
@@ -186,7 +191,7 @@ public CenterMachineDto getRegistrationCenterMachineDetails() {
     }
 
     @Override
-    public void syncCertificate(Runnable onFinish, String applicationId, String referenceId, String setApplicationId, String setReferenceId, boolean isManualSync) {
+    public void syncCertificate(Runnable onFinish, String applicationId, String referenceId, String setApplicationId, String setReferenceId, boolean isManualSync, String jobId) {
         CenterMachineDto centerMachineDto = getRegistrationCenterMachineDetails();
         if (centerMachineDto == null) {
             result = POLICY_KEY_SYNC_FAILED;
@@ -208,6 +213,11 @@ public void onResponse(Call> call, Response
                             certificateRequestDto.setReferenceId(setReferenceId);
                             certificateRequestDto.setCertificateData(response.body().getResponse().getCertificate());
                             certificateManagerService.uploadOtherDomainCertificate(certificateRequestDto);
+                            try {
+                                logLastSyncCompletionDateTime(jobId);
+                            } catch (Exception e) {
+                                Log.e(TAG, "Failed to store policy sync last sync time", e);
+                            }
                             if (isManualSync) {
                                 Toast.makeText(context, "Policy key Sync Completed", Toast.LENGTH_LONG).show();
                             }
@@ -249,9 +259,8 @@ public void onFailure(Call> call, Throwable
     }
 
     @Override
-    public void syncMasterData(Runnable onFinish, int retryNo, boolean isManualSync) {
+    public void syncMasterData(Runnable onFinish, int retryNo, boolean isManualSync, String jobId) {
         CenterMachineDto centerMachineDto = getRegistrationCenterMachineDetails();
-
         Map queryParams = new HashMap<>();
 
         try {
@@ -292,7 +301,7 @@ public void onResponse(Call> call, Response> call, Response> call, Throwable t)
     }
 
     @Override
-    public void syncGlobalParamsData(Runnable onFinish, boolean isManualSync) throws Exception {
+    public void syncGlobalParamsData(Runnable onFinish, boolean isManualSync, String jobId) throws Exception {
         Log.i(TAG, "config data sync is started");
         String serverVersion = getServerVersionFromConfigs();
 
@@ -353,6 +367,11 @@ public void onResponse(Call>> call, Response
                         if (isManualSync) {
                             Toast.makeText(context, context.getString(R.string.global_config_sync_completed), Toast.LENGTH_LONG).show();
                         }
+                        try {
+                            logLastSyncCompletionDateTime(jobId);
+                        } catch (Exception e) {
+                            Log.e(TAG, "Failed to store master data sync last sync time", e);
+                        }
                         onFinish.run();
                     } else {
                         result = GLOBAL_PARAMS_SYNC_FAILED;
@@ -384,7 +403,7 @@ public void onFailure(Call>> call, Throwable
     @SuppressWarnings("unchecked")
     private void saveGlobalParams(Map responseMap) {
         try {
-            
+
             Map globalParamMap = new HashMap<>();
 
             if (responseMap.get("configDetail") != null) {
@@ -516,7 +535,7 @@ private void saveProcessSpec(IdSchemaResponse idSchemaResponse, String jsonStrin
 
 
     @Override
-    public void syncUserDetails(Runnable onFinish, boolean isManualSync) throws Exception {
+    public void syncUserDetails(Runnable onFinish, boolean isManualSync, String jobId) throws Exception {
         String serverVersion = getServerVersionFromConfigs();
         if (serverVersion.startsWith(SERVER_VERSION_1_1_5)) {
             result = "";
@@ -524,6 +543,11 @@ public void syncUserDetails(Runnable onFinish, boolean isManualSync) throws Exce
                 Toast.makeText(context, "User Sync Completed", Toast.LENGTH_LONG).show();
             }
             Log.i(TAG, "Found 115 version, skipping userdetails sync");
+            try {
+                logLastSyncCompletionDateTime(jobId);
+            } catch (Exception e) {
+                Log.e(TAG, "Failed to store user details sync last sync time", e);
+            }
             onFinish.run();
             return;
         }
@@ -541,6 +565,12 @@ public void onResponse(Call> call, Response<
                         if (isManualSync) {
                             Toast.makeText(context, "User Sync Completed", Toast.LENGTH_LONG).show();
                         }
+                        try {
+                            logLastSyncCompletionDateTime(jobId);
+                        } catch (Exception e) {
+                            Log.e(TAG, "Failed to store user details sync last sync time", e);
+                        }
+
                         onFinish.run();
                     } else {
                         result = USER_DETAILS_SYNC_FAILED;
@@ -578,7 +608,7 @@ private void saveUserDetails(String encData) {
     }
 
     @Override
-    public void syncCACertificates(Runnable onFinish, boolean isManualSync) {
+    public void syncCACertificates(Runnable onFinish, boolean isManualSync, String jobId) {
         Call> call = syncRestService.getCACertificates(null,
                 BuildConfig.CLIENT_VERSION);
         call.enqueue(new Callback>() {
@@ -594,6 +624,11 @@ public void onResponse(Call> call, Res
                             if (isManualSync) {
                                 Toast.makeText(context, "CA Certificate Sync Completed", Toast.LENGTH_LONG).show();
                             }
+                            try {
+                                logLastSyncCompletionDateTime(jobId);
+                            } catch (Exception e) {
+                                Log.e(TAG, "Failed to store CA certificates sync last sync time", e);
+                            }
                             onFinish.run();
                             return;
                         } catch (Throwable t) {
@@ -712,6 +747,12 @@ private String getCurrentTime() {
         return Instant.now().toString();
     }
 
+    @Override
+    public void logLastSyncCompletionDateTime(String jobIdString) {
+        int jobId = jobManagerService.generateJobServiceId(jobIdString);
+        jobTransactionService.LogJobTransaction(jobId, Instant.now().toEpochMilli());
+    }
+
     private void downloadUrlData(Path path, JSONObject jsonObject, boolean isManualSync) {
         Log.i(TAG, "Started downloading mvel script: " + path.toString());
         try {
diff --git a/android/clientmanager/src/main/java/io/mosip/registration/clientmanager/service/PreRegistrationDataSyncDaoImpl.java b/android/clientmanager/src/main/java/io/mosip/registration/clientmanager/service/PreRegistrationDataSyncDaoImpl.java
index 469bb4780..b6067f503 100644
--- a/android/clientmanager/src/main/java/io/mosip/registration/clientmanager/service/PreRegistrationDataSyncDaoImpl.java
+++ b/android/clientmanager/src/main/java/io/mosip/registration/clientmanager/service/PreRegistrationDataSyncDaoImpl.java
@@ -2,6 +2,8 @@
 
 import android.util.Log;
 
+import java.sql.Timestamp;
+import java.util.Date;
 import java.util.List;
 
 import javax.inject.Inject;
@@ -46,12 +48,12 @@ public void save(PreRegistrationList preRegistration) {
         this.preRegistrationRepositoryDao.insert(preRegistration);
     }
 
-    public List fetchRecordsToBeDeleted(String startDate) {
+    public List fetchRecordsToBeDeleted(Date startDate) {
 
         Log.i(TAG, "REGISTRATION - PRE_REGISTRATION_DATA_SYNC_RECORD_FETCH - PRE_REGISTRATION_DATA_SYNC_DAO_IMPL" +
                 "Fetch Records that needs to be deleted");
 
-        return this.preRegistrationRepositoryDao.findByAppointmentDateBeforeAndIsDeleted(startDate, false);
+        return this.preRegistrationRepositoryDao.findByAppointmentDateBeforeAndIsDeleted(startDate.toString(), false);
     }
 
     public long update(String id, String updatedBy, String updatedTime) {
@@ -70,4 +72,28 @@ public String getLastPreRegPacketDownloadedTime() {
                 .findTopByOrderByLastUpdatedPreRegTimeStampDesc();
         return preRegistrationList != null ? preRegistrationList.getLastUpdatedPreRegTimeStamp() : null;
     }
-}
+
+    @Override
+    public void deleteAll(List preRegistrationList) {
+        try {
+            this.preRegistrationRepositoryDao.deleteAll(preRegistrationList);
+        } catch (Exception e) {
+            Log.e(TAG, "Error deleting pre-registration records: " + e.getMessage());
+            throw new RuntimeException("Failed to delete pre-registration records", e);
+        }
+    }
+
+    @Override
+    public Timestamp getLastPreRegPacketDownloadedTimeAsTimestamp() {
+        PreRegistrationList preRegistrationList = this.preRegistrationRepositoryDao
+                .findTopByOrderByLastUpdatedPreRegTimeStampDesc();
+        if (preRegistrationList != null && preRegistrationList.getLastUpdatedPreRegTimeStamp() != null) {
+            try {
+                return Timestamp.valueOf(preRegistrationList.getLastUpdatedPreRegTimeStamp());
+            } catch (Exception e) {
+                Log.e(TAG, "Error parsing timestamp: " + e.getMessage());
+            }
+        }
+        return null;
+    }
+}
\ No newline at end of file
diff --git a/android/clientmanager/src/main/java/io/mosip/registration/clientmanager/service/PreRegistrationDataSyncServiceImpl.java b/android/clientmanager/src/main/java/io/mosip/registration/clientmanager/service/PreRegistrationDataSyncServiceImpl.java
index cec0a520b..254aff425 100644
--- a/android/clientmanager/src/main/java/io/mosip/registration/clientmanager/service/PreRegistrationDataSyncServiceImpl.java
+++ b/android/clientmanager/src/main/java/io/mosip/registration/clientmanager/service/PreRegistrationDataSyncServiceImpl.java
@@ -1,5 +1,6 @@
 package io.mosip.registration.clientmanager.service;
 
+import static android.content.ContentValues.TAG;
 import static io.mosip.registration.clientmanager.config.SessionManager.USER_NAME;
 
 import android.content.Context;
@@ -12,11 +13,14 @@
 import io.mosip.registration.clientmanager.constant.RegistrationConstants;
 import io.mosip.registration.clientmanager.dao.PreRegistrationDataSyncDao;
 import io.mosip.registration.clientmanager.dto.CenterMachineDto;
+import io.mosip.registration.clientmanager.dto.ErrorResponseDto;
 import io.mosip.registration.clientmanager.dto.PreRegArchiveDto;
 import io.mosip.registration.clientmanager.dto.PreRegistrationDataSyncDto;
 import io.mosip.registration.clientmanager.dto.PreRegistrationDataSyncRequestDto;
 import io.mosip.registration.clientmanager.dto.PreRegistrationDto;
 import io.mosip.registration.clientmanager.dto.PreRegistrationIdsDto;
+import io.mosip.registration.clientmanager.dto.ResponseDto;
+import io.mosip.registration.clientmanager.dto.SuccessResponseDto;
 import io.mosip.registration.clientmanager.dto.http.ResponseWrapper;
 import io.mosip.registration.clientmanager.dto.http.ServiceError;
 import io.mosip.registration.clientmanager.entity.PreRegistrationList;
@@ -37,6 +41,8 @@
 import androidx.annotation.NonNull;
 
 import org.apache.commons.io.FileUtils;
+
+import java.io.File;
 import java.time.Instant;
 import java.util.Date;
 import java.sql.Timestamp;
@@ -45,7 +51,10 @@
 import java.time.ZoneOffset;
 import java.time.format.DateTimeFormatter;
 import java.util.Calendar;
+import java.util.LinkedList;
+import java.util.List;
 import java.util.Map;
+import java.util.Objects;
 import java.util.TimeZone;
 import java.util.UUID;
 import java.util.WeakHashMap;
@@ -88,13 +97,18 @@ public PreRegistrationDataSyncServiceImpl(Context context,PreRegistrationDataSyn
     }
 
     @Override
-    public void fetchPreRegistrationIds(Runnable onFinish) {
+    public void fetchPreRegistrationIds(Runnable onFinish, String jobId) {
         Log.i(TAG,"Fetching Pre-Registration Id's started {}");
 
         CenterMachineDto centerMachineDto = this.masterDataService.getRegistrationCenterMachineDetails();
         if (centerMachineDto == null) {
             result = APPLICATION_ID_SYNC_FAILED;
             onFinish.run();
+            try {
+                masterDataService.logLastSyncCompletionDateTime(jobId);
+            } catch (Exception e) {
+                Log.e(TAG, "Failed to log pre reg data sync completion", e);
+            }
             return;
         }
 
@@ -135,9 +149,9 @@ public void onResponse(Call> call, Respon
                                 getPreRegistrationPackets(preRegIds);
                                 Log.i(TAG,"Fetching Application data ended successfully");
                             }
-                           Toast.makeText(context, "Application Id Sync Completed", Toast.LENGTH_LONG).show();
-                           result = "";
-                           onFinish.run();
+                            Toast.makeText(context, "Application Id Sync Completed", Toast.LENGTH_LONG).show();
+                            result = "";
+                            onFinish.run();
                         } catch (Exception e) {
                             result = APPLICATION_ID_SYNC_FAILED;
                             Log.e(TAG, APPLICATION_ID_SYNC_FAILED, e);
@@ -214,7 +228,7 @@ public Map getPreRegistration(@NonNull String preRegistrationId,
 
     private PreRegistrationList fetchPreRegistration(String preRegistrationId, String lastUpdatedTimeStamp) throws Exception {
         Log.i(TAG,"Fetching Pre-Registration started for {}"+ preRegistrationId);
-       // PreRegistrationList preRegistration;
+        // PreRegistrationList preRegistration;
 
         /* Check in Database whether required record already exists or not */
         preRegistration = this.preRegistrationDao.get(preRegistrationId);
@@ -263,7 +277,7 @@ private Map setPacketToResponse(byte[] decryptedPacket, String p
     }
 
     private PreRegistrationList downloadAndSavePacket(@NonNull String preRegistrationId,
-                                                     String lastUpdatedTimeStamp) throws ClientCheckedException, ExecutionException, InterruptedException {
+                                                      String lastUpdatedTimeStamp) throws ClientCheckedException, ExecutionException, InterruptedException {
 
         CenterMachineDto centerMachineDto = this.masterDataService.getRegistrationCenterMachineDetails();
         if (centerMachineDto == null) {
@@ -307,7 +321,7 @@ private PreRegistrationList downloadAndSavePacket(@NonNull String preRegistratio
     }
 
     private PreRegistrationList preparePreRegistration(CenterMachineDto centerMachineDto,
-            PreRegistrationDto preRegistrationDto, String appointmentDate,String lastUpdatedTimeStamp) {
+                                                       PreRegistrationDto preRegistrationDto, String appointmentDate,String lastUpdatedTimeStamp) {
 
         LocalDateTime currentUTCTime = LocalDateTime.now(ZoneOffset.UTC);
         DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
@@ -318,7 +332,7 @@ private PreRegistrationList preparePreRegistration(CenterMachineDto centerMachin
         preRegistrationList.setId(id);
         preRegistrationList.setPreRegId(preRegistrationDto.getPreRegId());
         if(appointmentDate!=null){
-           preRegistrationList.setAppointmentDate(appointmentDate);
+            preRegistrationList.setAppointmentDate(appointmentDate);
         }
         preRegistrationList.setLastUpdatedPreRegTimeStamp(lastUpdatedTimeStamp == null ?
                 String.valueOf(Timestamp.valueOf(formattedCurrentUTCTime)) : lastUpdatedTimeStamp);
@@ -364,4 +378,129 @@ private String getFromDate(Timestamp reqTime) {
 
         return formatDate(cal);
     }
+
+    /**
+     Fetch and delete records based on configured days
+     */
+    public synchronized ResponseDto fetchAndDeleteRecords() {
+
+        ResponseDto responseDTO = new ResponseDto();
+        if (getGlobalConfigValueOf(RegistrationConstants.PRE_REG_DELETION_CONFIGURED_DAYS) != null) {
+
+            Calendar startCal = Calendar.getInstance();
+            startCal.add(Calendar.DATE, -(Integer
+                    .parseInt(Objects.requireNonNull(getGlobalConfigValueOf(RegistrationConstants.PRE_REG_DELETION_CONFIGURED_DAYS)))));
+
+            Date startDate = Date.from(startCal.toInstant());
+
+            // fetch the records that needs to be deleted
+            List preRegList = preRegistrationDao.fetchRecordsToBeDeleted(startDate);
+
+            deletePreRegRecords(responseDTO, preRegList);
+        }
+
+        return responseDTO;
+    }
+
+    /**
+     * Delete pre-registration records
+     */
+    public void deletePreRegRecords(ResponseDto responseDTO, final List preRegList) {
+
+        if (preRegList != null && !preRegList.isEmpty()) {
+
+            List preRegistrationsToBeDeletedList = new LinkedList<>();
+
+            for (PreRegistrationList preRegRecord : preRegList) {
+
+                if (null != preRegRecord) {
+                    try {
+                        File preRegPacket = FileUtils.getFile(preRegRecord.getPacketPath());
+                        if (preRegPacket.exists() && preRegPacket.delete()) {
+                            preRegistrationsToBeDeletedList.add(preRegRecord);
+                        }
+                    } catch (Exception e) {
+                        Log.e(TAG, "Error deleting packet file: " + e.getMessage());
+                    }
+                }
+            }
+
+            if (!preRegistrationsToBeDeletedList.isEmpty()) {
+                deleteRecords(responseDTO, preRegistrationsToBeDeletedList);
+            } else {
+                setErrorResponse(responseDTO, RegistrationConstants.PRE_REG_DELETE_FAILURE, null);
+            }
+        } else {
+            setSuccessResponse(responseDTO, RegistrationConstants.PRE_REG_DELETE_SUCCESS, null);
+        }
+    }
+
+    /**
+     * Delete records.
+     */
+    private ResponseDto deleteRecords(ResponseDto responseDTO, List preRegList) {
+
+        try {
+            preRegistrationDao.deleteAll(preRegList);
+
+            setSuccessResponse(responseDTO, RegistrationConstants.PRE_REG_DELETE_SUCCESS, null);
+        } catch (RuntimeException runtimeException) {
+            Log.i(TAG, "REGISTRATION - PRE_REGISTRATION_DELETE - PRE_REGISTRATION_DATA_SYNC_SERVICE_IMPL - " + runtimeException.getMessage());
+            setErrorResponse(responseDTO, RegistrationConstants.PRE_REG_DELETE_FAILURE, null);
+        }
+
+        return responseDTO;
+    }
+
+    /**
+     * Get pre-registration record for deletion
+     */
+    public PreRegistrationList getPreRegistrationRecordForDeletion(String preRegistrationId) {
+        if (preRegistrationId == null || preRegistrationId.isEmpty()) {
+            Log.e(TAG, "REGISTRATION - PRE_REGISTRATION_DATA_SYNC - PRE_REGISTRATION_DATA_SYNC_SERVICE_IMPL - The PreRegistrationId is empty");
+        }
+        return preRegistrationDao.get(preRegistrationId);
+    }
+
+    /**
+     * Get last pre-reg packet downloaded time
+     */
+    @Override
+    public Timestamp getLastPreRegPacketDownloadedTime() {
+        return preRegistrationDao.getLastPreRegPacketDownloadedTimeAsTimestamp();
+    }
+
+    /**
+     * Get global config value
+     */
+    private String getGlobalConfigValueOf(String key) {
+        try {
+            return globalParamRepository.getCachedStringGlobalParam(key);
+        } catch (Exception e) {
+            Log.e(TAG, "Error getting global config value for key: " + key, e);
+            return null;
+        }
+    }
+
+    /**
+     * Set success response
+     */
+    private void setSuccessResponse(ResponseDto responseDTO, String code, String message) {
+        SuccessResponseDto successResponseDto = new SuccessResponseDto();
+        successResponseDto.setCode(code);
+        successResponseDto.setMessage(message != null ? message : "Operation completed successfully");
+        responseDTO.setSuccessResponseDTO(successResponseDto);
+    }
+
+    /**
+     * Set error response
+     */
+    private void setErrorResponse(ResponseDto responseDTO, String code, String message) {
+        ErrorResponseDto errorResponseDto = new ErrorResponseDto();
+        errorResponseDto.setCode(code);
+        errorResponseDto.setMessage(message != null ? message : "Operation failed");
+        List errorList = new LinkedList<>();
+        errorList.add(errorResponseDto);
+        responseDTO.setErrorResponseDTOs(errorList);
+    }
 }
\ No newline at end of file
diff --git a/android/clientmanager/src/main/java/io/mosip/registration/clientmanager/service/RegistrationServiceImpl.java b/android/clientmanager/src/main/java/io/mosip/registration/clientmanager/service/RegistrationServiceImpl.java
index 0b81f7367..fa63c2e3f 100644
--- a/android/clientmanager/src/main/java/io/mosip/registration/clientmanager/service/RegistrationServiceImpl.java
+++ b/android/clientmanager/src/main/java/io/mosip/registration/clientmanager/service/RegistrationServiceImpl.java
@@ -13,7 +13,6 @@
 import android.content.SharedPreferences;
 import android.util.Log;
 
-import com.fasterxml.jackson.databind.ObjectMapper;
 import com.tom_roush.pdfbox.pdmodel.PDDocument;
 import com.tom_roush.pdfbox.pdmodel.PDPage;
 import com.tom_roush.pdfbox.pdmodel.PDPageContentStream;
@@ -37,7 +36,6 @@
 import java.util.LinkedList;
 import java.util.List;
 import java.util.Map;
-import java.util.Objects;
 import java.util.Optional;
 import java.util.UUID;
 
@@ -51,6 +49,7 @@
 import io.mosip.registration.clientmanager.constant.Modality;
 import io.mosip.registration.clientmanager.constant.RegistrationConstants;
 import io.mosip.registration.clientmanager.dto.CenterMachineDto;
+import io.mosip.registration.clientmanager.dto.ResponseDto;
 import io.mosip.registration.clientmanager.dto.registration.BiometricsDto;
 import io.mosip.registration.clientmanager.dto.registration.GeoLocationDto;
 import io.mosip.registration.clientmanager.dto.registration.RegistrationDto;
@@ -68,6 +67,9 @@
 import io.mosip.registration.clientmanager.spi.LocationValidationService;
 import io.mosip.registration.clientmanager.spi.MasterDataService;
 import io.mosip.registration.clientmanager.spi.RegistrationService;
+import io.mosip.registration.clientmanager.entity.PreRegistrationList;
+import io.mosip.registration.clientmanager.spi.PreRegistrationDataSyncService;
+import javax.inject.Provider;
 import io.mosip.registration.keymanager.repository.KeyStoreRepository;
 import io.mosip.registration.keymanager.spi.ClientCryptoManagerService;
 import io.mosip.registration.keymanager.util.CryptoUtil;
@@ -83,7 +85,6 @@
 import io.mosip.registration.packetmanager.dto.PacketWriter.BiometricRecord;
 import io.mosip.registration.packetmanager.dto.PacketWriter.BiometricType;
 import io.mosip.registration.packetmanager.dto.PacketWriter.Document;
-import io.mosip.registration.packetmanager.dto.PacketWriter.PacketInfo;
 import io.mosip.registration.packetmanager.dto.SimpleType;
 import io.mosip.registration.packetmanager.spi.PacketWriterService;
 import io.mosip.registration.packetmanager.util.DateUtils;
@@ -110,6 +111,7 @@ public class RegistrationServiceImpl implements RegistrationService {
     private AuditManagerService auditManagerService;
     private RegistrationCenterRepository registrationCenterRepository;
     private LocationValidationService locationValidationService;
+    private Provider preRegistrationDataSyncServiceProvider;
     public static final String BOOLEAN_FALSE = "false";
 
     private Biometrics095Service biometricService;
@@ -125,6 +127,7 @@ public RegistrationServiceImpl(Context context, PacketWriterService packetWriter
                                    AuditManagerService auditManagerService,
                                    RegistrationCenterRepository registrationCenterRepository,
                                    LocationValidationService locationValidationService,
+                                   Provider preRegistrationDataSyncServiceProvider,
                                    Biometrics095Service biometricService) {
         this.context = context;
         this.registrationDto = null;
@@ -138,6 +141,7 @@ public RegistrationServiceImpl(Context context, PacketWriterService packetWriter
         this.auditManagerService = auditManagerService;
         this.registrationCenterRepository = registrationCenterRepository;
         this.locationValidationService = locationValidationService;
+        this.preRegistrationDataSyncServiceProvider = preRegistrationDataSyncServiceProvider;
         this.biometricService = biometricService;
     }
 
@@ -218,30 +222,30 @@ public void submitRegistrationDto(String makerName) throws Exception {
         List selectedHandles = this.globalParamRepository.getSelectedHandles();
         if(selectedHandles != null) {
             if (this.registrationDto.getFlowType().equals("NEW") ||
-                 this.registrationDto.getFlowType().equals("Update")) {
+                    this.registrationDto.getFlowType().equals("Update")) {
                 this.registrationDto.getDemographics().put("selectedHandles", selectedHandles);
             }
         }
 
 //        try {
-            String individualBiometricsFieldId = this.globalParamRepository.getCachedStringGlobalParam(RegistrationConstants.INDIVIDUAL_BIOMETRICS_ID);
-            String serverVersion = this.globalParamRepository.getCachedStringGlobalParam(RegistrationConstants.SERVER_VERSION);
-
-            for (String fieldName : this.registrationDto.getDemographics().keySet()) {
-                switch (this.registrationDto.getFlowType()) {
-                    case "Update":
-                        if (this.registrationDto.getDemographics().get(fieldName) != null && (this.registrationDto.getUpdatableFields().contains(fieldName) ||
-                                fieldName.equals("UIN")))
-                            packetWriterService.setField(this.registrationDto.getRId(), fieldName, this.registrationDto.getDemographics().get(fieldName));
-                        break;
-                    case "Correction":
-                    case "Lost":
-                    case "NEW":
-                        if (this.registrationDto.getDemographics().get(fieldName) != null)
-                            packetWriterService.setField(this.registrationDto.getRId(), fieldName, this.registrationDto.getDemographics().get(fieldName));
-                        break;
-                }
+        String individualBiometricsFieldId = this.globalParamRepository.getCachedStringGlobalParam(RegistrationConstants.INDIVIDUAL_BIOMETRICS_ID);
+        String serverVersion = this.globalParamRepository.getCachedStringGlobalParam(RegistrationConstants.SERVER_VERSION);
+
+        for (String fieldName : this.registrationDto.getDemographics().keySet()) {
+            switch (this.registrationDto.getFlowType()) {
+                case "Update":
+                    if (this.registrationDto.getDemographics().get(fieldName) != null && (this.registrationDto.getUpdatableFields().contains(fieldName) ||
+                            fieldName.equals("UIN")))
+                        packetWriterService.setField(this.registrationDto.getRId(), fieldName, this.registrationDto.getDemographics().get(fieldName));
+                    break;
+                case "Correction":
+                case "Lost":
+                case "NEW":
+                    if (this.registrationDto.getDemographics().get(fieldName) != null)
+                        packetWriterService.setField(this.registrationDto.getRId(), fieldName, this.registrationDto.getDemographics().get(fieldName));
+                    break;
             }
+        }
 
             this.registrationDto.getAllDocumentFields().forEach(entry -> {
                 Document document = new Document();
@@ -249,68 +253,83 @@ public void submitRegistrationDto(String makerName) throws Exception {
                 document.setFormat(entry.getValue().getFormat());
                 document.setRefNumber(entry.getValue().getRefNumber());
                 document.setDocument(("pdf".equalsIgnoreCase(entry.getValue().getFormat()))?combineByteArray(entry.getValue().getContent()):convertImageToPDF(entry.getValue().getContent()));
-                Log.i(TAG, entry.getKey() + " >> PDF document size :" + document.getDocument().length);
+
                 packetWriterService.setDocument(this.registrationDto.getRId(), entry.getKey(), document);
                 packetWriterService.addMetaInfo(this.registrationDto.getRId(),"documents", document);
             });
 
-            if (serverVersion!=null && serverVersion.startsWith("1.1.5")) {
-                this.registrationDto.getBestBiometrics(individualBiometricsFieldId, Modality.EXCEPTION_PHOTO).forEach( b -> {
-                    Document document = new Document();
-                    document.setType("EOP");
-                    document.setFormat("jpg");
-                    document.setValue("POE_EOP");
-                    document.setDocument(convertImageToBytes(b.getBioValue()));
-                    Log.i(TAG,"Adding Proof of Exception document with size :" + document.getDocument().length);
-                    packetWriterService.setDocument(this.registrationDto.getRId(), "proofOfException", document);
-                });
-            }
+        if (serverVersion!=null && serverVersion.startsWith("1.1.5")) {
+            this.registrationDto.getBestBiometrics(individualBiometricsFieldId, Modality.EXCEPTION_PHOTO).forEach( b -> {
+                Document document = new Document();
+                document.setType("EOP");
+                document.setFormat("jpg");
+                document.setValue("POE_EOP");
+                document.setDocument(convertImageToBytes(b.getBioValue()));
+                packetWriterService.setDocument(this.registrationDto.getRId(), "proofOfException", document);
+            });
+        }
 
-            // Process biometrics and add metadata to packet
+        // Process biometrics and add metadata to packet
             setBiometrics(this.registrationDto);
 
-            CenterMachineDto centerMachineDto = this.masterDataService.getRegistrationCenterMachineDetails();
+        CenterMachineDto centerMachineDto = this.masterDataService.getRegistrationCenterMachineDetails();
 
-            packetWriterService.addAudits(this.registrationDto.getRId(), getAudits());
-            addMetaInfoMap(centerMachineDto.getCenterId(), centerMachineDto.getMachineId(), makerName);
-            String containerPath = packetWriterService.persistPacket(this.registrationDto.getRId(),
-                    this.registrationDto.getSchemaVersion().toString(),
-                    identitySchemaRepository.getSchemaJson(context, this.registrationDto.getSchemaVersion()),
-                    SOURCE,
-                    this.registrationDto.getProcess(),
-                    true, centerMachineDto.getMachineRefId());
+        packetWriterService.addAudits(this.registrationDto.getRId(), getAudits());
+        addMetaInfoMap(centerMachineDto.getCenterId(), centerMachineDto.getMachineId(), makerName);
 
-            if (containerPath != null || !containerPath.trim().isEmpty()) {
-               String packetId = containerPath.substring(containerPath.lastIndexOf("/") + 1);
+        String containerPath = packetWriterService.persistPacket(this.registrationDto.getRId(),
+                this.registrationDto.getSchemaVersion().toString(),
+                identitySchemaRepository.getSchemaJson(context, this.registrationDto.getSchemaVersion()),
+                SOURCE,
+                this.registrationDto.getProcess(),
+                true, centerMachineDto.getMachineRefId());
+
+
+
+        if (containerPath != null || !containerPath.trim().isEmpty()) {
+            String packetId = containerPath.substring(containerPath.lastIndexOf("/") + 1);
                packetId = packetId.replace(".zip", "");
                this.registrationDto.setPacketId(packetId);
-            }
+        }
 
-            JSONObject additionalInfo = new JSONObject();
-            additionalInfo.put("langCode", this.registrationDto.getSelectedLanguages().get(0));
-            //TODO add name, phone and email in additional info
-            List fullName = new ArrayList<>();
-            String fullNameKey = getKey(this.registrationDto, RegistrationConstants.UI_SCHEMA_SUBTYPE_FULL_NAME);
-            if(fullNameKey != null) {
-                List fullNameKeys = Arrays.asList(fullNameKey.split(RegistrationConstants.COMMA));
-                for (String key : fullNameKeys) {
-                    Object fullNameObj = this.registrationDto.getDemographics().get(key);
-                    fullName.add(getAdditionalInfo(fullNameObj));
-                }
+        JSONObject additionalInfo = new JSONObject();
+        additionalInfo.put("langCode", this.registrationDto.getSelectedLanguages().get(0));
+        //TODO add name, phone and email in additional info
+        List fullName = new ArrayList<>();
+        String fullNameKey = getKey(this.registrationDto, RegistrationConstants.UI_SCHEMA_SUBTYPE_FULL_NAME);
+        if(fullNameKey != null) {
+            List fullNameKeys = Arrays.asList(fullNameKey.split(RegistrationConstants.COMMA));
+            for (String key : fullNameKeys) {
+                Object fullNameObj = this.registrationDto.getDemographics().get(key);
+                fullName.add(getAdditionalInfo(fullNameObj));
             }
+        }
+
+        Object emailObj = this.registrationDto.getDemographics().get(getKey(this.registrationDto, RegistrationConstants.UI_SCHEMA_SUBTYPE_EMAIL));
+        Object phoneObj = this.registrationDto.getDemographics().get(getKey(this.registrationDto, RegistrationConstants.UI_SCHEMA_SUBTYPE_PHONE));
 
-            Object emailObj = this.registrationDto.getDemographics().get(getKey(this.registrationDto, RegistrationConstants.UI_SCHEMA_SUBTYPE_EMAIL));
-            Object phoneObj = this.registrationDto.getDemographics().get(getKey(this.registrationDto, RegistrationConstants.UI_SCHEMA_SUBTYPE_PHONE));
+        additionalInfo.put("name", String.join(" ", fullName));
+        additionalInfo.put("email", getAdditionalInfo(emailObj));
+        additionalInfo.put("phone", getAdditionalInfo(phoneObj));
 
-            additionalInfo.put("name", String.join(" ", fullName));
-            additionalInfo.put("email", getAdditionalInfo(emailObj));
-            additionalInfo.put("phone", getAdditionalInfo(phoneObj));
+        registrationRepository.insertRegistration(this.registrationDto.getPacketId(), containerPath,
+                centerMachineDto.getCenterId(), this.registrationDto.getProcess(), additionalInfo, this.registrationDto.getAdditionalInfoRequestId(), this.registrationDto.getRId(), this.registrationDto.getApplicationId());
 
-            registrationRepository.insertRegistration(this.registrationDto.getPacketId(), containerPath,
-                    centerMachineDto.getCenterId(), this.registrationDto.getProcess(), additionalInfo, this.registrationDto.getAdditionalInfoRequestId(), this.registrationDto.getRId(), this.registrationDto.getApplicationId());
+        // Delete pre-registration record after successful packet creation
+        if (this.registrationDto.getPreRegistrationId() != null
+                && !this.registrationDto.getPreRegistrationId().trim().isEmpty()) {
+
+            ResponseDto responseDTO = new ResponseDto();
+            List preRegistrationLists = new ArrayList<>();
+            PreRegistrationList preRegistrationList = preRegistrationDataSyncServiceProvider.get()
+                    .getPreRegistrationRecordForDeletion(
+                            this.registrationDto.getPreRegistrationId());
+            preRegistrationLists.add(preRegistrationList);
+            preRegistrationDataSyncServiceProvider.get().deletePreRegRecords(responseDTO, preRegistrationLists);
+        }
 
 //        } finally {
-            clearRegistration();
+        clearRegistration();
 //        }
     }
 
diff --git a/android/clientmanager/src/main/java/io/mosip/registration/clientmanager/service/external/PreRegZipHandlingService.java b/android/clientmanager/src/main/java/io/mosip/registration/clientmanager/service/external/PreRegZipHandlingService.java
index 7e0da3658..1b53ae985 100644
--- a/android/clientmanager/src/main/java/io/mosip/registration/clientmanager/service/external/PreRegZipHandlingService.java
+++ b/android/clientmanager/src/main/java/io/mosip/registration/clientmanager/service/external/PreRegZipHandlingService.java
@@ -19,7 +19,7 @@ public interface PreRegZipHandlingService {
 
     PreRegistrationDto encryptAndSavePreRegPacket(String preRegistrationId, String preRegPacket, CenterMachineDto centerMachineDto) ;
 
-    String storePreRegPacketToDisk(String preRegistrationId, byte[] encryptedPacket, CenterMachineDto centerMachineDto) throws RegBaseCheckedException, RegBaseUncheckedException;
+    String storePreRegPacketToDisk(String preRegistrationId, byte[] encryptedPacket, CenterMachineDto centerMachineDto) throws RegBaseUncheckedException;
 
 
     byte[] decryptPreRegPacket(String symmetricKey, byte[] encryptedPacket) throws Exception;
diff --git a/android/clientmanager/src/main/java/io/mosip/registration/clientmanager/spi/MasterDataService.java b/android/clientmanager/src/main/java/io/mosip/registration/clientmanager/spi/MasterDataService.java
index 55fcda93a..85dce0d45 100644
--- a/android/clientmanager/src/main/java/io/mosip/registration/clientmanager/spi/MasterDataService.java
+++ b/android/clientmanager/src/main/java/io/mosip/registration/clientmanager/spi/MasterDataService.java
@@ -24,21 +24,22 @@ public interface MasterDataService {
     /**
      * Fetches policy key
      */
-    void syncCertificate(Runnable onFinish, String applicationId, String referenceId, String setApplicationId, String setReferenceId, boolean isManualSync);
+    void syncCertificate(Runnable onFinish, String applicationId, String referenceId, String setApplicationId, String setReferenceId, boolean isManualSync, String jobId);
 
     /**
      * Fetches all the master data
      *
      * @throws Exception
      */
-    void syncMasterData(Runnable onFinish, int retryNo, boolean isManualSync) throws Exception;
+    void syncMasterData(Runnable onFinish, int retryNo, boolean isManualSync, String jobId) throws Exception;
+//    void syncMasterDataWithJob(Runnable onFinish, int retryNo, boolean isManualSync, String jobId) throws Exception;
 
     /**
      * Fetches all the global params from the server and sync locally.
      *
      * @throws Exception
      */
-    void syncGlobalParamsData(Runnable onFinish, boolean isManualSync) throws Exception;
+    void syncGlobalParamsData(Runnable onFinish, boolean isManualSync, String jobId) throws Exception;
 
     /**
      * Fetches latest Id schema and UI specs
@@ -52,12 +53,14 @@ public interface MasterDataService {
      *
      * @throws Exception
      */
-    void syncUserDetails(Runnable onFinish, boolean isManualSync) throws Exception;
+    void syncUserDetails(Runnable onFinish, boolean isManualSync, String jobId) throws Exception;
 
-    void syncCACertificates(Runnable onFinish, boolean isManualSync);
+    void syncCACertificates(Runnable onFinish, boolean isManualSync, String jobId);
 
     String onResponseComplete();
 
+    void logLastSyncCompletionDateTime(String jobId);
+
 
     /**
      * @param hierarchyLevelName
diff --git a/android/clientmanager/src/main/java/io/mosip/registration/clientmanager/spi/PreRegistrationDataSyncService.java b/android/clientmanager/src/main/java/io/mosip/registration/clientmanager/spi/PreRegistrationDataSyncService.java
index 00231c6de..cc58d9f6f 100644
--- a/android/clientmanager/src/main/java/io/mosip/registration/clientmanager/spi/PreRegistrationDataSyncService.java
+++ b/android/clientmanager/src/main/java/io/mosip/registration/clientmanager/spi/PreRegistrationDataSyncService.java
@@ -1,11 +1,17 @@
 package io.mosip.registration.clientmanager.spi;
 
+import java.sql.Timestamp;
+import java.util.List;
 import java.util.Map;
 
 import io.mosip.registration.clientmanager.dto.ResponseDto;
-import io.mosip.registration.clientmanager.exception.ClientCheckedException;
+import io.mosip.registration.clientmanager.entity.PreRegistrationList;
 
 public interface PreRegistrationDataSyncService {
-    public Map getPreRegistration(String preRegistrationId, boolean forceDownload);
-    void fetchPreRegistrationIds(Runnable onFinish);
+    Map getPreRegistration(String preRegistrationId, boolean forceDownload);
+    void fetchPreRegistrationIds(Runnable onFinish, String jobId);
+    ResponseDto fetchAndDeleteRecords();
+    void deletePreRegRecords(ResponseDto responseDTO, List preRegList);
+    PreRegistrationList getPreRegistrationRecordForDeletion(String preRegistrationId);
+    Timestamp getLastPreRegPacketDownloadedTime();
 }
\ No newline at end of file
diff --git a/android/clientmanager/src/main/java/io/mosip/registration/clientmanager/util/CronExpressionParser.java b/android/clientmanager/src/main/java/io/mosip/registration/clientmanager/util/CronExpressionParser.java
new file mode 100644
index 000000000..0699ab5e7
--- /dev/null
+++ b/android/clientmanager/src/main/java/io/mosip/registration/clientmanager/util/CronExpressionParser.java
@@ -0,0 +1,65 @@
+package io.mosip.registration.clientmanager.util;
+
+import android.util.Log;
+
+import com.cronutils.model.Cron;
+import com.cronutils.model.CronType;
+import com.cronutils.model.definition.CronDefinitionBuilder;
+import com.cronutils.model.time.ExecutionTime;
+import com.cronutils.parser.CronParser;
+
+import java.time.Instant;
+import java.time.ZoneId;
+import java.time.ZonedDateTime;
+import java.util.Optional;
+
+/**
+ * Simple utility for cron expression parsing and next sync time calculation
+ */
+public class CronExpressionParser {
+
+    private static final CronParser cronParser = new CronParser(
+            CronDefinitionBuilder.instanceDefinitionFor(CronType.QUARTZ)
+    );
+
+    /**
+     * Calculates next execution time from cron expression
+     * @param cronExpression e.g., "0 0 11 * * ?" (Every day at 11:00 AM)
+     * @return Next execution time or null if invalid
+     */
+    public static Instant getNextExecutionTime(String cronExpression) {
+        try {
+            if (cronExpression == null || cronExpression.trim().isEmpty()) {
+                return null;
+            }
+
+            Cron cron = cronParser.parse(cronExpression.trim());
+            ExecutionTime executionTime = ExecutionTime.forCron(cron);
+            ZonedDateTime now = ZonedDateTime.now(ZoneId.systemDefault());
+
+            Optional next = executionTime.nextExecution(now);
+            return next.map(ZonedDateTime::toInstant).orElse(null);
+        } catch (Exception e) {
+            Log.e("CronExpressionParser", "Error parsing cron expression", e);
+        }
+        return null;
+    }
+
+    /**
+     * Validates cron expression
+     * @param cronExpression The cron expression to validate
+     * @return true if valid
+     */
+    public static boolean isValidCronExpression(String cronExpression) {
+        try {
+            if (cronExpression == null || cronExpression.trim().isEmpty()) {
+                return false;
+            }
+            cronParser.parse(cronExpression.trim());
+            return true;
+        } catch (Exception e) {
+            Log.e("CronExpressionParser", "Invalid cron expression", e);
+        }
+        return false;
+    }
+}
\ No newline at end of file
diff --git a/android/clientmanager/src/main/java/io/mosip/registration/clientmanager/util/DateUtil.java b/android/clientmanager/src/main/java/io/mosip/registration/clientmanager/util/DateUtil.java
index e62801d50..6c6a5881e 100644
--- a/android/clientmanager/src/main/java/io/mosip/registration/clientmanager/util/DateUtil.java
+++ b/android/clientmanager/src/main/java/io/mosip/registration/clientmanager/util/DateUtil.java
@@ -4,9 +4,14 @@
 
 import java.text.DateFormat;
 import java.util.Date;
+import java.text.SimpleDateFormat;
+import java.util.Date;
 
 public class DateUtil {
 
+    private static final SimpleDateFormat DATE_FORMAT = new SimpleDateFormat("yyyy-MMM-dd");
+    private static final SimpleDateFormat TIME_FORMAT = new SimpleDateFormat("HH:mm:ss");
+
     DateFormat dateFormat;
     DateFormat timeFormat;
 
@@ -17,8 +22,10 @@ public DateUtil(Context context) {
 
     public String getDateTime(long dateTimeMillis) {
         Date date = new Date(dateTimeMillis);
-        String dateStr = dateFormat.format(date);
-        String time = timeFormat.format(date);
-        return String.format("%s %s", dateStr, time);
+
+        String dateStr = DATE_FORMAT.format(date);
+        String timeStr = TIME_FORMAT.format(date);
+
+        return String.format("%s %s", dateStr, timeStr);
     }
 }
diff --git a/android/clientmanager/src/test/java/io/mosip/registration/clientmanager/config/AppModuleTest.java b/android/clientmanager/src/test/java/io/mosip/registration/clientmanager/config/AppModuleTest.java
index b744f7bc0..58ac77e9d 100644
--- a/android/clientmanager/src/test/java/io/mosip/registration/clientmanager/config/AppModuleTest.java
+++ b/android/clientmanager/src/test/java/io/mosip/registration/clientmanager/config/AppModuleTest.java
@@ -11,10 +11,12 @@
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
 
+import javax.inject.Provider;
 import javax.inject.Singleton;
 
 import io.mosip.registration.clientmanager.dao.ApplicantValidDocumentDao;
 import io.mosip.registration.clientmanager.dao.FileSignatureDao;
+import io.mosip.registration.clientmanager.dao.LocalConfigDAO;
 import io.mosip.registration.clientmanager.dao.PreRegistrationDataSyncDao;
 import io.mosip.registration.clientmanager.dao.PreRegistrationDataSyncRepositoryDao;
 import io.mosip.registration.clientmanager.entity.PreRegistrationList;
@@ -91,6 +93,16 @@ public class AppModuleTest {
     @Mock PreRegistrationDataSyncRepositoryDao preRegistrationDataSyncRepositoryDao;
     @Mock PreRegZipHandlingService preRegZipHandlingService;
     @Mock PreRegistrationList preRegistrationList;
+    @Mock
+    Provider preRegistrationDataSyncServiceProvider;
+
+    @Mock Biometrics095Service biometricService;
+
+    @Mock JobTransactionService jobTransactionService;
+
+    @Mock PermittedLocalConfigRepository permittedLocalConfigRepository;
+
+    @Mock LocalConfigDAO localConfigDAO;
 
     private AppModule appModule;
 
@@ -146,7 +158,7 @@ public void testProvideMasterDataService() {
                 registrationCenterRepository, documentTypeRepository, applicantValidDocRepository, templateRepository,
                 dynamicFieldRepository, locationRepository, globalParamRepository, identitySchemaRepository,
                 blocklistedWordRepository, syncJobDefRepository, userDetailRepository, certificateManagerService,
-                languageRepository, jobManagerService, fileSignatureDao
+                languageRepository, jobManagerService, fileSignatureDao, jobTransactionService, permittedLocalConfigRepository, localConfigDAO
         );
         assertNotNull(service);
         assertTrue(service instanceof MasterDataServiceImpl);
@@ -168,7 +180,7 @@ public void testProvideLoginService() {
     public void testProvideRegistrationService() {
         RegistrationService service = appModule.provideRegistrationService(
                 packetWriterService, registrationRepository, mock(MasterDataService.class), identitySchemaRepository,
-                clientCryptoManagerService, keyStoreRepository, globalParamRepository, auditManagerService
+                clientCryptoManagerService, keyStoreRepository, globalParamRepository, auditManagerService,preRegistrationDataSyncServiceProvider,biometricService
         );
         assertNotNull(service);
         assertTrue(service instanceof RegistrationServiceImpl);
diff --git a/android/clientmanager/src/test/java/io/mosip/registration/clientmanager/jobs/ConfigDataSyncJobTest.java b/android/clientmanager/src/test/java/io/mosip/registration/clientmanager/jobs/ConfigDataSyncJobTest.java
index 3983e4dcd..41e8e4168 100644
--- a/android/clientmanager/src/test/java/io/mosip/registration/clientmanager/jobs/ConfigDataSyncJobTest.java
+++ b/android/clientmanager/src/test/java/io/mosip/registration/clientmanager/jobs/ConfigDataSyncJobTest.java
@@ -43,12 +43,12 @@ public void testTriggerJob_SuccessfulSync_ReturnsTrue() throws Exception {
             Runnable callback = invocation.getArgument(0);
             callback.run(); // Simulate callback execution
             return null;
-        }).when(masterDataService).syncGlobalParamsData(any(), anyBoolean());
+        }).when(masterDataService).syncGlobalParamsData(any(), anyBoolean(), "");
 
         boolean result = configDataSyncJob.triggerJob(jobId);
 
         assertTrue(result);
-        verify(masterDataService).syncGlobalParamsData(any(), anyBoolean());
+        verify(masterDataService).syncGlobalParamsData(any(), anyBoolean(), "");
         verify(configDataSyncJob).logJobTransaction(jobId, TimeUnit.MILLISECONDS.toSeconds(currentTimeMillis));
     }
 
@@ -56,12 +56,12 @@ public void testTriggerJob_SuccessfulSync_ReturnsTrue() throws Exception {
     public void testTriggerJob_SyncThrowsException_ReturnsFalse() throws Exception {
         int jobId = 1;
         doThrow(new RuntimeException("Sync failed"))
-                .when(masterDataService).syncGlobalParamsData(any(), anyBoolean());
+                .when(masterDataService).syncGlobalParamsData(any(), anyBoolean(), "");
 
         boolean result = configDataSyncJob.triggerJob(jobId);
 
         assertFalse(result);
-        verify(masterDataService).syncGlobalParamsData(any(), anyBoolean());
+        verify(masterDataService).syncGlobalParamsData(any(), anyBoolean(), "");
     }
 
     @Test
@@ -71,10 +71,10 @@ public void testTriggerJob_LogsStartAndCompletion() throws Exception {
             Runnable callback = invocation.getArgument(0);
             callback.run();
             return null;
-        }).when(masterDataService).syncGlobalParamsData(any(), anyBoolean());
+        }).when(masterDataService).syncGlobalParamsData(any(), anyBoolean(), "");
 
         configDataSyncJob.triggerJob(jobId);
 
-        verify(masterDataService).syncGlobalParamsData(any(), anyBoolean());
+        verify(masterDataService).syncGlobalParamsData(any(), anyBoolean(), "");
     }
 }
\ No newline at end of file
diff --git a/android/clientmanager/src/test/java/io/mosip/registration/clientmanager/service/MasterDataServiceImplTest.java b/android/clientmanager/src/test/java/io/mosip/registration/clientmanager/service/MasterDataServiceImplTest.java
index cbd92c192..5d8effceb 100644
--- a/android/clientmanager/src/test/java/io/mosip/registration/clientmanager/service/MasterDataServiceImplTest.java
+++ b/android/clientmanager/src/test/java/io/mosip/registration/clientmanager/service/MasterDataServiceImplTest.java
@@ -1764,7 +1764,7 @@ public void test_syncMasterData_success() {
             return null;
         }).when(mockMasterCall).enqueue(any());
         Runnable onFinish = mock(Runnable.class);
-        spyService.syncMasterData(onFinish, 0, false);
+        spyService.syncMasterData(onFinish, 0, false, "");
         verify(onFinish, atLeastOnce()).run();
     }
 
@@ -1788,7 +1788,7 @@ public void test_syncMasterData_error() {
             return null;
         }).when(mockMasterCall).enqueue(any());
         Runnable onFinish = mock(Runnable.class);
-        spyService.syncMasterData(onFinish, 0, false);
+        spyService.syncMasterData(onFinish, 0, false, "");
         verify(onFinish, atLeastOnce()).run();
     }
 
@@ -1810,7 +1810,7 @@ public void test_syncMasterData_failure() {
             return null;
         }).when(mockMasterCall).enqueue(any());
         Runnable onFinish = mock(Runnable.class);
-        spyService.syncMasterData(onFinish, 0, false);
+        spyService.syncMasterData(onFinish, 0, false, "");
         verify(onFinish, atLeastOnce()).run();
     }
 
@@ -1831,7 +1831,7 @@ public void test_syncGlobalParamsData_success() throws Exception {
             return null;
         }).when(mockGlobalCall).enqueue(any());
         Runnable onFinish = mock(Runnable.class);
-        spyService.syncGlobalParamsData(onFinish, false);
+        spyService.syncGlobalParamsData(onFinish, false, "");
         verify(onFinish, atLeastOnce()).run();
     }
 
@@ -1849,7 +1849,7 @@ public void test_syncGlobalParamsData_error() throws Exception {
             return null;
         }).when(mockGlobalCall).enqueue(any());
         Runnable onFinish = mock(Runnable.class);
-        spyService.syncGlobalParamsData(onFinish, false);
+        spyService.syncGlobalParamsData(onFinish, false, "");
         verify(onFinish, atLeastOnce()).run();
     }
 
@@ -1868,7 +1868,7 @@ public void test_syncGlobalParamsData_failure() throws Exception {
             return null;
         }).when(mockGlobalCall).enqueue(any());
         Runnable onFinish = mock(Runnable.class);
-        spyService.syncGlobalParamsData(onFinish, false);
+        spyService.syncGlobalParamsData(onFinish, false, "");
         verify(onFinish, atLeastOnce()).run();
     }
 
@@ -1888,7 +1888,7 @@ public void test_syncCACertificates_success() {
             return null;
         }).when(mockCACall).enqueue(any());
         Runnable onFinish = mock(Runnable.class);
-        spyService.syncCACertificates(onFinish, false);
+        spyService.syncCACertificates(onFinish, false, "");
         verify(onFinish, atLeastOnce()).run();
     }
 
@@ -1907,7 +1907,7 @@ public void test_syncCACertificates_error() {
             return null;
         }).when(mockCACall).enqueue(any());
         Runnable onFinish = mock(Runnable.class);
-        spyService.syncCACertificates(onFinish, false);
+        spyService.syncCACertificates(onFinish, false, "");
         verify(onFinish, atLeastOnce()).run();
     }
 
@@ -1924,7 +1924,7 @@ public void test_syncCACertificates_failure() {
             return null;
         }).when(mockCACall).enqueue(any());
         Runnable onFinish = mock(Runnable.class);
-        spyService.syncCACertificates(onFinish, false);
+        spyService.syncCACertificates(onFinish, false, "");
         verify(onFinish, atLeastOnce()).run();
     }
 
@@ -1948,7 +1948,7 @@ public void test_syncUserDetails_success() throws Exception {
             return null;
         }).when(mockUserCall).enqueue(any());
         Runnable onFinish = mock(Runnable.class);
-        spyService.syncUserDetails(onFinish, false);
+        spyService.syncUserDetails(onFinish, false, "");
         verify(onFinish, atLeastOnce()).run();
     }
 
@@ -1969,7 +1969,7 @@ public void test_syncUserDetails_error() throws Exception {
             return null;
         }).when(mockUserCall).enqueue(any());
         Runnable onFinish = mock(Runnable.class);
-        spyService.syncUserDetails(onFinish, false);
+        spyService.syncUserDetails(onFinish, false, "");
         verify(onFinish, atLeastOnce()).run();
     }
 
@@ -1991,7 +1991,7 @@ public void test_syncUserDetails_failure() throws Exception {
             return null;
         }).when(mockUserCall).enqueue(any());
         Runnable onFinish = mock(Runnable.class);
-        spyService.syncUserDetails(onFinish, false);
+        spyService.syncUserDetails(onFinish, false, "");
         verify(onFinish, atLeastOnce()).run();
     }
 
@@ -2078,7 +2078,7 @@ public void test_syncGlobalParamsData_onResponseNull() throws Exception {
             return null;
         }).when(mockGlobalCall).enqueue(any());
         Runnable onFinish = mock(Runnable.class);
-        spyService.syncGlobalParamsData(onFinish, false);
+        spyService.syncGlobalParamsData(onFinish, false, "");
     }
 
     /**
@@ -2140,6 +2140,8 @@ public void test_public_constructor_with_all_args() {
                 mockLanguageRepository,
                 mockJobManagerService,
                 mockFileSignatureDao,
+                null
+                mockFileSignatureDao,
                 mockPermittedLocalConfigRepository,
                 mockLocalConfigDao
         );
diff --git a/android/clientmanager/src/test/java/io/mosip/registration/clientmanager/service/PreRegistrationDataSyncServiceImplTest.java b/android/clientmanager/src/test/java/io/mosip/registration/clientmanager/service/PreRegistrationDataSyncServiceImplTest.java
index 8b27df71c..1fa932a96 100644
--- a/android/clientmanager/src/test/java/io/mosip/registration/clientmanager/service/PreRegistrationDataSyncServiceImplTest.java
+++ b/android/clientmanager/src/test/java/io/mosip/registration/clientmanager/service/PreRegistrationDataSyncServiceImplTest.java
@@ -45,7 +45,6 @@
 import java.lang.reflect.Field;
 import java.lang.reflect.InvocationTargetException;
 import java.lang.reflect.Method;
-import java.sql.Ref;
 import java.util.HashMap;
 import java.util.Map;
 import java.util.concurrent.ExecutorService;
@@ -160,7 +159,7 @@ public void fetchPreRegistrationIds_success_Test() throws IOException {
 
         service.fetchPreRegistrationIds(() -> {
             verify(mockContext).getString(anyInt());
-        });
+        }, "");
 
         verify(mockSyncRestService).getPreRegistrationIds(any());
     }
@@ -172,7 +171,7 @@ public void fetchPreRegistrationIds_noCenterMachineDetails_Test() {
 
         service.fetchPreRegistrationIds(() -> {
             verify(mockContext).getString(anyInt());
-        });
+        }, "");
 
         verify(mockSyncRestService, never()).getPreRegistrationIds(any());
     }
@@ -463,7 +462,7 @@ public void fetchPreRegistrationIds_handlesServiceError() {
             }).when(mockCall).enqueue(any());
 
             service.fetchPreRegistrationIds(() -> {
-            });
+            }, "");
             verify(mockSyncRestService).getPreRegistrationIds(any());
         }
     }
@@ -559,7 +558,7 @@ public void fetchPreRegistrationIds_handlesFailure() {
         }).when(mockCall).enqueue(any());
 
         service.fetchPreRegistrationIds(() -> {
-        });
+        }, "");
         verify(mockSyncRestService).getPreRegistrationIds(any());
     }
 
@@ -579,7 +578,7 @@ public void fetchPreRegistrationIds_handlesUnsuccessfulResponse() {
         }).when(mockCall).enqueue(any());
 
         service.fetchPreRegistrationIds(() -> {
-        });
+        }, "");
         verify(mockSyncRestService).getPreRegistrationIds(any());
     }
 
@@ -975,7 +974,7 @@ public void fetchPreRegistrationIds_successfulResponse_triggersToastAndOnFinish(
             Runnable onFinish = () -> onFinishCalled[0] = true;
 
             // Act
-            service.fetchPreRegistrationIds(onFinish);
+            service.fetchPreRegistrationIds(onFinish, "");
 
             // Assert
             // Toast.makeText should be called with "Application Id Sync Completed"
@@ -1034,7 +1033,7 @@ public void fetchPreRegistrationIds_onResponse_exceptionInTryBlock_triggersError
             };
 
             // Act
-            service.fetchPreRegistrationIds(onFinish);
+            service.fetchPreRegistrationIds(onFinish, "");
 
             // Wait for onFinish to be called (with timeout)
             synchronized (lock) {
@@ -1089,7 +1088,7 @@ public void fetchPreRegistrationIds_onResponse_serviceError_triggersErrorToastAn
             Runnable onFinish = () -> onFinishCalled[0] = true;
 
             // Act
-            service.fetchPreRegistrationIds(onFinish);
+            service.fetchPreRegistrationIds(onFinish, "");
 
             // Assert
             Toast.makeText(mockContext, "Application Id Sync failed service error message", Toast.LENGTH_LONG);
@@ -1552,4 +1551,4 @@ public void test_preparePreRegistration_allNulls() {
             assertTrue(e.getMessage() == null || e.getMessage().contains("getPreRegId"));
         }
     }
-}
+}
\ No newline at end of file
diff --git a/android/clientmanager/src/test/java/io/mosip/registration/clientmanager/service/RegistrationServiceImplTest.java b/android/clientmanager/src/test/java/io/mosip/registration/clientmanager/service/RegistrationServiceImplTest.java
index 5c336d0a6..bf39680e3 100644
--- a/android/clientmanager/src/test/java/io/mosip/registration/clientmanager/service/RegistrationServiceImplTest.java
+++ b/android/clientmanager/src/test/java/io/mosip/registration/clientmanager/service/RegistrationServiceImplTest.java
@@ -2,9 +2,7 @@
 
 import android.content.Context;
 import android.content.SharedPreferences;
-import android.content.res.Resources;
-import com.fasterxml.jackson.databind.ObjectMapper;
-import io.mosip.registration.clientmanager.config.SessionManager;
+
 import io.mosip.registration.clientmanager.constant.RegistrationConstants;
 import io.mosip.registration.clientmanager.dto.CenterMachineDto;
 import io.mosip.registration.clientmanager.dto.registration.RegistrationDto;
@@ -17,11 +15,12 @@
 import io.mosip.registration.clientmanager.spi.AuditManagerService;
 import io.mosip.registration.clientmanager.spi.LocationValidationService;
 import io.mosip.registration.clientmanager.spi.MasterDataService;
+import io.mosip.registration.clientmanager.spi.PreRegistrationDataSyncService;
 import io.mosip.registration.clientmanager.spi.RegistrationService;
 import io.mosip.registration.keymanager.repository.KeyStoreRepository;
 import io.mosip.registration.keymanager.spi.ClientCryptoManagerService;
 import io.mosip.registration.packetmanager.spi.PacketWriterService;
-import org.junit.After;
+
 import org.junit.Assert;
 import org.junit.Before;
 import org.junit.Test;
@@ -52,6 +51,8 @@
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.when;
 
+import javax.inject.Provider;
+
 @RunWith(MockitoJUnitRunner.class)
 public class RegistrationServiceImplTest {
 
@@ -81,6 +82,8 @@ public class RegistrationServiceImplTest {
     @Mock
     private LocationValidationService locationValidationService;
     @Mock
+    private Provider preRegistrationDataSyncServiceProvider;
+    @Mock
     private Biometrics095Service biometricService;
 
     @Before
@@ -92,9 +95,9 @@ public void setUp() {
         when(mockApplicationContext.getSharedPreferences(anyString(), anyInt())).thenReturn(mockSharedPreferences);
         registrationService = new RegistrationServiceImpl(mockApplicationContext, packetWriterService,
                 registrationRepository, masterDataService, identitySchemaRepository, clientCryptoManagerService,
-                keyStoreRepository, globalParamRepository, auditManagerService,registrationCenterRepository,locationValidationService, biometricService);
+                keyStoreRepository, globalParamRepository, auditManagerService,registrationCenterRepository,locationValidationService, preRegistrationDataSyncServiceProvider, biometricService);
     }
-    
+
     @Test(expected = ClientCheckedException.class)
     // Test for getRegistrationDto without starting registration
     public void getRegistrationDtoWithoutStartingRegistration() throws Exception {
@@ -461,10 +464,10 @@ public void testGetAttemptsCount_AllCases() throws Exception {
         for (Modality modality : Modality.values()) {
             int count = (int) getAttemptsCount.invoke(registrationService, modality);
             if (modality == Modality.FINGERPRINT_SLAB_LEFT ||
-                modality == Modality.FINGERPRINT_SLAB_RIGHT ||
-                modality == Modality.FINGERPRINT_SLAB_THUMBS ||
-                modality == Modality.IRIS_DOUBLE ||
-                modality == Modality.FACE) {
+                    modality == Modality.FINGERPRINT_SLAB_RIGHT ||
+                    modality == Modality.FINGERPRINT_SLAB_THUMBS ||
+                    modality == Modality.IRIS_DOUBLE ||
+                    modality == Modality.FACE) {
                 assertEquals(2, count);
             } else {
                 assertEquals(0, count);
@@ -681,7 +684,7 @@ public void testSubmitRegistrationDto_UpdateFlow_UINField() throws Exception {
         when(globalParamRepository.getSelectedHandles()).thenReturn(null);
         Mockito.when(globalParamRepository.getCachedStringGlobalParam(Mockito.eq(RegistrationConstants.AUDIT_EXPORTED_TILL))).thenReturn(null);
         Mockito.when(globalParamRepository.getCachedStringGlobalParam(Mockito.argThat(arg ->
-            !RegistrationConstants.AUDIT_EXPORTED_TILL.equals(arg)))).thenReturn("1.2.3");
+                !RegistrationConstants.AUDIT_EXPORTED_TILL.equals(arg)))).thenReturn("1.2.3");
         // Provide a fully initialized CenterMachineDto
         CenterMachineDto centerMachineDto = new CenterMachineDto();
         centerMachineDto.setCenterId("centerId");
@@ -722,7 +725,7 @@ public void testSubmitRegistrationDto_NewFlow_AllFields() throws Exception {
         when(globalParamRepository.getSelectedHandles()).thenReturn(Collections.singletonList("handle1"));
         Mockito.when(globalParamRepository.getCachedStringGlobalParam(Mockito.eq(RegistrationConstants.AUDIT_EXPORTED_TILL))).thenReturn(null);
         Mockito.when(globalParamRepository.getCachedStringGlobalParam(Mockito.argThat(arg ->
-            !RegistrationConstants.AUDIT_EXPORTED_TILL.equals(arg)))).thenReturn("1.2.3");
+                !RegistrationConstants.AUDIT_EXPORTED_TILL.equals(arg)))).thenReturn("1.2.3");
         // Provide a fully initialized CenterMachineDto
         CenterMachineDto centerMachineDto = new CenterMachineDto();
         centerMachineDto.setCenterId("centerId");
@@ -763,7 +766,7 @@ public void testSubmitRegistrationDto_CorrectionFlow() throws Exception {
         when(globalParamRepository.getSelectedHandles()).thenReturn(null);
         Mockito.when(globalParamRepository.getCachedStringGlobalParam(Mockito.eq(RegistrationConstants.AUDIT_EXPORTED_TILL))).thenReturn(null);
         Mockito.when(globalParamRepository.getCachedStringGlobalParam(Mockito.argThat(arg ->
-            !RegistrationConstants.AUDIT_EXPORTED_TILL.equals(arg)))).thenReturn("1.2.3");
+                !RegistrationConstants.AUDIT_EXPORTED_TILL.equals(arg)))).thenReturn("1.2.3");
         // Provide a fully initialized CenterMachineDto
         CenterMachineDto centerMachineDto = new CenterMachineDto();
         centerMachineDto.setCenterId("centerId");
@@ -804,7 +807,7 @@ public void testSubmitRegistrationDto_LostFlow() throws Exception {
         when(globalParamRepository.getSelectedHandles()).thenReturn(null);
         Mockito.when(globalParamRepository.getCachedStringGlobalParam(Mockito.eq(RegistrationConstants.AUDIT_EXPORTED_TILL))).thenReturn(null);
         Mockito.when(globalParamRepository.getCachedStringGlobalParam(Mockito.argThat(arg ->
-            !RegistrationConstants.AUDIT_EXPORTED_TILL.equals(arg)))).thenReturn("1.2.3");
+                !RegistrationConstants.AUDIT_EXPORTED_TILL.equals(arg)))).thenReturn("1.2.3");
         // Provide a fully initialized CenterMachineDto
         CenterMachineDto centerMachineDto = new CenterMachineDto();
         centerMachineDto.setCenterId("centerId");
@@ -845,7 +848,7 @@ public void testSubmitRegistrationDto_EmptyContainerPath() throws Exception {
         when(globalParamRepository.getSelectedHandles()).thenReturn(null);
         Mockito.when(globalParamRepository.getCachedStringGlobalParam(Mockito.eq(RegistrationConstants.AUDIT_EXPORTED_TILL))).thenReturn(null);
         Mockito.when(globalParamRepository.getCachedStringGlobalParam(Mockito.argThat(arg ->
-            !RegistrationConstants.AUDIT_EXPORTED_TILL.equals(arg)))).thenReturn("1.2.3");
+                !RegistrationConstants.AUDIT_EXPORTED_TILL.equals(arg)))).thenReturn("1.2.3");
         // Provide a fully initialized CenterMachineDto
         CenterMachineDto centerMachineDto = new CenterMachineDto();
         centerMachineDto.setCenterId("centerId");
@@ -1462,4 +1465,4 @@ public void testDoPreChecksBeforeRegistration_NullCenterMachineDto() throws Exce
             assertTrue(cause instanceof ClientCheckedException);
         }
     }
-}
+}
\ No newline at end of file
diff --git a/android/clientmanager/src/test/java/io/mosip/registration/clientmanager/service/SyncDataServiceImplTest.java b/android/clientmanager/src/test/java/io/mosip/registration/clientmanager/service/SyncDataServiceImplTest.java
index 61f867d72..e2dad939e 100644
--- a/android/clientmanager/src/test/java/io/mosip/registration/clientmanager/service/SyncDataServiceImplTest.java
+++ b/android/clientmanager/src/test/java/io/mosip/registration/clientmanager/service/SyncDataServiceImplTest.java
@@ -265,7 +265,7 @@ public void test_syncMasterData_successfulResponse_noError_centerMachinePresent(
 
         Runnable onFinish = mock(Runnable.class);
 
-        spyService.syncMasterData(onFinish, 0, true);
+        spyService.syncMasterData(onFinish, 0, true, "");
 
         ArgumentCaptor>> callbackCaptor = ArgumentCaptor.forClass(Callback.class);
         verify(mockCallClientSetting).enqueue(callbackCaptor.capture());
@@ -294,7 +294,7 @@ public void test_syncMasterData_successfulResponse_withError() throws Exception
 
         Runnable onFinish = mock(Runnable.class);
 
-        spyService.syncMasterData(onFinish, 0, true);
+        spyService.syncMasterData(onFinish, 0, true, "");
 
         ArgumentCaptor>> callbackCaptor = ArgumentCaptor.forClass(Callback.class);
         verify(mockCallClientSetting).enqueue(callbackCaptor.capture());
@@ -321,7 +321,7 @@ public void test_syncMasterData_unsuccessfulResponse() throws Exception {
 
         Runnable onFinish = mock(Runnable.class);
 
-        spyService.syncMasterData(onFinish, 0, true);
+        spyService.syncMasterData(onFinish, 0, true, "");
 
         ArgumentCaptor>> callbackCaptor = ArgumentCaptor.forClass(Callback.class);
         verify(mockCallClientSetting).enqueue(callbackCaptor.capture());
@@ -340,7 +340,7 @@ public void test_syncMasterData_onFailure() throws Exception {
 
         Runnable onFinish = mock(Runnable.class);
 
-        spyService.syncMasterData(onFinish, 0, true);
+        spyService.syncMasterData(onFinish, 0, true, "");
 
         ArgumentCaptor>> callbackCaptor = ArgumentCaptor.forClass(Callback.class);
         verify(mockCallClientSetting).enqueue(callbackCaptor.capture());
@@ -358,7 +358,7 @@ public void test_syncMasterData_recursiveRetry() throws Exception {
 
         Runnable onFinish = mock(Runnable.class);
 
-        spyService.syncMasterData(onFinish, 0, true);
+        spyService.syncMasterData(onFinish, 0, true,"");
 
         ArgumentCaptor>> callbackCaptor = ArgumentCaptor.forClass(Callback.class);
         verify(mockCallClientSetting).enqueue(callbackCaptor.capture());
@@ -390,7 +390,7 @@ public void test_syncGlobalParamsData_successful_noError() throws Exception {
             when(mockClientCryptoManagerService.getClientKeyIndex()).thenReturn("key1");
             when(mockSyncRestService.getGlobalConfigs(anyString(), anyString())).thenReturn(mockCall);
 
-            spyService.syncGlobalParamsData(mockOnFinish, true);
+            spyService.syncGlobalParamsData(mockOnFinish, true, "");
 
             ArgumentCaptor>>> callbackCaptor = ArgumentCaptor.forClass(Callback.class);
             verify(mockCall).enqueue(callbackCaptor.capture());
@@ -418,7 +418,7 @@ public void test_syncGlobalParamsData_successful_withError() throws Exception {
             when(mockClientCryptoManagerService.getClientKeyIndex()).thenReturn("key1");
             when(mockSyncRestService.getGlobalConfigs(anyString(), anyString())).thenReturn(mockCall);
 
-            spyService.syncGlobalParamsData(mockOnFinish, true);
+            spyService.syncGlobalParamsData(mockOnFinish, true, "");
 
             ArgumentCaptor>>> callbackCaptor = ArgumentCaptor.forClass(Callback.class);
             verify(mockCall).enqueue(callbackCaptor.capture());
@@ -450,7 +450,7 @@ public void test_syncGlobalParamsData_unsuccessfulResponse() throws Exception {
             when(mockClientCryptoManagerService.getClientKeyIndex()).thenReturn("key1");
             when(mockSyncRestService.getGlobalConfigs(anyString(), anyString())).thenReturn(mockCall);
 
-            spyService.syncGlobalParamsData(mockOnFinish, true);
+            spyService.syncGlobalParamsData(mockOnFinish, true, "");
 
             ArgumentCaptor>>> callbackCaptor = ArgumentCaptor.forClass(Callback.class);
             verify(mockCall).enqueue(callbackCaptor.capture());
@@ -473,7 +473,7 @@ public void test_syncGlobalParamsData_onFailure() throws Exception {
             when(mockClientCryptoManagerService.getClientKeyIndex()).thenReturn("key1");
             when(mockSyncRestService.getGlobalConfigs(anyString(), anyString())).thenReturn(mockCall);
 
-            spyService.syncGlobalParamsData(mockOnFinish, true);
+            spyService.syncGlobalParamsData(mockOnFinish, true, "");
 
             ArgumentCaptor>>> callbackCaptor = ArgumentCaptor.forClass(Callback.class);
             verify(mockCall).enqueue(callbackCaptor.capture());
@@ -540,13 +540,14 @@ public void test_handle_null_server_version() throws Exception {
                 mockContext, mockObjectMapper, mockSyncRestService, mockClientCryptoManagerService,
                 null, null, null, null, null, null, null, null,
                 mockGlobalParamRepository, null, null, null, mockUserDetailRepository,
+                null, null, null, null, null
                 null, null, null, null,null,null
         );
 
         Runnable mockOnFinish = mock(Runnable.class);
 
         assertThrows(NullPointerException.class, () -> {
-            masterDataService.syncUserDetails(mockOnFinish, true);
+            masterDataService.syncUserDetails(mockOnFinish, true, "");
         });
     }
 
diff --git a/assets/l10n/app_ar.arb b/assets/l10n/app_ar.arb
index 518dfe9fe..c2af4d6e1 100644
--- a/assets/l10n/app_ar.arb
+++ b/assets/l10n/app_ar.arb
@@ -331,5 +331,6 @@
   "scan_now": "امسح الآن",
   "enter_additional_info_req_id": "أدخل معرف طلب المعلومات الإضافية",
   "additional_info_req_id": "معرف طلب المعلومات الإضافية",
-  "no_access_to_this_page": "ليست لديك صلاحية الوصول إلى هذه الصفحة"
+  "no_access_to_this_page": "ليست لديك صلاحية الوصول إلى هذه الصفحة",
+  "scheduled_job_settings": "إعدادات المهمة المجدولة"
 }
\ No newline at end of file
diff --git a/assets/l10n/app_en.arb b/assets/l10n/app_en.arb
index 633e8562c..997e2b7e5 100644
--- a/assets/l10n/app_en.arb
+++ b/assets/l10n/app_en.arb
@@ -331,5 +331,6 @@
   "scan_now": "Scan Now",
   "enter_additional_info_req_id": "Enter Additional Info Request ID",
   "additional_info_req_id": "Additional Info Request ID",
+  "scheduled_job_settings": "Scheduled Job Settings",
   "no_access_to_this_page": "You don't have access to this page"
 }
\ No newline at end of file
diff --git a/assets/l10n/app_fr.arb b/assets/l10n/app_fr.arb
index 4d629a53f..d4bc2f01c 100644
--- a/assets/l10n/app_fr.arb
+++ b/assets/l10n/app_fr.arb
@@ -331,5 +331,6 @@
   "scan_now": "Analyser maintenant",
   "enter_additional_info_req_id": "Entrez l'identifiant de la demande d'information supplémentaire",
   "additional_info_req_id": "Identifiant de la demande d'information supplémentaire",
-  "no_access_to_this_page": "Vous n'avez pas accès à cette page"
+  "no_access_to_this_page": "Vous n'avez pas accès à cette page",
+  "scheduled_job_settings": "Paramètres des tâches planifiées"
 }
\ No newline at end of file
diff --git a/assets/l10n/app_hi.arb b/assets/l10n/app_hi.arb
index a2888414f..81f89da74 100644
--- a/assets/l10n/app_hi.arb
+++ b/assets/l10n/app_hi.arb
@@ -331,5 +331,6 @@
   "scan_now": "अभी स्कैन करें",
   "enter_additional_info_req_id": "अतिरिक्त जानकारी अनुरोध आईडी दर्ज करें",
   "additional_info_req_id": "अतिरिक्त जानकारी अनुरोध आईडी",
-  "no_access_to_this_page": "आपको इस पृष्ठ तक पहुँच नहीं है"
+  "no_access_to_this_page": "आपको इस पृष्ठ तक पहुँच नहीं है",
+  "scheduled_job_settings": "अनुसूचित कार्य सेटिंग्स"
 }
\ No newline at end of file
diff --git a/assets/l10n/app_kn.arb b/assets/l10n/app_kn.arb
index 3ceacb39b..8811d54b1 100644
--- a/assets/l10n/app_kn.arb
+++ b/assets/l10n/app_kn.arb
@@ -331,5 +331,6 @@
   "scan_now": "ಈಗಸ್ಕ್ಯಾನ್ ಮಾಡಿ",
   "enter_additional_info_req_id": "ಹೆಚ್ಚುವರಿ ಮಾಹಿತಿ ವಿನಂತಿ ಐಡಿ ನಮೂದಿಸಿ",
   "additional_info_req_id": "ಹೆಚ್ಚುವರಿ ಮಾಹಿತಿ ವಿನಂತಿ ಐಡಿ",
-  "no_access_to_this_page": "ನಿಮಗೆ ಈ ಪುಟಕ್ಕೆ ಪ್ರವೇಶವಿಲ್ಲ"
+  "no_access_to_this_page": "ನಿಮಗೆ ಈ ಪುಟಕ್ಕೆ ಪ್ರವೇಶವಿಲ್ಲ",
+  "scheduled_job_settings": "ನಿಗದಿತ ಉದ್ಯೋಗ ಸೆಟ್ಟಿಂಗ್‌ಗಳು"
 }
\ No newline at end of file
diff --git a/assets/l10n/app_ta.arb b/assets/l10n/app_ta.arb
index 135770fc0..50db73239 100644
--- a/assets/l10n/app_ta.arb
+++ b/assets/l10n/app_ta.arb
@@ -340,5 +340,6 @@
   "scan_now": "இப்போது ஸ்கேன் செய்யுங்கள்",
   "enter_additional_info_req_id": "கூடுதல் தகவல் கோரிக்கை ஐடியை உள்ளிடவும்",
   "additional_info_req_id": "கூடுதல் தகவல் கோரிக்கை ஐடி",
-  "no_access_to_this_page": "இந்தப் பக்கத்தை அணுக உங்களுக்கு அனுமதி இல்லை"
+  "no_access_to_this_page": "இந்தப் பக்கத்தை அணுக உங்களுக்கு அனுமதி இல்லை",
+  "scheduled_job_settings": "திட்டமிடப்பட்ட வேலை அமைப்புகள்"
 }
\ No newline at end of file
diff --git a/lib/platform_android/sync_response_service_impl.dart b/lib/platform_android/sync_response_service_impl.dart
index eb8215dbc..7bd0631ae 100644
--- a/lib/platform_android/sync_response_service_impl.dart
+++ b/lib/platform_android/sync_response_service_impl.dart
@@ -9,13 +9,14 @@ import 'package:flutter/material.dart';
 import 'package:flutter/services.dart';
 import 'package:registration_client/pigeon/master_data_sync_pigeon.dart';
 import 'package:registration_client/platform_spi/sync_response_service.dart';
+import 'package:flutter/services.dart' show MethodChannel;
 
 class SyncResponseServiceImpl implements SyncResponseService {
   @override
-  Future getPolicyKeySync(bool isManualSync) async {
+  Future getPolicyKeySync(bool isManualSync, String jobId) async {
     late Sync syncResponse;
     try {
-      syncResponse = await SyncApi().getPolicyKeySync(isManualSync);
+      syncResponse = await SyncApi().getPolicyKeySync(isManualSync, jobId);
     } on PlatformException {
       debugPrint('PolicyKeySync Api call failed, PlatformException');
     } catch (e) {
@@ -25,10 +26,10 @@ class SyncResponseServiceImpl implements SyncResponseService {
   }
 
   @override
-  Future getGlobalParamsSync(bool isManualSync) async {
+  Future getGlobalParamsSync(bool isManualSync, String jobId) async {
     late Sync syncResponse;
     try {
-      syncResponse = await SyncApi().getGlobalParamsSync(isManualSync);
+      syncResponse = await SyncApi().getGlobalParamsSync(isManualSync, jobId);
     } on PlatformException {
       debugPrint('GlobalParamsSync Api call failed, PlatformException');
     } catch (e) {
@@ -38,10 +39,10 @@ class SyncResponseServiceImpl implements SyncResponseService {
   }
 
   @override
-  Future getUserDetailsSync(bool isManualSync) async {
+  Future getUserDetailsSync(bool isManualSync, String jobId) async {
     late Sync syncResponse;
     try {
-      syncResponse = await SyncApi().getUserDetailsSync(isManualSync);
+      syncResponse = await SyncApi().getUserDetailsSync(isManualSync, jobId);
     } on PlatformException {
       debugPrint('UserDetailsSync Api call failed, PlatformException');
     } catch (e) {
@@ -64,10 +65,10 @@ class SyncResponseServiceImpl implements SyncResponseService {
   }
 
   @override
-  Future getMasterDataSync(bool isManualSync) async {
+  Future getMasterDataSync(bool isManualSync, String jobId) async {
     late Sync syncResponse;
     try {
-      syncResponse = await SyncApi().getMasterDataSync(isManualSync);
+      syncResponse = await SyncApi().getMasterDataSync(isManualSync, jobId);
     } on PlatformException {
       debugPrint('MasterDataSync Api call failed, PlatformException');
     } catch (e) {
@@ -76,6 +77,8 @@ class SyncResponseServiceImpl implements SyncResponseService {
     return syncResponse;
   }
 
+  // Removed per request: use getMasterDataSync(bool) only
+
   @override
   Future getLastSyncTime() async {
     late SyncTime syncTime;
@@ -90,10 +93,10 @@ class SyncResponseServiceImpl implements SyncResponseService {
   }
 
   @override
-  Future getCaCertsSync(bool isManualSync) async {
+  Future getCaCertsSync(bool isManualSync, String jobId) async {
     late Sync syncResponse;
     try {
-      syncResponse = await SyncApi().getCaCertsSync(isManualSync);
+      syncResponse = await SyncApi().getCaCertsSync(isManualSync, jobId);
     } on PlatformException {
       debugPrint('CaCerts Api call failed, PlatformException');
     } catch (e) {
@@ -101,7 +104,7 @@ class SyncResponseServiceImpl implements SyncResponseService {
     }
     return syncResponse;
   }
-  
+
   @override
   Future batchJob() async {
     String batchJobResponse = "";
@@ -116,10 +119,10 @@ class SyncResponseServiceImpl implements SyncResponseService {
   }
 
   @override
-  Future getPreRegIds() async {
+  Future getPreRegIds(String jobId) async {
     String preRegIdResponse = "";
     try {
-      preRegIdResponse = await SyncApi().getPreRegIds();
+      preRegIdResponse = await SyncApi().getPreRegIds(jobId);
     } on PlatformException {
       debugPrint('Application Id Api call failed, PlatformException');
     } catch (e) {
@@ -129,10 +132,10 @@ class SyncResponseServiceImpl implements SyncResponseService {
   }
 
   @override
-  Future getKernelCertsSync(bool isManualSync) async {
+  Future getKernelCertsSync(bool isManualSync, String jobId) async {
     late Sync syncResponse;
     try {
-      syncResponse = await SyncApi().getKernelCertsSync(isManualSync);
+      syncResponse = await SyncApi().getKernelCertsSync(isManualSync, jobId);
     } on PlatformException {
       debugPrint('KernelCerts Api call failed, PlatformException');
     } catch (e) {
@@ -158,7 +161,7 @@ class SyncResponseServiceImpl implements SyncResponseService {
   }
 
   @override
-  Future getSyncAndUploadInProgressStatus() async{
+  Future getSyncAndUploadInProgressStatus() async {
     bool syncAndUploadResponse = false;
     try {
       syncAndUploadResponse = await SyncApi().getSyncAndUploadInProgressStatus();
@@ -169,6 +172,77 @@ class SyncResponseServiceImpl implements SyncResponseService {
     }
     return syncAndUploadResponse;
   }
+
+  @override
+  Future> getActiveSyncJobs() async {
+    try {
+      final result = await SyncApi().getActiveSyncJobs();
+      final list = result;
+      return list;
+    } on PlatformException catch (e) {
+      debugPrint('getActiveSyncJobs PlatformException: ${e.message}');
+      return const [];
+    } catch (e) {
+      debugPrint('getActiveSyncJobs failed: $e');
+      return const [];
+    }
+  }
+
+  @override
+  Future deleteAuditLogs(String jobId) async {
+    try {
+      final deleteResponse = await SyncApi().deleteAuditLogs(jobId);
+      return deleteResponse;
+    } on PlatformException catch (e) {
+      debugPrint('deleteAuditLogs PlatformException: ${e.message}');
+      return false;
+    } catch (e) {
+      debugPrint('deleteAuditLogs failed: $e');
+      return false;
+    }
+  }
+
+  @override
+  Future deletePreRegRecords(String jobId) async {
+    try {
+      final deleteResponse = await SyncApi().deletePreRegRecords(jobId);
+      return deleteResponse;
+    } on PlatformException catch (e) {
+      debugPrint('deleteAuditLogs PlatformException: ${e.message}');
+      return false;
+    } catch (e) {
+      debugPrint('deleteAuditLogs failed: $e');
+      return false;
+    }
+  }
+
+  @override
+  Future getLastSyncTimeByJobId(String jobId) async{
+    try {
+      final lastSyncTime = await SyncApi().getLastSyncTimeByJobId(jobId);
+      return lastSyncTime;
+    } on PlatformException catch (e) {
+      debugPrint('lastSync PlatformException: ${e.message}');
+      return "false";
+    } catch (e) {
+      debugPrint('lastSync failed: $e');
+      return "false";
+    }
+  }
+
+  @override
+  Future getNextSyncTimeByJobId(String jobId) async{
+    try {
+      final nextSyncTime = await SyncApi().getNextSyncTimeByJobId(jobId);
+      return nextSyncTime;
+    } on PlatformException catch (e) {
+      debugPrint('nextSync PlatformException: ${e.message}');
+      return "false";
+    } catch (e) {
+      debugPrint('nextSync failed: $e');
+      return "false";
+    }
+  }
 }
 
 SyncResponseService getSyncResponseServiceImpl() => SyncResponseServiceImpl();
diff --git a/lib/platform_spi/sync_response_service.dart b/lib/platform_spi/sync_response_service.dart
index 13123ac5e..4251e9376 100644
--- a/lib/platform_spi/sync_response_service.dart
+++ b/lib/platform_spi/sync_response_service.dart
@@ -10,19 +10,25 @@ import 'package:registration_client/platform_android/sync_response_service_impl.
 
 abstract class SyncResponseService {
   Future getLastSyncTime();
-  Future getPolicyKeySync(bool isManualSync);
-  Future getGlobalParamsSync(bool isManualSync);
-  Future getUserDetailsSync(bool isManualSync);
+  Future getPolicyKeySync(bool isManualSync, String jobId);
+  Future getGlobalParamsSync(bool isManualSync, String jobId);
+  Future getUserDetailsSync(bool isManualSync, String jobId);
   Future getIDSchemaSync(bool isManualSync);
-  Future getMasterDataSync(bool isManualSync);
-  Future getCaCertsSync(bool isManualSync);
+  Future getMasterDataSync(bool isManualSync, String jobId);
+  Future getCaCertsSync(bool isManualSync, String jobId);
   Future batchJob();
-  Future getPreRegIds();
+  Future getPreRegIds(String jobId);
 
   Future> getReasonList(String langCode);
 
-  Future getKernelCertsSync(bool isManualSync);
+  Future getKernelCertsSync(bool isManualSync, String jobId);
   Future getSyncAndUploadInProgressStatus();
+  Future deleteAuditLogs(String jobId);
+  Future deletePreRegRecords(String jobId);
+
+  Future> getActiveSyncJobs();
+  Future getLastSyncTimeByJobId(String jobId);
+  Future getNextSyncTimeByJobId(String jobId);
 
   factory SyncResponseService() => getSyncResponseServiceImpl();
 }
\ No newline at end of file
diff --git a/lib/provider/sync_provider.dart b/lib/provider/sync_provider.dart
index b0283885c..2f85874a5 100644
--- a/lib/provider/sync_provider.dart
+++ b/lib/provider/sync_provider.dart
@@ -5,6 +5,7 @@
  *
 */
 
+import 'dart:convert';
 import 'dart:developer';
 
 import 'package:flutter/widgets.dart';
@@ -12,6 +13,7 @@ import 'package:registration_client/pigeon/master_data_sync_pigeon.dart';
 
 import 'package:flutter_gen/gen_l10n/app_localizations.dart';
 import 'package:registration_client/platform_spi/sync_response_service.dart';
+import 'package:registration_client/utils/sync_job_def.dart';
 
 class SyncProvider with ChangeNotifier {
   final SyncResponseService syncResponseService = SyncResponseService();
@@ -79,38 +81,69 @@ class SyncProvider with ChangeNotifier {
   setIsGlobalSyncInProgress(bool isGlobalSyncInProgress) {
     _isGlobalSyncInProgress = isGlobalSyncInProgress;
   }
+  
+  Future _getJobIdFinder() async {
+    List activeJobs = [];
+    try {
+      List activeJobJsonList = await syncResponseService.getActiveSyncJobs();
+      activeJobs = activeJobJsonList
+          .whereType()
+          .map((jsonStr) {
+            try {
+              return SyncJobDef.fromJson(json.decode(jsonStr) as Map);
+            } catch (e) {
+              log("Failed to parse job JSON: $jsonStr, error: $e");
+              return null;
+            }
+          })
+          .whereType()
+          .toList();
+    } catch (e) {
+      log("Failed to fetch active job IDs: $e");
+    }
+    return (String apiName) {
+
+      var job = activeJobs.where((job) => job.apiName == apiName).firstOrNull;
+      return job?.id ?? "";
+    };
+  }
 
   autoSync(BuildContext context) async {
+    // Get the job ID finder function
+    String Function(String) findJobIdByApiName = await _getJobIdFinder();
+
     await syncResponseService
-        .getGlobalParamsSync(false)
+        .getMasterDataSync(false, findJobIdByApiName("masterSyncJob"))
         .then((Sync getAutoSync) async {
       setCurrentProgressType(getAutoSync.syncType!);
       if (getAutoSync.errorCode == "") {
-        _policyKeySyncSuccess = true;
+        _globalParamsSyncSuccess = true;
         _currentSyncProgress = getAutoSync.syncProgress!;
         notifyListeners();
+        findJobIdByApiName = await _getJobIdFinder();
+
       } else {
-        log(AppLocalizations.of(context)!.global_params_sync_failed);
+        log(AppLocalizations.of(context)!.master_data_sync_failed);
       }
       notifyListeners();
     });
 
     await syncResponseService
-        .getMasterDataSync(false)
+        .getGlobalParamsSync(false, findJobIdByApiName("synchConfigDataJob"))
         .then((Sync getAutoSync) async {
       setCurrentProgressType(getAutoSync.syncType!);
       if (getAutoSync.errorCode == "") {
-        _globalParamsSyncSuccess = true;
+        _policyKeySyncSuccess = true;
         _currentSyncProgress = getAutoSync.syncProgress!;
         notifyListeners();
       } else {
-        log(AppLocalizations.of(context)!.master_data_sync_failed);
+        log(AppLocalizations.of(context)!.global_params_sync_failed);
       }
       notifyListeners();
     });
 
     await syncResponseService
-        .getUserDetailsSync(false)
+        .getUserDetailsSync(false, findJobIdByApiName("userDetailServiceJob"))
         .then((Sync getAutoSync) async {
       setCurrentProgressType(getAutoSync.syncType!);
       if (getAutoSync.errorCode == "") {
@@ -138,7 +171,7 @@ class SyncProvider with ChangeNotifier {
     });
 
     await syncResponseService
-        .getPolicyKeySync(false)
+        .getPolicyKeySync(false, findJobIdByApiName("keyPolicySyncJob"))
         .then((Sync getAutoSync) async {
       setCurrentProgressType(getAutoSync.syncType!);
       if (getAutoSync.errorCode == "") {
@@ -151,7 +184,7 @@ class SyncProvider with ChangeNotifier {
       notifyListeners();
     });
 
-    await syncResponseService.getCaCertsSync(false).then((Sync getAutoSync) {
+    await syncResponseService.getCaCertsSync(false, findJobIdByApiName("syncCertificateJob")).then((Sync getAutoSync) {
       setCurrentProgressType(getAutoSync.syncType!);
       if (getAutoSync.errorCode == "") {
         _cacertsSyncSuccess = true;
@@ -163,7 +196,7 @@ class SyncProvider with ChangeNotifier {
       notifyListeners();
     });
 
-    await syncResponseService.getKernelCertsSync(false).then((Sync getAutoSync) {
+    await syncResponseService.getKernelCertsSync(false, findJobIdByApiName("publicKeySyncJob")).then((Sync getAutoSync) {
       setCurrentProgressType(getAutoSync.syncType!);
       if (getAutoSync.errorCode == "") {
         _kernelCertsSyncSuccess = true;
@@ -193,19 +226,22 @@ class SyncProvider with ChangeNotifier {
 
   manualSync() async {
     isSyncInProgress = true;
-    Sync syncResult = await syncResponseService.getMasterDataSync(true);
+    // Get the job ID finder function
+    String Function(String) findJobIdByApiName = await _getJobIdFinder();
+    
+    Sync syncResult = await syncResponseService.getMasterDataSync(true, findJobIdByApiName("masterSyncJob"));
     if (syncResult.errorCode != null && syncResult.errorCode!.isEmpty) {
       syncResult = await syncResponseService.getIDSchemaSync(true);
       if (syncResult.errorCode != null && syncResult.errorCode!.isEmpty) {
-        syncResult = await syncResponseService.getUserDetailsSync(true);
+        syncResult = await syncResponseService.getUserDetailsSync(true, findJobIdByApiName("userDetailServiceJob"));
         if (syncResult.errorCode != null && syncResult.errorCode!.isEmpty) {
-          syncResult = await syncResponseService.getGlobalParamsSync(true);
+          syncResult = await syncResponseService.getGlobalParamsSync(true, findJobIdByApiName("synchConfigDataJob"));
           if (syncResult.errorCode != null && syncResult.errorCode!.isEmpty) {
-            syncResult = await syncResponseService.getKernelCertsSync(true);
+            syncResult = await syncResponseService.getKernelCertsSync(true, findJobIdByApiName("publicKeySyncJob"));
             if (syncResult.errorCode != null && syncResult.errorCode!.isEmpty) {
-              syncResult = await syncResponseService.getPolicyKeySync(true);
+              syncResult = await syncResponseService.getPolicyKeySync(true, findJobIdByApiName("keyPolicySyncJob"));
               if (syncResult.errorCode != null && syncResult.errorCode!.isEmpty) {
-                syncResult = await syncResponseService.getCaCertsSync(true);
+                syncResult = await syncResponseService.getCaCertsSync(true, findJobIdByApiName("syncCertificateJob"));
                 await getLastSyncTime();
                 isSyncInProgress= false;
               }
@@ -221,6 +257,27 @@ class SyncProvider with ChangeNotifier {
   }
 
   getPreRegistrationIds() async {
-    await syncResponseService.getPreRegIds();
+    String Function(String) findJobIdByApiName = await _getJobIdFinder();
+    await syncResponseService.getPreRegIds(findJobIdByApiName("preRegistrationDataSyncJob"));
+  }
+
+  Future getLastSyncTimeByJobId(String jobId) async {
+    try {
+      final value = await syncResponseService.getLastSyncTimeByJobId(jobId);
+      return value;
+    } catch (e) {
+      log("Failed to get last sync time for job $jobId: $e");
+      return null;
+    }
+  }
+
+  Future getNextSyncTimeByJobId(String jobId) async {
+    try {
+      final value = await syncResponseService.getNextSyncTimeByJobId(jobId);
+      return value;
+    } catch (e) {
+      log("Failed to get next sync time for job $jobId: $e");
+      return null;
+    }
   }
 }
diff --git a/lib/ui/settings/settings_screen.dart b/lib/ui/settings/settings_screen.dart
index 020eda4e0..30a4e15bf 100644
--- a/lib/ui/settings/settings_screen.dart
+++ b/lib/ui/settings/settings_screen.dart
@@ -8,6 +8,8 @@ import 'package:registration_client/provider/global_provider.dart';
 import 'package:registration_client/ui/process_ui/widgets/device_settings_tab.dart';
 import 'package:registration_client/utils/app_config.dart';
 import 'package:flutter_gen/gen_l10n/app_localizations.dart';
+import 'package:registration_client/platform_spi/sync_response_service.dart';
+import 'widgets/scheduled_jobs_settings.dart';
 
 import 'widgets/global_config_settings_tab.dart';
 
@@ -28,12 +30,16 @@ class _SettingsScreenState extends State {
   List settingUiByRole  = [];
   bool isLoadingUiSpec = true;
   late AuthProvider authProvider;
+  late SyncResponseService syncResponseService;
+  List activeJobs = const [];
 
   @override
   void initState() {
     super.initState();
     authProvider = Provider.of(context, listen: false);
+    syncResponseService = SyncResponseService();
     _loadUiSpec();
+    _loadActiveJobs();
   }
 
   Future _loadUiSpec() async {
@@ -56,6 +62,17 @@ class _SettingsScreenState extends State {
     setState(() => isLoadingUiSpec = false);
   }
 
+  Future _loadActiveJobs() async {
+    try {
+      final jobs = await syncResponseService.getActiveSyncJobs();
+      setState(() {
+        activeJobs = jobs;
+      });
+    } catch (e) {
+      debugPrint('Failed to load active sync jobs: $e');
+    }
+  }
+
   @override
   Widget build(BuildContext context) {
     if (isLoadingUiSpec) {
@@ -133,7 +150,7 @@ class _SettingsScreenState extends State {
             ),
           ),
           SizedBox(
-            height: MediaQuery.of(context).size.height/1.4,
+            height: MediaQuery.of(context).size.height,
             child: TabBarView(
               children: [
                 for (final settings in settingUiByRole) _buildTabContent(settings),
@@ -159,8 +176,8 @@ class _SettingsScreenState extends State {
     final controllerName = _getControllerName(settings);
 
     switch (controllerName) {
-      case 'ScheduledJobsController':
-        return Center(child: Text("${settings.name}"));
+      case 'ScheduledJobsSettingsController':
+        return ScheduledJobsSettings(jobJsonList: activeJobs);
       case 'GlobalConfigSettingsController':
         return const GlobalConfigSettingsTab();
       case 'DeviceSettingsController':
diff --git a/lib/ui/settings/widgets/Scheduled_jobs_settings.dart b/lib/ui/settings/widgets/Scheduled_jobs_settings.dart
new file mode 100644
index 000000000..61daa6540
--- /dev/null
+++ b/lib/ui/settings/widgets/Scheduled_jobs_settings.dart
@@ -0,0 +1,252 @@
+import 'dart:convert';
+import 'package:flutter/material.dart';
+import 'package:intl/intl.dart';
+import 'package:flutter_gen/gen_l10n/app_localizations.dart';
+import 'package:provider/provider.dart';
+import 'package:registration_client/platform_spi/sync_response_service.dart';
+import 'package:registration_client/utils/sync_job_def.dart';
+
+import '../../../provider/sync_provider.dart';
+
+// Dart equivalent of the Java PACKET_JOBS constant
+const List PACKET_JOBS = ['RPS_J00006', 'RSJ_J00014', 'PUJ_J00017', 'PVS_J00015'];
+
+class ScheduledJobsSettings extends StatelessWidget {
+  const ScheduledJobsSettings({
+    super.key,
+    required this.jobJsonList,
+    this.onRefreshJob,
+  });
+
+  final List jobJsonList;
+  final void Function(String jobId)? onRefreshJob;
+
+  @override
+  Widget build(BuildContext context) {
+    final jobs = jobJsonList
+        .whereType()
+        .map((e) => _ScheduledJob.fromJson(json.decode(e) as Map))
+        .toList();
+
+    return Padding(
+      padding: const EdgeInsets.all(12.0),
+      child: Column(
+        crossAxisAlignment: CrossAxisAlignment.start,
+        children: [
+          Text(
+            AppLocalizations.of(context)!.scheduled_job_settings,
+            style: const TextStyle(fontSize: 20, fontWeight: FontWeight.w600),
+          ),
+          const SizedBox(height: 12),
+          LayoutBuilder(
+            builder: (context, constraints) {
+              int crossAxisCount = 1;
+              if (constraints.maxWidth >= 1200) {
+                crossAxisCount = 3;
+              } else if (constraints.maxWidth >= 700) {
+                crossAxisCount = 2;
+              }
+              return GridView.builder(
+                shrinkWrap: true,
+                physics: const NeverScrollableScrollPhysics(),
+                gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
+                  crossAxisCount: crossAxisCount,
+                  mainAxisSpacing: 12,
+                  crossAxisSpacing: 12,
+                  childAspectRatio: 3.5,
+                ),
+                itemCount: jobs.length,
+                itemBuilder: (context, index) {
+                  final job = jobs[index];
+                  return _JobCard(job: job, onRefresh: onRefreshJob);
+                },
+              );
+            },
+          ),
+        ],
+      ),
+    );
+  }
+}
+
+class _JobCard extends StatefulWidget {
+  const _JobCard({required this.job, this.onRefresh});
+  final _ScheduledJob job;
+  final void Function(String jobId)? onRefresh;
+
+  @override
+  State<_JobCard> createState() => _JobCardState();
+}
+
+class _JobCardState extends State<_JobCard> {
+  String? _lastSync;
+  String? _nextSync;
+  late SyncProvider syncProvider;
+
+
+  @override
+  void initState() {
+    super.initState();
+    syncProvider = Provider.of(context, listen: false);
+    _loadLastSyncTime(); // Fetch last sync when widget loads
+    _loadNextSyncTime();
+  }
+
+  Future _loadLastSyncTime() async {
+    if (widget.job.id != null && widget.job.id!.isNotEmpty) {
+      final value = await syncProvider.getLastSyncTimeByJobId(widget.job.id!);
+      setState(() => _lastSync = value ?? '-');
+      if (widget.job.apiName == "masterSyncJob" && _lastSync == "NA") {
+        _lastSync = formatDate(syncProvider.lastSuccessfulSyncTime);
+        setState(() {});
+      }
+    } else {
+      setState(() => _lastSync = '-');
+    }
+  }
+
+  String formatDate(String dateString) {
+    // Parse the input UTC date string
+    DateTime dateTime = DateTime.parse(dateString).toLocal(); // Convert to local time
+
+    // Format the date
+    String formattedDate = DateFormat("yyyy-MMM-dd HH:mm:ss").format(dateTime);
+
+    return formattedDate;
+  }
+
+  Future _loadNextSyncTime() async {
+    if (widget.job.id != null && widget.job.id!.isNotEmpty) {
+      final value = await syncProvider.getNextSyncTimeByJobId(widget.job.id!);
+      setState(() => _nextSync = value ?? '-');
+    } else {
+      setState(() => _nextSync = '-');
+    }
+  }
+
+  Future _triggerJobSync(BuildContext context, String? apiName, String? jobId) async {
+    if (apiName == null || apiName.isEmpty) return;
+    final service = SyncResponseService();
+
+    try {
+      switch (apiName) {
+        case 'masterSyncJob':
+          await service.getMasterDataSync(true, jobId ?? '');
+          break;
+        case 'keyPolicySyncJob':
+          await service.getPolicyKeySync(true, jobId ?? '');
+          break;
+        case 'preRegistrationDataSyncJob':
+          await service.getPreRegIds(jobId ?? '');
+          break;
+        case 'userDetailServiceJob':
+          await service.getUserDetailsSync(true, jobId ?? '');
+          break;
+        case 'syncCertificateJob':
+          await service.getCaCertsSync(true, jobId ?? '');
+          break;
+        case 'publicKeySyncJob':
+          await service.getKernelCertsSync(true, jobId ?? '');
+          break;
+        case 'deleteAuditLogsJob':
+          await service.deleteAuditLogs(jobId ?? '');
+          break;
+        case 'synchConfigDataJob':
+          await service.getGlobalParamsSync(true, jobId ?? '');
+          break;
+        case 'preRegistrationPacketDeletionJob':
+          await service.deletePreRegRecords(jobId ?? '');
+          break;
+        default:
+          debugPrint('No handler for sync job: $apiName');
+          return;
+      }
+
+      // Refresh last and next sync time after successful sync
+      await _loadLastSyncTime();
+      await _loadNextSyncTime();
+
+    } catch (e) {
+      debugPrint('Sync failed for ${widget.job.id}: $e');
+    }
+  }
+
+
+  @override
+  Widget build(BuildContext context) {
+    final job = widget.job;
+
+    return Container(
+      decoration: BoxDecoration(
+        color: Colors.white,
+        borderRadius: BorderRadius.circular(8),
+        border: Border.all(color: const Color(0xFFE5EBFA), width: 0.8),
+        boxShadow: const [BoxShadow(color: Color(0x11000000), blurRadius: 4, offset: Offset(0, 2))],
+      ),
+      child: Padding(
+        padding: const EdgeInsets.all(12.0),
+        child: Row(
+          crossAxisAlignment: CrossAxisAlignment.start,
+          children: [
+            Expanded(
+              child: Column(
+                crossAxisAlignment: CrossAxisAlignment.start,
+                children: [
+                  Text(job.name ?? job.apiName ?? 'Unknown Job',
+                      style: const TextStyle(fontSize: 16, fontWeight: FontWeight.w600)),
+                  const SizedBox(height: 8),
+                  _kv('Next Run', _nextSync ?? '-'),
+                  _kv('Last Sync', _lastSync ?? '-'),
+                  const SizedBox(height: 6),
+                  _kv('Cron Expression', job.syncFreq ?? '-'),
+                ],
+              ),
+            ),
+            if (!PACKET_JOBS.contains(job.id))
+              SizedBox(
+                width: 40,
+                child: OutlinedButton(
+                  onPressed: () => _triggerJobSync(context, job.apiName, job.id),
+                  style: OutlinedButton.styleFrom(
+                    padding: EdgeInsets.zero,
+                    minimumSize: const Size(40, 40),
+                    side: const BorderSide(color: Color(0xFF2A4EA7)),
+                  ),
+                  child: const Icon(Icons.sync, size: 20, color: Color(0xFF2A4EA7)),
+                ),
+              ),
+          ],
+        ),
+      ),
+    );
+  }
+
+  Widget _kv(String k, String v) => Row(
+    children: [
+      Text(k, style: const TextStyle(fontSize: 12, color: Colors.black54)),
+      const SizedBox(width: 8),
+      Flexible(
+          child: Text(v, style: const TextStyle(fontSize: 12, color: Colors.black87))),
+    ],
+  );
+}
+
+class _ScheduledJob {
+  _ScheduledJob({required this.syncJobDef, this.nextRun, this.lastRun});
+
+  final SyncJobDef syncJobDef;
+  final String? nextRun;
+  final String? lastRun;
+
+  // Convenience getters to maintain compatibility
+  String? get id => syncJobDef.id;
+  String? get name => syncJobDef.name;
+  String? get apiName => syncJobDef.apiName;
+  String? get syncFreq => syncJobDef.syncFreq;
+
+  factory _ScheduledJob.fromJson(Map json) => _ScheduledJob(
+    syncJobDef: SyncJobDef.fromJson(json),
+    nextRun: null,
+    lastRun: null,
+  );
+}
\ No newline at end of file
diff --git a/lib/utils/sync_job_def.dart b/lib/utils/sync_job_def.dart
new file mode 100644
index 000000000..977b5feea
--- /dev/null
+++ b/lib/utils/sync_job_def.dart
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) Modular Open Source Identity Platform
+ * This source code is licensed under the MIT license found in the
+ * LICENSE file in the root directory of this source tree.
+ *
+*/
+
+/// Model for SyncJobDef entity from Android
+class SyncJobDef {
+  final String? id;
+  final String? name;
+  final String? apiName;
+  final String? parentSyncJobId;
+  final String? syncFreq;
+  final String? lockDuration;
+  final String? langCode;
+  final bool? isDeleted;
+  final bool? isActive;
+
+  SyncJobDef({
+    this.id,
+    this.name,
+    this.apiName,
+    this.parentSyncJobId,
+    this.syncFreq,
+    this.lockDuration,
+    this.langCode,
+    this.isDeleted,
+    this.isActive,
+  });
+
+  factory SyncJobDef.fromJson(Map json) {
+    return SyncJobDef(
+      id: json['id'] as String?,
+      name: json['name'] as String?,
+      apiName: json['apiName'] as String?,
+      parentSyncJobId: json['parentSyncJobId'] as String?,
+      syncFreq: json['syncFreq'] as String?,
+      lockDuration: json['lockDuration'] as String?,
+      langCode: json['langCode'] as String?,
+      isDeleted: json['isDeleted'] as bool?,
+      isActive: json['isActive'] as bool?,
+    );
+  }
+}
diff --git a/pigeon/master_data_sync.dart b/pigeon/master_data_sync.dart
index 95790a32a..1ed9e9830 100644
--- a/pigeon/master_data_sync.dart
+++ b/pigeon/master_data_sync.dart
@@ -20,22 +20,22 @@ abstract class SyncApi {
   SyncTime getLastSyncTime();
 
   @async
-  Sync getPolicyKeySync(bool isManualSync);
+  Sync getPolicyKeySync(bool isManualSync, String jobId);
 
   @async
-  Sync getGlobalParamsSync(bool isManualSync);
+  Sync getGlobalParamsSync(bool isManualSync, String jobId);
 
   @async
-  Sync getUserDetailsSync(bool isManualSync);
+  Sync getUserDetailsSync(bool isManualSync, String jobId);
 
   @async
   Sync getIDSchemaSync(bool isManualSync);
 
   @async
-  Sync getMasterDataSync(bool isManualSync);
+  Sync getMasterDataSync(bool isManualSync, String jobId);
 
   @async
-  Sync getCaCertsSync(bool isManualSync);
+  Sync getCaCertsSync(bool isManualSync, String jobId);
 
   @async
   String batchJob();
@@ -44,9 +44,19 @@ abstract class SyncApi {
   List getReasonList(String langCode);
 
   @async
-  String getPreRegIds();
+  String getPreRegIds(String jobId);
   @async
-  Sync getKernelCertsSync(bool isManualSync);
+  Sync getKernelCertsSync(bool isManualSync, String jobId);
   @async
   bool getSyncAndUploadInProgressStatus();
+  @async
+  bool deleteAuditLogs(String jobId);
+  @async
+  bool deletePreRegRecords(String jobId);
+  @async
+  String getLastSyncTimeByJobId(String jobId);
+  @async
+  String getNextSyncTimeByJobId(String jobId);
+  @async
+  List getActiveSyncJobs();
 }

From dd2a0aba37e610ecb91a303ca91f0d42d072c675 Mon Sep 17 00:00:00 2001
From: Sachin S  P <52343650+SachinPremkumar@users.noreply.github.com>
Date: Fri, 31 Oct 2025 11:30:45 +0530
Subject: [PATCH 36/44] fixed build failure issue (#599)

Signed-off-by: sachin.sp 
Co-authored-by: sachin.sp 
---
 android/app/build.gradle | 2 +-
 pigeon.sh                | 5 +----
 2 files changed, 2 insertions(+), 5 deletions(-)

diff --git a/android/app/build.gradle b/android/app/build.gradle
index 17c60e724..0687753e5 100644
--- a/android/app/build.gradle
+++ b/android/app/build.gradle
@@ -136,7 +136,7 @@ dependencies {
     annotationProcessor 'com.google.dagger:dagger-android-processor:2.41'
     implementation 'androidx.appcompat:appcompat:1.4.1'
     implementation 'com.squareup.okhttp3:okhttp:4.9.2'
-    implementation 'com.squareup.okio:okio@1.17.6'
+    implementation 'com.squareup.okio:okio:3.4.0'
     implementation 'com.google.code.gson:gson:2.8.9'
     implementation 'com.google.android.material:material:1.4.0'
     implementation 'androidx.lifecycle:lifecycle-extensions:2.2.0'
diff --git a/pigeon.sh b/pigeon.sh
index 167072bdc..3d9033560 100644
--- a/pigeon.sh
+++ b/pigeon.sh
@@ -59,7 +59,4 @@ dart run pigeon --input pigeon/document_category.dart --dart_out lib/pigeon/docu
 dart run pigeon --input pigeon/dash_board.dart --dart_out lib/pigeon/dash_board_pigeon.dart --objc_header_out ios/Runner/pigeon.h --objc_source_out ios/Runner/pigeon.m --java_out ./android/app/src/main/java/io/mosip/registration_client/model/DashBoardPigeon.java --java_package "io.mosip.registration_client.model"
 
 # Generate global config settings files
-dart run pigeon --input pigeon/global_config_settings.dart --dart_out lib/pigeon/global_config_settings_pigeon.dart --objc_header_out ios/Runner/pigeon.h --objc_source_out ios/Runner/pigeon.m --java_out ./android/app/src/main/java/io/mosip/registration_client/model/GlobalConfigSettingsPigeon.java --java_package "io.mosip.registration_client.model"
-
-# Generate location pigeon files
-dart run pigeon --input pigeon/location.dart --dart_out lib/pigeon/location_pigeon.dart --objc_header_out ios/Runner/pigeon.h --objc_source_out ios/Runner/pigeon.m --java_out ./android/app/src/main/java/io/mosip/registration_client/model/LocationPigeon.java --java_package "io.mosip.registration_client.model"
\ No newline at end of file
+dart run pigeon --input pigeon/global_config_settings.dart --dart_out lib/pigeon/global_config_settings_pigeon.dart --objc_header_out ios/Runner/pigeon.h --objc_source_out ios/Runner/pigeon.m --java_out ./android/app/src/main/java/io/mosip/registration_client/model/GlobalConfigSettingsPigeon.java --java_package "io.mosip.registration_client.model"
\ No newline at end of file

From ec124742d7ff4d9f2091c317080a8197b2191798 Mon Sep 17 00:00:00 2001
From: Sachin S  P <52343650+SachinPremkumar@users.noreply.github.com>
Date: Fri, 31 Oct 2025 12:08:38 +0530
Subject: [PATCH 37/44] fixed build failure issue (#600)

Signed-off-by: sachin.sp 
Co-authored-by: sachin.sp 
---
 ...{Scheduled_jobs_settings.dart => scheduled_jobs_settings.dart} | 0
 1 file changed, 0 insertions(+), 0 deletions(-)
 rename lib/ui/settings/widgets/{Scheduled_jobs_settings.dart => scheduled_jobs_settings.dart} (100%)

diff --git a/lib/ui/settings/widgets/Scheduled_jobs_settings.dart b/lib/ui/settings/widgets/scheduled_jobs_settings.dart
similarity index 100%
rename from lib/ui/settings/widgets/Scheduled_jobs_settings.dart
rename to lib/ui/settings/widgets/scheduled_jobs_settings.dart

From e12a8dd78cd3f210d9e0c22c2b311503ddc19c58 Mon Sep 17 00:00:00 2001
From: Sachin S  P <52343650+SachinPremkumar@users.noreply.github.com>
Date: Fri, 7 Nov 2025 15:16:30 +0530
Subject: [PATCH 38/44] RCF-571: verify and save button twice to get onboard
 (#601)

Signed-off-by: sachin.sp 
Co-authored-by: sachin.sp 
---
 .../api_services/BiometricsDetailsApi.java    |  2 ++
 .../operator_biometrics_capture_view.dart     | 32 +++++++++----------
 2 files changed, 17 insertions(+), 17 deletions(-)

diff --git a/android/app/src/main/java/io/mosip/registration_client/api_services/BiometricsDetailsApi.java b/android/app/src/main/java/io/mosip/registration_client/api_services/BiometricsDetailsApi.java
index 0306ecfc0..e7b580b90 100644
--- a/android/app/src/main/java/io/mosip/registration_client/api_services/BiometricsDetailsApi.java
+++ b/android/app/src/main/java/io/mosip/registration_client/api_services/BiometricsDetailsApi.java
@@ -547,6 +547,8 @@ public void saveOperatorBiometrics(@NonNull BiometricsPigeon.Result resu
             userOnboardService.onboardOperator(userOnboardService.getOperatorBiometrics(), () -> {
                 if(userOnboardService.getIsOnboardSuccess()) {
                     result.success("OK");
+                } else {
+                    result.success("FAILED");
                 }
             });
         }catch (Exception e){
diff --git a/lib/ui/onboard/widgets/operator_biometrics_capture_view.dart b/lib/ui/onboard/widgets/operator_biometrics_capture_view.dart
index 87b03d798..35de245fc 100644
--- a/lib/ui/onboard/widgets/operator_biometrics_capture_view.dart
+++ b/lib/ui/onboard/widgets/operator_biometrics_capture_view.dart
@@ -236,12 +236,9 @@ class _OperatorBiometricsCaptureState
 
                   String isOperatorBiometricSaved = "";
                   await BiometricsApi().saveOperatorBiometrics().timeout(
-                    Duration(seconds: 10),
+                    const Duration(seconds: 30),
                     onTimeout: () {
-                      setState(() {
-                        isSavingBiometrics = false;
-                      });
-                      return "";
+                      return "TIMEOUT";
                     },
                   ).then((value) {
                     isOperatorBiometricSaved = value;
@@ -250,7 +247,8 @@ class _OperatorBiometricsCaptureState
                   setState(() {
                     isSavingBiometrics = false;
                   });
-                  if (isOperatorBiometricSaved != "") {
+                  
+                  if (isOperatorBiometricSaved == "OK") {
                     await context.read().getLastUpdatedTime();
                     Navigator.pop(context);
                     showDialog(
@@ -311,17 +309,6 @@ class _OperatorBiometricsCaptureState
                   }
                 }
               },
-              child: isSavingBiometrics
-                  ? CircularProgressIndicator(
-                color: appWhite,
-              )
-                  : Text(
-                appLocalizations.verify_and_save,
-                style: Theme.of(context)
-                    .textTheme
-                    .bodyLarge
-                    ?.copyWith(fontSize: 26.h, color: pureWhite),
-              ),
               style: OutlinedButton.styleFrom(
                   backgroundColor: (
                       ((globalProvider.operatorOnboardingAttributes
@@ -376,6 +363,17 @@ class _OperatorBiometricsCaptureState
                               biometricCaptureControlProvider.face.isScanned) : true))
                       ? solidPrimary
                       : secondaryColors.elementAt(22)),
+              child: isSavingBiometrics
+                  ? const CircularProgressIndicator(
+                color: appWhite,
+              )
+                  : Text(
+                appLocalizations.verify_and_save,
+                style: Theme.of(context)
+                    .textTheme
+                    .bodyLarge
+                    ?.copyWith(fontSize: 26.h, color: pureWhite),
+              ),
             ),
           ),
         ),

From a01fc5b1b19c95fa1d1c5e41c460506f051ecf1d Mon Sep 17 00:00:00 2001
From: Madhuravas reddy 
Date: Fri, 7 Nov 2025 15:25:14 +0530
Subject: [PATCH 39/44] RCF-1266 resolved schoduled jobs alignment issues
 (#608)

Signed-off-by: Madhuravas Reddy 
---
 .../widgets/scheduled_jobs_settings.dart      | 72 +++++++++++--------
 1 file changed, 41 insertions(+), 31 deletions(-)

diff --git a/lib/ui/settings/widgets/scheduled_jobs_settings.dart b/lib/ui/settings/widgets/scheduled_jobs_settings.dart
index 61daa6540..e253d2707 100644
--- a/lib/ui/settings/widgets/scheduled_jobs_settings.dart
+++ b/lib/ui/settings/widgets/scheduled_jobs_settings.dart
@@ -28,41 +28,51 @@ class ScheduledJobsSettings extends StatelessWidget {
         .map((e) => _ScheduledJob.fromJson(json.decode(e) as Map))
         .toList();
 
-    return Padding(
-      padding: const EdgeInsets.all(12.0),
-      child: Column(
-        crossAxisAlignment: CrossAxisAlignment.start,
-        children: [
-          Text(
-            AppLocalizations.of(context)!.scheduled_job_settings,
-            style: const TextStyle(fontSize: 20, fontWeight: FontWeight.w600),
+    final bottomInset = MediaQuery.of(context).padding.bottom;
+    final bottomSpacer = bottomInset + kBottomNavigationBarHeight + 230;
+    final mediaSize = MediaQuery.of(context).size;
+    final bool isTablet = mediaSize.shortestSide <= 450;
+    final int crossAxisCount = isTablet ? 1 : 2;
+    final double childAspectRatio = MediaQuery.of(context).orientation == Orientation.landscape ? 5 : 3;
+    return SafeArea(
+      top: false,
+      bottom: true,
+      child: CustomScrollView(
+        slivers: [
+          SliverPadding(
+            padding: const EdgeInsets.all(12.0),
+            sliver: SliverToBoxAdapter(
+              child: Column(
+                crossAxisAlignment: CrossAxisAlignment.start,
+                children: [
+                  Text(
+                    AppLocalizations.of(context)!.scheduled_job_settings,
+                    style: const TextStyle(fontSize: 20, fontWeight: FontWeight.w600),
+                  ),
+                  const SizedBox(height: 12),
+                ],
+              ),
+            ),
           ),
-          const SizedBox(height: 12),
-          LayoutBuilder(
-            builder: (context, constraints) {
-              int crossAxisCount = 1;
-              if (constraints.maxWidth >= 1200) {
-                crossAxisCount = 3;
-              } else if (constraints.maxWidth >= 700) {
-                crossAxisCount = 2;
-              }
-              return GridView.builder(
-                shrinkWrap: true,
-                physics: const NeverScrollableScrollPhysics(),
-                gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
-                  crossAxisCount: crossAxisCount,
-                  mainAxisSpacing: 12,
-                  crossAxisSpacing: 12,
-                  childAspectRatio: 3.5,
-                ),
-                itemCount: jobs.length,
-                itemBuilder: (context, index) {
+          SliverPadding(
+            padding: const EdgeInsets.symmetric(horizontal: 12.0),
+              sliver: SliverGrid(
+              gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
+                crossAxisCount: crossAxisCount,
+                  mainAxisSpacing: 8,
+                crossAxisSpacing: 12,
+                  childAspectRatio: childAspectRatio,
+              ),
+              delegate: SliverChildBuilderDelegate(
+                (context, index) {
                   final job = jobs[index];
                   return _JobCard(job: job, onRefresh: onRefreshJob);
                 },
-              );
-            },
+                childCount: jobs.length,
+              ),
+            ),
           ),
+          SliverToBoxAdapter(child: SizedBox(height: bottomSpacer)),
         ],
       ),
     );
@@ -184,7 +194,7 @@ class _JobCardState extends State<_JobCard> {
         boxShadow: const [BoxShadow(color: Color(0x11000000), blurRadius: 4, offset: Offset(0, 2))],
       ),
       child: Padding(
-        padding: const EdgeInsets.all(12.0),
+        padding: const EdgeInsets.all(10.0),
         child: Row(
           crossAxisAlignment: CrossAxisAlignment.start,
           children: [

From a4312f31959f0e337bad2c431be82a594cb26346 Mon Sep 17 00:00:00 2001
From: Rakshithasai123 
Date: Fri, 7 Nov 2025 15:26:56 +0530
Subject: [PATCH 40/44] Fixed-In the global config settings page the Global
 Config settings heading is not displaying (#607)

Signed-off-by: Rakshithasai123 
---
 lib/ui/settings/settings_screen.dart          |  2 +-
 .../widgets/global_config_settings_tab.dart   | 22 ++++++++++++++++++-
 2 files changed, 22 insertions(+), 2 deletions(-)

diff --git a/lib/ui/settings/settings_screen.dart b/lib/ui/settings/settings_screen.dart
index 30a4e15bf..a8aa1482e 100644
--- a/lib/ui/settings/settings_screen.dart
+++ b/lib/ui/settings/settings_screen.dart
@@ -179,7 +179,7 @@ class _SettingsScreenState extends State {
       case 'ScheduledJobsSettingsController':
         return ScheduledJobsSettings(jobJsonList: activeJobs);
       case 'GlobalConfigSettingsController':
-        return const GlobalConfigSettingsTab();
+        return GlobalConfigSettingsTab(settings: settings,selectedLan: selectedLang);
       case 'DeviceSettingsController':
         return DeviceSettingsTab(settings: settings, selectedLan: selectedLang);
       default:
diff --git a/lib/ui/settings/widgets/global_config_settings_tab.dart b/lib/ui/settings/widgets/global_config_settings_tab.dart
index ba8b7bd47..7096bdb07 100644
--- a/lib/ui/settings/widgets/global_config_settings_tab.dart
+++ b/lib/ui/settings/widgets/global_config_settings_tab.dart
@@ -1,5 +1,6 @@
 import 'package:flutter/material.dart';
 import 'package:registration_client/utils/app_config.dart';
+import '../../../model/settings.dart';
 import '../../../pigeon/common_details_pigeon.dart';
 import '../../../pigeon/global_config_settings_pigeon.dart';
 import 'package:flutter_gen/gen_l10n/app_localizations.dart';
@@ -8,7 +9,9 @@ import '../../../provider/global_provider.dart';
 import 'package:restart_app/restart_app.dart';
 
 class GlobalConfigSettingsTab extends StatefulWidget {
-  const GlobalConfigSettingsTab({Key? key}) : super(key: key);
+  final Settings settings;
+  final String selectedLan;
+  GlobalConfigSettingsTab({Key? key,required this.settings,required this.selectedLan,}) : super(key: key);
 
   @override
   State createState() =>
@@ -240,6 +243,10 @@ class _GlobalConfigSettingsTabState extends State {
 
   @override
   Widget build(BuildContext context) {
+    final heading = widget.settings.label?[widget.selectedLan] ??
+        widget.settings.label?['eng'] ??
+        (widget.settings.label?.values.first ?? 'Unknown');
+
     return Scaffold(
       body: Card(
         margin: const EdgeInsets.all(5),
@@ -248,7 +255,20 @@ class _GlobalConfigSettingsTabState extends State {
           borderRadius: BorderRadius.circular(4),
         ),
         child: Column(
+          crossAxisAlignment: CrossAxisAlignment.start,
           children: [
+            const SizedBox(height: 10),
+            Padding(
+              padding: const EdgeInsets.only(left: 12.0, right: 8.0),
+              child: Text(
+                heading,
+                style: const TextStyle(
+                  fontSize: 20,
+                  fontWeight: FontWeight.w600,
+                ),
+              ),
+            ),
+            const SizedBox(height: 12),
             Container(
               padding: const EdgeInsets.all(16),
               decoration: BoxDecoration(

From 8caa7ffbc96f306d5ccc0ba10110c876713c4f72 Mon Sep 17 00:00:00 2001
From: Rakshithasai123 
Date: Fri, 7 Nov 2025 15:27:32 +0530
Subject: [PATCH 41/44] Instead of submit, better to have log as Authenticat at
 pending approvals page (#597)

Signed-off-by: Rakshithasai123 
---
 lib/ui/approve_packet/approve_packet_ui.dart | 26 ++++++++++----------
 1 file changed, 13 insertions(+), 13 deletions(-)

diff --git a/lib/ui/approve_packet/approve_packet_ui.dart b/lib/ui/approve_packet/approve_packet_ui.dart
index bf8512b7e..dbfe58ad6 100644
--- a/lib/ui/approve_packet/approve_packet_ui.dart
+++ b/lib/ui/approve_packet/approve_packet_ui.dart
@@ -62,20 +62,20 @@ class _ApprovePacketsPageState extends State {
             },
       style: ElevatedButton.styleFrom(
         backgroundColor: solidPrimary,
+        minimumSize: const Size(double.infinity, 60),
+        padding: const EdgeInsets.symmetric(horizontal: 4),
       ),
-      child: SizedBox(
-        height: 60,
-        child: Row(
-          mainAxisAlignment: MainAxisAlignment.center,
-          children: [
-            Text(
-              AppLocalizations.of(context)!.submit,
-              style: Theme.of(context)
-                  .textTheme
-                  .titleLarge
-                  ?.copyWith(color: Colors.white, fontSize: 17),
-            ),
-          ],
+      child: Center(
+        child: FittedBox(
+          fit: BoxFit.scaleDown,
+          child: Text(
+            appLocalizations.authenticate,
+            textAlign: TextAlign.center,
+            style: Theme.of(context)
+                .textTheme
+                .titleLarge
+                ?.copyWith(color: Colors.white, fontSize: 17),
+          ),
         ),
       ),
     );

From 7ed2205d9fc0366f0b74dfdb3c57a909bf33e205 Mon Sep 17 00:00:00 2001
From: Sachin S  P <52343650+SachinPremkumar@users.noreply.github.com>
Date: Fri, 7 Nov 2025 15:31:00 +0530
Subject: [PATCH 42/44] RCF-1177: pdf box security bug (#610)

Signed-off-by: sachin.sp 
Co-authored-by: sachin.sp 
---
 android/app/build.gradle           | 2 +-
 android/clientmanager/build.gradle | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/android/app/build.gradle b/android/app/build.gradle
index 0687753e5..8bc7b4ef4 100644
--- a/android/app/build.gradle
+++ b/android/app/build.gradle
@@ -293,7 +293,7 @@ dependencies {
     implementation 'org.apache.velocity:velocity:1.7'
     implementation 'org.mvel:mvel2:2.4.14.Final'
 
-    implementation('com.tom-roush:pdfbox-android:2.0.20.0') {
+    implementation('com.tom-roush:pdfbox-android:2.0.27.0') {
         exclude group: 'org.bouncycastle'
     }
 
diff --git a/android/clientmanager/build.gradle b/android/clientmanager/build.gradle
index 001ca3f2a..1b1cc29a7 100644
--- a/android/clientmanager/build.gradle
+++ b/android/clientmanager/build.gradle
@@ -124,7 +124,7 @@ dependencies {
     implementation 'org.apache.velocity:velocity:1.7'
     implementation 'org.mvel:mvel2:2.4.14.Final'
 
-    implementation('com.tom-roush:pdfbox-android:2.0.20.0') {
+    implementation('com.tom-roush:pdfbox-android:2.0.27.0') {
         exclude group: 'org.bouncycastle'
     }
 

From b77ee5f97b95a2e412ba12a12e1a36078ff1ebd9 Mon Sep 17 00:00:00 2001
From: Sachin S  P <52343650+SachinPremkumar@users.noreply.github.com>
Date: Fri, 7 Nov 2025 15:34:34 +0530
Subject: [PATCH 43/44] RCF-1260: Authenticate button not clickable (#603)

Signed-off-by: sachin.sp 
Co-authored-by: sachin.sp 
---
 .../service/RegistrationServiceImpl.java              | 11 +++++++++--
 lib/ui/process_ui/generic_process.dart                |  2 +-
 2 files changed, 10 insertions(+), 3 deletions(-)

diff --git a/android/clientmanager/src/main/java/io/mosip/registration/clientmanager/service/RegistrationServiceImpl.java b/android/clientmanager/src/main/java/io/mosip/registration/clientmanager/service/RegistrationServiceImpl.java
index fa63c2e3f..0a3da5c43 100644
--- a/android/clientmanager/src/main/java/io/mosip/registration/clientmanager/service/RegistrationServiceImpl.java
+++ b/android/clientmanager/src/main/java/io/mosip/registration/clientmanager/service/RegistrationServiceImpl.java
@@ -787,8 +787,15 @@ private void setBiometrics(RegistrationDto registrationDto) throws RegBaseChecke
         for(String key : registrationDto.EXCEPTIONS.keySet()) {
             String fieldId = key.split("_")[0];
             String bioAttribute = key.split("_")[1];
-            BIR bir = buildBIR(new BiometricsDto(null, bioAttribute, null, null, true, null, null, false, 0, 0.0, 0.0f));
-            capturedBiometrics.getOrDefault(fieldId, new ArrayList<>()).add(bir);
+            registrationDto.EXCEPTIONS.get(key).forEach((v) -> {
+                Modality modality = Modality.getModality(v);
+                BiometricsDto exceptionBiometricDto = new BiometricsDto(
+                        modality.getSingleType().value(),
+                        Modality.getSpecBioSubType(v),
+                        null, null, true, null, null, false, 0, 0.0, 0.0f);
+                BIR bir = buildBIR(exceptionBiometricDto);
+                capturedBiometrics.getOrDefault(fieldId, new ArrayList<>()).add(bir);
+            });
             exceptionMetaInfo.computeIfAbsent(fieldId, field -> new HashMap<>()).put(bioAttribute,
                     registrationDto.EXCEPTIONS.get(key));
         }
diff --git a/lib/ui/process_ui/generic_process.dart b/lib/ui/process_ui/generic_process.dart
index 13e1a93e4..9e5521a3c 100644
--- a/lib/ui/process_ui/generic_process.dart
+++ b/lib/ui/process_ui/generic_process.dart
@@ -695,7 +695,7 @@ class _GenericProcessState extends State
           }
           RegistrationSubmitResponse registrationSubmitResponse =
               await registrationTaskProvider.submitRegistrationDto(username);
-          if (registrationSubmitResponse.errorCode!.isNotEmpty) {
+          if (registrationSubmitResponse.errorCode != null && registrationSubmitResponse.errorCode!.isNotEmpty) {
             _showInSnackBar(registrationSubmitResponse.errorCode!);
             return;
           }

From b6f4a3f5e0409b85068ddaac1f6e8077058eb333 Mon Sep 17 00:00:00 2001
From: Sachin S  P <52343650+SachinPremkumar@users.noreply.github.com>
Date: Wed, 12 Nov 2025 12:12:18 +0530
Subject: [PATCH 44/44] RCF-1271 : DB migration logic and bug fix (#614)

* RCF-1271:DB migration logic and bug fix

Signed-off-by: sachin.sp 

* updated the review comment

Signed-off-by: sachin.sp 

---------

Signed-off-by: sachin.sp 
Co-authored-by: sachin.sp 
---
 .../clientmanager/config/ClientDatabase.java  | 22 +-----
 .../config/ClientDatabaseMigrations.java      | 76 +++++++++++++++++++
 .../clientmanager/config/RoomModule.java      |  1 +
 .../config/ClientDatabaseTest.java            | 15 ----
 .../clientmanager/config/RoomModuleTest.java  | 10 +++
 lib/ui/onboard/portrait/mobile_home_page.dart | 48 ++++++------
 lib/ui/settings/settings_screen.dart          |  6 +-
 .../widgets/global_config_settings_tab.dart   | 64 +++++++++-------
 8 files changed, 151 insertions(+), 91 deletions(-)
 create mode 100644 android/clientmanager/src/main/java/io/mosip/registration/clientmanager/config/ClientDatabaseMigrations.java

diff --git a/android/clientmanager/src/main/java/io/mosip/registration/clientmanager/config/ClientDatabase.java b/android/clientmanager/src/main/java/io/mosip/registration/clientmanager/config/ClientDatabase.java
index 1980ee8dc..3d6965edb 100644
--- a/android/clientmanager/src/main/java/io/mosip/registration/clientmanager/config/ClientDatabase.java
+++ b/android/clientmanager/src/main/java/io/mosip/registration/clientmanager/config/ClientDatabase.java
@@ -72,25 +72,9 @@
         BlocklistedWord.class, SyncJobDef.class, UserDetail.class, UserBiometric.class, UserPassword.class, JobTransaction.class,
         CACertificateStore.class, Language.class, Audit.class, FileSignature.class, ProcessSpec.class,PreRegistrationList.class,
         PermittedLocalConfig.class, LocalPreferences.class},
-        version = 1, exportSchema = false)
+        version = 2, exportSchema = false)
 public abstract class ClientDatabase extends RoomDatabase {
 
-    private static final String DATABASE_NAME = "regclient";
-    private static ClientDatabase INSTANCE;
-
-    public synchronized static ClientDatabase getDatabase(Context context) {
-        if (INSTANCE == null) {
-            INSTANCE = buildDatabase(context);
-        }
-        return INSTANCE;
-    }
-
-    public static ClientDatabase buildDatabase(Context context) {
-        return Room.databaseBuilder(context, ClientDatabase.class, DATABASE_NAME)
-                .allowMainThreadQueries()
-                .build();
-    }
-
     public abstract UserTokenDao userTokenDao();
 
     public abstract UserRoleDao userRoleDao();
@@ -148,10 +132,6 @@ public static ClientDatabase buildDatabase(Context context) {
     public abstract PermittedLocalConfigDao permittedLocalConfigDao();
 
     public abstract LocalPreferencesDao localPreferencesDao();
-
-    public static void destroyDB() {
-        INSTANCE = null;
-    }
 }
 
 
diff --git a/android/clientmanager/src/main/java/io/mosip/registration/clientmanager/config/ClientDatabaseMigrations.java b/android/clientmanager/src/main/java/io/mosip/registration/clientmanager/config/ClientDatabaseMigrations.java
new file mode 100644
index 000000000..73d7cc09d
--- /dev/null
+++ b/android/clientmanager/src/main/java/io/mosip/registration/clientmanager/config/ClientDatabaseMigrations.java
@@ -0,0 +1,76 @@
+package io.mosip.registration.clientmanager.config;
+
+import android.util.Log;
+
+import androidx.annotation.NonNull;
+import androidx.room.migration.Migration;
+import androidx.sqlite.db.SupportSQLiteDatabase;
+import android.database.Cursor;
+
+public final class ClientDatabaseMigrations {
+
+    private static final String TAG = ClientDatabaseMigrations.class.getSimpleName();
+
+    private ClientDatabaseMigrations() {}
+
+    public static final Migration MIGRATION_1_2 = new Migration(1, 2) {
+        @Override
+        public void migrate(@NonNull SupportSQLiteDatabase database) {
+            database.execSQL("CREATE TABLE IF NOT EXISTS `permitted_local_config` (" +
+                    "`code` TEXT NOT NULL, " +
+                    "`name` TEXT, " +
+                    "`config_type` TEXT, " +
+                    "`is_active` INTEGER, " +
+                    "`is_deleted` INTEGER, " +
+                    "`del_dtimes` INTEGER, " +
+                    "PRIMARY KEY(`code`))");
+
+            database.execSQL("CREATE TABLE IF NOT EXISTS `local_preferences` (" +
+                    "`id` TEXT NOT NULL, " +
+                    "`name` TEXT, " +
+                    "`val` TEXT, " +
+                    "`config_type` TEXT, " +
+                    "`cr_by` TEXT, " +
+                    "`cr_dtime` INTEGER, " +
+                    "`upd_by` TEXT, " +
+                    "`upd_dtimes` INTEGER, " +
+                    "`is_deleted` INTEGER, " +
+                    "`del_dtimes` INTEGER, " +
+                    "PRIMARY KEY(`id`))");
+
+            database.execSQL("CREATE TABLE IF NOT EXISTS `user_role` (" +
+                    "`usr_id` TEXT NOT NULL, " +
+                    "`role_code` TEXT NOT NULL, " +
+                    "`lang_code` TEXT, " +
+                    "PRIMARY KEY(`usr_id`, `role_code`))");
+
+            if (!hasColumn(database, "registration", "id")) {
+                database.execSQL("ALTER TABLE `registration` ADD COLUMN `id` TEXT");
+            }
+
+            // Note: This UPDATE has no effect on fresh migrations since local_preferences was just created empty.
+            // Remove if not needed for schema correction scenarios.
+            database.execSQL("UPDATE local_preferences SET config_type = 'CONFIGURATION' WHERE config_type IS NULL");
+            Log.i(TAG, "Migration 1_2 completed successfully.");
+        }
+    };
+
+    private static boolean hasColumn(@NonNull SupportSQLiteDatabase database, @NonNull String table, @NonNull String column) {
+        Cursor cursor = null;
+        try {
+            cursor = database.query("PRAGMA table_info(`" + table + "`)");
+            int nameIndex = cursor.getColumnIndex("name");
+            while (cursor.moveToNext()) {
+                if (column.equalsIgnoreCase(cursor.getString(nameIndex))) {
+                    return true;
+                }
+            }
+            return false;
+        } finally {
+            if (cursor != null) {
+                cursor.close();
+            }
+        }
+    }
+}
+
diff --git a/android/clientmanager/src/main/java/io/mosip/registration/clientmanager/config/RoomModule.java b/android/clientmanager/src/main/java/io/mosip/registration/clientmanager/config/RoomModule.java
index 8102ab32c..5a7741353 100644
--- a/android/clientmanager/src/main/java/io/mosip/registration/clientmanager/config/RoomModule.java
+++ b/android/clientmanager/src/main/java/io/mosip/registration/clientmanager/config/RoomModule.java
@@ -112,6 +112,7 @@ public RoomModule(Application application, ApplicationInfo applicationInfo) {
             }
             clientDatabase = Room.databaseBuilder(application, ClientDatabase.class, DATABASE_NAME)
                     .openHelperFactory(new SupportFactory(dbPwd.getBytes()))
+                    .addMigrations(ClientDatabaseMigrations.MIGRATION_1_2)
                     .allowMainThreadQueries()
                     .build();
         } catch (Exception e) {
diff --git a/android/clientmanager/src/test/java/io/mosip/registration/clientmanager/config/ClientDatabaseTest.java b/android/clientmanager/src/test/java/io/mosip/registration/clientmanager/config/ClientDatabaseTest.java
index 32851e1fa..325711ba4 100644
--- a/android/clientmanager/src/test/java/io/mosip/registration/clientmanager/config/ClientDatabaseTest.java
+++ b/android/clientmanager/src/test/java/io/mosip/registration/clientmanager/config/ClientDatabaseTest.java
@@ -30,21 +30,6 @@ public void tearDown() {
         clientDatabase.close();
     }
 
-    @Test
-    public void testGetDatabase_SingletonInstance() {
-        ClientDatabase instance1 = ClientDatabase.getDatabase(context);
-        ClientDatabase instance2 = ClientDatabase.getDatabase(context);
-        assertSame(instance1, instance2);
-    }
-
-    @Test
-    public void testDestroyDB_CreatesNewInstance() {
-        ClientDatabase instance1 = ClientDatabase.getDatabase(context);
-        ClientDatabase.destroyDB();
-        ClientDatabase instance2 = ClientDatabase.getDatabase(context);
-        assertNotSame(instance1, instance2);
-    }
-
     @Test
     public void testDaos_NotNull() {
         assertNotNull(clientDatabase.userTokenDao());
diff --git a/android/clientmanager/src/test/java/io/mosip/registration/clientmanager/config/RoomModuleTest.java b/android/clientmanager/src/test/java/io/mosip/registration/clientmanager/config/RoomModuleTest.java
index 6bf5c156a..531adf075 100644
--- a/android/clientmanager/src/test/java/io/mosip/registration/clientmanager/config/RoomModuleTest.java
+++ b/android/clientmanager/src/test/java/io/mosip/registration/clientmanager/config/RoomModuleTest.java
@@ -8,6 +8,7 @@
 import androidx.annotation.NonNull;
 import androidx.room.Room;
 import androidx.room.RoomDatabase;
+import androidx.room.migration.Migration;
 import androidx.security.crypto.EncryptedSharedPreferences;
 import androidx.security.crypto.MasterKey;
 
@@ -42,6 +43,8 @@
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
+import io.mosip.registration.clientmanager.config.ClientDatabaseMigrations;
+
 @RunWith(MockitoJUnitRunner.class)
 public class RoomModuleTest {
 
@@ -98,10 +101,13 @@ public void setUp() throws Exception {
                     .thenReturn(sharedPreferences);
 
             when(builder.openHelperFactory(any(SupportFactory.class))).thenReturn(builder);
+            when(builder.addMigrations(any(Migration[].class))).thenReturn(builder);
             when(builder.allowMainThreadQueries()).thenReturn(builder);
             when(builder.build()).thenReturn(clientDatabase);
 
             roomModule = new RoomModule(application, applicationInfo);
+
+            verify(builder).addMigrations(ClientDatabaseMigrations.MIGRATION_1_2);
         }
     }
 
@@ -125,6 +131,7 @@ public void testConstructor_DebugMode_UsesDebugPassword() {
                     .thenReturn(sharedPreferences);
 
             when(builder.openHelperFactory(any(SupportFactory.class))).thenReturn(builder);
+            when(builder.addMigrations(any(Migration[].class))).thenReturn(builder);
             when(builder.allowMainThreadQueries()).thenReturn(builder);
             when(builder.build()).thenReturn(clientDatabase);
             when(sharedPreferences.edit()).thenReturn(editor);
@@ -134,6 +141,7 @@ public void testConstructor_DebugMode_UsesDebugPassword() {
 
             verify(editor).putString("db_password", BuildConfig.DEBUG_PASSWORD);
             verify(editor).apply();
+            verify(builder).addMigrations(ClientDatabaseMigrations.MIGRATION_1_2);
         }
     }
 
@@ -175,6 +183,7 @@ public void testConstructor_EncryptExistingDb_Success() throws Exception {
                     .thenReturn(sharedPreferences);
 
             when(builder.openHelperFactory(any(SupportFactory.class))).thenReturn(builder);
+            when(builder.addMigrations(any(Migration[].class))).thenReturn(builder);
             when(builder.allowMainThreadQueries()).thenReturn(builder);
             when(builder.build()).thenReturn(clientDatabase);
             doNothing().when(existingDb).rawExecSQL(anyString());
@@ -190,6 +199,7 @@ public void testConstructor_EncryptExistingDb_Success() throws Exception {
             verify(sharedPreferences).edit();
             verify(editor).putString(eq("db_password"), anyString());
             verify(editor).apply();
+            verify(builder).addMigrations(ClientDatabaseMigrations.MIGRATION_1_2);
         }
     }
 
diff --git a/lib/ui/onboard/portrait/mobile_home_page.dart b/lib/ui/onboard/portrait/mobile_home_page.dart
index 21a38ccc3..6d4899af2 100644
--- a/lib/ui/onboard/portrait/mobile_home_page.dart
+++ b/lib/ui/onboard/portrait/mobile_home_page.dart
@@ -50,7 +50,7 @@ class _MobileHomePageState extends State {
 
   @override
   Widget build(BuildContext context) {
-    List bottomNavPages = [
+    List bottomNavPages = [
       const UserDashBoard(),
       SettingsScreen(
         getSettingsUI: (BuildContext context) async {
@@ -87,30 +87,30 @@ class _MobileHomePageState extends State {
     return SafeArea(
       child: Scaffold(
         bottomNavigationBar: _getBottomNavigationBar(),
-        body: SingleChildScrollView(
-          child: Column(
-            children: [
-              bottomNavPages[selectedTab],
-              selectedTab != 1
-                  ? Text(
-                      "Community Registration - Client Version ${context.watch().versionNoApp}",
-                      style: TextStyle(
-                          color: const Color(0xff6F6E6E),
-                          fontSize: 14,
-                          fontWeight: regular),
-                    )
-                  : const SizedBox(),
-              selectedTab != 1
-                  ? Text(
-                      "Git Commit Id ${context.watch().commitIdApp}",
-                      style: TextStyle(
-                          color: const Color(0xff6F6E6E),
-                          fontSize: 14,
-                          fontWeight: regular),
-                    )
-                  : const SizedBox(),
+        body: Column(
+          children: [
+            Expanded(
+              child: bottomNavPages[selectedTab],
+            ),
+            if (selectedTab != 1) ...[
+              Text(
+                "Community Registration - Client Version ${context.watch().versionNoApp}",
+                style: TextStyle(
+                  color: const Color(0xff6F6E6E),
+                  fontSize: 14,
+                  fontWeight: regular,
+                ),
+              ),
+              Text(
+                "Git Commit Id ${context.watch().commitIdApp}",
+                style: TextStyle(
+                  color: const Color(0xff6F6E6E),
+                  fontSize: 14,
+                  fontWeight: regular,
+                ),
+              ),
             ],
-          ),
+          ],
         ),
       ),
     );
diff --git a/lib/ui/settings/settings_screen.dart b/lib/ui/settings/settings_screen.dart
index a8aa1482e..3d7eb85b8 100644
--- a/lib/ui/settings/settings_screen.dart
+++ b/lib/ui/settings/settings_screen.dart
@@ -149,11 +149,11 @@ class _SettingsScreenState extends State {
               ],
             ),
           ),
-          SizedBox(
-            height: MediaQuery.of(context).size.height,
+          Expanded(
             child: TabBarView(
               children: [
-                for (final settings in settingUiByRole) _buildTabContent(settings),
+                for (final settings in settingUiByRole)
+                  _buildTabContent(settings),
               ],
             ),
           ),
diff --git a/lib/ui/settings/widgets/global_config_settings_tab.dart b/lib/ui/settings/widgets/global_config_settings_tab.dart
index 7096bdb07..98eb3adfc 100644
--- a/lib/ui/settings/widgets/global_config_settings_tab.dart
+++ b/lib/ui/settings/widgets/global_config_settings_tab.dart
@@ -109,20 +109,26 @@ class _GlobalConfigSettingsTabState extends State {
       return false;
     }
 
-    // Check if any local value is different from server value
     for (String key in localValues.keys) {
-      String serverValue = serverValues?[key]?.toString() ?? '-';
-      String localValue = localValues[key]!;
-
-      // 1. Local value is not empty and different from server value, OR
-      // 2. Local value is empty but there was a previous local configuration
-      if (localValue.isNotEmpty && localValue != serverValue) {
-        return true;
+      final String localValue = localValues[key]!;
+      final String? previousLocal = localConfigurations[key];
+
+      if (localValue.isEmpty) {
+        if (previousLocal != null) {
+          return true;
+        }
+        final String serverValue = serverValues?[key]?.toString() ?? '';
+        if (serverValue.isNotEmpty) {
+          return true;
+        }
+        continue;
       }
-      if (localValue.isEmpty && localConfigurations.containsKey(key)) {
+
+      if (previousLocal == null || previousLocal != localValue) {
         return true;
       }
     }
+
     return false;
   }
 
@@ -225,8 +231,7 @@ class _GlobalConfigSettingsTabState extends State {
       String serverValue = serverValues![key]?.toString() ?? '-';
       String localValue = _getLocalValue(key);
       bool isEditable = _isConfigurationPermitted(key);
-      bool isModified =
-          localValues.containsKey(key) && localValues[key] != serverValue;
+      bool isModified = localValues.containsKey(key);
 
       GlobalConfigItem item = GlobalConfigItem(
         key: key,
@@ -317,24 +322,27 @@ class _GlobalConfigSettingsTabState extends State {
             Expanded(
               child: _buildContent(),
             ),
-            Container(
-              padding: const EdgeInsets.all(10),
-              alignment: Alignment.centerRight, // Align content to the end
-              child: ElevatedButton(
-                onPressed: () {
-                  _onSaveChanges();
-                },
-                style: ElevatedButton.styleFrom(
-                  backgroundColor: solidPrimary,
-                  foregroundColor: Colors.white,
-                  padding:
-                      const EdgeInsets.symmetric(vertical: 16, horizontal: 60),
-                  elevation: 4,
-                ),
-                child: Text(AppLocalizations.of(context)!.submit),
+          ],
+        ),
+      ),
+      floatingActionButtonLocation: FloatingActionButtonLocation.endFloat,
+      floatingActionButton: SafeArea(
+        top: false,
+        child: Padding(
+          padding: const EdgeInsets.only(right: 16),
+          child: ElevatedButton(
+            onPressed: _onSaveChanges,
+            style: ElevatedButton.styleFrom(
+              backgroundColor: solidPrimary,
+              foregroundColor: Colors.white,
+              padding: const EdgeInsets.symmetric(
+                vertical: 18,
+                horizontal: 56,
               ),
+              elevation: 4,
             ),
-          ],
+            child: Text(AppLocalizations.of(context)!.submit),
+          ),
         ),
       ),
     );
@@ -381,7 +389,7 @@ class _GlobalConfigSettingsTabState extends State {
     return SizedBox(
       width: double.infinity,
       child: ListView.separated(
-        padding: const EdgeInsets.only(top: 10, bottom: 15),
+        padding: const EdgeInsets.only(top: 10, bottom: 90),
         itemCount: configs.length,
         separatorBuilder: (_, __) =>
             Divider(height: 1, color: Colors.grey[300]),