From 90b47046a1c3137e262b48adb95401141af7c5b2 Mon Sep 17 00:00:00 2001 From: TheYoungWolf-Productions Date: Fri, 21 Jan 2022 22:11:56 +0500 Subject: [PATCH 01/23] Add assets for auth screen --- assets/Fonts/Brandon_bld.otf | Bin 0 -> 89928 bytes assets/Fonts/Brandon_med.otf | Bin 0 -> 89536 bytes assets/Images/login.svg | 1 + assets/Images/login_bottomRight.svg | 62 ++++++++++++++++++++++++ assets/Images/login_bottomRight_png.png | Bin 0 -> 12155 bytes assets/Images/login_topLeftBubble_1.png | Bin 0 -> 51572 bytes pubspec.lock | 36 ++++++++++++++ pubspec.yaml | 17 ++++++- 8 files changed, 115 insertions(+), 1 deletion(-) create mode 100644 assets/Fonts/Brandon_bld.otf create mode 100644 assets/Fonts/Brandon_med.otf create mode 100644 assets/Images/login.svg create mode 100644 assets/Images/login_bottomRight.svg create mode 100644 assets/Images/login_bottomRight_png.png create mode 100644 assets/Images/login_topLeftBubble_1.png diff --git a/assets/Fonts/Brandon_bld.otf b/assets/Fonts/Brandon_bld.otf new file mode 100644 index 0000000000000000000000000000000000000000..d70c281048459fdba23cd8ff9f09386df64ed9e5 GIT binary patch literal 89928 zcmcG02S60Z_y6o2yLaxvsho#!=iZ@$y&`sFL+l+CQ7lLi6alF!MUE?UIqs-p!46_U z#okL|i@nAeOJWi=niw_C;iCD!-9tr_{J!P)`-`x%Q{J>UZ{EDmn;qxvJq}4w3KF6& z9z%yZpF$Jz5VF07P|m?&PYBbKPvs<#w zTrEO`GeT%qzujpCgS{wDkx@aI$; zAD)sm&6?pULgNwf8eRm%3*tB;A#hLtEkW7VC-EJ$;|;`0#6p2UNC^aG2z4HhoTu>w z;Lq^ML%5(bD-axfca4}~qaYHU5h~>(38R1;5oc%kAU0@lL|CA;FqEw;+Q<1X+4}G`{UzF&D?T|WDmoNscInc! zQN0((p(B^)uO&mHo&B9-qWlAc=KDv@bB+l9yFUE2TmQQI%l^6dAu%zLeL8oJ zkB{#Z5*HX85grrWDIj7#@<0(N5-mbeC=|^>At(mew+#vac65fN&;@>aLufYSa7M$C zKMIGRAQTO6aZoZGorzLqv1CSN(P}o$T=9o9L2yo zO2gni0$RZ3TYzHW=?r-yfL0)y2yb&BE(}UUebN$ZJ3ehiAHL+jqR!=d-^Wke^4FGh z{Lqrg(2^)}!QAmWuP@0DQ(-zqwDM(;WV%j4a zY62420X0RA$O$Qs5;a2%QXw@=S98IV|KKN^4r!jc&bOK}MDL_?wD!_f#d5{*Km(HJxq_K5Ll0xSS8 zyiK@{K^n~b5^d|-rp2R3(7%_$zL5w5%A{*gR7=E1Xr%Eu339 zcX96HJj6NDd69F5^XBHV<}I4HYTl{2ck^k@XS5KspjtF+Vc$aDLeWCiqJ4|uEoQX{ zay@JLlNJ2=C)DkX%Ft2tCAtD5ejojaULXv0z7aS=onJwnw?5RFqI%&hb9QuY=IqSZ z*_*F3#yO>4onBC%m>py`& zU<>cIf<~}L|KZ=q+&}|XEx&R<&pR9VisQ=&;Jhcmodba{V}ZYx5|e;O2Lsop5etb$ zz^P{7+aTbFc;HEYnD0bFL-@d|m=EhB9#+O8;3-2LPsO2PA|0&(ZsK@qH_Y31q6w^( z%P@D}!g}FW%P+8AxYcqS)=LI(xB}J+w^G^=PQbk(=xf*n&cl{;2?W?x5Omjo`)C%&pQ)cP%h}zM)U`Ijq*UInNbaBgcekQSd3M7W}3L|d5elSBvf710TONpwW>&_&p~ub{OAjW!c9w2f#A ztFmw1nj8n~a|Aj9W{MRJn>BmZ z_)xQiTzm8uNP(yq!-8=DG2RLUwL6GpPY}A3K(P9QFb#)EOooXu!Vs4M!|y={&@m9I z7hr1dp(ijMwID>LggxO1EYS``SWjXI2%NA zje?zm!-C_2(}D|v>w-Iihl1Y(tWYGh6Uu~YVM}3KVP|1q;ZWfip_g!$aGr31FkYw? zW`Mw1E-V*r748=v6MiW?C%huOCHzkKMEJW9+X!qVHjQnX*|e}}W8-GyZqvi2w@rT= z51Y|8lWYQP!faw~l5H|=@@-0O*4b>fIcRgn=9mJefjfklAD|SwyZOH<8=P{p2z7GLK-* zvWSEtnaD-tCh8*^A(|!%7o~{IqLrcwQMKrl=(^~(=%MIW(Oa=d+(fJvw-vjI2Z~3D zGsIts?{o@}4GZ&_7#kkirOTi$gXa4OL`8%TnjIAs7c?j;G<=SKKx|CVpolpU;X(5T zdGc=_*1rLvQ30{@gTsOrdIb1GA&{QD4~67i8YqIfz{Je{a|bfWqA=#PzzuH%j9 zdYNMQVlnk%th_Ne28JM(?|iJa5wUzDV!26+t>2PZ>!8H*wZ(s|E&e@k#Ph7M=wr$v zK4LLnVDX2k7%?(*Zt%=t_&+n0`xD0J>J;D~$!FvOA4%|UoN)LU@DGdOo6E(#ubK;6 zThE2~o_X}<`@y|)UE!Yfd&9kdXcG5QH)dSW+EG68qwuIVa-EKVn zR7|LUSYT){yvGE=5Ql+{Bs9Q3EIJnCVGI~rpap@k0Wo0_i=k)`P#)TA=+MPMQ4yVD zz@!lbe`Dgga10nixVPYl*eLE18ppjwhc4v)f|L)3XAoyef@gRrUy!E)EsB`W5#j?J zEo*=$#|L?e)(}UO4{>y@0iHA;v{L7Td_f&6F`s4%3!2Z#rMk+vOnl78OhMs+ zu$}Nt37Y>QI2*Rv5pp4Z6}}IAq*%AuAmLxz5=uciQ|{DA${X~uNa~p=M6_3QNOV=~DGn5ehz(+sxKO-ITqfQs z-YY&PJ}-VCe%zpMgZKuC4OTX&Zm_q(-3C9?&FB_%0KJy3rVrDPB!r}q#8J{*(n``* z(nHc$GE0&s$(0mKR!P=Kwn?fb$0TPY=Oy1rewDnjMYauWrMAs&``Qk$9b@Zf8(^Da zn_*jEyV|zW_OR_4+iSK@ZJ*n|wG-Hh?UZ&c?b_LOvGcGSX*bz!s@*KR1$G)cqunyQ zb#~=;Rd##q4%?lyyK481-S>8n?4H@ZwtHjur&JSrBv))&bHrSwtSVhJB~zU>w=lqUg7**=7C2O{U%jJz!;&nOw@8x3 z-0y&GzdpQn(`HqHIipZ#n!VpqXHLz~=*7v4!k2_8Cxq;)PFLf6DnH*;kgd)(Wfz+i z81?+dg_ZPZ$C4`C@Q{4FadX8^<@U<3;H7HGa)%MjK^BooCX;@d@_TBTxwu%bW>432 zC-c(Nj2fkeN;Met>1y`e+wNqt-kiKliRWUi{27iUmr}p6k)%Y9J#OXa<`(LToFa}G z@-^8hIw!VQTSK}*o2zwN5t5r~N-N28l5Q<8-?}w?V@OCuL`cZS@U3de@r&|>tFDj7 z_DbCR;gc6w&f0w0Zil+h=HSZxipovfPaePNYcQ*dw9CxqqU|RgO$F)8HF@G?@n0Nq zRkGbixVW+O<8hCJ)b~PnhfGn-3Jmob+2^aJ234wQah5h|&KSqk1fwB8RV=Z@6~@&} zjjxEemmS67xpHleS#MUBQU$rjyrpXFY4IhE6dqRVOX_p-4Ec~^Hs_gh)ObRTJ6V#e zEl5&!rnFj}E<^2F+mcM9Sa(YoQdX9iVSqt`V+agVhMMhG+Xd2ET3V8_qoxe4NeiWt zw3?(`HH=a|RcKyFZy7|h`BchuI#i@FYYSD9ay(tmihgd7NlgCy3l?Fr^DivPlAYUg z6Gk|k*tPfA(cLq=CeE5Zd6NIWlPZaDC;nZ|`r+{Ail)EuMb7ilJZ~}fn7Mr!D2}&1AYcQk%*SfQdS$Djc z%uP2KwMthiL7R|lR^x^2_oQSf!|srup^Uk?Mm63fGN$DkR8y!yexxBSBg3G`2_yBn z=|U)u~6~))%pwEH&$wEmlsXfV~XR zW`b>#rq9siX`Lji5~pq*sbmGcIx-|mRJluYjb;VT7tNztZ;tc()p5Q& zS(l%*OnHDZoAPpDtv#!0PfF&_h>b2XC#zD8DH&`3u)%kC3UkTWhr9QEOH09))O^VI1$VO6EHNwzspynf9&$&EvMPoMFx@=%BDcwuFPJyt$o-6=y_nnBH~MOve_Ky{sx zJ(|Esj^c50*S#HZquW)xN>`|g=8}?Pkl%?)UrMV_12HKP@gu+C3+B^!_OV2M_2l6T zh3cYgUBMD%Af?mlwHa#3?6CR4!JERjsU_c2rTGN~x$1)$k@yHDF=gmYsmfp~S*MZ6 z^ED=IahA#CRJNLo*t%!&0VO7XdWuE+6ZS0Fs$RbymUE%jlD2%M;>4~!$5t#iXi8LVSPwZ?V1_g$ zUEhZc{;K5HCq{ncVnto3~hh9PJGL#M_!$cTTVIuHIIZOQ93%A6rf4+-}2LryGu|}0ElHICad*;|p1s1ly$~I>0+Iz6V zFV1*Z$EwmrvPTg~okqATum;D(_UX|uwE#w4j^4_mU)^1W62 zE-X`BNUWMZL*YF&*n5(1)p3=yVnt$XY-~bIXzZ%&Otryi$TH|6=Qf=R+38pG>Wzi&K5~>)WZu-PPwL(EYXKW&QpfPt*!tvsX&Gm!hSTJ z9?nzSBGF)kXJI7yX{|iDAf-h0165pDSggihif{>ggG|rKODj-ff?8!>T?~ac;~#Jd z-cK$o)|4$&wx&|`Ab!=Xk*y-}8c}gdVX~?lm83~YhH-Y4<1?&1wVlbtO~`LY(Pu;j zT62o3ucbfLlb%F@2uuedSX(=i>?LwzF!@rB{jiQ?bt0*#P-~Xp>seT8nU3v%>%fpk4lh!LOPpNgeWvf!v?D3j5pq}Y+^~zLAujAwn>sWhRj@#i!WHyC6vX4lq zMO8tc0Fhg(qWB4xXzovn!y~SK`Kx3!{o5A0HAd8zYd7y+y>^MVSe0)m1i`uGoMWyj zqfl=YmoD;KGg%2rOEj;vTmX3*&53S~KVa!f({j^{D$Goy3`Ph@IK`%Mlw>b^_BU+v?A#OV@>;S{^Wyu<7k`$-GqWXJzk=)fWf?8M ze)`mn8)Hum8aQs;z=5a6-B3%a3pQ2kQy$n9;;ojjQ-QlA_M5N(H-zDi^)3}PzEVTqyi35(nav{GNa;lQ#4E8=le0BTl zheF9^JmfNQ{I2JE36lCY+Z@U02p3bwlI7^nlq4i5SR|5Ayu_4T z^}uR-$+p5BhtDg|9iBXD^pr`XB_Lb&Gf;fPYtUP4C7}A{sU#Ki@7qhb9sMphZoBDw z5?D27Bxj#}O;o}kA$A2xN#IE@@MtWwm#}BC5J$#I_R+6^K!!;r0nz0r31E`BT}V=( zDyJj_V2}uKw-9hV=n1GF8q5$G2yI1xw4o}5wjd&tK-&-?LV)uTOKs401aKuF+GrO- zI|!lx0SZYJHbDEpCl3*22=FFiH9~t4u|@>2AhAh+_9J2oLWdEcasY0lLx|Wa0F;o} zjsPztcGv)hN$ep3Z3o~R5If=!LMIS$SPY0XaSEZY5OJCS0E;+_z%Kwn_&fsl0OA}0 zKqhgX0Hlk!Xao2bag9J55ny}hB0=0h0ErSe8vytS*e1Z71mMfp5b-?%n3MQH%(;z~&A!sB7?34qKlaWA<02dWF5P+fzz>QFg1WpK$RDps3ELG49 z0g5VM5TLsP6#`^cphf`Q37iq2y@KXKKz;?T2>c`f00v(R!2JNZ1xOgh5@;R)2r+=e zfZ>9(0f2r0;tEg>Rx(hMF3FO-wiVj;wjE^~Ynx_!84N5nb`rapc601j*;Uw` zwmWBc!S11ylFFrS(lyfk(o+q)HOy~V)Udqak%q?`HE3kpD5BBAM%x-yH@ep7o5lkh zdo&)?cuM2Q##xP5Hr~?sMC04`G4_}3ui4+R|6L}NwUK$s&daXJZpdymp_}w;lF(#J zli%d7a)0?U`AY|ThprCZ4jP97ho?gd|swX^F`S1;GOu0OUK*=l90-&(zEEp6SVb&uAQ zT8FgOw=QiXYvbA`s?F}UZQJ%~8__ngt+DOuwkO-(Z~JGvR_*$=Thz|n?qIvy?OU|> zXkXg?d!`-ybhEgN+&$cvxPRGQ)!nOmO83(}9D2;|v7^WS9!Gne>T#>bFFjuLsOc%~*|KM^ zo+Elr?HSZFvS&h1bI!s?|zt@aj$-VM=t?RX?*N?q^>)ogK zmfny0$ooX~Io0P`-`0J*^&Q@KMqf?elD^yf9`1Xw@4bFK`)&Th_ls>`JnlcT|GEL5 z1Fj5=9n@ryW>EEDm%*zB?;QNQM*|O)hqFfukHH@P9$P)md(;l`9ikudt!E$44W7G) zl0$umt{O%Tiy3xoxN`Wo;S+{?4WBgJXSnb1X~Q=Szc6CH#%zcp)sm4oyQCwvwX~+G0(=ZV{OMa9qThTc#tem)e;**JQyrf=Zy{3DG zc&+o==C$8@y!UQzc2d}+tCOcquJm#98Q?R*XR6OUpGY60Pl3-`pZz|UeO^zIPH8p8 zeTwIliBqzttef)Hl*hgfzN39t`F`p9dTQIL{!@1hq-(oN;XgY?>a4-NExY20JGhMy ztMNK{C0PE<=4|y2yoJOzpfw4sJ0weqcCeMCHXG~{$`P!ed`4C9o_$qSd-n!!pFT4< zXogBU$dZAl5jf70ArGV30S;lb6x(HCozD^6>j+K>!9O?4{k)G5Wm#3OS|>1z_okFTmQ6{eSJ@)i{j-|J=)Zx$7%?q}wSSSDq3 z&khRK@sG)mf>k3k$Ba~rTQ+V_+R})!=Lh7FgM}}7E(TCLv;C0Ma8=ELwTxW zwP|1_6&(s+H!n~TI4^vb4iu#f%>(Z^Jm`Bo{K3=jK{HwnkFOp)`(BoC6nE7ylWV(v z!N~R;9m24?*U&j(pP(r$4 zBztrn50$&#>yBmE;qtk%6{@R)OA|_SiVB^ocdcEcDO^(I1Azfy(jIcN|ws*$kfjj`Q3n9XKJ5*o_+s@t%I6^dNY_L*T7ECxjVpQO4oB zpy4&Y2%WT0!11nh#)GTAWC$xC%w9%9G(e;dWqag9FJ4svv(Mjoae(qHX-Si*1kFQ*f5? z;?6&8d$yg3uh$FCH0>xU>!!iISY@33Hax-evaD>|75Pk9k}BEwvQl%lvgc5r6pc!w z%}g4# zdej`6C|@T}O3P0vR$ik_`FSQVu=&)qlqg zJ|9VsD~qe?$Bi;K3C%ex+Jg$Z#sQ9#o)qiC+NGss=(Dv>c~i4f3-tLpPCu+9rO&fo zTjpYtz>l%La1(ENQ^Dk10x1+m9ldb#@$S>&9Va$ce+`I4-=El)tmKQfU@_9>EXmU! zm~Q*R84EazJ@?%k&wc@quAM>fvszJ=<$UU$OMnE(U*xWh{xC${uYS&EVl> zaoF{xWh}JwITj1I&SbE#n!X4+|0FCGp1dZXzwYbFufb~d@+F)(n!5kQworG+PB>~5 zeG%+|mwMCe0Z~HX!c{8ViMqYZcg*N%-ou7ZIFg&D)|yf?bb8;Zj!VFrR-6c@acMcd z8%!z*m=x}gps|MSA@4Ki_C@t(MlHQi7H7GH5pi^-JfS$f2#kfx3kpk3YJ9jxM4CD< zweD8=cYvU3r}^EYePO?UHNAg4gQa-sGgv?rQCZGlo2fM0R)bxzBX%Lq zU>70SEHiYC*9KFII(i^qLbd~f9mOa7Z$FSr4B*(W$(I;RaZ}+CXKo+xeY`B<{ z)|iP9BVAcpCQn$VEjFw0Z`hwSE;X9-6h={=!EAt9f5RbUvN=(kpzsu>f;}N!h3B$O z*tu*Ys5LDuRUxh9_P2?cu!nF!X)ru-uHX3;6!VJo&%JafC; zf^9PFgAH>3bVrlklw~%Gi&t&faawt(B5aP@lU2{@pzybv5M=lLS-)c1a$fU0p8s4E zkKGG~NF|Pzv%xUFgYk$Fs)97LF}GmtS;ySMG;@kk%r^h3H5{&c zat6Q_xHVn?=WK#)&W>so)OFct8gt<%9vU|%DX73uMbnfrQ+OndX z?O&bUw{2IM+D!SEZkcmQiTizp`@o#*0oED8R5H9Quf@Jc`f)n*nFiUt~i9Kf-n}iuwg4MED{J|d^C@lTu z4z~HZ|FOx-)iTTe)n`xLQoQQ?Eh|y6i+Y0vjok=))N9e)5acfw%>tHF3$F?8K@eocP&JwxO-|_j!zt5jR7tk_GKSuV-9jcFw!5ud}_HB&$n+NBenPy#%<#8Lwnh* zy=&x28Rpbt<&PAoTBdCEmzIWPc1~6npop~$K!WD^O0BGecd6BhYWM)=YhLVl6gn^k)pR0w$ z6ul0VA?X*i)FN9$yMS`$0pn-_!7&{-%wzD9D*89Jp_*L+GwHy7xr(+lVLjvU_#C

5@$ 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Ŧbwg0>%6#JaK2y4?7ke&naHGfj*Oi^wK4(Qm}Q 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 Fe*%f=JV^im literal 0 HcmV?d00001 diff --git a/assets/Fonts/Brandon_med.otf b/assets/Fonts/Brandon_med.otf new file mode 100644 index 0000000000000000000000000000000000000000..113eb2459d731ceeaf8ec567f22e11a6e92b3745 GIT binary patch literal 89536 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 literal 0 HcmV?d00001 diff --git a/assets/Images/login.svg b/assets/Images/login.svg new file mode 100644 index 0000000..cc6272d --- /dev/null +++ b/assets/Images/login.svg @@ -0,0 +1 @@ +Login \ No newline at end of file diff --git a/assets/Images/login_bottomRight.svg b/assets/Images/login_bottomRight.svg new file mode 100644 index 0000000..517f851 --- /dev/null +++ b/assets/Images/login_bottomRight.svg @@ -0,0 +1,62 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/Images/login_bottomRight_png.png b/assets/Images/login_bottomRight_png.png new file mode 100644 index 0000000000000000000000000000000000000000..38bae3b00f1b705f1738112b01dd3f37c95ef652 GIT binary patch literal 12155 zcmXwfbyOSQ^EL!`4GzIAxJxPS?gT3ocZ$1Hw73^{3GOXUaVhS_3N28qxbvo;@B8~> zvuDrQo!ooJo_S_sG}Pp=(8%xfVGc7u1Zh%gj1HbrBqEJ7!!}<@Wm2sIL(V zgrBWs_WGulO81B~xAzV=ChFklTV$WD@6%su&Zhga&pK~&&%}P4N`=6|0}vY! z#UIq+0bQ}4HO;-XRdtHo2Q>qaSK3hqHBf&75b1?=z*7VH72Syxbv0c5?%iLhsYQ%^ zCcN2)82Ta^4Gp;2nHdEkip7Z5adS#;dkOowJx$Srk@W}(9eC5B;MeX)s3BcqCYU}# zfkFupSxctYYYA6Z*NYnbAlkbnc7L_kJ14#IpK$Y^N79GpDchv>t?^0YLox;is7WdG z_NuC4=FK9gajR+vp4L*dXpieq-WhohBhWJfNM+{=w92S#CI8m?MV5qzul6%g(m~KL+C2LqfFJ87!GOfH4Qzgi~34 znkqUi4}!_S0l12ioQ72m60;Wkk4hNdYWEu(t8L0v{13R^oT(?^Qy0c{_&iT1eHK&} zEcD@nd#}~C@iTj2Yb%l7?h+#z=a~|hBp*#WB11t6jR76FKqibwS{6O0mvvL{#&_S& zC)ix>8qWWgN_#>0X>(cM5LD}>GcjOQjA1d1`4AuzU@Y*gP(Sc%DvExw?O{Gg;U1Sd z+c?x(>jN_$KAFlAJoK>oZzlfgg93iwa?^_Xc zfb{nCV9ws*=vitYY?QO8t}e8}D9_d!)!=!~f!DMcbi!}&eDd-}HO=i!l1>pJ!Fxpm z0!0Lk0mLT{1{MMd18Q)WJs!kCV-lSlpi9JLUOE70E_Z^NKqV&raM5WbuaQC>bq6L4 zBvqAZ6&<^)9)_f5JRDuEUL{c_Ue`2vjT5FY%{azpII(mFM14dmIi_M#KS?D-7)2*= z3=9;rQ>U&W5I{1s=GQ@!IbrrX7NW1`S<2I59{j0u9$84jhRA>>vGDL9$3qJDcg?l| z7g>5y(N{*{;^|&ne;K6DISQP0FgtO^wl zQmd;*lYPYOQP!qHcra4M&m$GnLl`|+%7f<@gGTy5fFF%|<&r$hDn(G`v*K(ogv84w z)-_^&JKg0S9u}SfkTmz#VMCLg5IZQ%PbP%>K8PC}tYn1L3Wwk1YFEis;)O`AXLXXy zO7C7tq9VoNf*T%ci}f)Q0*4Q8P$%)8`?F)|x8hnZG8F8Xz@WL(9lI-|YgEEL6G%Ww zsiU?>ONz#vVU+@*lJ%Jcm%73@B7d`1Gk6k8{SHm08>i=;zbn$X*}MJ;a$tC5k|>)& zA9Beqv=!N^R$$a{3OfZ#l-kX$LU=Je*@+XZ*lX1;CpUapK-QY!;aSSYCdJNVX={Zh zJs~E425rKHf5`P6dZOc+=~&=Hu| zQ;HCuZvn=xT+LjIJFY>9^s*3khz=eZIzZsMECjxhI~zGNo5-4&x<-YARtL9TjwR+x zPL8);VBog@!^u|~MiipFo=l>mjA02coWH_QwyaVW{{}QiBd@L2sBHzW9Sb0En6K54 z3cyXmV#eDB_?x+lPN8oeQ`S}vdCyJm6rpBAn|pIKIrKf4FOC{}d3Nv%(o*f@n^KKP z^^Z~nD`NO@=ANOrmF_%g6}ZtyVZ1gRSVI0sUO@#tc*#j`BrzF@qG(dICd2|*LfU!= zRrK^@BH3(s4bjACYkCGeoGqn#Ni9aOIZLAM`FbADdTLoe1<*h-r#^^8NK7gB2r8oE zW&|N``uyCY`K`948ke9cx4VyZrti(C84?^G{L#i-CG}gF6iQZ%nOtnVWJhI&H`3^%hZ zBRQ9Kd$g()oA5oaKY{3)UgD^J5v=rbz9L08n(Kx_(k4%5$HOeN>Sq7Md~tU;ZF+e4 z@-EdV)E2^M#VjW6YlM^b`MZuMCViNZtd!S>@$)if#>F&T%q<2wZ(2l$YDl8M=QM)tebxO zCE&hV!;i#8LSSYf0r$F^iHxiWvpzJSXzQb2wDgr>@h>WNr7pjn(={SqmTYFe@1>3< z3=kGsxSLT)lfKvx6&A(VKOq0|^NXp_D=t$mZWi;XADXH{$BPm3n$kBrgZZL5vG5-x z!v@!LjSH9Yub(=}9jx49NU96yHS*VV^?$M{9e2`g(mFyDz zi$tofb0M*K_lT&+LuAZ^`*Ft>d|e{ZDg^4BY7GT1($Pl$>DT*4PbpVU&4JKk+~ z#ew1i1Ta8D3AJ{Z?9-ddrhz8=?+IP|dxLMbuiLfqWp>7x_VX{o=kcFEv1v#&|+9JVrK54|Y zb1NAt**h!!T})L^C;{cYKC_c$%A!%*pL7{YfiLO;$Gw9X?>TIlYw8Cl43y{GLWwM$ zXx_yr%2M+vNk&8>_cndF?(e?Boo+loR4kCa)|_VlYQuHd!YHFBYThcM*d!%}U|Y9I zUvs-G1R838RTYhTKcLwdxL}*@)LoAQ=FR`x0k~%PdPW)+MkFL#+SPI~QbhNtrmRHf zR2uam)?y@f_bkJ6@5|7Tz%pA-5#`h1L4(|?YP5WpZcUC|q0gE5YrA7!W=T$HNkgM;!L z;x*4cugTQMN^Px`)g6LpC5s=`lh^o)EAAS*DDn&d$OjvS&&X$NAq`p3q;p9hz*pJ3 zQSt*aRA5x#8*kHHQJ8ArFR}+UFKH-N!18V3Hy@g^kdo6Oyzu7>K>$rsg?0Z6b-lO~ zu}^Z6WEAhExr8DBGh|aLgdK>CV0s93i!=q+fM~WQX=NR}h1KG(%;2}~++q>#eZvuT zlUG7ZXJLS<$>L-#X#{4 z;1txlc+E8Re&G^yv6P5p)Wb03Ehsm{%CGZRc;R|?vpOST6S9sb;~AbiNNk;vmR6S- zuf-e+o#L<7u}ZHW(-#1b>car%qHfmrk;D^mIvR5W7O{A3H z4|b%sJSH^z`t*vm!O}6hxyKP%wIzLnSQfNlDIMKV#Gf9?^*O0j91_BE4)?K;8GK*~ ziRZPJZ;DR^DPtDalEoUjVGqyxmem-G~t01L^wBu$jOS2If zuMXZ$40XRob2#U?z5!n09$2VSwVrn!89UbZ!xPKZ0w8w?)-xAc0mUpytGmZqE(zF7FWud<(Mz38TB~U4MrK zvQC34dp$%h$XR9~y37fE6Yq3SVLew+jgGRk1Rh+t^cjJXUr~iw3Q!7O;UQ;KsbJ=P ztC0IR_VLuSUk>a4_@20Ml7=s=G+}U9o@|t=8KdC5;`kxJRZ+ zfTq~D!+GLI;=InxaxLX3?Ph8BGhO|wfx0kSur{7;&mbCz%h*(}ikz?VtXWa}qs{D~ z(C}U#Xo*uD0~o0i?xb%Wwx$;tSyXOSDy;*t8sj!)lP&!DEG0wE1)0kXgrGuel5`!6F zyQ=ChaQ$KPbYy(2Q|QldtN$PVWc0|d59pzlY(E!bz%2S4KTK*8(jxtfiTyCLpeNTB zx@kE<0n|O}7vEy&uwWX2U#9%QGV7#Yne*5<>Q5jgjacl5fP#}tre9R^APLj<$OVuX z%k>uFUlQxP0Jd~U2(lyr@udjAZjy+wc?Au06v5DyTI0_dQs4cdxyez3eFN*jNC_Rz zqJ{7aUx%Fz0O$*L7}5aG)21GnL(kE2iKEoz4R+5vF5zJS z(?~>JYE~43W*!HV4*EUcEXsgx5C(RdZAQIHQeZHTgX!+sAx*Bu?ac-bMM6#@VzFC9 zx9H`IWxM{Phd2>zS&$wcJh_s<%ZYjh&hjW%?2b!iYSyTgui!IcFQaQ>rSyef_U;+M zy_$??1HW!00rVy!@!K7ho`*)5tayv4SnCaDmLIsJwZ~qt7i#aH8Z^VLKY_&eIK<+4 zQDyewQQSG=nZX=ep}UJTb$;f}0Ye3}+pO1C zv+6aU4RjEUy$?oU`CUACcLFIc#k3;I2MeGXh$z}d`MO1Ba{~HmC%#m-pkGljBi#iE zt$Z5+jc@+`r}d+YE?$#{2I9uG#ST{pXVWfyO$^i{rEEU?l2vuhZX%;>?Z6xgqgoPa zcrPdSF8pC(!XCn>-E(mr#Kvq}wE(GmlO|*~J(?UIcW4fkq^`y(t~~JToxfk6*CB(Y zUzoMTG$g`o?gnPJWY^)y@?xTP7nLf0Bw$$0(ws%n;kEA%v6Xvf@y+H6q*wFDay5pF zMt9Xk+zv4}o(VJc9PQ6|D{#`EzBkAw0b7T~wV<7m6*|jmV&py;CLV;u?hLDtGnBoY6o`W=h)qE{CD6Z(t;&YtDs&3k_#SGbAPxUJ+gg17I-KRH;r2Bi{C=>Mny zP54+_4ushK92V11#Q8&rSnS11vEpr?TQv7Yv5pX{??Tu6aD<24Ne~(96C^3?F17ip z0b3gOZ{KE1mKXFnjVGdGHQ%oMcxd$4XS@vQsANcdBl4bD3@VKqz4qzv^P2P_t>S3B z^J?P0{L}Zaij)`0w;S-NGAF+bo=tuk+W8z{7~t9Z_BFWNSY%`A!I%>K_b~_a5O+|} zXR0|4#Nr#c`KZDB-kC%OY0Dwv6wjz2w$$04{j%khg5szaw9ra1M1QYe&l`62 z_fkdZI3e^kqOjny?$AUm)*c|||7-xz^v6vA2^R!(cQ{&DwrCBp+5Uy8y=kayK_zY7xa2MTJVX5|^Q37wqVXADFd)$VqAm25OY6-E(raH>} z?!0F?YzQ80%}qPV=-HqFa}X2d+YY)9QPlZhD+q(bUE5(##^7F5@I{gl{LF=*gt!I8}A(ET#U*7~W( zQVKq5VOx3rInFsR771ax$o*fR%>*{W88ReaeWFal%sQ>AGV_i?q=&}sui;XT)L?9c zJ6f<>lksEYm56qay!dSL@xX{uU1nL7vTVOrb{48!DEE^aSENx51@ors0LK`4^RI-* zFe=(Y1c`S!QWf)y_IzaEXMHFw-N}_Ym=zP2x*?b_pIi)L``ntd;T9Q|q4vsWGrd7_ zZn0TLpxMa!2_NZT_na%I(pIjvmPyf`J6yn;=37cb;_veK;3z8ALacz>f)@VJet6ET zDQxk(xfw@qCo|)PtzZ$WtK};?=+4vqZjbmc6Lo$0v9G$~dKEz_f}3~VqbqmjHne`02VXD)iW(vU$MEIKF7C#Oie|8+8t3MwtU;`grI}*soy_Ar~d=P_pY2H?XQaKghd$~AFG*IAXVy=Jn$i< zX=(P8Ue!pQldgU%2SM7YDRSgvCr%+&(W*t|z?K^|ZaD!nzPZL)t=Cl$%fHzOK(mm4epD--L$yfScArs)GVtYL~lr z@^a1$C^tOE>+To&ZLI6WnlNrLW>>m_iNot-84(;Wnw9AI>`sENt4H3F<&iiwE59Aj zV|zM)-SwG~0BIJfwF6rDmf#Zb3;R;i;39YKd|q4nW5L~?=DR!`42J7>3_ zBjXqY<=#%x-kgo8@@3l#j1lgJHn=@#iR*nX$jH_cGOby(ksD&BcMYjYGsezQL>K2P ztOb#fe;wP7XXl~Q8Ba2@{Pz2jSnPpOtW+Msx$J9T_mitmyb}Bv^9sR{Y`D4i=%;xL z`H{uHt{ve>UXG)Kl-rJTGwQ!e<1L=sQlz8QWQ}{FkwMU?fGW_$2~(c=?mdhXcbpyDbvMP3u7E~N{!#X0EyH!sn=w87A=L({y>jyZ22>`Ya&xAywN za>1m`1Sj%CtP8?<~&oz(AM&s|o$%z_&z13=@^u3?j;d~+27_2Mb;Tcl#~{C%N# za^apPvYnwl>RWP0*|>tzMA)e~Lij?2#I{3iSPs}!654@omV~j&q@-`BU;6SXX;=t+ zterY#kuQLT;|j8UQY6IJlC+jVWh&;HD$PFV5q zcrUIRd(RWC7;a}5mX{+-g2Cwnigq_YMED-TiSynp`p5f6Iot6G6}zaW@1FM>>^+U{ zFmhV5zkg3Gzk~AIb=*m%*pF3g)bCxj^dg49nt5F+p=AHi>vbh-vE(~dm3VvW!#t&K zwYc{d;h!p{YG~+vw)wdJZgatzZb}ensuy%UWuTH0M3@S(aFBcpup}&R_W<6-h2DnW zMsj|NH`06$j}2({i7+H9t>LO$YyX1?9syp2LJ@2-bVPGO$=A555Z-TP>_4BT3;7}8 zB(R9v78k1*>zrmQc(#%<=tqM~G5MJ*Xa&(E@(?`<=ry_BK@~N4D5YnQWJazkBfCct z3AP1{LhH&TMIBb!`uKzbkOQbDH)zwCB?O>zNysR|e+K!%JbLqkU$6=h@rBoxC!gKf zPJEQK;+NV=M$r@0*3{UUiY;_-sh)gCew7r=4;l=PCI`lm1CB=0GRZGPph-pslh|6H z;B*0_FlZ+@x+b$w&00aJ{^MAqDUgqxVhURlo*qJT3XexY2tR6{{5R9lIJG;GYWK3k zqsp8V0Hv&9K1TrV%V*;*a@ zp?VRzI^=rl<>$NLZX+3(aaYx=DcjjPJ~aW7Teajf+`o+KW2t@sliSiBHK07aU{rfn zS06_JyCndjD+mtOn~dOq|;G9|r@lJ;0eGwI;!{<8fi4BVUd7c17I+&y;d zn<5*6DZYn~+9NeB(Vi}}Q9I~&&dV&wr+lpcGp~OS8W)A`^>j_i4N+|p`TWg{9z$=& zZIKV5g>yqCF)qu%{^E0Zx?>R)_X~Cm=>5eZ+_*n^uZMo^=Ldc^H*4Z?A|@hQvlL~X zSdbZu%IE0F&GbIr)$t>7P=N3qen&v5A}+~ZoaJk#Z5jx*mC$P=3}q|^SXZb#0dw$P z;O0Bw$1ha8nnE&jr)Q7H%cD95#2}xW4XGVG;V+iJiFekX2Nz%^I;%*%D&a!&$p^5O$)JFK{kXIEPA1fQ4An@ z!*A!S0=icIg6__)@>?#v)lMX87hgp$L~u-r0i6)?nGoL66_~?tbY%b9>3xe$SFlsS<6+w@s;P(So{6mtVM$ChrCgWi|FcQioq-eD&HzCe<$}Xhvu-U7D5JHn zao94wUwi=_&~#b+>#H`6?XzNhyGue^P6AparTNWwX1jWNWI=u?1~Wrm%%;ZKmdbkX z?r6NW?YSPuU>Hi>=Mr-Cm>!5#;=T-9P{@WQ##QW&zt!#t`$y-;9rqzs;xLc(j zW_jDkQK^mzRCZ2CT*0GjIp>vyNw4W!R?%l2FUuCGTDeA=Rwt!aFISU*jWw@RXYhwo z@n*|v{fEY$N0Gp0Ez+LRAMk@Z+-kr1_8;FO>8i%MLKta}=zK(Ry$oH)h?9U#YEMWF zSdQm6u{>A6Uza$3Rm>&LaKB%;&+v_Lgb8=;S9UFz-2K)&vu!85CI=~5$Kxv=aj25s zcvjoAr?*74{6GS&J0`SeqhN;5hp~&SCoY;R*P47Vi_+mx>=)(8g04t+sW08c@mz^a zbXUH`Q&;~y9Hc2{^Y`=C6CIoR)d6Oe3SSIVXci1hu)0-DAZrzQSW;aH4L#IUG4kOZRddyBB=0+Jb|bsZqnFR1h=!SRaa)wa6J} zL;q~>=qh}>-S!c1)#Hf?}%NX?axR$6PwuOXmy;@eD2Glx!v#{B4`LnHmXtr>%WUTv;EH9rng`0s-eQ zqM0LHKIIyW6F|f8^L`mn45k77A`K7`Bsf`1m`wz3pWW(>7c0KfgRJq8M&hWtOrh%> z`igIkMlME0?nmPC*;wifD2tL~(p`U;r$%WE-+Il#$)SV~PQdDDRHd3?pSnG{%PR;*{UMW1>3b3>&= z4S887iqSb+0G&+V8UEif#s)>1e07tx9ij4 zO53s=mUlY{AII+Uf-?9^PlWHk{P=Z8fzf5`#rA~(Opk7MUJhM~AI1HTg9$8Vic|k> zJ$zJXW*x z7j5_gjRE)0vmq-5)8qmGhuT7sn;ZTauarPMG z0D(0W(pDXm#6GKV0(Z}`JaTXOsC_qtU?N50O5`~cd;Cj0L}A8^mr)qHi|3=s?wy_DRS7-oj}tbM%5lY*;n#A;x!$on zA{efxe~2e|=q!L1_pZ*2SqTYFBWW*vUg>@li)f0{HaJup?O9aAWM0lw&tea6+`i@$ z6a#_`g71th5A@B;L$ouD(7TL@TU?FOcF^uToEbM(>(a0Etru=VxYrx%AW*s_Ou_f} znFU=z`=?~n(da9!bS|Cqrq47R)FaoSMrMu@anOvxVoY_o=})`b7Y5XId7oq298u;# zS62v-JBzHQazq=bMTu#dgSM6S7 z6WWC^;dAUzN?xV;nu$cV`T2;o1k+ z{ZCm^dmF6zx&IF6H|=v?3`msO_jskq&o66aJH3*`p+~HN(yHw;8^EbXc9&9b9LMwi zecJaor;)|+(}22r3PEcb#(zQ3sLettnEA9fCTMtw_t#rv37kvRw~{)2H|!&?iyH4< z8Pj(jk4zCPSA?B?&w)_;++xf&HbIp%TA>_b6F2#Cj%9!FKTZ$ z6z>Q%;eCBGiPDU_+x2RbFEjFz5nsHt5pS`hq+KO>v%0v}$q+ zJhYh?^;`~7#|LWYc+eeLo~Az^Dfqrg0*-H00OZjKJy$SfDf;xJ9GtVHdHCHXM#2+PfaMr;AhI_O$15G{R}BI?KV`}qcE#;J>)0Q@ zpSxpK>IoCVj6WlIHZWxyKX_v(D(ERjFZln%@;|&44>&wq9Z4Zbm>JwCHo^rawLR{= zt~%a$2iAh(AZd6-8Ju}M{Q1`~Z|Z}^+kOv^SZHf)nRxe*@BtGyCnF=a(`R&Q*TZSN1Msm>PL#?9xx01)iV4GUgigC~QVF>1DewiM843 z_L5WGf#%s$xfrmG{geXUhj0h#bhS8|g}dvf&FWGJyE!lX`228!US`?Ad1GO|-p@g_ zQm17zU4NTN-+M7$%1Sct6cgJRq`Q>wYPUl1?quYB4RbhFi2K%8t5FTv2&M;naU#PQ zTY0AX;oc0cpzT}~s_3t4Co$+De}@06PWP-N4#{aEe>UjF7jBOS!5mg>-Tc0~c*8*0 z%=OA$EUYpl&&d6)ME0IMyOBVl1i}OxpfZp5|wsFt4r*BT|p$>5813oUi)m#_IyJk$JDWxp#?l ztlPUoDKAX!^%e5A0qvlgW?9nBZ#&Rp7VlF%N1d87%>bc)t}Cw?ES6FklFj={d9k5A z$Xn|6w*)teoA>`BPJ?FJj+4f;Nqnx+uheG)v5ZQR8hwft)=Xt00Ho7-wGeZY!XJhP zQj0M;8f<4TwwbIMtWu`248cEohtulsSZxpg${;yzc^o$*7biQe!u=c+pw(w5U)eqo z=YxoW$G7pfH+ZtMJe(VdGyhwC_y5i`b8&e&5S=CjP`%9!@deu+8fzji+j=<*)7C_2 z|F#CK*Dd1$U1@K3pLQLrU=3?X2Pcf@EM*SIaooyjhBo%#3Abmt|Mrrtr)8z)We@J! z+>QWyJp9DWJPTrjqPFO#^%FDy=8&IehvfopKT1vb`}^N?oJ5B>7C*+Jp6?Y$FAebE?#I`s*>Th5*6PCEtsEzC z0>@oV4PnjUEa+)0Phla03fsf{1{3}kY}5zxi?{+uu5oig{d*4QAuX^(O>m zDJL*w_b!h>lRxaYm464#USg zSXjtE9&w}c5x8z7y}~u^Pj|!QUkb@Fy!jGvjNathgTx=Qno7YoD3tP1{WZ)PdytD4cNB)(6UR5t58oAm&Eyr z^=J9FvP0gcyK`veZU1m9YzP7k?SV8Y{Z9s#ie8op%RM?6FoneKSKG>;1o$$iStmyXwzdfXOpiFk8AsS`+Mfb%3 literal 0 HcmV?d00001 diff --git a/assets/Images/login_topLeftBubble_1.png b/assets/Images/login_topLeftBubble_1.png new file mode 100644 index 0000000000000000000000000000000000000000..df0f7c9e8c74e4f3fbedd58116c9706495ef7491 GIT binary patch literal 51572 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.15.1 <3.0.0" + flutter: ">=2.4.0-0.0.pre" diff --git a/pubspec.yaml b/pubspec.yaml index c472dfc..0ce6c9b 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,5 +1,5 @@ name: testify -description: A new Flutter project. +description: A Self-assessment System deployed in the medical industry to prepare fresh graduates for their next big step as practitioners. # The following line prevents the package from being accidentally published to # pub.dev using `flutter pub publish`. This is preferred for private packages. @@ -34,6 +34,7 @@ dependencies: # The following adds the Cupertino Icons font to your application. # Use with the CupertinoIcons class for iOS style icons. cupertino_icons: ^1.0.2 + flutter_svg: ^1.0.2 dev_dependencies: flutter_test: @@ -61,6 +62,20 @@ flutter: # assets: # - images/a_dot_burr.jpeg # - images/a_dot_ham.jpeg + assets: + - assets/Images/login_topLeftBubble_1.png + - assets/Images/login.svg + - assets/Images/login_bottomRight.svg + - assets/Images/login_bottomRight_png.png + +fonts: + - family: Brandon-bld + fonts: + - asset: assets/Fonts/Brandon_bld.otf + - family: Brandon-med + fonts: + - asset: assets/Fonts/Brandon_med.otf + # An image asset can refer to one or more resolution-specific "variants", see # https://flutter.dev/assets-and-images/#resolution-aware. From 1c45c77c2b5f4cfe5b20a0a4ba2bd855eda54580 Mon Sep 17 00:00:00 2001 From: TheYoungWolf-Productions Date: Fri, 21 Jan 2022 22:12:43 +0500 Subject: [PATCH 02/23] Add auth UI --- lib/main.dart | 113 +-------- lib/screens/Authentication/login.dart | 335 ++++++++++++++++++++++++++ lib/screens/home.dart | 38 +++ lib/screens/wrapper.dart | 11 + 4 files changed, 394 insertions(+), 103 deletions(-) create mode 100644 lib/screens/Authentication/login.dart create mode 100644 lib/screens/home.dart create mode 100644 lib/screens/wrapper.dart diff --git a/lib/main.dart b/lib/main.dart index 202509b..0bfa363 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -1,115 +1,22 @@ import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; +import 'package:testify/screens/wrapper.dart'; void main() { - runApp(const MyApp()); + WidgetsFlutterBinding.ensureInitialized(); + SystemChrome.setPreferredOrientations([ + DeviceOrientation.portraitUp, + DeviceOrientation.portraitDown, + ]); + runApp(MyApp()); } class MyApp extends StatelessWidget { - const MyApp({Key? key}) : super(key: key); - // This widget is the root of your application. @override Widget build(BuildContext context) { return MaterialApp( - title: 'Flutter Demo', - theme: ThemeData( - // This is the theme of your application. - // - // Try running your application with "flutter run". You'll see the - // application has a blue toolbar. Then, without quitting the app, try - // changing the primarySwatch below to Colors.green and then invoke - // "hot reload" (press "r" in the console where you ran "flutter run", - // or simply save your changes to "hot reload" in a Flutter IDE). - // Notice that the counter didn't reset back to zero; the application - // is not restarted. - primarySwatch: Colors.blue, - ), - home: const MyHomePage(title: 'Flutter Demo Home Page'), - ); - } -} - -class MyHomePage extends StatefulWidget { - const MyHomePage({Key? key, required this.title}) : super(key: key); - - // This widget is the home page of your application. It is stateful, meaning - // that it has a State object (defined below) that contains fields that affect - // how it looks. - - // This class is the configuration for the state. It holds the values (in this - // case the title) provided by the parent (in this case the App widget) and - // used by the build method of the State. Fields in a Widget subclass are - // always marked "final". - - final String title; - - @override - State createState() => _MyHomePageState(); -} - -class _MyHomePageState extends State { - int _counter = 0; - - void _incrementCounter() { - setState(() { - // This call to setState tells the Flutter framework that something has - // changed in this State, which causes it to rerun the build method below - // so that the display can reflect the updated values. If we changed - // _counter without calling setState(), then the build method would not be - // called again, and so nothing would appear to happen. - _counter++; - }); - } - - @override - Widget build(BuildContext context) { - // This method is rerun every time setState is called, for instance as done - // by the _incrementCounter method above. - // - // The Flutter framework has been optimized to make rerunning build methods - // fast, so that you can just rebuild anything that needs updating rather - // than having to individually change instances of widgets. - return Scaffold( - appBar: AppBar( - // Here we take the value from the MyHomePage object that was created by - // the App.build method, and use it to set our appbar title. - title: Text(widget.title), - ), - body: Center( - // Center is a layout widget. It takes a single child and positions it - // in the middle of the parent. - child: Column( - // Column is also a layout widget. It takes a list of children and - // arranges them vertically. By default, it sizes itself to fit its - // children horizontally, and tries to be as tall as its parent. - // - // Invoke "debug painting" (press "p" in the console, choose the - // "Toggle Debug Paint" action from the Flutter Inspector in Android - // Studio, or the "Toggle Debug Paint" command in Visual Studio Code) - // to see the wireframe for each widget. - // - // Column has various properties to control how it sizes itself and - // how it positions its children. Here we use mainAxisAlignment to - // center the children vertically; the main axis here is the vertical - // axis because Columns are vertical (the cross axis would be - // horizontal). - mainAxisAlignment: MainAxisAlignment.center, - children: [ - const Text( - 'You have pushed the button this many times:', - ), - Text( - '$_counter', - style: Theme.of(context).textTheme.headline4, - ), - ], - ), - ), - floatingActionButton: FloatingActionButton( - onPressed: _incrementCounter, - tooltip: 'Increment', - child: const Icon(Icons.add), - ), // This trailing comma makes auto-formatting nicer for build methods. + home: Wrapper(), ); } -} +} \ No newline at end of file diff --git a/lib/screens/Authentication/login.dart b/lib/screens/Authentication/login.dart new file mode 100644 index 0000000..2e5dd53 --- /dev/null +++ b/lib/screens/Authentication/login.dart @@ -0,0 +1,335 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_svg/flutter_svg.dart'; +import 'package:testify/screens/home.dart'; + +class Login extends StatefulWidget { + const Login({Key? key}) : super(key: key); + + @override + State createState() => _LoginState(); +} + +class _LoginState extends State { + //Data Fields: + final _formKey = GlobalKey(); + String _username = ""; + String _password = ""; + bool _isChecked = false; + + //After form validation navigation to next screen. + void _navigateAndDisplaySelection(BuildContext context) async { + // Navigator.push returns a Future that completes after calling + // Navigator.pop on the Selection Screen. + final result = await Navigator.push( + context, + MaterialPageRoute(builder: (context) => const Home()), + ); + + // After the Selection Screen returns a result, hide any previous snackbars + // and show the new result. + //Can be used to show if input is invalid. + /* + ScaffoldMessenger.of(context) + ..removeCurrentSnackBar() + ..showSnackBar(SnackBar(content: Text('$result')));*/ + } + + @override + Widget build(BuildContext context) { + return Scaffold( + backgroundColor: Color(0xff3F2668),//Color copied from xD=#3F2668 + body: SingleChildScrollView( + child: Container( + height: (MediaQuery.of(context).size.height), + child: Column( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Container( + height: (MediaQuery.of(context).size.height) *0.3, + color: Colors.transparent, + child: Align( + alignment: Alignment.topLeft, + child: Image( + image: AssetImage("assets/Images/login_topLeftBubble_1.png"), + ), + ), + ), + SizedBox(height: (MediaQuery.of(context).size.height) *0.02159,), + Container( + child: Form( + key: _formKey, + child: Stack( + alignment: Alignment.bottomCenter, + children: [ + Column(//Add extra space at the end of the container(the one that has TextFormField) so that the login button can be aligned. + children: [ + Container(//For Borders of lighter area //Main Container to add Welcome, TextFormFields and Login. + //tbd: Get the color right! + margin: EdgeInsets.only(top: 0, bottom: 0, left: (MediaQuery.of(context).size.width) *(31/428), right: (MediaQuery.of(context).size.width) *(31/428),), + padding: EdgeInsets.only(top: 0, bottom: (MediaQuery.of(context).size.height) *0.0179, left: 0, right: 0,), + decoration: BoxDecoration( + color: Color.fromRGBO(176, 166, 194, 210),//0xffB0A6C2, rgba(176, 166, 194, 1) + borderRadius: BorderRadius.all(Radius.circular(10)), + border: Border.all( + color: Color(0xff757575), + width: 0, + ), + boxShadow: [ + BoxShadow( + color: Color(0xff0000004D), + ), + ], + ), + child: Column( + children: [ + Container( + padding: EdgeInsets.only(top: (MediaQuery.of(context).size.height) *0.020518, bottom: 0, left: 0, right: 0,), + child: Text("Welcome!", + style: TextStyle( + color: Color(0xffFFFEFE), + fontFamily: 'Brandon-bld', + fontSize: (MediaQuery.of(context).size.height) *0.0410,//38, + ),), + ), + Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Container( + padding: EdgeInsets.only(top: 0, bottom: 0, left: 0, right: 0,), + child: Text("Don't have an account?", + style: TextStyle( + color: Color.fromRGBO(255, 255, 255, 100), + fontFamily: 'Brandon-med', + fontSize: (MediaQuery.of(context).size.height)*0.0194, + ),), + ), + Container( + padding: EdgeInsets.only(top: 0, bottom: 0, left: 0, right: 0,), + child: Text(" Sign Up", + style: TextStyle( + color: Color(0xffFFFEFE), + fontFamily: 'Brandon-med', + fontSize: (MediaQuery.of(context).size.height)*0.0194, + ),), + ), + ], + ), + SizedBox(height: (MediaQuery.of(context).size.height)*0.04535,), + Container( + //color: Colors.white, + height: (MediaQuery.of(context).size.height)*0.055, + //padding: EdgeInsets.fromLTRB(20.0, (MediaQuery.of(context).size.height - MediaQuery.of(context).padding.top)*0.0037797, 20.0, (MediaQuery.of(context).size.height - MediaQuery.of(context).padding.top)*0.0037797), + margin: EdgeInsets.only(top: 0, bottom: 0, left: (MediaQuery.of(context).size.width) *(45/428), right: (MediaQuery.of(context).size.width) *(45/428),), + decoration: BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.all(Radius.circular(10)), + border: Border.all( + color: Color(0xff757575), + width: 1, + ), + boxShadow: [ + BoxShadow( + color: Color(0xff0000004D), + ), + ], + ), + child: TextFormField( + decoration: InputDecoration( + hintText: "Username", + hintStyle: TextStyle(color: Color(0xffAEAEAE), + fontSize: (MediaQuery.of(context).size.height)*0.0194, + fontFamily: 'Brandon-med',), + contentPadding: EdgeInsets.fromLTRB(20.0, (MediaQuery.of(context).size.height)*0.0037797, 20.0, (MediaQuery.of(context).size.height)*0.0037797), + enabledBorder: OutlineInputBorder( + borderSide: BorderSide( + color: Colors.transparent, + width: 0.0, + ), + borderRadius: BorderRadius.circular(10.0), + ), + focusedBorder: OutlineInputBorder( + borderSide: BorderSide( + color: Colors.transparent, + width: 0.0, + ), + ), + ), + validator: (val) => val!.isEmpty ? "Please enter a Username." : null, + onChanged: (val) { + _username = val; + }, + style: TextStyle( + color: Colors.black, + ), + ), + ), + SizedBox(height: (MediaQuery.of(context).size.height)*0.0226781,), + Container( + //color: Colors.white, + height: (MediaQuery.of(context).size.height)*0.055, + margin: EdgeInsets.only(top: 0, bottom: 0, left: (MediaQuery.of(context).size.width) *(45/428), right: (MediaQuery.of(context).size.width) *(45/428),), + decoration: BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.all(Radius.circular(10)), + border: Border.all( + color: Color(0xff757575), + width: 1, + ), + boxShadow: [ + BoxShadow( + color: Color(0xff0000004D), + ), + ], + ), + child: TextFormField( + obscureText: true, + decoration: InputDecoration( + hintText: "Password", + hintStyle: TextStyle(color: Color(0xffAEAEAE), + fontSize: (MediaQuery.of(context).size.height)*0.0194, + fontFamily: 'Brandon-med',), + contentPadding: EdgeInsets.fromLTRB(20.0, (MediaQuery.of(context).size.height)*0.0037797, 20.0, (MediaQuery.of(context).size.height)*0.0037797), + enabledBorder: OutlineInputBorder( + borderSide: BorderSide( + color: Colors.transparent, + width: 0.0, + ), + borderRadius: BorderRadius.circular(10.0), + ), + focusedBorder: OutlineInputBorder( + borderSide: BorderSide( + color: Colors.transparent, + width: 0.0, + ), + ), + ), + validator: (val) => val!.isEmpty ? "Please enter a Password." : null, + onChanged: (val) { + setState(() { + _password = val; + }); + }, + style: TextStyle( + color: Colors.black, + ), + ), + ), + SizedBox(height: (MediaQuery.of(context).size.height)*0.024838,), + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Container( + margin: EdgeInsets.only(top: 0, bottom: 0, left: (MediaQuery.of(context).size.width) *(45/428), right: 0,), + height: (MediaQuery.of(context).size.height)*0.0167, + width: (MediaQuery.of(context).size.height)*0.0167, + color: Colors.white, + child: Transform.scale( + scale: (MediaQuery.of(context).size.height)*0.001, + child: Checkbox( + side: BorderSide( + color: Color(0xffB0A6C2), + width: 0, + ), + checkColor: Colors.white, + value: _isChecked, + onChanged: (bool? value) { + setState(() { + _isChecked = value!; + }); + }, + ), + ), + ), + Container( + padding: EdgeInsets.only(top: 0, bottom: 0, left: (MediaQuery.of(context).size.width) *(5/428), right: 0,), + child: Text("Remember me!", + style: TextStyle( + color: Color.fromRGBO(255, 255, 255, 100), + fontFamily: 'Brandon-med', + fontSize: (MediaQuery.of(context).size.height)*0.0161987, + ),), + ), + ], + ), + Container( + padding: EdgeInsets.only(top: 0, bottom: 0, left: 0, right: (MediaQuery.of(context).size.width) *(45/428),), + child: Text("Forgot Password?", + style: TextStyle( + color: Color(0xffFFFEFE), + fontFamily: 'Brandon-med', + fontSize: (MediaQuery.of(context).size.height)*0.0161987, + ),), + ), + ], + ), + SizedBox(height: (MediaQuery.of(context).size.height) *0.0864,), + ], + ), + ), + SizedBox(height: (MediaQuery.of(context).size.height) *(25/926),), + ], + ), + GestureDetector( + child: Container(//Login button + child: Align( + alignment: Alignment.center, + child: SvgPicture.asset( + "assets/Images/login.svg", + height: (MediaQuery.of(context).size.height) *0.0486, + ), + ), + ), + onTap: () { + if(_formKey.currentState!.validate()) { + _navigateAndDisplaySelection(context); + } + }, + ), + ], + ), + ), + ), + Row( + mainAxisAlignment: MainAxisAlignment.end, + //crossAxisAlignment: CrossAxisAlignment.end, + children: [ + Stack( + //alignment: Alignment.centerRight, + children: [ + Positioned( + left: (MediaQuery.of(context).size.height) *(80/926), + top: (MediaQuery.of(context).size.height) *(50/926), + child: Align( + alignment: Alignment.bottomRight, + child: SvgPicture.asset( + "assets/Images/login_bottomRight.svg", + height: (MediaQuery.of(context).size.height) *0.183, + width: (MediaQuery.of(context).size.height) *0.183, + ), + ), + ), + Positioned(//Remove and add again + child: Align( + alignment: Alignment.bottomRight, + child: SvgPicture.asset( + "assets/Images/login_bottomRight.svg", + height: (MediaQuery.of(context).size.height) *0.183, + width: (MediaQuery.of(context).size.height) *0.183, + color: Colors.transparent, + ), + ), + ), + ], + ), + ], + ), + ], + ), + ), + ), + ); + } +} diff --git a/lib/screens/home.dart b/lib/screens/home.dart new file mode 100644 index 0000000..9e54de3 --- /dev/null +++ b/lib/screens/home.dart @@ -0,0 +1,38 @@ +import 'package:flutter/material.dart'; + +class Home extends StatefulWidget { + const Home({Key? key}) : super(key: key); + + @override + _HomeState createState() => _HomeState(); +} + +class _HomeState extends State { + @override + Widget build(BuildContext context) { + return Scaffold( + backgroundColor: Color(0xff3F2668), + appBar: AppBar( + backgroundColor: Colors.transparent, + elevation: 2, + centerTitle: true, + title: const Text("Home", + style: TextStyle( + color: Color(0xffFFFEFE), + fontFamily: 'Brandon-bld', + ), + ), + leading: Text(""), + actions: [ + TextButton( + onPressed: () { Navigator.pop(context, "logout"); }, + child: const Icon( + Icons.logout, + color: Colors.white, + ), + ), + ], + ), + ); + } +} diff --git a/lib/screens/wrapper.dart b/lib/screens/wrapper.dart new file mode 100644 index 0000000..e01a552 --- /dev/null +++ b/lib/screens/wrapper.dart @@ -0,0 +1,11 @@ +import 'package:flutter/material.dart'; +import 'package:testify/screens/Authentication/login.dart'; + +class Wrapper extends StatelessWidget { + @override + Widget build(BuildContext context) { + + // return either home or authenticate + return Login(); + } +} From 02074c7304520af61e4a83f6bfc3651027af7975 Mon Sep 17 00:00:00 2001 From: TheYoungWolf-Productions Date: Fri, 21 Jan 2022 22:14:45 +0500 Subject: [PATCH 03/23] Fix with recommended action --- test/widget_test.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/widget_test.dart b/test/widget_test.dart index f903217..6f150a5 100644 --- a/test/widget_test.dart +++ b/test/widget_test.dart @@ -13,7 +13,7 @@ import 'package:testify/main.dart'; void main() { testWidgets('Counter increments smoke test', (WidgetTester tester) async { // Build our app and trigger a frame. - await tester.pumpWidget(const MyApp()); + await tester.pumpWidget(MyApp()); // Verify that our counter starts at 0. expect(find.text('0'), findsOneWidget); From e4d652e160f7aadd910a6bbf004c2324e5b4a370 Mon Sep 17 00:00:00 2001 From: TheYoungWolf <68595463+TheYoungWolf-Productions@users.noreply.github.com> Date: Fri, 21 Jan 2022 22:35:35 +0500 Subject: [PATCH 04/23] Update README.md --- README.md | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 9fb5ee9..5184195 100644 --- a/README.md +++ b/README.md @@ -15,11 +15,15 @@ git clone https://github.com/TheYoungWolf-Productions/testify.git cd testify flutter pub get ``` -`Note:` You need your [GitHub](https://docs.github.com/en/get-started/quickstart/set-up-git) and [Flutter](https://docs.flutter.dev/get-started/install/windows) already setup. +`Note:` You need your [GitHub](https://docs.github.com/en/get-started/quickstart/set-up-git) and [Flutter](https://docs.flutter.dev/get-started/install/windows) already setup. I recommend using *VSCode* as the editor with __Flutter__ extension. + +### :loudspeaker: Guidelines +- :bulb: The team will ***STRICTLY*** follow the [Git Workflow](https://nvie.com/posts/a-successful-git-branching-model/) +- :bulb: Every pull request needs to have a assigned reviewer. ## Contributors -- theYoungWolf +- :wolf: theYoungWolf :wolf: - Muhammad Abdullah - Minahial Khalid - **Sponsors:** Pookidevs :v: From c320425fc2e108a6899f21b26c0f064554fd55fb Mon Sep 17 00:00:00 2001 From: TheYoungWolf <68595463+TheYoungWolf-Productions@users.noreply.github.com> Date: Sat, 22 Jan 2022 14:16:35 +0500 Subject: [PATCH 05/23] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 5184195..971ed7b 100644 --- a/README.md +++ b/README.md @@ -19,7 +19,7 @@ flutter pub get ### :loudspeaker: Guidelines - :bulb: The team will ***STRICTLY*** follow the [Git Workflow](https://nvie.com/posts/a-successful-git-branching-model/) -- :bulb: Every pull request needs to have a assigned reviewer. +- :bulb: Every pull request needs to have an **assigned** reviewer. ## Contributors From 707c32bd746573c0323271ee66c239afb0b9cc6a Mon Sep 17 00:00:00 2001 From: TheYoungWolf-Productions Date: Wed, 26 Jan 2022 21:07:57 +0500 Subject: [PATCH 06/23] Add req/res functionality --- pubspec.lock | 114 ++++++++++++++++++++++++++++++++++++++++++++++++++- pubspec.yaml | 3 ++ 2 files changed, 116 insertions(+), 1 deletion(-) diff --git a/pubspec.lock b/pubspec.lock index cf7fbe8..a6a45fc 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -57,6 +57,20 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "1.2.0" + ffi: + dependency: transitive + description: + name: ffi + url: "https://pub.dartlang.org" + source: hosted + version: "1.1.2" + file: + dependency: transitive + description: + name: file + url: "https://pub.dartlang.org" + source: hosted + version: "6.1.2" flutter: dependency: "direct main" description: flutter @@ -81,6 +95,20 @@ packages: description: flutter source: sdk version: "0.0.0" + http: + dependency: "direct main" + description: + name: http + url: "https://pub.dartlang.org" + source: hosted + version: "0.13.4" + http_parser: + dependency: transitive + description: + name: http_parser + url: "https://pub.dartlang.org" + source: hosted + version: "4.0.0" lints: dependency: transitive description: @@ -123,6 +151,55 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "1.0.0" + path_provider: + dependency: "direct main" + description: + name: path_provider + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.8" + path_provider_android: + dependency: transitive + description: + name: path_provider_android + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.11" + path_provider_ios: + dependency: transitive + description: + name: path_provider_ios + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.7" + path_provider_linux: + dependency: transitive + description: + name: path_provider_linux + url: "https://pub.dartlang.org" + source: hosted + version: "2.1.5" + path_provider_macos: + dependency: transitive + description: + name: path_provider_macos + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.5" + path_provider_platform_interface: + dependency: transitive + description: + name: path_provider_platform_interface + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.3" + path_provider_windows: + dependency: transitive + description: + name: path_provider_windows + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.5" petitparser: dependency: transitive description: @@ -130,6 +207,27 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "4.4.0" + platform: + dependency: transitive + description: + name: platform + url: "https://pub.dartlang.org" + source: hosted + version: "3.1.0" + plugin_platform_interface: + dependency: transitive + description: + name: plugin_platform_interface + url: "https://pub.dartlang.org" + source: hosted + version: "2.1.2" + process: + dependency: transitive + description: + name: process + url: "https://pub.dartlang.org" + source: hosted + version: "4.2.4" sky_engine: dependency: transitive description: flutter @@ -191,6 +289,20 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "2.1.1" + win32: + dependency: transitive + description: + name: win32 + url: "https://pub.dartlang.org" + source: hosted + version: "2.3.8" + xdg_directories: + dependency: transitive + description: + name: xdg_directories + url: "https://pub.dartlang.org" + source: hosted + version: "0.2.0" xml: dependency: transitive description: @@ -200,4 +312,4 @@ packages: version: "5.3.1" sdks: dart: ">=2.15.1 <3.0.0" - flutter: ">=2.4.0-0.0.pre" + flutter: ">=2.5.0" diff --git a/pubspec.yaml b/pubspec.yaml index 0ce6c9b..61fd2a9 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -35,6 +35,8 @@ dependencies: # Use with the CupertinoIcons class for iOS style icons. cupertino_icons: ^1.0.2 flutter_svg: ^1.0.2 + http: ^0.13.4 + path_provider: ^2.0.8 dev_dependencies: flutter_test: @@ -67,6 +69,7 @@ flutter: - assets/Images/login.svg - assets/Images/login_bottomRight.svg - assets/Images/login_bottomRight_png.png + - assets/Images/create_quiz.svg fonts: - family: Brandon-bld From d5b14a28eabbd1b66cdef47c51734533d9b81688 Mon Sep 17 00:00:00 2001 From: TheYoungWolf-Productions Date: Wed, 26 Jan 2022 21:09:49 +0500 Subject: [PATCH 07/23] Add quiz generation --- assets/Images/create_quiz.svg | 57 ++++ .../Welcome/GenerateQuiz/difficulty.dart | 281 ++++++++++++++++++ .../Welcome/GenerateQuiz/generate_quiz.dart | 259 ++++++++++++++++ .../GenerateQuiz/generate_quiz_last.dart | 276 +++++++++++++++++ .../Welcome/GenerateQuiz/question_types.dart | 281 ++++++++++++++++++ lib/screens/Welcome/side_menu_bar.dart | 46 +++ 6 files changed, 1200 insertions(+) create mode 100644 assets/Images/create_quiz.svg create mode 100644 lib/screens/Welcome/GenerateQuiz/difficulty.dart create mode 100644 lib/screens/Welcome/GenerateQuiz/generate_quiz.dart create mode 100644 lib/screens/Welcome/GenerateQuiz/generate_quiz_last.dart create mode 100644 lib/screens/Welcome/GenerateQuiz/question_types.dart create mode 100644 lib/screens/Welcome/side_menu_bar.dart diff --git a/assets/Images/create_quiz.svg b/assets/Images/create_quiz.svg new file mode 100644 index 0000000..1682976 --- /dev/null +++ b/assets/Images/create_quiz.svg @@ -0,0 +1,57 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/lib/screens/Welcome/GenerateQuiz/difficulty.dart b/lib/screens/Welcome/GenerateQuiz/difficulty.dart new file mode 100644 index 0000000..0a42723 --- /dev/null +++ b/lib/screens/Welcome/GenerateQuiz/difficulty.dart @@ -0,0 +1,281 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_svg/flutter_svg.dart'; +import 'package:testify/screens/Authentication/login.dart'; +import 'package:testify/screens/Welcome/GenerateQuiz/generate_quiz_last.dart'; +import 'package:testify/screens/Welcome/GenerateQuiz/question_types.dart'; +import 'package:testify/screens/Welcome/side_menu_bar.dart'; + +class Difficulty extends StatefulWidget { + @override + State createState() => _DifficultyState(); +} + +class _DifficultyState extends State { + //Fields + + @override + Widget build(BuildContext context) { + return Scaffold( + backgroundColor: Color(0xffF8F9FB), + drawer: SideMenuBar(), + appBar: AppBar( + backgroundColor: Color(0xff3F2668), + elevation: 2, + centerTitle: true, + flexibleSpace: Container( + decoration: BoxDecoration( + gradient: LinearGradient( + begin: Alignment.topCenter, + end: Alignment.bottomCenter, + colors: [ + Color(0xff7F1AF1), + Color(0xff482384) + ]) + ), + ), + title: const Text("Generate Quiz", + style: TextStyle( + color: Color(0xffFFFEFE), + fontFamily: 'Brandon-bld', + ), + ), + actions: [ + TextButton( + onPressed: () async { + final result = await Navigator.push( + context, + MaterialPageRoute(builder: (context) => const Login(fromWhere:"Home")), + ); + }, + child: const Icon( + Icons.logout, + color: Colors.white, + ), + ), + ], + ), + body: Container( + padding: EdgeInsets.only(top:(MediaQuery.of(context).size.height) *(15/926), + bottom: (MediaQuery.of(context).size.height) *(8/926), + left: (MediaQuery.of(context).size.width) *(18/428), + right: (MediaQuery.of(context).size.width) *(18/428)), + child: Column( + children: [ + Row( + children: [ + Container( + width: (MediaQuery.of(context).size.width) *(221/428), + //height: (MediaQuery.of(context).size.height) *(91/926), + child: Column( + children: [ + Align( + alignment: Alignment.topLeft, + child: Text("Create Quiz", + style: TextStyle( + color: Color(0xff232323), + fontFamily: 'Brandon-bld', + fontSize: (MediaQuery.of(context).size.height) *(20/926),//38, + ),), + ), + SizedBox(height: (MediaQuery.of(context).size.height) *(2/926),), + Text("Lorem ipsum dolor sit amet, consectetur adipiscing elit. Cras imperdiet finibus elit non luctus. Morbi auctor mattis ante.", + style: TextStyle( + color: Color(0xFF483A3A), + fontFamily: 'Brandon-med', + fontSize: (MediaQuery.of(context).size.height) *(10/926),//38, + ),), + ], + ), + ), + SizedBox(width: (MediaQuery.of(context).size.width) *(39/428),), + Container( + //color: Colors.transparent, + child: SvgPicture.asset( + "assets/Images/create_quiz.svg", + height: (MediaQuery.of(context).size.height) *(100/926), + //width: (MediaQuery.of(context).size.width) *(132/428), + ), + ), + ], + ), + SizedBox(height: (MediaQuery.of(context).size.height) *(25/926),), + //a + Container( + height: (MediaQuery.of(context).size.height) *(35.32/926), + decoration: BoxDecoration( + color: Color(0xff3F2668),//0xffB0A6C2, rgba(176, 166, 194, 1) + borderRadius: BorderRadius.only(topLeft: Radius.circular(50), topRight: Radius.circular(50)), + boxShadow: [ + BoxShadow( + color: Colors.black12,//Color(0xff00000029), + spreadRadius: 5, + blurRadius: 5, + offset: Offset(0, 0), + ), + ], + ), + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + SizedBox(width: (MediaQuery.of(context).size.width) *(28/428),), + Container( + padding: EdgeInsets.only(top: (MediaQuery.of(context).size.height) *(9/926), bottom: (MediaQuery.of(context).size.height) *(4/926)), + height: (MediaQuery.of(context).size.height) *(35.32/926), + width: (MediaQuery.of(context).size.width) *(113/428), + color: Color(0xFF3F2668), + child: Column( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text(" Systems/Subjects/Topics ", + style: TextStyle( + color: Color(0xffFEFEFE), + fontFamily: 'Brandon-bld', + fontSize: (MediaQuery.of(context).size.height) *(12/926), + ),), + ], + ), + ), + Container( + padding: EdgeInsets.only(top: (MediaQuery.of(context).size.height) *(5/926), bottom: (MediaQuery.of(context).size.height) *(5/926)), + height: (MediaQuery.of(context).size.height) *(35.32/926), + width: (MediaQuery.of(context).size.width) *(80/428), + color: Color(0xFF3F2668), + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Text("Question Types", + style: TextStyle( + color: Color(0xffFEFEFE), + fontFamily: 'Brandon-bld', + fontSize: (MediaQuery.of(context).size.height) *(12/926), + ),), + ], + ), + ), + Container( + padding: EdgeInsets.only(top: (MediaQuery.of(context).size.height) *(5/926), bottom: (MediaQuery.of(context).size.height) *(5/926)), + height: (MediaQuery.of(context).size.height) *(35.32/926), + width: (MediaQuery.of(context).size.width) *(65/428), + color: Colors.white, + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Text("Difficulty", + style: TextStyle( + color: Color(0xFF3F2668),//0xFF3F2668 + fontFamily: 'Brandon-bld', + fontSize: (MediaQuery.of(context).size.height) *(12/926), + ),), + Container( + padding: EdgeInsets.only(left: (MediaQuery.of(context).size.width) *(13/428), right: (MediaQuery.of(context).size.width) *(13/428)), + //margin: EdgeInsets.only(top: (MediaQuery.of(context).size.height) *(1/926)), + child: Divider(height: 3, + thickness: 2, + color: Color(0xFF3F2668),), + ), + ], + ), + ), + Container( + padding: EdgeInsets.only(top: (MediaQuery.of(context).size.height) *(5/926), bottom: (MediaQuery.of(context).size.height) *(5/926)), + height: (MediaQuery.of(context).size.height) *(35.32/926), + width: (MediaQuery.of(context).size.width) *(75/428), + color: Color(0xFF3F2668), + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Text("Generate Quiz", + style: TextStyle( + color: Color(0xffFEFEFE), + fontFamily: 'Brandon-bld', + fontSize: (MediaQuery.of(context).size.height) *(12/926), + ),), + ], + ), + ), + SizedBox(width: (MediaQuery.of(context).size.width) *(28/428),), + ], + ), + ), + SizedBox(height: (MediaQuery.of(context).size.height) *(15.28/926),), + Container( + height: (MediaQuery.of(context).size.height) *(167.52/926), + color: Colors.red, + ), + SizedBox(height: (MediaQuery.of(context).size.height) *(10.74/926),), + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + InkWell( + child: Container( + height: (MediaQuery.of(context).size.height) *(42/926), + width: (MediaQuery.of(context).size.width) *(68/428), + decoration: BoxDecoration( + color: Color(0xff3F2668),//0xffB0A6C2, rgba(176, 166, 194, 1) + borderRadius: BorderRadius.all(Radius.circular(3)), + boxShadow: [ + BoxShadow( + color: Colors.black12,//Color(0xff00000029), + spreadRadius: 2, + blurRadius: 2, + offset: Offset(0, 0), + ), + ], + ), + child: TextButton( + onPressed: () { + Navigator.pop(context); + }, + child: Center( + child: Text("Back", + style: TextStyle( + color: Colors.white, + fontFamily: 'Brandon-med', + ), + ), + ), + ), + ), + ), + InkWell( + child: Container( + height: (MediaQuery.of(context).size.height) *(42/926), + width: (MediaQuery.of(context).size.width) *(68/428), + decoration: BoxDecoration( + color: Color(0xff3F2668),//0xffB0A6C2, rgba(176, 166, 194, 1) + borderRadius: BorderRadius.all(Radius.circular(3)), + boxShadow: [ + BoxShadow( + color: Colors.black12,//Color(0xff00000029), + spreadRadius: 2, + blurRadius: 2, + offset: Offset(0, 0), + ), + ], + ), + child: TextButton( + onPressed: () async { + final result = await Navigator.push( + context, + MaterialPageRoute(builder: (context) => GenerateQuizLast()), + ); + }, + child: Center( + child: Text("Next", + style: TextStyle( + color: Colors.white, + fontFamily: 'Brandon-med', + ), + ), + ), + ), + ), + ), + ], + ), + ], + ), + ), + ); + } +} \ No newline at end of file diff --git a/lib/screens/Welcome/GenerateQuiz/generate_quiz.dart b/lib/screens/Welcome/GenerateQuiz/generate_quiz.dart new file mode 100644 index 0000000..cd4d420 --- /dev/null +++ b/lib/screens/Welcome/GenerateQuiz/generate_quiz.dart @@ -0,0 +1,259 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_svg/flutter_svg.dart'; +import 'package:testify/screens/Authentication/login.dart'; +import 'package:testify/screens/Welcome/GenerateQuiz/question_types.dart'; +import 'package:testify/screens/Welcome/side_menu_bar.dart'; + +class GenerateQuiz extends StatefulWidget { + @override + State createState() => _GenerateQuizState(); +} + +class _GenerateQuizState extends State { + // This is the first Page + + @override + Widget build(BuildContext context) { + return Scaffold( + backgroundColor: Color(0xffF8F9FB), + drawer: SideMenuBar(), + appBar: AppBar( + backgroundColor: Color(0xff3F2668), + elevation: 2, + centerTitle: true, + flexibleSpace: Container( + decoration: BoxDecoration( + gradient: LinearGradient( + begin: Alignment.topCenter, + end: Alignment.bottomCenter, + colors: [ + Color(0xff7F1AF1), + Color(0xff482384) + ]) + ), + ), + title: const Text("Generate Quiz", + style: TextStyle( + color: Color(0xffFFFEFE), + fontFamily: 'Brandon-bld', + ), + ), + actions: [ + TextButton( + onPressed: () async { + final result = await Navigator.push( + context, + MaterialPageRoute(builder: (context) => const Login(fromWhere:"Home")), + ); + }, + child: const Icon( + Icons.logout, + color: Colors.white, + ), + ), + ], + ), + body: Container( + padding: EdgeInsets.only(top:(MediaQuery.of(context).size.height) *(15/926), + bottom: (MediaQuery.of(context).size.height) *(8/926), + left: (MediaQuery.of(context).size.width) *(18/428), + right: (MediaQuery.of(context).size.width) *(18/428)), + child: Column( + children: [ + Row( + children: [ + Container( + width: (MediaQuery.of(context).size.width) *(221/428), + //height: (MediaQuery.of(context).size.height) *(91/926), + child: Column( + children: [ + Align( + alignment: Alignment.topLeft, + child: Text("Create Quiz", + style: TextStyle( + color: Color(0xff232323), + fontFamily: 'Brandon-bld', + fontSize: (MediaQuery.of(context).size.height) *(20/926),//38, + ),), + ), + SizedBox(height: (MediaQuery.of(context).size.height) *(2/926),), + Text("Lorem ipsum dolor sit amet, consectetur adipiscing elit. Cras imperdiet finibus elit non luctus. Morbi auctor mattis ante.", + style: TextStyle( + color: Color(0xFF483A3A), + fontFamily: 'Brandon-med', + fontSize: (MediaQuery.of(context).size.height) *(10/926),//38, + ),), + ], + ), + ), + SizedBox(width: (MediaQuery.of(context).size.width) *(39/428),), + Container( + //color: Colors.transparent, + child: SvgPicture.asset( + "assets/Images/create_quiz.svg", + height: (MediaQuery.of(context).size.height) *(100/926), + //width: (MediaQuery.of(context).size.width) *(132/428), + ), + ), + ], + ), + SizedBox(height: (MediaQuery.of(context).size.height) *(25/926),), + //a + Container( + height: (MediaQuery.of(context).size.height) *(35.32/926), + decoration: BoxDecoration( + color: Color(0xff3F2668),//0xffB0A6C2, rgba(176, 166, 194, 1) + borderRadius: BorderRadius.only(topLeft: Radius.circular(50), topRight: Radius.circular(50)), + boxShadow: [ + BoxShadow( + color: Colors.black12,//Color(0xff00000029), + spreadRadius: 5, + blurRadius: 5, + offset: Offset(0, 0), + ), + ], + ), + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + SizedBox(width: (MediaQuery.of(context).size.width) *(28/428),), + Container( + padding: EdgeInsets.only(top: (MediaQuery.of(context).size.height) *(9/926), bottom: (MediaQuery.of(context).size.height) *(4/926)), + height: (MediaQuery.of(context).size.height) *(35.32/926), + width: (MediaQuery.of(context).size.width) *(113/428), + color: Colors.white, + child: Column( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text(" Systems/Subjects/Topics ", + style: TextStyle( + color: Color(0xFF3F2668), + fontFamily: 'Brandon-bld', + fontSize: (MediaQuery.of(context).size.height) *(12/926), + ),), + Container( + padding: EdgeInsets.only(left: (MediaQuery.of(context).size.width) *(17/428), right: (MediaQuery.of(context).size.width) *(17/428)), + //margin: EdgeInsets.only(top: (MediaQuery.of(context).size.height) *(1/926)), + child: Divider(height: 3, + thickness: 2, + color: Color(0xFF3F2668),), + ), + ], + ), + ), + Container( + padding: EdgeInsets.only(top: (MediaQuery.of(context).size.height) *(5/926), bottom: (MediaQuery.of(context).size.height) *(5/926)), + height: (MediaQuery.of(context).size.height) *(35.32/926), + width: (MediaQuery.of(context).size.width) *(80/428), + color: Color(0xFF3F2668), + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Text("Question Types", + style: TextStyle( + color: Color(0xffFEFEFE), + fontFamily: 'Brandon-bld', + fontSize: (MediaQuery.of(context).size.height) *(12/926), + ),), + ], + ), + ), + Container( + padding: EdgeInsets.only(top: (MediaQuery.of(context).size.height) *(5/926), bottom: (MediaQuery.of(context).size.height) *(5/926)), + height: (MediaQuery.of(context).size.height) *(35.32/926), + width: (MediaQuery.of(context).size.width) *(65/428), + color: Color(0xFF3F2668), + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Text("Difficulty", + style: TextStyle( + color: Color(0xffFEFEFE), + fontFamily: 'Brandon-bld', + fontSize: (MediaQuery.of(context).size.height) *(12/926), + ),), + ], + ), + ), + Container( + padding: EdgeInsets.only(top: (MediaQuery.of(context).size.height) *(5/926), bottom: (MediaQuery.of(context).size.height) *(5/926)), + height: (MediaQuery.of(context).size.height) *(35.32/926), + width: (MediaQuery.of(context).size.width) *(75/428), + color: Color(0xFF3F2668), + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Text("Generate Quiz", + style: TextStyle( + color: Color(0xffFEFEFE), + fontFamily: 'Brandon-bld', + fontSize: (MediaQuery.of(context).size.height) *(12/926), + ),), + ], + ), + ), + SizedBox(width: (MediaQuery.of(context).size.width) *(28/428),), + ], + ), + ), + SizedBox(height: (MediaQuery.of(context).size.height) *(15.28/926),), + Container( + height: (MediaQuery.of(context).size.height) *(167.52/926), + color: Colors.red, + ), + SizedBox(height: (MediaQuery.of(context).size.height) *(17.9/926),), + Container( + height: (MediaQuery.of(context).size.height) *(167.52/926), + color: Colors.red, + ), + SizedBox(height: (MediaQuery.of(context).size.height) *(17.9/926),), + Container( + height: (MediaQuery.of(context).size.height) *(167.52/926), + color: Colors.red, + ), + SizedBox(height: (MediaQuery.of(context).size.height) *(10.74/926),), + Row( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + InkWell( + child: Container( + height: (MediaQuery.of(context).size.height) *(42/926), + width: (MediaQuery.of(context).size.width) *(68/428), + decoration: BoxDecoration( + color: Color(0xff3F2668),//0xffB0A6C2, rgba(176, 166, 194, 1) + borderRadius: BorderRadius.all(Radius.circular(3)), + boxShadow: [ + BoxShadow( + color: Colors.black12,//Color(0xff00000029), + spreadRadius: 2, + blurRadius: 2, + offset: Offset(0, 0), + ), + ], + ), + child: TextButton( + onPressed: () async { + final result = await Navigator.push( + context, + MaterialPageRoute(builder: (context) => QuestionTypes()), + ); + }, + child: Center( + child: Text("Next", + style: TextStyle( + color: Colors.white, + fontFamily: 'Brandon-med', + ), + ), + ), + ), + ), + ), + ], + ), + ], + ), + ), + ); + } +} \ No newline at end of file diff --git a/lib/screens/Welcome/GenerateQuiz/generate_quiz_last.dart b/lib/screens/Welcome/GenerateQuiz/generate_quiz_last.dart new file mode 100644 index 0000000..2a2f85e --- /dev/null +++ b/lib/screens/Welcome/GenerateQuiz/generate_quiz_last.dart @@ -0,0 +1,276 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_svg/flutter_svg.dart'; +import 'package:testify/screens/Authentication/login.dart'; +import 'package:testify/screens/Welcome/GenerateQuiz/difficulty.dart'; +import 'package:testify/screens/Welcome/GenerateQuiz/question_types.dart'; +import 'package:testify/screens/Welcome/side_menu_bar.dart'; + +class GenerateQuizLast extends StatefulWidget { + @override + State createState() => _GenerateQuizLastState(); +} + +class _GenerateQuizLastState extends State { + //Fields + + @override + Widget build(BuildContext context) { + return Scaffold( + backgroundColor: Color(0xffF8F9FB), + drawer: SideMenuBar(), + appBar: AppBar( + backgroundColor: Color(0xff3F2668), + elevation: 2, + centerTitle: true, + flexibleSpace: Container( + decoration: BoxDecoration( + gradient: LinearGradient( + begin: Alignment.topCenter, + end: Alignment.bottomCenter, + colors: [ + Color(0xff7F1AF1), + Color(0xff482384) + ]) + ), + ), + title: const Text("Generate Quiz", + style: TextStyle( + color: Color(0xffFFFEFE), + fontFamily: 'Brandon-bld', + ), + ), + actions: [ + TextButton( + onPressed: () async { + final result = await Navigator.push( + context, + MaterialPageRoute(builder: (context) => const Login(fromWhere:"Home")), + ); + }, + child: const Icon( + Icons.logout, + color: Colors.white, + ), + ), + ], + ), + body: Container( + padding: EdgeInsets.only(top:(MediaQuery.of(context).size.height) *(15/926), + bottom: (MediaQuery.of(context).size.height) *(8/926), + left: (MediaQuery.of(context).size.width) *(18/428), + right: (MediaQuery.of(context).size.width) *(18/428)), + child: Column( + children: [ + Row( + children: [ + Container( + width: (MediaQuery.of(context).size.width) *(221/428), + //height: (MediaQuery.of(context).size.height) *(91/926), + child: Column( + children: [ + Align( + alignment: Alignment.topLeft, + child: Text("Create Quiz", + style: TextStyle( + color: Color(0xff232323), + fontFamily: 'Brandon-bld', + fontSize: (MediaQuery.of(context).size.height) *(20/926),//38, + ),), + ), + SizedBox(height: (MediaQuery.of(context).size.height) *(2/926),), + Text("Lorem ipsum dolor sit amet, consectetur adipiscing elit. Cras imperdiet finibus elit non luctus. Morbi auctor mattis ante.", + style: TextStyle( + color: Color(0xFF483A3A), + fontFamily: 'Brandon-med', + fontSize: (MediaQuery.of(context).size.height) *(10/926),//38, + ),), + ], + ), + ), + SizedBox(width: (MediaQuery.of(context).size.width) *(39/428),), + Container( + //color: Colors.transparent, + child: SvgPicture.asset( + "assets/Images/create_quiz.svg", + height: (MediaQuery.of(context).size.height) *(100/926), + //width: (MediaQuery.of(context).size.width) *(132/428), + ), + ), + ], + ), + SizedBox(height: (MediaQuery.of(context).size.height) *(25/926),), + //a + Container( + height: (MediaQuery.of(context).size.height) *(35.32/926), + decoration: BoxDecoration( + color: Color(0xff3F2668),//0xffB0A6C2, rgba(176, 166, 194, 1) + borderRadius: BorderRadius.only(topLeft: Radius.circular(50), topRight: Radius.circular(50)), + boxShadow: [ + BoxShadow( + color: Colors.black12,//Color(0xff00000029), + spreadRadius: 5, + blurRadius: 5, + offset: Offset(0, 0), + ), + ], + ), + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + SizedBox(width: (MediaQuery.of(context).size.width) *(28/428),), + Container( + padding: EdgeInsets.only(top: (MediaQuery.of(context).size.height) *(9/926), bottom: (MediaQuery.of(context).size.height) *(4/926)), + height: (MediaQuery.of(context).size.height) *(35.32/926), + width: (MediaQuery.of(context).size.width) *(113/428), + color: Color(0xFF3F2668), + child: Column( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text(" Systems/Subjects/Topics ", + style: TextStyle( + color: Color(0xffFEFEFE), + fontFamily: 'Brandon-bld', + fontSize: (MediaQuery.of(context).size.height) *(12/926), + ),), + ], + ), + ), + Container( + padding: EdgeInsets.only(top: (MediaQuery.of(context).size.height) *(5/926), bottom: (MediaQuery.of(context).size.height) *(5/926)), + height: (MediaQuery.of(context).size.height) *(35.32/926), + width: (MediaQuery.of(context).size.width) *(80/428), + color: Color(0xFF3F2668), + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Text("Question Types", + style: TextStyle( + color: Color(0xffFEFEFE), + fontFamily: 'Brandon-bld', + fontSize: (MediaQuery.of(context).size.height) *(12/926), + ),), + ], + ), + ), + Container( + padding: EdgeInsets.only(top: (MediaQuery.of(context).size.height) *(5/926), bottom: (MediaQuery.of(context).size.height) *(5/926)), + height: (MediaQuery.of(context).size.height) *(35.32/926), + width: (MediaQuery.of(context).size.width) *(65/428), + color: Color(0xFF3F2668), + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Text("Difficulty", + style: TextStyle( + color: Color(0xffFEFEFE), + fontFamily: 'Brandon-bld', + fontSize: (MediaQuery.of(context).size.height) *(12/926), + ),), + ], + ), + ), + Container( + padding: EdgeInsets.only(top: (MediaQuery.of(context).size.height) *(5/926), bottom: (MediaQuery.of(context).size.height) *(5/926)), + height: (MediaQuery.of(context).size.height) *(35.32/926), + width: (MediaQuery.of(context).size.width) *(75/428), + color: Colors.white, + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Text("Generate Quiz", + style: TextStyle( + color: Color(0xFF3F2668),//0xFF3F2668 + fontFamily: 'Brandon-bld', + fontSize: (MediaQuery.of(context).size.height) *(12/926), + ),), + Container( + padding: EdgeInsets.only(left: (MediaQuery.of(context).size.width) *(13/428), right: (MediaQuery.of(context).size.width) *(13/428)), + //margin: EdgeInsets.only(top: (MediaQuery.of(context).size.height) *(1/926)), + child: Divider(height: 3, + thickness: 2, + color: Color(0xFF3F2668),), + ), + ], + ), + ), + SizedBox(width: (MediaQuery.of(context).size.width) *(28/428),), + ], + ), + ), + SizedBox(height: (MediaQuery.of(context).size.height) *(15.28/926),), + Container( + height: (MediaQuery.of(context).size.height) *(167.52/926), + color: Colors.red, + ), + SizedBox(height: (MediaQuery.of(context).size.height) *(10.74/926),), + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + InkWell( + child: Container( + height: (MediaQuery.of(context).size.height) *(42/926), + width: (MediaQuery.of(context).size.width) *(68/428), + decoration: BoxDecoration( + color: Color(0xff3F2668),//0xffB0A6C2, rgba(176, 166, 194, 1) + borderRadius: BorderRadius.all(Radius.circular(3)), + boxShadow: [ + BoxShadow( + color: Colors.black12,//Color(0xff00000029), + spreadRadius: 2, + blurRadius: 2, + offset: Offset(0, 0), + ), + ], + ), + child: TextButton( + onPressed: () { + Navigator.pop(context); + }, + child: Center( + child: Text("Back", + style: TextStyle( + color: Colors.white, + fontFamily: 'Brandon-med', + ), + ), + ), + ), + ), + ), + InkWell( + child: Container( + height: (MediaQuery.of(context).size.height) *(42/926), + width: (MediaQuery.of(context).size.width) *(100/428), + decoration: BoxDecoration( + color: Color(0xff3F2668),//0xffB0A6C2, rgba(176, 166, 194, 1) + borderRadius: BorderRadius.all(Radius.circular(3)), + boxShadow: [ + BoxShadow( + color: Colors.black12,//Color(0xff00000029), + spreadRadius: 2, + blurRadius: 2, + offset: Offset(0, 0), + ), + ], + ), + child: TextButton( + onPressed: () { }, + child: Center( + child: Text("Create Quiz", + style: TextStyle( + color: Colors.white, + fontFamily: 'Brandon-med', + ), + ), + ), + ), + ), + ), + ], + ), + ], + ), + ), + ); + } +} \ No newline at end of file diff --git a/lib/screens/Welcome/GenerateQuiz/question_types.dart b/lib/screens/Welcome/GenerateQuiz/question_types.dart new file mode 100644 index 0000000..6ca3bf1 --- /dev/null +++ b/lib/screens/Welcome/GenerateQuiz/question_types.dart @@ -0,0 +1,281 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_svg/flutter_svg.dart'; +import 'package:testify/screens/Authentication/login.dart'; +import 'package:testify/screens/Welcome/GenerateQuiz/difficulty.dart'; +import 'package:testify/screens/Welcome/GenerateQuiz/question_types.dart'; +import 'package:testify/screens/Welcome/side_menu_bar.dart'; + +class QuestionTypes extends StatefulWidget { + @override + State createState() => _QuestionTypesState(); +} + +class _QuestionTypesState extends State { + //Fields + + @override + Widget build(BuildContext context) { + return Scaffold( + backgroundColor: Color(0xffF8F9FB), + drawer: SideMenuBar(), + appBar: AppBar( + backgroundColor: Color(0xff3F2668), + elevation: 2, + centerTitle: true, + flexibleSpace: Container( + decoration: BoxDecoration( + gradient: LinearGradient( + begin: Alignment.topCenter, + end: Alignment.bottomCenter, + colors: [ + Color(0xff7F1AF1), + Color(0xff482384) + ]) + ), + ), + title: const Text("Generate Quiz", + style: TextStyle( + color: Color(0xffFFFEFE), + fontFamily: 'Brandon-bld', + ), + ), + actions: [ + TextButton( + onPressed: () async { + final result = await Navigator.push( + context, + MaterialPageRoute(builder: (context) => const Login(fromWhere:"Home")), + ); + }, + child: const Icon( + Icons.logout, + color: Colors.white, + ), + ), + ], + ), + body: Container( + padding: EdgeInsets.only(top:(MediaQuery.of(context).size.height) *(15/926), + bottom: (MediaQuery.of(context).size.height) *(8/926), + left: (MediaQuery.of(context).size.width) *(18/428), + right: (MediaQuery.of(context).size.width) *(18/428)), + child: Column( + children: [ + Row( + children: [ + Container( + width: (MediaQuery.of(context).size.width) *(221/428), + //height: (MediaQuery.of(context).size.height) *(91/926), + child: Column( + children: [ + Align( + alignment: Alignment.topLeft, + child: Text("Create Quiz", + style: TextStyle( + color: Color(0xff232323), + fontFamily: 'Brandon-bld', + fontSize: (MediaQuery.of(context).size.height) *(20/926),//38, + ),), + ), + SizedBox(height: (MediaQuery.of(context).size.height) *(2/926),), + Text("Lorem ipsum dolor sit amet, consectetur adipiscing elit. Cras imperdiet finibus elit non luctus. Morbi auctor mattis ante.", + style: TextStyle( + color: Color(0xFF483A3A), + fontFamily: 'Brandon-med', + fontSize: (MediaQuery.of(context).size.height) *(10/926),//38, + ),), + ], + ), + ), + SizedBox(width: (MediaQuery.of(context).size.width) *(39/428),), + Container( + //color: Colors.transparent, + child: SvgPicture.asset( + "assets/Images/create_quiz.svg", + height: (MediaQuery.of(context).size.height) *(100/926), + //width: (MediaQuery.of(context).size.width) *(132/428), + ), + ), + ], + ), + SizedBox(height: (MediaQuery.of(context).size.height) *(25/926),), + //a + Container( + height: (MediaQuery.of(context).size.height) *(35.32/926), + decoration: BoxDecoration( + color: Color(0xff3F2668),//0xffB0A6C2, rgba(176, 166, 194, 1) + borderRadius: BorderRadius.only(topLeft: Radius.circular(50), topRight: Radius.circular(50)), + boxShadow: [ + BoxShadow( + color: Colors.black12,//Color(0xff00000029), + spreadRadius: 5, + blurRadius: 5, + offset: Offset(0, 0), + ), + ], + ), + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + SizedBox(width: (MediaQuery.of(context).size.width) *(28/428),), + Container( + padding: EdgeInsets.only(top: (MediaQuery.of(context).size.height) *(9/926), bottom: (MediaQuery.of(context).size.height) *(4/926)), + height: (MediaQuery.of(context).size.height) *(35.32/926), + width: (MediaQuery.of(context).size.width) *(113/428), + color: Color(0xFF3F2668), + child: Column( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text(" Systems/Subjects/Topics ", + style: TextStyle( + color: Color(0xffFEFEFE), + fontFamily: 'Brandon-bld', + fontSize: (MediaQuery.of(context).size.height) *(12/926), + ),), + ], + ), + ), + Container( + padding: EdgeInsets.only(top: (MediaQuery.of(context).size.height) *(5/926), bottom: (MediaQuery.of(context).size.height) *(5/926)), + height: (MediaQuery.of(context).size.height) *(35.32/926), + width: (MediaQuery.of(context).size.width) *(80/428), + color: Colors.white, + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Text("Question Types", + style: TextStyle( + color: Color(0xFF3F2668), + fontFamily: 'Brandon-bld', + fontSize: (MediaQuery.of(context).size.height) *(12/926), + ),), + Container( + padding: EdgeInsets.only(left: (MediaQuery.of(context).size.width) *(13/428), right: (MediaQuery.of(context).size.width) *(13/428)), + //margin: EdgeInsets.only(top: (MediaQuery.of(context).size.height) *(1/926)), + child: Divider(height: 3, + thickness: 2, + color: Color(0xFF3F2668),), + ), + ], + ), + ), + Container( + padding: EdgeInsets.only(top: (MediaQuery.of(context).size.height) *(5/926), bottom: (MediaQuery.of(context).size.height) *(5/926)), + height: (MediaQuery.of(context).size.height) *(35.32/926), + width: (MediaQuery.of(context).size.width) *(65/428), + color: Color(0xFF3F2668), + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Text("Difficulty", + style: TextStyle( + color: Color(0xffFEFEFE), + fontFamily: 'Brandon-bld', + fontSize: (MediaQuery.of(context).size.height) *(12/926), + ),), + ], + ), + ), + Container( + padding: EdgeInsets.only(top: (MediaQuery.of(context).size.height) *(5/926), bottom: (MediaQuery.of(context).size.height) *(5/926)), + height: (MediaQuery.of(context).size.height) *(35.32/926), + width: (MediaQuery.of(context).size.width) *(75/428), + color: Color(0xFF3F2668), + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Text("Generate Quiz", + style: TextStyle( + color: Color(0xffFEFEFE), + fontFamily: 'Brandon-bld', + fontSize: (MediaQuery.of(context).size.height) *(12/926), + ),), + ], + ), + ), + SizedBox(width: (MediaQuery.of(context).size.width) *(28/428),), + ], + ), + ), + SizedBox(height: (MediaQuery.of(context).size.height) *(15.28/926),), + Container( + height: (MediaQuery.of(context).size.height) *(167.52/926), + color: Colors.red, + ), + SizedBox(height: (MediaQuery.of(context).size.height) *(10.74/926),), + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + InkWell( + child: Container( + height: (MediaQuery.of(context).size.height) *(42/926), + width: (MediaQuery.of(context).size.width) *(68/428), + decoration: BoxDecoration( + color: Color(0xff3F2668),//0xffB0A6C2, rgba(176, 166, 194, 1) + borderRadius: BorderRadius.all(Radius.circular(3)), + boxShadow: [ + BoxShadow( + color: Colors.black12,//Color(0xff00000029), + spreadRadius: 2, + blurRadius: 2, + offset: Offset(0, 0), + ), + ], + ), + child: TextButton( + onPressed: () { + Navigator.pop(context); + }, + child: Center( + child: Text("Back", + style: TextStyle( + color: Colors.white, + fontFamily: 'Brandon-med', + ), + ), + ), + ), + ), + ), + InkWell( + child: Container( + height: (MediaQuery.of(context).size.height) *(42/926), + width: (MediaQuery.of(context).size.width) *(68/428), + decoration: BoxDecoration( + color: Color(0xff3F2668),//0xffB0A6C2, rgba(176, 166, 194, 1) + borderRadius: BorderRadius.all(Radius.circular(3)), + boxShadow: [ + BoxShadow( + color: Colors.black12,//Color(0xff00000029), + spreadRadius: 2, + blurRadius: 2, + offset: Offset(0, 0), + ), + ], + ), + child: TextButton( + onPressed: () async { + final result = await Navigator.push( + context, + MaterialPageRoute(builder: (context) => Difficulty()), + ); + }, + child: Center( + child: Text("Next", + style: TextStyle( + color: Colors.white, + fontFamily: 'Brandon-med', + ), + ), + ), + ), + ), + ), + ], + ), + ], + ), + ), + ); + } +} \ No newline at end of file diff --git a/lib/screens/Welcome/side_menu_bar.dart b/lib/screens/Welcome/side_menu_bar.dart new file mode 100644 index 0000000..4f7d3ab --- /dev/null +++ b/lib/screens/Welcome/side_menu_bar.dart @@ -0,0 +1,46 @@ +import 'package:flutter/material.dart'; +import 'package:testify/screens/Welcome/GenerateQuiz/generate_quiz.dart'; + +class SideMenuBar extends StatelessWidget { + @override + Widget build(BuildContext context) { + return Container( + width: (MediaQuery.of(context).size.width) *0.7, + child: Drawer( + child: ListView( + // Remove padding + padding: EdgeInsets.zero, + children: [ + Container( + padding: EdgeInsets.only(top: MediaQuery.of(context).padding.top), + height: (MediaQuery.of(context).size.height), + color: Color(0xffB0A6C2), + width: (MediaQuery.of(context).size.width) *0.7, + child: Column( + children: [ + ListTile( + leading: Icon(Icons.arrow_back), + title: Text('Back'), + onTap: () => Navigator.pop(context), + ), + Divider(), + ListTile( + leading: Icon(Icons.quiz_outlined), + title: Text('Generate Quiz'), + onTap: () async { + final result = await Navigator.push( + context, + MaterialPageRoute(builder: (context) => GenerateQuiz()), + ); + }, + ), + ], + ), + ), + //Divider(), + ], + ), + ), + ); + } +} \ No newline at end of file From abb06004b04365aa347c8bec2f39f1a90933fb19 Mon Sep 17 00:00:00 2001 From: TheYoungWolf-Productions Date: Wed, 26 Jan 2022 21:11:03 +0500 Subject: [PATCH 08/23] Add models --- lib/models/user_model_successful_login.dart | 57 +++++++++++++++++++ lib/models/user_model_unsuccessful_login.dart | 45 +++++++++++++++ 2 files changed, 102 insertions(+) create mode 100644 lib/models/user_model_successful_login.dart create mode 100644 lib/models/user_model_unsuccessful_login.dart diff --git a/lib/models/user_model_successful_login.dart b/lib/models/user_model_successful_login.dart new file mode 100644 index 0000000..02c7bb9 --- /dev/null +++ b/lib/models/user_model_successful_login.dart @@ -0,0 +1,57 @@ +// To parse this JSON data, do +// +// final userModelSuccessfulLogin = userModelSuccessfulLoginFromJson(jsonString); + +import 'dart:convert'; + +UserModelSuccessfulLogin userModelSuccessfulLoginFromJson(String str) => UserModelSuccessfulLogin.fromJson(json.decode(str)); + +String userModelSuccessfulLoginToJson(UserModelSuccessfulLogin data) => json.encode(data.toJson()); + +class UserModelSuccessfulLogin { + UserModelSuccessfulLogin({ + required this.data, + }); + + Data data; + + factory UserModelSuccessfulLogin.fromJson(Map json) => UserModelSuccessfulLogin( + data: Data.fromJson(json["data"]), + ); + + Map toJson() => { + "data": data.toJson(), + }; +} + +class Data { + Data({ + required this.status, + required this.id, + required this.username, + required this.ifAdmin, + required this.token, + }); + + bool status; + int id; + String username; + bool ifAdmin; + String token; + + factory Data.fromJson(Map json) => Data( + status: json["status"], + id: json["ID"], + username: json["username"], + ifAdmin: json["ifAdmin"], + token: json["token"], + ); + + Map toJson() => { + "status": status, + "ID": id, + "username": username, + "ifAdmin": ifAdmin, + "token": token, + }; +} diff --git a/lib/models/user_model_unsuccessful_login.dart b/lib/models/user_model_unsuccessful_login.dart new file mode 100644 index 0000000..2546b25 --- /dev/null +++ b/lib/models/user_model_unsuccessful_login.dart @@ -0,0 +1,45 @@ +// To parse this JSON data, do +// +// final userModelUnsuccessfulLogin = userModelUnsuccessfulLoginFromJson(jsonString); + +import 'dart:convert'; + +UserModelUnsuccessfulLogin userModelUnsuccessfulLoginFromJson(String str) => UserModelUnsuccessfulLogin.fromJson(json.decode(str)); + +String userModelUnsuccessfulLoginToJson(UserModelUnsuccessfulLogin data) => json.encode(data.toJson()); + +class UserModelUnsuccessfulLogin { + UserModelUnsuccessfulLogin({ + required this.data, + }); + + Data data; + + factory UserModelUnsuccessfulLogin.fromJson(Map json) => UserModelUnsuccessfulLogin( + data: Data.fromJson(json["data"]), + ); + + Map toJson() => { + "data": data.toJson(), + }; +} + +class Data { + Data({ + required this.status, + required this.message, + }); + + bool status; + String message; + + factory Data.fromJson(Map json) => Data( + status: json["status"], + message: json["message"], + ); + + Map toJson() => { + "status": status, + "message": message, + }; +} From 859fb479c9fab5f6d5d86a86b4027b808f4e4784 Mon Sep 17 00:00:00 2001 From: TheYoungWolf-Productions Date: Wed, 26 Jan 2022 21:12:23 +0500 Subject: [PATCH 09/23] Fix login --- lib/auth_storage.dart | 41 ++ lib/screens/Authentication/login.dart | 576 ++++++++++++++++---------- 2 files changed, 400 insertions(+), 217 deletions(-) create mode 100644 lib/auth_storage.dart diff --git a/lib/auth_storage.dart b/lib/auth_storage.dart new file mode 100644 index 0000000..98286ac --- /dev/null +++ b/lib/auth_storage.dart @@ -0,0 +1,41 @@ +import 'package:path_provider/path_provider.dart'; +import 'dart:io'; + + +class AuthStorage { + Future getLocalPath() async { + var dir = await getApplicationDocumentsDirectory(); + return dir.path; + } + + Future getLocalFile() async { + String path = await getLocalPath(); + return File('$path/auth.txt'); + } + + Future writeAuth(String email, String password) async { + File file = await getLocalFile(); + return file.writeAsString('$email' + ' ' + '$password'); + } + + Future readAuth() async { + try { + final file = await getLocalFile(); + String content = await file.readAsString(); + return content; + } catch(e) { + return ""; + } + } + + Future deleteFile() async { + try { + final file = await getLocalFile(); + + await file.delete(); + return ""; + } catch (e) { + return ""; + } + } +} \ No newline at end of file diff --git a/lib/screens/Authentication/login.dart b/lib/screens/Authentication/login.dart index 2e5dd53..ae264f5 100644 --- a/lib/screens/Authentication/login.dart +++ b/lib/screens/Authentication/login.dart @@ -1,10 +1,19 @@ +import 'dart:convert'; +import 'dart:io'; + import 'package:flutter/material.dart'; import 'package:flutter_svg/flutter_svg.dart'; +import 'package:http/http.dart' as http; +import 'package:path_provider/path_provider.dart'; +import 'package:testify/auth_storage.dart'; +import 'package:testify/models/user_model_successful_login.dart'; +import 'package:testify/models/user_model_unsuccessful_login.dart'; import 'package:testify/screens/home.dart'; class Login extends StatefulWidget { - const Login({Key? key}) : super(key: key); + const Login({Key? key, required this.fromWhere}) : super(key: key); + final String fromWhere; @override State createState() => _LoginState(); } @@ -12,26 +21,129 @@ class Login extends StatefulWidget { class _LoginState extends State { //Data Fields: final _formKey = GlobalKey(); - String _username = ""; + String _email = ""; String _password = ""; bool _isChecked = false; + //To start animation + bool _loaded = false; + var _duration = const Duration(milliseconds: 450); + var _dataPreviouslyStored = false; + late UserModelSuccessfulLogin _successfulUser; + late UserModelUnsuccessfulLogin _unsuccessfulUser; + + //The data gets stored to local storage. Continue from there. + AuthStorage storage = new AuthStorage(); + + @override + void initState() { + super.initState(); + //To delete the auth file when the user logs out. + if(widget.fromWhere == "Home") { + storage.deleteFile(); + print("Deleted + :" + storage.readAuth().toString()); + setState(() { + _email = ""; + _password = ""; + _isChecked = false; + _dataPreviouslyStored = false; + }); + } + else { + storage.readAuth().then((value) { + if(value.length != 0) { + var temp = value.split(" "); + print(temp); + setState(() { + _email = temp[0]; + _password = temp[1]; + _dataPreviouslyStored = true; + }); + print("Email + Password: " + _email + _password); + } + else { + + } + }); + } + Future.delayed(Duration(milliseconds: 1), () { + setState(() { + _loaded = true; + }); + }); + } + + //https://demo.pookidevs.com/auth/login + Future getUserData(BuildContext context, String email, String password) async { + final String apiUrl = "https://demo.pookidevs.com/auth/login"; + http.post(Uri.parse(apiUrl), headers: { + 'Content-type': 'application/json; charset=UTF-8', + }, body: json.encode( + { + "user": + { + "user_email": email, + "user_pass": password + } + }) + ).then((response) { + if(response.statusCode == 200) { + //The entered credentials are correct. + if(json.decode(response.body).toString().substring(0,20) == "{data: {status: true") { + final responseString = (response.body); + var loginData = userModelSuccessfulLoginFromJson(responseString); + final UserModelSuccessfulLogin successfulUser = loginData; + setState(() { + _successfulUser = successfulUser; + }); + _navigateAndDisplaySelection(context); + print(_successfulUser.data.status); + } + //Credentials are incorrect + else if(json.decode(response.body).toString().substring(0,21) == "{data: {status: false") { + final responseString = (response.body); + var loginData = userModelUnsuccessfulLoginFromJson(responseString); + final UserModelUnsuccessfulLogin unsuccessfulUser = loginData; + setState(() { + _unsuccessfulUser = unsuccessfulUser; + }); + print(_unsuccessfulUser.data.status); + ScaffoldMessenger.of(context) + ..removeCurrentSnackBar() + ..showSnackBar(SnackBar(content: Text(_unsuccessfulUser.data.message))); + _navigateAndDisplaySelection(context); + } + //loginData = userModelLoginFromJson(responseString); + } else { + + } + }); + + } //After form validation navigation to next screen. void _navigateAndDisplaySelection(BuildContext context) async { - // Navigator.push returns a Future that completes after calling - // Navigator.pop on the Selection Screen. - final result = await Navigator.push( - context, - MaterialPageRoute(builder: (context) => const Home()), - ); - - // After the Selection Screen returns a result, hide any previous snackbars - // and show the new result. - //Can be used to show if input is invalid. - /* - ScaffoldMessenger.of(context) + if(_successfulUser.data.status == true) { + if(_isChecked == true) { + storage.writeAuth(_email, _password); + print("Email + Password: " + _email + _password); + final result = await Navigator.push( + context, + MaterialPageRoute(builder: (context) => const Home()), + ); + } + else { + storage.writeAuth(_email, _password); + storage.deleteFile(); + print("Email + Password: " + _email + _password); + final result = await Navigator.push( + context, + MaterialPageRoute(builder: (context) => const Home()), + ); + } + } + /*ScaffoldMessenger.of(context) ..removeCurrentSnackBar() - ..showSnackBar(SnackBar(content: Text('$result')));*/ + ..showSnackBar(SnackBar(content: Text(_unsuccessfulUser.data.message)));*/ } @override @@ -44,88 +156,48 @@ class _LoginState extends State { child: Column( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ - Container( - height: (MediaQuery.of(context).size.height) *0.3, - color: Colors.transparent, - child: Align( - alignment: Alignment.topLeft, - child: Image( - image: AssetImage("assets/Images/login_topLeftBubble_1.png"), + AnimatedCrossFade( + crossFadeState: _loaded ? CrossFadeState.showFirst : CrossFadeState.showSecond, + duration: _duration, + firstChild: Container( + height: (MediaQuery.of(context).size.height) *0.3, + color: Colors.transparent, + child: Align( + alignment: Alignment.topLeft, + child: Image( + image: AssetImage("assets/Images/login_topLeftBubble_1.png"), + ), ), ), + secondChild: Container( + height: (MediaQuery.of(context).size.height) *0.3, + color: Colors.transparent, + child: Text(""), + ), ), SizedBox(height: (MediaQuery.of(context).size.height) *0.02159,), - Container( - child: Form( - key: _formKey, - child: Stack( - alignment: Alignment.bottomCenter, - children: [ - Column(//Add extra space at the end of the container(the one that has TextFormField) so that the login button can be aligned. - children: [ - Container(//For Borders of lighter area //Main Container to add Welcome, TextFormFields and Login. - //tbd: Get the color right! - margin: EdgeInsets.only(top: 0, bottom: 0, left: (MediaQuery.of(context).size.width) *(31/428), right: (MediaQuery.of(context).size.width) *(31/428),), - padding: EdgeInsets.only(top: 0, bottom: (MediaQuery.of(context).size.height) *0.0179, left: 0, right: 0,), - decoration: BoxDecoration( - color: Color.fromRGBO(176, 166, 194, 210),//0xffB0A6C2, rgba(176, 166, 194, 1) - borderRadius: BorderRadius.all(Radius.circular(10)), - border: Border.all( - color: Color(0xff757575), - width: 0, - ), - boxShadow: [ - BoxShadow( - color: Color(0xff0000004D), - ), - ], - ), - child: Column( - children: [ - Container( - padding: EdgeInsets.only(top: (MediaQuery.of(context).size.height) *0.020518, bottom: 0, left: 0, right: 0,), - child: Text("Welcome!", - style: TextStyle( - color: Color(0xffFFFEFE), - fontFamily: 'Brandon-bld', - fontSize: (MediaQuery.of(context).size.height) *0.0410,//38, - ),), - ), - Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Container( - padding: EdgeInsets.only(top: 0, bottom: 0, left: 0, right: 0,), - child: Text("Don't have an account?", - style: TextStyle( - color: Color.fromRGBO(255, 255, 255, 100), - fontFamily: 'Brandon-med', - fontSize: (MediaQuery.of(context).size.height)*0.0194, - ),), - ), - Container( - padding: EdgeInsets.only(top: 0, bottom: 0, left: 0, right: 0,), - child: Text(" Sign Up", - style: TextStyle( - color: Color(0xffFFFEFE), - fontFamily: 'Brandon-med', - fontSize: (MediaQuery.of(context).size.height)*0.0194, - ),), - ), - ], - ), - SizedBox(height: (MediaQuery.of(context).size.height)*0.04535,), - Container( - //color: Colors.white, - height: (MediaQuery.of(context).size.height)*0.055, - //padding: EdgeInsets.fromLTRB(20.0, (MediaQuery.of(context).size.height - MediaQuery.of(context).padding.top)*0.0037797, 20.0, (MediaQuery.of(context).size.height - MediaQuery.of(context).padding.top)*0.0037797), - margin: EdgeInsets.only(top: 0, bottom: 0, left: (MediaQuery.of(context).size.width) *(45/428), right: (MediaQuery.of(context).size.width) *(45/428),), + AnimatedCrossFade( + crossFadeState: _loaded ? CrossFadeState.showFirst : CrossFadeState.showSecond, + duration: _duration, + secondChild: Text(""), + firstChild: Container( + child: Form( + key: _formKey, + child: Stack( + alignment: Alignment.bottomCenter, + children: [ + Column(//Add extra space at the end of the container(the one that has TextFormField) so that the login button can be aligned. + children: [ + Container(//For Borders of lighter area //Main Container to add Welcome, TextFormFields and Login. + //tbd: Get the color right! + margin: EdgeInsets.only(top: 0, bottom: 0, left: (MediaQuery.of(context).size.width) *(31/428), right: (MediaQuery.of(context).size.width) *(31/428),), + padding: EdgeInsets.only(top: 0, bottom: (MediaQuery.of(context).size.height) *0.0179, left: 0, right: 0,), decoration: BoxDecoration( - color: Colors.white, + color: Color.fromRGBO(176, 166, 194, 210),//0xffB0A6C2, rgba(176, 166, 194, 1) borderRadius: BorderRadius.all(Radius.circular(10)), border: Border.all( color: Color(0xff757575), - width: 1, + width: 0, ), boxShadow: [ BoxShadow( @@ -133,40 +205,45 @@ class _LoginState extends State { ), ], ), - child: TextFormField( - decoration: InputDecoration( - hintText: "Username", - hintStyle: TextStyle(color: Color(0xffAEAEAE), - fontSize: (MediaQuery.of(context).size.height)*0.0194, - fontFamily: 'Brandon-med',), - contentPadding: EdgeInsets.fromLTRB(20.0, (MediaQuery.of(context).size.height)*0.0037797, 20.0, (MediaQuery.of(context).size.height)*0.0037797), - enabledBorder: OutlineInputBorder( - borderSide: BorderSide( - color: Colors.transparent, - width: 0.0, + child: Column( + children: [ + Container( + padding: EdgeInsets.only(top: (MediaQuery.of(context).size.height) *0.020518, bottom: 0, left: 0, right: 0,), + child: Text("Welcome!", + style: TextStyle( + color: Color(0xffFFFEFE), + fontFamily: 'Brandon-bld', + fontSize: (MediaQuery.of(context).size.height) *0.0410,//38, + ),), + ), + Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Container( + padding: EdgeInsets.only(top: 0, bottom: 0, left: 0, right: 0,), + child: Text("Don't have an account?", + style: TextStyle( + color: Color.fromRGBO(255, 255, 255, 100), + fontFamily: 'Brandon-med', + fontSize: (MediaQuery.of(context).size.height)*0.0194, + ),), ), - borderRadius: BorderRadius.circular(10.0), - ), - focusedBorder: OutlineInputBorder( - borderSide: BorderSide( - color: Colors.transparent, - width: 0.0, + Container( + padding: EdgeInsets.only(top: 0, bottom: 0, left: 0, right: 0,), + child: Text(" Sign Up", + style: TextStyle( + color: Color(0xffFFFEFE), + fontFamily: 'Brandon-med', + fontSize: (MediaQuery.of(context).size.height)*0.0194, + ),), ), - ), - ), - validator: (val) => val!.isEmpty ? "Please enter a Username." : null, - onChanged: (val) { - _username = val; - }, - style: TextStyle( - color: Colors.black, + ], ), - ), - ), - SizedBox(height: (MediaQuery.of(context).size.height)*0.0226781,), + SizedBox(height: (MediaQuery.of(context).size.height)*0.04535,), Container( //color: Colors.white, height: (MediaQuery.of(context).size.height)*0.055, + //padding: EdgeInsets.fromLTRB(20.0, (MediaQuery.of(context).size.height - MediaQuery.of(context).padding.top)*0.0037797, 20.0, (MediaQuery.of(context).size.height - MediaQuery.of(context).padding.top)*0.0037797), margin: EdgeInsets.only(top: 0, bottom: 0, left: (MediaQuery.of(context).size.width) *(45/428), right: (MediaQuery.of(context).size.width) *(45/428),), decoration: BoxDecoration( color: Colors.white, @@ -182,11 +259,10 @@ class _LoginState extends State { ], ), child: TextFormField( - obscureText: true, decoration: InputDecoration( - hintText: "Password", - hintStyle: TextStyle(color: Color(0xffAEAEAE), - fontSize: (MediaQuery.of(context).size.height)*0.0194, + hintText: _dataPreviouslyStored == null ? "Loading..." : (_dataPreviouslyStored ? _email : "Username"), + hintStyle: TextStyle(color: _dataPreviouslyStored ? Color(0xff171616) : Color(0xffAEAEAE), + fontSize: (MediaQuery.of(context).size.height)*(20/926), fontFamily: 'Brandon-med',), contentPadding: EdgeInsets.fromLTRB(20.0, (MediaQuery.of(context).size.height)*0.0037797, 20.0, (MediaQuery.of(context).size.height)*0.0037797), enabledBorder: OutlineInputBorder( @@ -203,128 +279,194 @@ class _LoginState extends State { ), ), ), - validator: (val) => val!.isEmpty ? "Please enter a Password." : null, + //validator: (val) => val!.isEmpty ? "Please enter a Username." : null, onChanged: (val) { - setState(() { - _password = val; - }); + _dataPreviouslyStored == null ? val = "" : + (_dataPreviouslyStored ? val = _email : _email = val); + //_email = val; }, style: TextStyle( color: Colors.black, + fontSize: (MediaQuery.of(context).size.height)*(20/926), + fontFamily: 'Brandon-med', ), ), ), - SizedBox(height: (MediaQuery.of(context).size.height)*0.024838,), - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Row( - mainAxisAlignment: MainAxisAlignment.start, - children: [ - Container( - margin: EdgeInsets.only(top: 0, bottom: 0, left: (MediaQuery.of(context).size.width) *(45/428), right: 0,), - height: (MediaQuery.of(context).size.height)*0.0167, - width: (MediaQuery.of(context).size.height)*0.0167, - color: Colors.white, - child: Transform.scale( - scale: (MediaQuery.of(context).size.height)*0.001, - child: Checkbox( - side: BorderSide( - color: Color(0xffB0A6C2), - width: 0, - ), - checkColor: Colors.white, - value: _isChecked, - onChanged: (bool? value) { - setState(() { - _isChecked = value!; - }); - }, - ), - ), - ), - Container( - padding: EdgeInsets.only(top: 0, bottom: 0, left: (MediaQuery.of(context).size.width) *(5/428), right: 0,), - child: Text("Remember me!", - style: TextStyle( - color: Color.fromRGBO(255, 255, 255, 100), - fontFamily: 'Brandon-med', - fontSize: (MediaQuery.of(context).size.height)*0.0161987, - ),), + SizedBox(height: (MediaQuery.of(context).size.height)*0.0226781,), + Container( + //color: Colors.white, + height: (MediaQuery.of(context).size.height)*0.055, + margin: EdgeInsets.only(top: 0, bottom: 0, left: (MediaQuery.of(context).size.width) *(45/428), right: (MediaQuery.of(context).size.width) *(45/428),), + decoration: BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.all(Radius.circular(10)), + border: Border.all( + color: Color(0xff757575), + width: 1, + ), + boxShadow: [ + BoxShadow( + color: Color(0xff0000004D), ), ], ), - Container( - padding: EdgeInsets.only(top: 0, bottom: 0, left: 0, right: (MediaQuery.of(context).size.width) *(45/428),), - child: Text("Forgot Password?", - style: TextStyle( - color: Color(0xffFFFEFE), - fontFamily: 'Brandon-med', - fontSize: (MediaQuery.of(context).size.height)*0.0161987, - ),), + child: TextFormField( + obscureText: true, + decoration: InputDecoration( + hintText: _dataPreviouslyStored == null ? "Loading..." : (_dataPreviouslyStored ? _password : "Password"), + hintStyle: TextStyle(color: _dataPreviouslyStored ? Colors.black : Color(0xffAEAEAE), + fontSize: (MediaQuery.of(context).size.height)*(20/926), + fontFamily: 'Brandon-med',), + contentPadding: EdgeInsets.fromLTRB(20.0, (MediaQuery.of(context).size.height)*0.0037797, 20.0, (MediaQuery.of(context).size.height)*0.0037797), + enabledBorder: OutlineInputBorder( + borderSide: BorderSide( + color: Colors.transparent, + width: 0.0, + ), + borderRadius: BorderRadius.circular(10.0), + ), + focusedBorder: OutlineInputBorder( + borderSide: BorderSide( + color: Colors.transparent, + width: 0.0, + ), + ), + ), + //validator: (val) => val!.isEmpty ? "Please enter a Password." : null, + onChanged: (val) { + setState(() { + _dataPreviouslyStored == null ? val = "" : + (_dataPreviouslyStored ? val = _password : _password = val); + }); + }, + style: TextStyle( + color: Colors.black, + fontSize: (MediaQuery.of(context).size.height)*(20/926), + fontFamily: 'Brandon-med', + ), ), - ], - ), - SizedBox(height: (MediaQuery.of(context).size.height) *0.0864,), - ], - ), + ), + SizedBox(height: (MediaQuery.of(context).size.height)*0.024838,), + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Container( + margin: EdgeInsets.only(top: 0, bottom: 0, left: (MediaQuery.of(context).size.width) *(45/428), right: 0,), + height: (MediaQuery.of(context).size.height)*0.0167, + width: (MediaQuery.of(context).size.height)*0.0167, + color: Colors.white, + child: Transform.scale( + scale: (MediaQuery.of(context).size.height)*0.001, + child: Checkbox( + side: BorderSide( + color: Color(0xffB0A6C2), + width: 0, + ), + checkColor: Colors.white, + value: _isChecked, + onChanged: (bool? value) { + setState(() { + _isChecked = value!; + }); + }, + ), + ), + ), + Container( + padding: EdgeInsets.only(top: 0, bottom: 0, left: (MediaQuery.of(context).size.width) *(5/428), right: 0,), + child: Text("Remember me!", + style: TextStyle( + color: Color.fromRGBO(255, 255, 255, 100), + fontFamily: 'Brandon-med', + fontSize: (MediaQuery.of(context).size.height)*0.0161987, + ),), + ), + ], + ), + Container( + padding: EdgeInsets.only(top: 0, bottom: 0, left: 0, right: (MediaQuery.of(context).size.width) *(45/428),), + child: Text("Forgot Password?", + style: TextStyle( + color: Color(0xffFFFEFE), + fontFamily: 'Brandon-med', + fontSize: (MediaQuery.of(context).size.height)*0.0161987, + ),), + ), + ], + ), + SizedBox(height: (MediaQuery.of(context).size.height) *0.0864,), + ], + ), + ), + SizedBox(height: (MediaQuery.of(context).size.height) *(25/926),), + ], + ), + GestureDetector( + child: Container(//Login button + child: Align( + alignment: Alignment.center, + child: SvgPicture.asset( + "assets/Images/login.svg", + height: (MediaQuery.of(context).size.height) *0.0486, ), - SizedBox(height: (MediaQuery.of(context).size.height) *(25/926),), - ], - ), - GestureDetector( - child: Container(//Login button - child: Align( - alignment: Alignment.center, - child: SvgPicture.asset( - "assets/Images/login.svg", - height: (MediaQuery.of(context).size.height) *0.0486, ), ), + onTap: () { + if(_formKey.currentState!.validate()) { + //_navigateAndDisplaySelection(context); + //print(_isChecked); + getUserData(context, _email, _password); + } + }, ), - onTap: () { - if(_formKey.currentState!.validate()) { - _navigateAndDisplaySelection(context); - } - }, - ), - ], + ], + ), ), ), ), - Row( - mainAxisAlignment: MainAxisAlignment.end, - //crossAxisAlignment: CrossAxisAlignment.end, - children: [ - Stack( - //alignment: Alignment.centerRight, - children: [ - Positioned( - left: (MediaQuery.of(context).size.height) *(80/926), - top: (MediaQuery.of(context).size.height) *(50/926), - child: Align( - alignment: Alignment.bottomRight, - child: SvgPicture.asset( - "assets/Images/login_bottomRight.svg", - height: (MediaQuery.of(context).size.height) *0.183, - width: (MediaQuery.of(context).size.height) *0.183, - ), - ), - ), - Positioned(//Remove and add again + AnimatedCrossFade( + crossFadeState: _loaded ? CrossFadeState.showFirst : CrossFadeState.showSecond, + duration: _duration, + secondChild: Container( + height: (MediaQuery.of(context).size.height) *0.183, + child: Text("")), + firstChild: Row( + mainAxisAlignment: MainAxisAlignment.end, + //crossAxisAlignment: CrossAxisAlignment.end, + children: [ + Stack( + //alignment: Alignment.centerRight, + children: [ + Positioned( + left: (MediaQuery.of(context).size.height) *(80/926), + top: (MediaQuery.of(context).size.height) *(50/926), child: Align( alignment: Alignment.bottomRight, child: SvgPicture.asset( "assets/Images/login_bottomRight.svg", height: (MediaQuery.of(context).size.height) *0.183, width: (MediaQuery.of(context).size.height) *0.183, - color: Colors.transparent, ), ), - ), - ], - ), - ], + ), + Positioned(//Remove and add again + child: Align( + alignment: Alignment.bottomRight, + child: SvgPicture.asset( + "assets/Images/login_bottomRight.svg", + height: (MediaQuery.of(context).size.height) *0.183, + width: (MediaQuery.of(context).size.height) *0.183, + color: Colors.transparent, + ), + ), + ), + ], + ), + ], + ), ), ], ), From 8da77fb1dd4c90611270d3d3a6186893416dead9 Mon Sep 17 00:00:00 2001 From: TheYoungWolf-Productions Date: Wed, 26 Jan 2022 21:14:32 +0500 Subject: [PATCH 10/23] Convert to Stateful --- lib/main.dart | 21 +++++++++++++++------ lib/screens/wrapper.dart | 11 ----------- 2 files changed, 15 insertions(+), 17 deletions(-) delete mode 100644 lib/screens/wrapper.dart diff --git a/lib/main.dart b/lib/main.dart index 0bfa363..60efcaa 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -1,22 +1,31 @@ import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; -import 'package:testify/screens/wrapper.dart'; +import 'package:testify/auth_storage.dart'; +import 'package:testify/screens/Authentication/login.dart'; +import 'package:testify/screens/home.dart'; -void main() { +void main() async { WidgetsFlutterBinding.ensureInitialized(); SystemChrome.setPreferredOrientations([ DeviceOrientation.portraitUp, DeviceOrientation.portraitDown, ]); + runApp(MyApp()); } -class MyApp extends StatelessWidget { +class MyApp extends StatefulWidget { // This widget is the root of your application. + @override + State createState() => _MyAppState(); +} + +class _MyAppState extends State { @override Widget build(BuildContext context) { return MaterialApp( - home: Wrapper(), - ); + home: Login( + fromWhere: "main", + )); } -} \ No newline at end of file +} diff --git a/lib/screens/wrapper.dart b/lib/screens/wrapper.dart deleted file mode 100644 index e01a552..0000000 --- a/lib/screens/wrapper.dart +++ /dev/null @@ -1,11 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:testify/screens/Authentication/login.dart'; - -class Wrapper extends StatelessWidget { - @override - Widget build(BuildContext context) { - - // return either home or authenticate - return Login(); - } -} From eefd63b7553d95da02eb0cb83000f337f9910093 Mon Sep 17 00:00:00 2001 From: TheYoungWolf-Productions Date: Wed, 26 Jan 2022 21:15:18 +0500 Subject: [PATCH 11/23] Fix widget styling --- lib/screens/home.dart | 27 +++++++++++++++++++++++---- 1 file changed, 23 insertions(+), 4 deletions(-) diff --git a/lib/screens/home.dart b/lib/screens/home.dart index 9e54de3..9edd147 100644 --- a/lib/screens/home.dart +++ b/lib/screens/home.dart @@ -1,4 +1,7 @@ import 'package:flutter/material.dart'; +import 'package:testify/auth_storage.dart'; +import 'package:testify/screens/Authentication/login.dart'; +import 'package:testify/screens/Welcome/side_menu_bar.dart'; class Home extends StatefulWidget { const Home({Key? key}) : super(key: key); @@ -11,21 +14,37 @@ class _HomeState extends State { @override Widget build(BuildContext context) { return Scaffold( - backgroundColor: Color(0xff3F2668), + backgroundColor: Colors.white, + drawer: SideMenuBar(), appBar: AppBar( - backgroundColor: Colors.transparent, + backgroundColor: Color(0xff3F2668), elevation: 2, centerTitle: true, + flexibleSpace: Container( + decoration: BoxDecoration( + gradient: LinearGradient( + begin: Alignment.topCenter, + end: Alignment.bottomCenter, + colors: [ + Color(0xff7F1AF1), + Color(0xff482384) + ]) + ), + ), title: const Text("Home", style: TextStyle( color: Color(0xffFFFEFE), fontFamily: 'Brandon-bld', ), ), - leading: Text(""), actions: [ TextButton( - onPressed: () { Navigator.pop(context, "logout"); }, + onPressed: () async { + final result = await Navigator.push( + context, + MaterialPageRoute(builder: (context) => const Login(fromWhere:"Home")), + ); + }, child: const Icon( Icons.logout, color: Colors.white, From a2dc2a2250a41b0efb7ca882cf0438389c2ef375 Mon Sep 17 00:00:00 2001 From: TheYoungWolf-Productions Date: Sun, 27 Feb 2022 18:07:39 +0500 Subject: [PATCH 12/23] Add sprint 3 --- .gitignore | 92 +- .metadata | 20 +- README.md | 58 +- analysis_options.yaml | 58 +- android/.gitignore | 26 +- android/app/build.gradle | 136 +- android/app/src/debug/AndroidManifest.xml | 14 +- android/app/src/main/AndroidManifest.xml | 68 +- .../com/example/testify/MainActivity.kt | 12 +- .../res/drawable-v21/launch_background.xml | 24 +- .../main/res/drawable/launch_background.xml | 24 +- .../app/src/main/res/values-night/styles.xml | 36 +- android/app/src/main/res/values/styles.xml | 36 +- android/app/src/profile/AndroidManifest.xml | 14 +- android/build.gradle | 62 +- android/gradle.properties | 6 +- .../gradle/wrapper/gradle-wrapper.properties | 12 +- android/settings.gradle | 22 +- ios/.gitignore | 68 +- ios/Flutter/AppFrameworkInfo.plist | 52 +- ios/Flutter/Debug.xcconfig | 2 +- ios/Flutter/Release.xcconfig | 2 +- ios/Runner.xcodeproj/project.pbxproj | 962 ++++----- .../contents.xcworkspacedata | 14 +- .../xcshareddata/IDEWorkspaceChecks.plist | 16 +- .../xcshareddata/WorkspaceSettings.xcsettings | 16 +- .../xcshareddata/xcschemes/Runner.xcscheme | 174 +- .../contents.xcworkspacedata | 14 +- .../xcshareddata/IDEWorkspaceChecks.plist | 16 +- .../xcshareddata/WorkspaceSettings.xcsettings | 16 +- ios/Runner/AppDelegate.swift | 26 +- .../AppIcon.appiconset/Contents.json | 244 +-- .../LaunchImage.imageset/Contents.json | 46 +- .../LaunchImage.imageset/README.md | 8 +- ios/Runner/Base.lproj/LaunchScreen.storyboard | 74 +- ios/Runner/Base.lproj/Main.storyboard | 52 +- ios/Runner/Info.plist | 94 +- ios/Runner/Runner-Bridging-Header.h | 2 +- lib/auth_storage.dart | 80 +- lib/main.dart | 61 +- lib/models/user_model_successful_login.dart | 114 +- lib/models/user_model_unsuccessful_login.dart | 90 +- lib/screens/Authentication/login.dart | 996 ++++----- .../Welcome/GenerateQuiz/difficulty.dart | 560 ++--- .../Welcome/GenerateQuiz/generate_quiz.dart | 1891 ++++++++++++++--- .../GenerateQuiz/generate_quiz_last.dart | 550 ++--- .../Welcome/GenerateQuiz/question_types.dart | 560 ++--- lib/screens/Welcome/side_menu_bar.dart | 91 +- lib/screens/home.dart | 123 +- pubspec.yaml | 221 +- test/widget_test.dart | 60 +- web/index.html | 208 +- web/manifest.json | 70 +- 53 files changed, 4863 insertions(+), 3430 deletions(-) diff --git a/.gitignore b/.gitignore index 0fa6b67..8906afc 100644 --- a/.gitignore +++ b/.gitignore @@ -1,46 +1,46 @@ -# Miscellaneous -*.class -*.log -*.pyc -*.swp -.DS_Store -.atom/ -.buildlog/ -.history -.svn/ - -# IntelliJ related -*.iml -*.ipr -*.iws -.idea/ - -# The .vscode folder contains launch configuration and tasks you configure in -# VS Code which you may wish to be included in version control, so this line -# is commented out by default. -#.vscode/ - -# Flutter/Dart/Pub related -**/doc/api/ -**/ios/Flutter/.last_build_id -.dart_tool/ -.flutter-plugins -.flutter-plugins-dependencies -.packages -.pub-cache/ -.pub/ -/build/ - -# Web related -lib/generated_plugin_registrant.dart - -# Symbolication related -app.*.symbols - -# Obfuscation related -app.*.map.json - -# Android Studio will place build artifacts here -/android/app/debug -/android/app/profile -/android/app/release +# Miscellaneous +*.class +*.log +*.pyc +*.swp +.DS_Store +.atom/ +.buildlog/ +.history +.svn/ + +# IntelliJ related +*.iml +*.ipr +*.iws +.idea/ + +# The .vscode folder contains launch configuration and tasks you configure in +# VS Code which you may wish to be included in version control, so this line +# is commented out by default. +#.vscode/ + +# Flutter/Dart/Pub related +**/doc/api/ +**/ios/Flutter/.last_build_id +.dart_tool/ +.flutter-plugins +.flutter-plugins-dependencies +.packages +.pub-cache/ +.pub/ +/build/ + +# Web related +lib/generated_plugin_registrant.dart + +# Symbolication related +app.*.symbols + +# Obfuscation related +app.*.map.json + +# Android Studio will place build artifacts here +/android/app/debug +/android/app/profile +/android/app/release diff --git a/.metadata b/.metadata index fd70cab..6376fbe 100644 --- a/.metadata +++ b/.metadata @@ -1,10 +1,10 @@ -# This file tracks properties of this Flutter project. -# Used by Flutter tool to assess capabilities and perform upgrades etc. -# -# This file should be version controlled and should not be manually edited. - -version: - revision: 77d935af4db863f6abd0b9c31c7e6df2a13de57b - channel: stable - -project_type: app +# This file tracks properties of this Flutter project. +# Used by Flutter tool to assess capabilities and perform upgrades etc. +# +# This file should be version controlled and should not be manually edited. + +version: + revision: 77d935af4db863f6abd0b9c31c7e6df2a13de57b + channel: stable + +project_type: app diff --git a/README.md b/README.md index 971ed7b..014ebc9 100644 --- a/README.md +++ b/README.md @@ -1,29 +1,29 @@ -# Testify - -Self-assessment or Self-evaluation is defined as the wide variety of mechanisms and techniques through which students describe (i.e., assess) and possibly assign merit or worth (i.e., evaluate) to the qualities of their own learning/knowledge. -We aim to shed light onto these mechanisms and techniques through an all-inclusive, easy to use Self-assessment System (i.e., framework) in the medical industry which enhances self-regulated learning (SRL) or at least the central components of it such as goal setting and monitoring, or metacognition. - - -## Poster! -![fyp-w (1)](https://user-images.githubusercontent.com/68595463/150567109-712b122e-9e15-42c9-b5f9-0ab05ff6e9d0.png) - -## Getting started - -In your project folder, run the following commands in your terminal: -``` -git clone https://github.com/TheYoungWolf-Productions/testify.git -cd testify -flutter pub get -``` -`Note:` You need your [GitHub](https://docs.github.com/en/get-started/quickstart/set-up-git) and [Flutter](https://docs.flutter.dev/get-started/install/windows) already setup. I recommend using *VSCode* as the editor with __Flutter__ extension. - -### :loudspeaker: Guidelines -- :bulb: The team will ***STRICTLY*** follow the [Git Workflow](https://nvie.com/posts/a-successful-git-branching-model/) -- :bulb: Every pull request needs to have an **assigned** reviewer. - -## Contributors - -- :wolf: theYoungWolf :wolf: -- Muhammad Abdullah -- Minahial Khalid -- **Sponsors:** Pookidevs :v: +# Testify + +Self-assessment or Self-evaluation is defined as the wide variety of mechanisms and techniques through which students describe (i.e., assess) and possibly assign merit or worth (i.e., evaluate) to the qualities of their own learning/knowledge. +We aim to shed light onto these mechanisms and techniques through an all-inclusive, easy to use Self-assessment System (i.e., framework) in the medical industry which enhances self-regulated learning (SRL) or at least the central components of it such as goal setting and monitoring, or metacognition. + + +## Poster! +![fyp-w (1)](https://user-images.githubusercontent.com/68595463/150567109-712b122e-9e15-42c9-b5f9-0ab05ff6e9d0.png) + +## Getting started + +In your project folder, run the following commands in your terminal: +``` +git clone https://github.com/TheYoungWolf-Productions/testify.git +cd testify +flutter pub get +``` +`Note:` You need your [GitHub](https://docs.github.com/en/get-started/quickstart/set-up-git) and [Flutter](https://docs.flutter.dev/get-started/install/windows) already setup. I recommend using *VSCode* as the editor with __Flutter__ extension. + +### :loudspeaker: Guidelines +- :bulb: The team will ***STRICTLY*** follow the [Git Workflow](https://nvie.com/posts/a-successful-git-branching-model/) +- :bulb: Every pull request needs to have an **assigned** reviewer. + +## Contributors + +- :wolf: theYoungWolf :wolf: +- Muhammad Abdullah +- Minahial Khalid +- **Sponsors:** Pookidevs :v: diff --git a/analysis_options.yaml b/analysis_options.yaml index 61b6c4d..a7acf24 100644 --- a/analysis_options.yaml +++ b/analysis_options.yaml @@ -1,29 +1,29 @@ -# This file configures the analyzer, which statically analyzes Dart code to -# check for errors, warnings, and lints. -# -# The issues identified by the analyzer are surfaced in the UI of Dart-enabled -# IDEs (https://dart.dev/tools#ides-and-editors). The analyzer can also be -# invoked from the command line by running `flutter analyze`. - -# The following line activates a set of recommended lints for Flutter apps, -# packages, and plugins designed to encourage good coding practices. -include: package:flutter_lints/flutter.yaml - -linter: - # The lint rules applied to this project can be customized in the - # section below to disable rules from the `package:flutter_lints/flutter.yaml` - # included above or to enable additional rules. A list of all available lints - # and their documentation is published at - # https://dart-lang.github.io/linter/lints/index.html. - # - # Instead of disabling a lint rule for the entire project in the - # section below, it can also be suppressed for a single line of code - # or a specific dart file by using the `// ignore: name_of_lint` and - # `// ignore_for_file: name_of_lint` syntax on the line or in the file - # producing the lint. - rules: - # avoid_print: false # Uncomment to disable the `avoid_print` rule - # prefer_single_quotes: true # Uncomment to enable the `prefer_single_quotes` rule - -# Additional information about this file can be found at -# https://dart.dev/guides/language/analysis-options +# This file configures the analyzer, which statically analyzes Dart code to +# check for errors, warnings, and lints. +# +# The issues identified by the analyzer are surfaced in the UI of Dart-enabled +# IDEs (https://dart.dev/tools#ides-and-editors). The analyzer can also be +# invoked from the command line by running `flutter analyze`. + +# The following line activates a set of recommended lints for Flutter apps, +# packages, and plugins designed to encourage good coding practices. +include: package:flutter_lints/flutter.yaml + +linter: + # The lint rules applied to this project can be customized in the + # section below to disable rules from the `package:flutter_lints/flutter.yaml` + # included above or to enable additional rules. A list of all available lints + # and their documentation is published at + # https://dart-lang.github.io/linter/lints/index.html. + # + # Instead of disabling a lint rule for the entire project in the + # section below, it can also be suppressed for a single line of code + # or a specific dart file by using the `// ignore: name_of_lint` and + # `// ignore_for_file: name_of_lint` syntax on the line or in the file + # producing the lint. + rules: + # avoid_print: false # Uncomment to disable the `avoid_print` rule + # prefer_single_quotes: true # Uncomment to enable the `prefer_single_quotes` rule + +# Additional information about this file can be found at +# https://dart.dev/guides/language/analysis-options diff --git a/android/.gitignore b/android/.gitignore index 6f56801..5d99765 100644 --- a/android/.gitignore +++ b/android/.gitignore @@ -1,13 +1,13 @@ -gradle-wrapper.jar -/.gradle -/captures/ -/gradlew -/gradlew.bat -/local.properties -GeneratedPluginRegistrant.java - -# Remember to never publicly share your keystore. -# See https://flutter.dev/docs/deployment/android#reference-the-keystore-from-the-app -key.properties -**/*.keystore -**/*.jks +gradle-wrapper.jar +/.gradle +/captures/ +/gradlew +/gradlew.bat +/local.properties +GeneratedPluginRegistrant.java + +# Remember to never publicly share your keystore. +# See https://flutter.dev/docs/deployment/android#reference-the-keystore-from-the-app +key.properties +**/*.keystore +**/*.jks diff --git a/android/app/build.gradle b/android/app/build.gradle index 5050e0c..2ed36dc 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -1,68 +1,68 @@ -def localProperties = new Properties() -def localPropertiesFile = rootProject.file('local.properties') -if (localPropertiesFile.exists()) { - localPropertiesFile.withReader('UTF-8') { reader -> - localProperties.load(reader) - } -} - -def flutterRoot = localProperties.getProperty('flutter.sdk') -if (flutterRoot == null) { - throw new GradleException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.") -} - -def flutterVersionCode = localProperties.getProperty('flutter.versionCode') -if (flutterVersionCode == null) { - flutterVersionCode = '1' -} - -def flutterVersionName = localProperties.getProperty('flutter.versionName') -if (flutterVersionName == null) { - flutterVersionName = '1.0' -} - -apply plugin: 'com.android.application' -apply plugin: 'kotlin-android' -apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle" - -android { - compileSdkVersion flutter.compileSdkVersion - - compileOptions { - sourceCompatibility JavaVersion.VERSION_1_8 - targetCompatibility JavaVersion.VERSION_1_8 - } - - kotlinOptions { - jvmTarget = '1.8' - } - - sourceSets { - main.java.srcDirs += 'src/main/kotlin' - } - - defaultConfig { - // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). - applicationId "com.example.testify" - minSdkVersion flutter.minSdkVersion - targetSdkVersion flutter.targetSdkVersion - versionCode flutterVersionCode.toInteger() - versionName flutterVersionName - } - - buildTypes { - release { - // TODO: Add your own signing config for the release build. - // Signing with the debug keys for now, so `flutter run --release` works. - signingConfig signingConfigs.debug - } - } -} - -flutter { - source '../..' -} - -dependencies { - implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" -} +def localProperties = new Properties() +def localPropertiesFile = rootProject.file('local.properties') +if (localPropertiesFile.exists()) { + localPropertiesFile.withReader('UTF-8') { reader -> + localProperties.load(reader) + } +} + +def flutterRoot = localProperties.getProperty('flutter.sdk') +if (flutterRoot == null) { + throw new GradleException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.") +} + +def flutterVersionCode = localProperties.getProperty('flutter.versionCode') +if (flutterVersionCode == null) { + flutterVersionCode = '1' +} + +def flutterVersionName = localProperties.getProperty('flutter.versionName') +if (flutterVersionName == null) { + flutterVersionName = '1.0' +} + +apply plugin: 'com.android.application' +apply plugin: 'kotlin-android' +apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle" + +android { + compileSdkVersion flutter.compileSdkVersion + + compileOptions { + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + } + + kotlinOptions { + jvmTarget = '1.8' + } + + sourceSets { + main.java.srcDirs += 'src/main/kotlin' + } + + defaultConfig { + // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). + applicationId "com.example.testify" + minSdkVersion flutter.minSdkVersion + targetSdkVersion flutter.targetSdkVersion + versionCode flutterVersionCode.toInteger() + versionName flutterVersionName + } + + buildTypes { + release { + // TODO: Add your own signing config for the release build. + // Signing with the debug keys for now, so `flutter run --release` works. + signingConfig signingConfigs.debug + } + } +} + +flutter { + source '../..' +} + +dependencies { + implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" +} diff --git a/android/app/src/debug/AndroidManifest.xml b/android/app/src/debug/AndroidManifest.xml index 2cc5f64..580437e 100644 --- a/android/app/src/debug/AndroidManifest.xml +++ b/android/app/src/debug/AndroidManifest.xml @@ -1,7 +1,7 @@ - - - - + + + + diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml index f30c238..5df60fe 100644 --- a/android/app/src/main/AndroidManifest.xml +++ b/android/app/src/main/AndroidManifest.xml @@ -1,34 +1,34 @@ - - - - - - - - - - - - - - + + + + + + + + + + + + + + diff --git a/android/app/src/main/kotlin/com/example/testify/MainActivity.kt b/android/app/src/main/kotlin/com/example/testify/MainActivity.kt index 4ecad09..ae508d7 100644 --- a/android/app/src/main/kotlin/com/example/testify/MainActivity.kt +++ b/android/app/src/main/kotlin/com/example/testify/MainActivity.kt @@ -1,6 +1,6 @@ -package com.example.testify - -import io.flutter.embedding.android.FlutterActivity - -class MainActivity: FlutterActivity() { -} +package com.example.testify + +import io.flutter.embedding.android.FlutterActivity + +class MainActivity: FlutterActivity() { +} diff --git a/android/app/src/main/res/drawable-v21/launch_background.xml b/android/app/src/main/res/drawable-v21/launch_background.xml index f74085f..1cb7aa2 100644 --- a/android/app/src/main/res/drawable-v21/launch_background.xml +++ b/android/app/src/main/res/drawable-v21/launch_background.xml @@ -1,12 +1,12 @@ - - - - - - - - + + + + + + + + diff --git a/android/app/src/main/res/drawable/launch_background.xml b/android/app/src/main/res/drawable/launch_background.xml index 304732f..8403758 100644 --- a/android/app/src/main/res/drawable/launch_background.xml +++ b/android/app/src/main/res/drawable/launch_background.xml @@ -1,12 +1,12 @@ - - - - - - - - + + + + + + + + diff --git a/android/app/src/main/res/values-night/styles.xml b/android/app/src/main/res/values-night/styles.xml index 3db14bb..6b2369f 100644 --- a/android/app/src/main/res/values-night/styles.xml +++ b/android/app/src/main/res/values-night/styles.xml @@ -1,18 +1,18 @@ - - - - - - - + + + + + + + diff --git a/android/app/src/main/res/values/styles.xml b/android/app/src/main/res/values/styles.xml index d460d1e..3e29b54 100644 --- a/android/app/src/main/res/values/styles.xml +++ b/android/app/src/main/res/values/styles.xml @@ -1,18 +1,18 @@ - - - - - - - + + + + + + + diff --git a/android/app/src/profile/AndroidManifest.xml b/android/app/src/profile/AndroidManifest.xml index 2cc5f64..580437e 100644 --- a/android/app/src/profile/AndroidManifest.xml +++ b/android/app/src/profile/AndroidManifest.xml @@ -1,7 +1,7 @@ - - - - + + + + diff --git a/android/build.gradle b/android/build.gradle index 24047dc..6b57dfa 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -1,31 +1,31 @@ -buildscript { - ext.kotlin_version = '1.3.50' - repositories { - google() - mavenCentral() - } - - dependencies { - classpath 'com.android.tools.build:gradle:4.1.0' - classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" - } -} - -allprojects { - repositories { - google() - mavenCentral() - } -} - -rootProject.buildDir = '../build' -subprojects { - project.buildDir = "${rootProject.buildDir}/${project.name}" -} -subprojects { - project.evaluationDependsOn(':app') -} - -task clean(type: Delete) { - delete rootProject.buildDir -} +buildscript { + ext.kotlin_version = '1.3.50' + repositories { + google() + mavenCentral() + } + + dependencies { + classpath 'com.android.tools.build:gradle:4.1.0' + classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" + } +} + +allprojects { + repositories { + google() + mavenCentral() + } +} + +rootProject.buildDir = '../build' +subprojects { + project.buildDir = "${rootProject.buildDir}/${project.name}" +} +subprojects { + project.evaluationDependsOn(':app') +} + +task clean(type: Delete) { + delete rootProject.buildDir +} diff --git a/android/gradle.properties b/android/gradle.properties index 94adc3a..46c1f16 100644 --- a/android/gradle.properties +++ b/android/gradle.properties @@ -1,3 +1,3 @@ -org.gradle.jvmargs=-Xmx1536M -android.useAndroidX=true -android.enableJetifier=true +org.gradle.jvmargs=-Xmx1536M +android.useAndroidX=true +android.enableJetifier=true diff --git a/android/gradle/wrapper/gradle-wrapper.properties b/android/gradle/wrapper/gradle-wrapper.properties index bc6a58a..571984a 100644 --- a/android/gradle/wrapper/gradle-wrapper.properties +++ b/android/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ -#Fri Jun 23 08:50:38 CEST 2017 -distributionBase=GRADLE_USER_HOME -distributionPath=wrapper/dists -zipStoreBase=GRADLE_USER_HOME -zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-6.7-all.zip +#Fri Jun 23 08:50:38 CEST 2017 +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-6.7-all.zip diff --git a/android/settings.gradle b/android/settings.gradle index 44e62bc..33f0745 100644 --- a/android/settings.gradle +++ b/android/settings.gradle @@ -1,11 +1,11 @@ -include ':app' - -def localPropertiesFile = new File(rootProject.projectDir, "local.properties") -def properties = new Properties() - -assert localPropertiesFile.exists() -localPropertiesFile.withReader("UTF-8") { reader -> properties.load(reader) } - -def flutterSdkPath = properties.getProperty("flutter.sdk") -assert flutterSdkPath != null, "flutter.sdk not set in local.properties" -apply from: "$flutterSdkPath/packages/flutter_tools/gradle/app_plugin_loader.gradle" +include ':app' + +def localPropertiesFile = new File(rootProject.projectDir, "local.properties") +def properties = new Properties() + +assert localPropertiesFile.exists() +localPropertiesFile.withReader("UTF-8") { reader -> properties.load(reader) } + +def flutterSdkPath = properties.getProperty("flutter.sdk") +assert flutterSdkPath != null, "flutter.sdk not set in local.properties" +apply from: "$flutterSdkPath/packages/flutter_tools/gradle/app_plugin_loader.gradle" diff --git a/ios/.gitignore b/ios/.gitignore index 7a7f987..ad322bc 100644 --- a/ios/.gitignore +++ b/ios/.gitignore @@ -1,34 +1,34 @@ -**/dgph -*.mode1v3 -*.mode2v3 -*.moved-aside -*.pbxuser -*.perspectivev3 -**/*sync/ -.sconsign.dblite -.tags* -**/.vagrant/ -**/DerivedData/ -Icon? -**/Pods/ -**/.symlinks/ -profile -xcuserdata -**/.generated/ -Flutter/App.framework -Flutter/Flutter.framework -Flutter/Flutter.podspec -Flutter/Generated.xcconfig -Flutter/ephemeral/ -Flutter/app.flx -Flutter/app.zip -Flutter/flutter_assets/ -Flutter/flutter_export_environment.sh -ServiceDefinitions.json -Runner/GeneratedPluginRegistrant.* - -# Exceptions to above rules. -!default.mode1v3 -!default.mode2v3 -!default.pbxuser -!default.perspectivev3 +**/dgph +*.mode1v3 +*.mode2v3 +*.moved-aside +*.pbxuser +*.perspectivev3 +**/*sync/ +.sconsign.dblite +.tags* +**/.vagrant/ +**/DerivedData/ +Icon? +**/Pods/ +**/.symlinks/ +profile +xcuserdata +**/.generated/ +Flutter/App.framework +Flutter/Flutter.framework +Flutter/Flutter.podspec +Flutter/Generated.xcconfig +Flutter/ephemeral/ +Flutter/app.flx +Flutter/app.zip +Flutter/flutter_assets/ +Flutter/flutter_export_environment.sh +ServiceDefinitions.json +Runner/GeneratedPluginRegistrant.* + +# Exceptions to above rules. +!default.mode1v3 +!default.mode2v3 +!default.pbxuser +!default.perspectivev3 diff --git a/ios/Flutter/AppFrameworkInfo.plist b/ios/Flutter/AppFrameworkInfo.plist index 8d4492f..80391e4 100644 --- a/ios/Flutter/AppFrameworkInfo.plist +++ b/ios/Flutter/AppFrameworkInfo.plist @@ -1,26 +1,26 @@ - - - - - CFBundleDevelopmentRegion - en - CFBundleExecutable - App - CFBundleIdentifier - io.flutter.flutter.app - CFBundleInfoDictionaryVersion - 6.0 - CFBundleName - App - CFBundlePackageType - FMWK - CFBundleShortVersionString - 1.0 - CFBundleSignature - ???? - CFBundleVersion - 1.0 - MinimumOSVersion - 9.0 - - + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + App + CFBundleIdentifier + io.flutter.flutter.app + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + App + CFBundlePackageType + FMWK + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1.0 + MinimumOSVersion + 9.0 + + diff --git a/ios/Flutter/Debug.xcconfig b/ios/Flutter/Debug.xcconfig index 592ceee..0b2d479 100644 --- a/ios/Flutter/Debug.xcconfig +++ b/ios/Flutter/Debug.xcconfig @@ -1 +1 @@ -#include "Generated.xcconfig" +#include "Generated.xcconfig" diff --git a/ios/Flutter/Release.xcconfig b/ios/Flutter/Release.xcconfig index 592ceee..0b2d479 100644 --- a/ios/Flutter/Release.xcconfig +++ b/ios/Flutter/Release.xcconfig @@ -1 +1 @@ -#include "Generated.xcconfig" +#include "Generated.xcconfig" diff --git a/ios/Runner.xcodeproj/project.pbxproj b/ios/Runner.xcodeproj/project.pbxproj index 974c657..8048b3f 100644 --- a/ios/Runner.xcodeproj/project.pbxproj +++ b/ios/Runner.xcodeproj/project.pbxproj @@ -1,481 +1,481 @@ -// !$*UTF8*$! -{ - archiveVersion = 1; - classes = { - }; - objectVersion = 50; - objects = { - -/* Begin PBXBuildFile section */ - 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; }; - 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; }; - 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; }; - 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; }; - 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; }; - 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; }; -/* End PBXBuildFile section */ - -/* Begin PBXCopyFilesBuildPhase section */ - 9705A1C41CF9048500538489 /* Embed Frameworks */ = { - isa = PBXCopyFilesBuildPhase; - buildActionMask = 2147483647; - dstPath = ""; - dstSubfolderSpec = 10; - files = ( - ); - name = "Embed Frameworks"; - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXCopyFilesBuildPhase section */ - -/* Begin PBXFileReference section */ - 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = ""; }; - 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = ""; }; - 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = ""; }; - 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Runner-Bridging-Header.h"; sourceTree = ""; }; - 74858FAE1ED2DC5600515810 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; - 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = ""; }; - 9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = ""; }; - 9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = ""; }; - 97C146EE1CF9000F007C117D /* Runner.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Runner.app; sourceTree = BUILT_PRODUCTS_DIR; }; - 97C146FB1CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; - 97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; - 97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; - 97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; -/* End PBXFileReference section */ - -/* Begin PBXFrameworksBuildPhase section */ - 97C146EB1CF9000F007C117D /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXFrameworksBuildPhase section */ - -/* Begin PBXGroup section */ - 9740EEB11CF90186004384FC /* Flutter */ = { - isa = PBXGroup; - children = ( - 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */, - 9740EEB21CF90195004384FC /* Debug.xcconfig */, - 7AFA3C8E1D35360C0083082E /* Release.xcconfig */, - 9740EEB31CF90195004384FC /* Generated.xcconfig */, - ); - name = Flutter; - sourceTree = ""; - }; - 97C146E51CF9000F007C117D = { - isa = PBXGroup; - children = ( - 9740EEB11CF90186004384FC /* Flutter */, - 97C146F01CF9000F007C117D /* Runner */, - 97C146EF1CF9000F007C117D /* Products */, - ); - sourceTree = ""; - }; - 97C146EF1CF9000F007C117D /* Products */ = { - isa = PBXGroup; - children = ( - 97C146EE1CF9000F007C117D /* Runner.app */, - ); - name = Products; - sourceTree = ""; - }; - 97C146F01CF9000F007C117D /* Runner */ = { - isa = PBXGroup; - children = ( - 97C146FA1CF9000F007C117D /* Main.storyboard */, - 97C146FD1CF9000F007C117D /* Assets.xcassets */, - 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */, - 97C147021CF9000F007C117D /* Info.plist */, - 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */, - 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */, - 74858FAE1ED2DC5600515810 /* AppDelegate.swift */, - 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */, - ); - path = Runner; - sourceTree = ""; - }; -/* End PBXGroup section */ - -/* Begin PBXNativeTarget section */ - 97C146ED1CF9000F007C117D /* Runner */ = { - isa = PBXNativeTarget; - buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */; - buildPhases = ( - 9740EEB61CF901F6004384FC /* Run Script */, - 97C146EA1CF9000F007C117D /* Sources */, - 97C146EB1CF9000F007C117D /* Frameworks */, - 97C146EC1CF9000F007C117D /* Resources */, - 9705A1C41CF9048500538489 /* Embed Frameworks */, - 3B06AD1E1E4923F5004D2608 /* Thin Binary */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = Runner; - productName = Runner; - productReference = 97C146EE1CF9000F007C117D /* Runner.app */; - productType = "com.apple.product-type.application"; - }; -/* End PBXNativeTarget section */ - -/* Begin PBXProject section */ - 97C146E61CF9000F007C117D /* Project object */ = { - isa = PBXProject; - attributes = { - LastUpgradeCheck = 1300; - ORGANIZATIONNAME = ""; - TargetAttributes = { - 97C146ED1CF9000F007C117D = { - CreatedOnToolsVersion = 7.3.1; - LastSwiftMigration = 1100; - }; - }; - }; - buildConfigurationList = 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */; - compatibilityVersion = "Xcode 9.3"; - developmentRegion = en; - hasScannedForEncodings = 0; - knownRegions = ( - en, - Base, - ); - mainGroup = 97C146E51CF9000F007C117D; - productRefGroup = 97C146EF1CF9000F007C117D /* Products */; - projectDirPath = ""; - projectRoot = ""; - targets = ( - 97C146ED1CF9000F007C117D /* Runner */, - ); - }; -/* End PBXProject section */ - -/* Begin PBXResourcesBuildPhase section */ - 97C146EC1CF9000F007C117D /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */, - 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */, - 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */, - 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXResourcesBuildPhase section */ - -/* Begin PBXShellScriptBuildPhase section */ - 3B06AD1E1E4923F5004D2608 /* Thin Binary */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputPaths = ( - ); - name = "Thin Binary"; - outputPaths = ( - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" embed_and_thin"; - }; - 9740EEB61CF901F6004384FC /* Run Script */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputPaths = ( - ); - name = "Run Script"; - outputPaths = ( - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build"; - }; -/* End PBXShellScriptBuildPhase section */ - -/* Begin PBXSourcesBuildPhase section */ - 97C146EA1CF9000F007C117D /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */, - 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXSourcesBuildPhase section */ - -/* Begin PBXVariantGroup section */ - 97C146FA1CF9000F007C117D /* Main.storyboard */ = { - isa = PBXVariantGroup; - children = ( - 97C146FB1CF9000F007C117D /* Base */, - ); - name = Main.storyboard; - sourceTree = ""; - }; - 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */ = { - isa = PBXVariantGroup; - children = ( - 97C147001CF9000F007C117D /* Base */, - ); - name = LaunchScreen.storyboard; - sourceTree = ""; - }; -/* End PBXVariantGroup section */ - -/* Begin XCBuildConfiguration section */ - 249021D3217E4FDB00AE95B9 /* Profile */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_ANALYZER_NONNULL = YES; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_COMMA = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INFINITE_RECURSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; - CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; - CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; - CLANG_WARN_STRICT_PROTOTYPES = YES; - CLANG_WARN_SUSPICIOUS_MOVE = YES; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; - COPY_PHASE_STRIP = NO; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - ENABLE_NS_ASSERTIONS = NO; - ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; - GCC_NO_COMMON_BLOCKS = YES; - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 9.0; - MTL_ENABLE_DEBUG_INFO = NO; - SDKROOT = iphoneos; - SUPPORTED_PLATFORMS = iphoneos; - TARGETED_DEVICE_FAMILY = "1,2"; - VALIDATE_PRODUCT = YES; - }; - name = Profile; - }; - 249021D4217E4FDB00AE95B9 /* Profile */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; - buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - CLANG_ENABLE_MODULES = YES; - CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; - ENABLE_BITCODE = NO; - INFOPLIST_FILE = Runner/Info.plist; - LD_RUNPATH_SEARCH_PATHS = ( - "$(inherited)", - "@executable_path/Frameworks", - ); - PRODUCT_BUNDLE_IDENTIFIER = com.example.testify; - PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; - SWIFT_VERSION = 5.0; - VERSIONING_SYSTEM = "apple-generic"; - }; - name = Profile; - }; - 97C147031CF9000F007C117D /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_ANALYZER_NONNULL = YES; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_COMMA = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INFINITE_RECURSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; - CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; - CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; - CLANG_WARN_STRICT_PROTOTYPES = YES; - CLANG_WARN_SUSPICIOUS_MOVE = YES; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; - COPY_PHASE_STRIP = NO; - DEBUG_INFORMATION_FORMAT = dwarf; - ENABLE_STRICT_OBJC_MSGSEND = YES; - ENABLE_TESTABILITY = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; - GCC_DYNAMIC_NO_PIC = NO; - GCC_NO_COMMON_BLOCKS = YES; - GCC_OPTIMIZATION_LEVEL = 0; - GCC_PREPROCESSOR_DEFINITIONS = ( - "DEBUG=1", - "$(inherited)", - ); - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 9.0; - MTL_ENABLE_DEBUG_INFO = YES; - ONLY_ACTIVE_ARCH = YES; - SDKROOT = iphoneos; - TARGETED_DEVICE_FAMILY = "1,2"; - }; - name = Debug; - }; - 97C147041CF9000F007C117D /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_ANALYZER_NONNULL = YES; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_COMMA = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INFINITE_RECURSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; - CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; - CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; - CLANG_WARN_STRICT_PROTOTYPES = YES; - CLANG_WARN_SUSPICIOUS_MOVE = YES; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; - COPY_PHASE_STRIP = NO; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - ENABLE_NS_ASSERTIONS = NO; - ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; - GCC_NO_COMMON_BLOCKS = YES; - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 9.0; - MTL_ENABLE_DEBUG_INFO = NO; - SDKROOT = iphoneos; - SUPPORTED_PLATFORMS = iphoneos; - SWIFT_COMPILATION_MODE = wholemodule; - SWIFT_OPTIMIZATION_LEVEL = "-O"; - TARGETED_DEVICE_FAMILY = "1,2"; - VALIDATE_PRODUCT = YES; - }; - name = Release; - }; - 97C147061CF9000F007C117D /* Debug */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */; - buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - CLANG_ENABLE_MODULES = YES; - CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; - ENABLE_BITCODE = NO; - INFOPLIST_FILE = Runner/Info.plist; - LD_RUNPATH_SEARCH_PATHS = ( - "$(inherited)", - "@executable_path/Frameworks", - ); - PRODUCT_BUNDLE_IDENTIFIER = com.example.testify; - PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; - SWIFT_OPTIMIZATION_LEVEL = "-Onone"; - SWIFT_VERSION = 5.0; - VERSIONING_SYSTEM = "apple-generic"; - }; - name = Debug; - }; - 97C147071CF9000F007C117D /* Release */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; - buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - CLANG_ENABLE_MODULES = YES; - CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; - ENABLE_BITCODE = NO; - INFOPLIST_FILE = Runner/Info.plist; - LD_RUNPATH_SEARCH_PATHS = ( - "$(inherited)", - "@executable_path/Frameworks", - ); - PRODUCT_BUNDLE_IDENTIFIER = com.example.testify; - PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; - SWIFT_VERSION = 5.0; - VERSIONING_SYSTEM = "apple-generic"; - }; - name = Release; - }; -/* End XCBuildConfiguration section */ - -/* Begin XCConfigurationList section */ - 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 97C147031CF9000F007C117D /* Debug */, - 97C147041CF9000F007C117D /* Release */, - 249021D3217E4FDB00AE95B9 /* Profile */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 97C147061CF9000F007C117D /* Debug */, - 97C147071CF9000F007C117D /* Release */, - 249021D4217E4FDB00AE95B9 /* Profile */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; -/* End XCConfigurationList section */ - }; - rootObject = 97C146E61CF9000F007C117D /* Project object */; -} +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 50; + objects = { + +/* Begin PBXBuildFile section */ + 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; }; + 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; }; + 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; }; + 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; }; + 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; }; + 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; }; +/* End PBXBuildFile section */ + +/* Begin PBXCopyFilesBuildPhase section */ + 9705A1C41CF9048500538489 /* Embed Frameworks */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = ""; + dstSubfolderSpec = 10; + files = ( + ); + name = "Embed Frameworks"; + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXCopyFilesBuildPhase section */ + +/* Begin PBXFileReference section */ + 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = ""; }; + 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = ""; }; + 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = ""; }; + 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Runner-Bridging-Header.h"; sourceTree = ""; }; + 74858FAE1ED2DC5600515810 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; + 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = ""; }; + 9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = ""; }; + 9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = ""; }; + 97C146EE1CF9000F007C117D /* Runner.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Runner.app; sourceTree = BUILT_PRODUCTS_DIR; }; + 97C146FB1CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; + 97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; + 97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; + 97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 97C146EB1CF9000F007C117D /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 9740EEB11CF90186004384FC /* Flutter */ = { + isa = PBXGroup; + children = ( + 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */, + 9740EEB21CF90195004384FC /* Debug.xcconfig */, + 7AFA3C8E1D35360C0083082E /* Release.xcconfig */, + 9740EEB31CF90195004384FC /* Generated.xcconfig */, + ); + name = Flutter; + sourceTree = ""; + }; + 97C146E51CF9000F007C117D = { + isa = PBXGroup; + children = ( + 9740EEB11CF90186004384FC /* Flutter */, + 97C146F01CF9000F007C117D /* Runner */, + 97C146EF1CF9000F007C117D /* Products */, + ); + sourceTree = ""; + }; + 97C146EF1CF9000F007C117D /* Products */ = { + isa = PBXGroup; + children = ( + 97C146EE1CF9000F007C117D /* Runner.app */, + ); + name = Products; + sourceTree = ""; + }; + 97C146F01CF9000F007C117D /* Runner */ = { + isa = PBXGroup; + children = ( + 97C146FA1CF9000F007C117D /* Main.storyboard */, + 97C146FD1CF9000F007C117D /* Assets.xcassets */, + 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */, + 97C147021CF9000F007C117D /* Info.plist */, + 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */, + 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */, + 74858FAE1ED2DC5600515810 /* AppDelegate.swift */, + 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */, + ); + path = Runner; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 97C146ED1CF9000F007C117D /* Runner */ = { + isa = PBXNativeTarget; + buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */; + buildPhases = ( + 9740EEB61CF901F6004384FC /* Run Script */, + 97C146EA1CF9000F007C117D /* Sources */, + 97C146EB1CF9000F007C117D /* Frameworks */, + 97C146EC1CF9000F007C117D /* Resources */, + 9705A1C41CF9048500538489 /* Embed Frameworks */, + 3B06AD1E1E4923F5004D2608 /* Thin Binary */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = Runner; + productName = Runner; + productReference = 97C146EE1CF9000F007C117D /* Runner.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 97C146E61CF9000F007C117D /* Project object */ = { + isa = PBXProject; + attributes = { + LastUpgradeCheck = 1300; + ORGANIZATIONNAME = ""; + TargetAttributes = { + 97C146ED1CF9000F007C117D = { + CreatedOnToolsVersion = 7.3.1; + LastSwiftMigration = 1100; + }; + }; + }; + buildConfigurationList = 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */; + compatibilityVersion = "Xcode 9.3"; + developmentRegion = en; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = 97C146E51CF9000F007C117D; + productRefGroup = 97C146EF1CF9000F007C117D /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 97C146ED1CF9000F007C117D /* Runner */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 97C146EC1CF9000F007C117D /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */, + 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */, + 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */, + 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXShellScriptBuildPhase section */ + 3B06AD1E1E4923F5004D2608 /* Thin Binary */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + ); + name = "Thin Binary"; + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" embed_and_thin"; + }; + 9740EEB61CF901F6004384FC /* Run Script */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + ); + name = "Run Script"; + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build"; + }; +/* End PBXShellScriptBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 97C146EA1CF9000F007C117D /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */, + 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXVariantGroup section */ + 97C146FA1CF9000F007C117D /* Main.storyboard */ = { + isa = PBXVariantGroup; + children = ( + 97C146FB1CF9000F007C117D /* Base */, + ); + name = Main.storyboard; + sourceTree = ""; + }; + 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */ = { + isa = PBXVariantGroup; + children = ( + 97C147001CF9000F007C117D /* Base */, + ); + name = LaunchScreen.storyboard; + sourceTree = ""; + }; +/* End PBXVariantGroup section */ + +/* Begin XCBuildConfiguration section */ + 249021D3217E4FDB00AE95B9 /* Profile */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 9.0; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = iphoneos; + SUPPORTED_PLATFORMS = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + }; + name = Profile; + }; + 249021D4217E4FDB00AE95B9 /* Profile */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; + ENABLE_BITCODE = NO; + INFOPLIST_FILE = Runner/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = com.example.testify; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; + SWIFT_VERSION = 5.0; + VERSIONING_SYSTEM = "apple-generic"; + }; + name = Profile; + }; + 97C147031CF9000F007C117D /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 9.0; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; + 97C147041CF9000F007C117D /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 9.0; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = iphoneos; + SUPPORTED_PLATFORMS = iphoneos; + SWIFT_COMPILATION_MODE = wholemodule; + SWIFT_OPTIMIZATION_LEVEL = "-O"; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + 97C147061CF9000F007C117D /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; + ENABLE_BITCODE = NO; + INFOPLIST_FILE = Runner/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = com.example.testify; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 5.0; + VERSIONING_SYSTEM = "apple-generic"; + }; + name = Debug; + }; + 97C147071CF9000F007C117D /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; + ENABLE_BITCODE = NO; + INFOPLIST_FILE = Runner/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = com.example.testify; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; + SWIFT_VERSION = 5.0; + VERSIONING_SYSTEM = "apple-generic"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 97C147031CF9000F007C117D /* Debug */, + 97C147041CF9000F007C117D /* Release */, + 249021D3217E4FDB00AE95B9 /* Profile */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 97C147061CF9000F007C117D /* Debug */, + 97C147071CF9000F007C117D /* Release */, + 249021D4217E4FDB00AE95B9 /* Profile */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 97C146E61CF9000F007C117D /* Project object */; +} diff --git a/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata index 919434a..c4b79bd 100644 --- a/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata +++ b/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -1,7 +1,7 @@ - - - - - + + + + + diff --git a/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist index 18d9810..fc6bf80 100644 --- a/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist +++ b/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -1,8 +1,8 @@ - - - - - IDEDidComputeMac32BitWarning - - - + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings b/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings index f9b0d7c..af0309c 100644 --- a/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings +++ b/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings @@ -1,8 +1,8 @@ - - - - - PreviewsEnabled - - - + + + + + PreviewsEnabled + + + diff --git a/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme index c87d15a..f9cbb25 100644 --- a/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme +++ b/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme @@ -1,87 +1,87 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ios/Runner.xcworkspace/contents.xcworkspacedata b/ios/Runner.xcworkspace/contents.xcworkspacedata index 1d526a1..59c6d39 100644 --- a/ios/Runner.xcworkspace/contents.xcworkspacedata +++ b/ios/Runner.xcworkspace/contents.xcworkspacedata @@ -1,7 +1,7 @@ - - - - - + + + + + diff --git a/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist index 18d9810..fc6bf80 100644 --- a/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist +++ b/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -1,8 +1,8 @@ - - - - - IDEDidComputeMac32BitWarning - - - + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings b/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings index f9b0d7c..af0309c 100644 --- a/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings +++ b/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings @@ -1,8 +1,8 @@ - - - - - PreviewsEnabled - - - + + + + + PreviewsEnabled + + + diff --git a/ios/Runner/AppDelegate.swift b/ios/Runner/AppDelegate.swift index 70693e4..3763683 100644 --- a/ios/Runner/AppDelegate.swift +++ b/ios/Runner/AppDelegate.swift @@ -1,13 +1,13 @@ -import UIKit -import Flutter - -@UIApplicationMain -@objc class AppDelegate: FlutterAppDelegate { - override func application( - _ application: UIApplication, - didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? - ) -> Bool { - GeneratedPluginRegistrant.register(with: self) - return super.application(application, didFinishLaunchingWithOptions: launchOptions) - } -} +import UIKit +import Flutter + +@UIApplicationMain +@objc class AppDelegate: FlutterAppDelegate { + override func application( + _ application: UIApplication, + didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? + ) -> Bool { + GeneratedPluginRegistrant.register(with: self) + return super.application(application, didFinishLaunchingWithOptions: launchOptions) + } +} diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json index d36b1fa..1950fd8 100644 --- a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json +++ b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -1,122 +1,122 @@ -{ - "images" : [ - { - "size" : "20x20", - "idiom" : "iphone", - "filename" : "Icon-App-20x20@2x.png", - "scale" : "2x" - }, - { - "size" : "20x20", - "idiom" : "iphone", - "filename" : "Icon-App-20x20@3x.png", - "scale" : "3x" - }, - { - "size" : "29x29", - "idiom" : "iphone", - "filename" : "Icon-App-29x29@1x.png", - "scale" : "1x" - }, - { - "size" : "29x29", - "idiom" : "iphone", - "filename" : "Icon-App-29x29@2x.png", - "scale" : "2x" - }, - { - "size" : "29x29", - "idiom" : "iphone", - "filename" : "Icon-App-29x29@3x.png", - "scale" : "3x" - }, - { - "size" : "40x40", - "idiom" : "iphone", - "filename" : "Icon-App-40x40@2x.png", - "scale" : "2x" - }, - { - "size" : "40x40", - "idiom" : "iphone", - "filename" : "Icon-App-40x40@3x.png", - "scale" : "3x" - }, - { - "size" : "60x60", - "idiom" : "iphone", - "filename" : "Icon-App-60x60@2x.png", - "scale" : "2x" - }, - { - "size" : "60x60", - "idiom" : "iphone", - "filename" : "Icon-App-60x60@3x.png", - "scale" : "3x" - }, - { - "size" : "20x20", - "idiom" : "ipad", - "filename" : "Icon-App-20x20@1x.png", - "scale" : "1x" - }, - { - "size" : "20x20", - "idiom" : "ipad", - "filename" : "Icon-App-20x20@2x.png", - "scale" : "2x" - }, - { - "size" : "29x29", - "idiom" : "ipad", - "filename" : "Icon-App-29x29@1x.png", - "scale" : "1x" - }, - { - "size" : "29x29", - "idiom" : "ipad", - "filename" : "Icon-App-29x29@2x.png", - "scale" : "2x" - }, - { - "size" : "40x40", - "idiom" : "ipad", - "filename" : "Icon-App-40x40@1x.png", - "scale" : "1x" - }, - { - "size" : "40x40", - "idiom" : "ipad", - "filename" : "Icon-App-40x40@2x.png", - "scale" : "2x" - }, - { - "size" : "76x76", - "idiom" : "ipad", - "filename" : "Icon-App-76x76@1x.png", - "scale" : "1x" - }, - { - "size" : "76x76", - "idiom" : "ipad", - "filename" : "Icon-App-76x76@2x.png", - "scale" : "2x" - }, - { - "size" : "83.5x83.5", - "idiom" : "ipad", - "filename" : "Icon-App-83.5x83.5@2x.png", - "scale" : "2x" - }, - { - "size" : "1024x1024", - "idiom" : "ios-marketing", - "filename" : "Icon-App-1024x1024@1x.png", - "scale" : "1x" - } - ], - "info" : { - "version" : 1, - "author" : "xcode" - } -} +{ + "images" : [ + { + "size" : "20x20", + "idiom" : "iphone", + "filename" : "Icon-App-20x20@2x.png", + "scale" : "2x" + }, + { + "size" : "20x20", + "idiom" : "iphone", + "filename" : "Icon-App-20x20@3x.png", + "scale" : "3x" + }, + { + "size" : "29x29", + "idiom" : "iphone", + "filename" : "Icon-App-29x29@1x.png", + "scale" : "1x" + }, + { + "size" : "29x29", + "idiom" : "iphone", + "filename" : "Icon-App-29x29@2x.png", + "scale" : "2x" + }, + { + "size" : "29x29", + "idiom" : "iphone", + "filename" : "Icon-App-29x29@3x.png", + "scale" : "3x" + }, + { + "size" : "40x40", + "idiom" : "iphone", + "filename" : "Icon-App-40x40@2x.png", + "scale" : "2x" + }, + { + "size" : "40x40", + "idiom" : "iphone", + "filename" : "Icon-App-40x40@3x.png", + "scale" : "3x" + }, + { + "size" : "60x60", + "idiom" : "iphone", + "filename" : "Icon-App-60x60@2x.png", + "scale" : "2x" + }, + { + "size" : "60x60", + "idiom" : "iphone", + "filename" : "Icon-App-60x60@3x.png", + "scale" : "3x" + }, + { + "size" : "20x20", + "idiom" : "ipad", + "filename" : "Icon-App-20x20@1x.png", + "scale" : "1x" + }, + { + "size" : "20x20", + "idiom" : "ipad", + "filename" : "Icon-App-20x20@2x.png", + "scale" : "2x" + }, + { + "size" : "29x29", + "idiom" : "ipad", + "filename" : "Icon-App-29x29@1x.png", + "scale" : "1x" + }, + { + "size" : "29x29", + "idiom" : "ipad", + "filename" : "Icon-App-29x29@2x.png", + "scale" : "2x" + }, + { + "size" : "40x40", + "idiom" : "ipad", + "filename" : "Icon-App-40x40@1x.png", + "scale" : "1x" + }, + { + "size" : "40x40", + "idiom" : "ipad", + "filename" : "Icon-App-40x40@2x.png", + "scale" : "2x" + }, + { + "size" : "76x76", + "idiom" : "ipad", + "filename" : "Icon-App-76x76@1x.png", + "scale" : "1x" + }, + { + "size" : "76x76", + "idiom" : "ipad", + "filename" : "Icon-App-76x76@2x.png", + "scale" : "2x" + }, + { + "size" : "83.5x83.5", + "idiom" : "ipad", + "filename" : "Icon-App-83.5x83.5@2x.png", + "scale" : "2x" + }, + { + "size" : "1024x1024", + "idiom" : "ios-marketing", + "filename" : "Icon-App-1024x1024@1x.png", + "scale" : "1x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} diff --git a/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json b/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json index 0bedcf2..d08a4de 100644 --- a/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json +++ b/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json @@ -1,23 +1,23 @@ -{ - "images" : [ - { - "idiom" : "universal", - "filename" : "LaunchImage.png", - "scale" : "1x" - }, - { - "idiom" : "universal", - "filename" : "LaunchImage@2x.png", - "scale" : "2x" - }, - { - "idiom" : "universal", - "filename" : "LaunchImage@3x.png", - "scale" : "3x" - } - ], - "info" : { - "version" : 1, - "author" : "xcode" - } -} +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "LaunchImage.png", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "LaunchImage@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "LaunchImage@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} diff --git a/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md b/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md index 89c2725..65a94b5 100644 --- a/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md +++ b/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md @@ -1,5 +1,5 @@ -# Launch Screen Assets - -You can customize the launch screen with your own desired assets by replacing the image files in this directory. - +# Launch Screen Assets + +You can customize the launch screen with your own desired assets by replacing the image files in this directory. + You can also do it by opening your Flutter project's Xcode project with `open ios/Runner.xcworkspace`, selecting `Runner/Assets.xcassets` in the Project Navigator and dropping in the desired images. \ No newline at end of file diff --git a/ios/Runner/Base.lproj/LaunchScreen.storyboard b/ios/Runner/Base.lproj/LaunchScreen.storyboard index f2e259c..497371e 100644 --- a/ios/Runner/Base.lproj/LaunchScreen.storyboard +++ b/ios/Runner/Base.lproj/LaunchScreen.storyboard @@ -1,37 +1,37 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ios/Runner/Base.lproj/Main.storyboard b/ios/Runner/Base.lproj/Main.storyboard index f3c2851..bbb83ca 100644 --- a/ios/Runner/Base.lproj/Main.storyboard +++ b/ios/Runner/Base.lproj/Main.storyboard @@ -1,26 +1,26 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ios/Runner/Info.plist b/ios/Runner/Info.plist index 37f1375..0f37f86 100644 --- a/ios/Runner/Info.plist +++ b/ios/Runner/Info.plist @@ -1,47 +1,47 @@ - - - - - CFBundleDevelopmentRegion - $(DEVELOPMENT_LANGUAGE) - CFBundleDisplayName - Testify - CFBundleExecutable - $(EXECUTABLE_NAME) - CFBundleIdentifier - $(PRODUCT_BUNDLE_IDENTIFIER) - CFBundleInfoDictionaryVersion - 6.0 - CFBundleName - testify - CFBundlePackageType - APPL - CFBundleShortVersionString - $(FLUTTER_BUILD_NAME) - CFBundleSignature - ???? - CFBundleVersion - $(FLUTTER_BUILD_NUMBER) - LSRequiresIPhoneOS - - UILaunchStoryboardName - LaunchScreen - UIMainStoryboardFile - Main - UISupportedInterfaceOrientations - - UIInterfaceOrientationPortrait - UIInterfaceOrientationLandscapeLeft - UIInterfaceOrientationLandscapeRight - - UISupportedInterfaceOrientations~ipad - - UIInterfaceOrientationPortrait - UIInterfaceOrientationPortraitUpsideDown - UIInterfaceOrientationLandscapeLeft - UIInterfaceOrientationLandscapeRight - - UIViewControllerBasedStatusBarAppearance - - - + + + + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleDisplayName + Testify + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + testify + CFBundlePackageType + APPL + CFBundleShortVersionString + $(FLUTTER_BUILD_NAME) + CFBundleSignature + ???? + CFBundleVersion + $(FLUTTER_BUILD_NUMBER) + LSRequiresIPhoneOS + + UILaunchStoryboardName + LaunchScreen + UIMainStoryboardFile + Main + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UISupportedInterfaceOrientations~ipad + + UIInterfaceOrientationPortrait + UIInterfaceOrientationPortraitUpsideDown + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UIViewControllerBasedStatusBarAppearance + + + diff --git a/ios/Runner/Runner-Bridging-Header.h b/ios/Runner/Runner-Bridging-Header.h index 308a2a5..fae207f 100644 --- a/ios/Runner/Runner-Bridging-Header.h +++ b/ios/Runner/Runner-Bridging-Header.h @@ -1 +1 @@ -#import "GeneratedPluginRegistrant.h" +#import "GeneratedPluginRegistrant.h" diff --git a/lib/auth_storage.dart b/lib/auth_storage.dart index 98286ac..03a99db 100644 --- a/lib/auth_storage.dart +++ b/lib/auth_storage.dart @@ -1,41 +1,41 @@ -import 'package:path_provider/path_provider.dart'; -import 'dart:io'; - - -class AuthStorage { - Future getLocalPath() async { - var dir = await getApplicationDocumentsDirectory(); - return dir.path; - } - - Future getLocalFile() async { - String path = await getLocalPath(); - return File('$path/auth.txt'); - } - - Future writeAuth(String email, String password) async { - File file = await getLocalFile(); - return file.writeAsString('$email' + ' ' + '$password'); - } - - Future readAuth() async { - try { - final file = await getLocalFile(); - String content = await file.readAsString(); - return content; - } catch(e) { - return ""; - } - } - - Future deleteFile() async { - try { - final file = await getLocalFile(); - - await file.delete(); - return ""; - } catch (e) { - return ""; - } - } +import 'package:path_provider/path_provider.dart'; +import 'dart:io'; + + +class AuthStorage { + Future getLocalPath() async { + var dir = await getApplicationDocumentsDirectory(); + return dir.path; + } + + Future getLocalFile() async { + String path = await getLocalPath(); + return File('$path/auth.txt'); + } + + Future writeAuth(String email, String password) async { + File file = await getLocalFile(); + return file.writeAsString('$email' + ' ' + '$password'); + } + + Future readAuth() async { + try { + final file = await getLocalFile(); + String content = await file.readAsString(); + return content; + } catch(e) { + return ""; + } + } + + Future deleteFile() async { + try { + final file = await getLocalFile(); + + await file.delete(); + return ""; + } catch (e) { + return ""; + } + } } \ No newline at end of file diff --git a/lib/main.dart b/lib/main.dart index 60efcaa..0f01647 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -1,31 +1,30 @@ -import 'package:flutter/material.dart'; -import 'package:flutter/services.dart'; -import 'package:testify/auth_storage.dart'; -import 'package:testify/screens/Authentication/login.dart'; -import 'package:testify/screens/home.dart'; - -void main() async { - WidgetsFlutterBinding.ensureInitialized(); - SystemChrome.setPreferredOrientations([ - DeviceOrientation.portraitUp, - DeviceOrientation.portraitDown, - ]); - - runApp(MyApp()); -} - -class MyApp extends StatefulWidget { - // This widget is the root of your application. - @override - State createState() => _MyAppState(); -} - -class _MyAppState extends State { - @override - Widget build(BuildContext context) { - return MaterialApp( - home: Login( - fromWhere: "main", - )); - } -} +import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; +import 'package:testify/auth_storage.dart'; +import 'package:testify/screens/Authentication/login.dart'; +import 'package:testify/screens/home.dart'; + +void main() async { + WidgetsFlutterBinding.ensureInitialized(); + SystemChrome.setPreferredOrientations([ + DeviceOrientation.portraitUp, + DeviceOrientation.portraitDown, + ]); + + runApp(MyApp()); +} + +class MyApp extends StatefulWidget { + // This widget is the root of your application. + @override + State createState() => _MyAppState(); +} + +class _MyAppState extends State { + + @override + Widget build(BuildContext context) { + return MaterialApp( + home: Login(fromWhere: "main",)); + } +} \ No newline at end of file diff --git a/lib/models/user_model_successful_login.dart b/lib/models/user_model_successful_login.dart index 02c7bb9..f179778 100644 --- a/lib/models/user_model_successful_login.dart +++ b/lib/models/user_model_successful_login.dart @@ -1,57 +1,57 @@ -// To parse this JSON data, do -// -// final userModelSuccessfulLogin = userModelSuccessfulLoginFromJson(jsonString); - -import 'dart:convert'; - -UserModelSuccessfulLogin userModelSuccessfulLoginFromJson(String str) => UserModelSuccessfulLogin.fromJson(json.decode(str)); - -String userModelSuccessfulLoginToJson(UserModelSuccessfulLogin data) => json.encode(data.toJson()); - -class UserModelSuccessfulLogin { - UserModelSuccessfulLogin({ - required this.data, - }); - - Data data; - - factory UserModelSuccessfulLogin.fromJson(Map json) => UserModelSuccessfulLogin( - data: Data.fromJson(json["data"]), - ); - - Map toJson() => { - "data": data.toJson(), - }; -} - -class Data { - Data({ - required this.status, - required this.id, - required this.username, - required this.ifAdmin, - required this.token, - }); - - bool status; - int id; - String username; - bool ifAdmin; - String token; - - factory Data.fromJson(Map json) => Data( - status: json["status"], - id: json["ID"], - username: json["username"], - ifAdmin: json["ifAdmin"], - token: json["token"], - ); - - Map toJson() => { - "status": status, - "ID": id, - "username": username, - "ifAdmin": ifAdmin, - "token": token, - }; -} +// To parse this JSON data, do +// +// final userModelSuccessfulLogin = userModelSuccessfulLoginFromJson(jsonString); + +import 'dart:convert'; + +UserModelSuccessfulLogin userModelSuccessfulLoginFromJson(String str) => UserModelSuccessfulLogin.fromJson(json.decode(str)); + +String userModelSuccessfulLoginToJson(UserModelSuccessfulLogin data) => json.encode(data.toJson()); + +class UserModelSuccessfulLogin { + UserModelSuccessfulLogin({ + required this.data, + }); + + Data data; + + factory UserModelSuccessfulLogin.fromJson(Map json) => UserModelSuccessfulLogin( + data: Data.fromJson(json["data"]), + ); + + Map toJson() => { + "data": data.toJson(), + }; +} + +class Data { + Data({ + required this.status, + required this.id, + required this.username, + required this.ifAdmin, + required this.token, + }); + + bool status; + int id; + String username; + bool ifAdmin; + String token; + + factory Data.fromJson(Map json) => Data( + status: json["status"], + id: json["ID"], + username: json["username"], + ifAdmin: json["ifAdmin"], + token: json["token"], + ); + + Map toJson() => { + "status": status, + "ID": id, + "username": username, + "ifAdmin": ifAdmin, + "token": token, + }; +} diff --git a/lib/models/user_model_unsuccessful_login.dart b/lib/models/user_model_unsuccessful_login.dart index 2546b25..6eb9603 100644 --- a/lib/models/user_model_unsuccessful_login.dart +++ b/lib/models/user_model_unsuccessful_login.dart @@ -1,45 +1,45 @@ -// To parse this JSON data, do -// -// final userModelUnsuccessfulLogin = userModelUnsuccessfulLoginFromJson(jsonString); - -import 'dart:convert'; - -UserModelUnsuccessfulLogin userModelUnsuccessfulLoginFromJson(String str) => UserModelUnsuccessfulLogin.fromJson(json.decode(str)); - -String userModelUnsuccessfulLoginToJson(UserModelUnsuccessfulLogin data) => json.encode(data.toJson()); - -class UserModelUnsuccessfulLogin { - UserModelUnsuccessfulLogin({ - required this.data, - }); - - Data data; - - factory UserModelUnsuccessfulLogin.fromJson(Map json) => UserModelUnsuccessfulLogin( - data: Data.fromJson(json["data"]), - ); - - Map toJson() => { - "data": data.toJson(), - }; -} - -class Data { - Data({ - required this.status, - required this.message, - }); - - bool status; - String message; - - factory Data.fromJson(Map json) => Data( - status: json["status"], - message: json["message"], - ); - - Map toJson() => { - "status": status, - "message": message, - }; -} +// To parse this JSON data, do +// +// final userModelUnsuccessfulLogin = userModelUnsuccessfulLoginFromJson(jsonString); + +import 'dart:convert'; + +UserModelUnsuccessfulLogin userModelUnsuccessfulLoginFromJson(String str) => UserModelUnsuccessfulLogin.fromJson(json.decode(str)); + +String userModelUnsuccessfulLoginToJson(UserModelUnsuccessfulLogin data) => json.encode(data.toJson()); + +class UserModelUnsuccessfulLogin { + UserModelUnsuccessfulLogin({ + required this.data, + }); + + Data data; + + factory UserModelUnsuccessfulLogin.fromJson(Map json) => UserModelUnsuccessfulLogin( + data: Data.fromJson(json["data"]), + ); + + Map toJson() => { + "data": data.toJson(), + }; +} + +class Data { + Data({ + required this.status, + required this.message, + }); + + bool status; + String message; + + factory Data.fromJson(Map json) => Data( + status: json["status"], + message: json["message"], + ); + + Map toJson() => { + "status": status, + "message": message, + }; +} diff --git a/lib/screens/Authentication/login.dart b/lib/screens/Authentication/login.dart index ae264f5..b554aa3 100644 --- a/lib/screens/Authentication/login.dart +++ b/lib/screens/Authentication/login.dart @@ -1,477 +1,519 @@ -import 'dart:convert'; -import 'dart:io'; - -import 'package:flutter/material.dart'; -import 'package:flutter_svg/flutter_svg.dart'; -import 'package:http/http.dart' as http; -import 'package:path_provider/path_provider.dart'; -import 'package:testify/auth_storage.dart'; -import 'package:testify/models/user_model_successful_login.dart'; -import 'package:testify/models/user_model_unsuccessful_login.dart'; -import 'package:testify/screens/home.dart'; - -class Login extends StatefulWidget { - const Login({Key? key, required this.fromWhere}) : super(key: key); - - final String fromWhere; - @override - State createState() => _LoginState(); -} - -class _LoginState extends State { - //Data Fields: - final _formKey = GlobalKey(); - String _email = ""; - String _password = ""; - bool _isChecked = false; - //To start animation - bool _loaded = false; - var _duration = const Duration(milliseconds: 450); - var _dataPreviouslyStored = false; - late UserModelSuccessfulLogin _successfulUser; - late UserModelUnsuccessfulLogin _unsuccessfulUser; - - //The data gets stored to local storage. Continue from there. - AuthStorage storage = new AuthStorage(); - - @override - void initState() { - super.initState(); - //To delete the auth file when the user logs out. - if(widget.fromWhere == "Home") { - storage.deleteFile(); - print("Deleted + :" + storage.readAuth().toString()); - setState(() { - _email = ""; - _password = ""; - _isChecked = false; - _dataPreviouslyStored = false; - }); - } - else { - storage.readAuth().then((value) { - if(value.length != 0) { - var temp = value.split(" "); - print(temp); - setState(() { - _email = temp[0]; - _password = temp[1]; - _dataPreviouslyStored = true; - }); - print("Email + Password: " + _email + _password); - } - else { - - } - }); - } - Future.delayed(Duration(milliseconds: 1), () { - setState(() { - _loaded = true; - }); - }); - } - - //https://demo.pookidevs.com/auth/login - Future getUserData(BuildContext context, String email, String password) async { - final String apiUrl = "https://demo.pookidevs.com/auth/login"; - http.post(Uri.parse(apiUrl), headers: { - 'Content-type': 'application/json; charset=UTF-8', - }, body: json.encode( - { - "user": - { - "user_email": email, - "user_pass": password - } - }) - ).then((response) { - if(response.statusCode == 200) { - //The entered credentials are correct. - if(json.decode(response.body).toString().substring(0,20) == "{data: {status: true") { - final responseString = (response.body); - var loginData = userModelSuccessfulLoginFromJson(responseString); - final UserModelSuccessfulLogin successfulUser = loginData; - setState(() { - _successfulUser = successfulUser; - }); - _navigateAndDisplaySelection(context); - print(_successfulUser.data.status); - } - //Credentials are incorrect - else if(json.decode(response.body).toString().substring(0,21) == "{data: {status: false") { - final responseString = (response.body); - var loginData = userModelUnsuccessfulLoginFromJson(responseString); - final UserModelUnsuccessfulLogin unsuccessfulUser = loginData; - setState(() { - _unsuccessfulUser = unsuccessfulUser; - }); - print(_unsuccessfulUser.data.status); - ScaffoldMessenger.of(context) - ..removeCurrentSnackBar() - ..showSnackBar(SnackBar(content: Text(_unsuccessfulUser.data.message))); - _navigateAndDisplaySelection(context); - } - //loginData = userModelLoginFromJson(responseString); - } else { - - } - }); - - } - - //After form validation navigation to next screen. - void _navigateAndDisplaySelection(BuildContext context) async { - if(_successfulUser.data.status == true) { - if(_isChecked == true) { - storage.writeAuth(_email, _password); - print("Email + Password: " + _email + _password); - final result = await Navigator.push( - context, - MaterialPageRoute(builder: (context) => const Home()), - ); - } - else { - storage.writeAuth(_email, _password); - storage.deleteFile(); - print("Email + Password: " + _email + _password); - final result = await Navigator.push( - context, - MaterialPageRoute(builder: (context) => const Home()), - ); - } - } - /*ScaffoldMessenger.of(context) - ..removeCurrentSnackBar() - ..showSnackBar(SnackBar(content: Text(_unsuccessfulUser.data.message)));*/ - } - - @override - Widget build(BuildContext context) { - return Scaffold( - backgroundColor: Color(0xff3F2668),//Color copied from xD=#3F2668 - body: SingleChildScrollView( - child: Container( - height: (MediaQuery.of(context).size.height), - child: Column( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - AnimatedCrossFade( - crossFadeState: _loaded ? CrossFadeState.showFirst : CrossFadeState.showSecond, - duration: _duration, - firstChild: Container( - height: (MediaQuery.of(context).size.height) *0.3, - color: Colors.transparent, - child: Align( - alignment: Alignment.topLeft, - child: Image( - image: AssetImage("assets/Images/login_topLeftBubble_1.png"), - ), - ), - ), - secondChild: Container( - height: (MediaQuery.of(context).size.height) *0.3, - color: Colors.transparent, - child: Text(""), - ), - ), - SizedBox(height: (MediaQuery.of(context).size.height) *0.02159,), - AnimatedCrossFade( - crossFadeState: _loaded ? CrossFadeState.showFirst : CrossFadeState.showSecond, - duration: _duration, - secondChild: Text(""), - firstChild: Container( - child: Form( - key: _formKey, - child: Stack( - alignment: Alignment.bottomCenter, - children: [ - Column(//Add extra space at the end of the container(the one that has TextFormField) so that the login button can be aligned. - children: [ - Container(//For Borders of lighter area //Main Container to add Welcome, TextFormFields and Login. - //tbd: Get the color right! - margin: EdgeInsets.only(top: 0, bottom: 0, left: (MediaQuery.of(context).size.width) *(31/428), right: (MediaQuery.of(context).size.width) *(31/428),), - padding: EdgeInsets.only(top: 0, bottom: (MediaQuery.of(context).size.height) *0.0179, left: 0, right: 0,), - decoration: BoxDecoration( - color: Color.fromRGBO(176, 166, 194, 210),//0xffB0A6C2, rgba(176, 166, 194, 1) - borderRadius: BorderRadius.all(Radius.circular(10)), - border: Border.all( - color: Color(0xff757575), - width: 0, - ), - boxShadow: [ - BoxShadow( - color: Color(0xff0000004D), - ), - ], - ), - child: Column( - children: [ - Container( - padding: EdgeInsets.only(top: (MediaQuery.of(context).size.height) *0.020518, bottom: 0, left: 0, right: 0,), - child: Text("Welcome!", - style: TextStyle( - color: Color(0xffFFFEFE), - fontFamily: 'Brandon-bld', - fontSize: (MediaQuery.of(context).size.height) *0.0410,//38, - ),), - ), - Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Container( - padding: EdgeInsets.only(top: 0, bottom: 0, left: 0, right: 0,), - child: Text("Don't have an account?", - style: TextStyle( - color: Color.fromRGBO(255, 255, 255, 100), - fontFamily: 'Brandon-med', - fontSize: (MediaQuery.of(context).size.height)*0.0194, - ),), - ), - Container( - padding: EdgeInsets.only(top: 0, bottom: 0, left: 0, right: 0,), - child: Text(" Sign Up", - style: TextStyle( - color: Color(0xffFFFEFE), - fontFamily: 'Brandon-med', - fontSize: (MediaQuery.of(context).size.height)*0.0194, - ),), - ), - ], - ), - SizedBox(height: (MediaQuery.of(context).size.height)*0.04535,), - Container( - //color: Colors.white, - height: (MediaQuery.of(context).size.height)*0.055, - //padding: EdgeInsets.fromLTRB(20.0, (MediaQuery.of(context).size.height - MediaQuery.of(context).padding.top)*0.0037797, 20.0, (MediaQuery.of(context).size.height - MediaQuery.of(context).padding.top)*0.0037797), - margin: EdgeInsets.only(top: 0, bottom: 0, left: (MediaQuery.of(context).size.width) *(45/428), right: (MediaQuery.of(context).size.width) *(45/428),), - decoration: BoxDecoration( - color: Colors.white, - borderRadius: BorderRadius.all(Radius.circular(10)), - border: Border.all( - color: Color(0xff757575), - width: 1, - ), - boxShadow: [ - BoxShadow( - color: Color(0xff0000004D), - ), - ], - ), - child: TextFormField( - decoration: InputDecoration( - hintText: _dataPreviouslyStored == null ? "Loading..." : (_dataPreviouslyStored ? _email : "Username"), - hintStyle: TextStyle(color: _dataPreviouslyStored ? Color(0xff171616) : Color(0xffAEAEAE), - fontSize: (MediaQuery.of(context).size.height)*(20/926), - fontFamily: 'Brandon-med',), - contentPadding: EdgeInsets.fromLTRB(20.0, (MediaQuery.of(context).size.height)*0.0037797, 20.0, (MediaQuery.of(context).size.height)*0.0037797), - enabledBorder: OutlineInputBorder( - borderSide: BorderSide( - color: Colors.transparent, - width: 0.0, - ), - borderRadius: BorderRadius.circular(10.0), - ), - focusedBorder: OutlineInputBorder( - borderSide: BorderSide( - color: Colors.transparent, - width: 0.0, - ), - ), - ), - //validator: (val) => val!.isEmpty ? "Please enter a Username." : null, - onChanged: (val) { - _dataPreviouslyStored == null ? val = "" : - (_dataPreviouslyStored ? val = _email : _email = val); - //_email = val; - }, - style: TextStyle( - color: Colors.black, - fontSize: (MediaQuery.of(context).size.height)*(20/926), - fontFamily: 'Brandon-med', - ), - ), - ), - SizedBox(height: (MediaQuery.of(context).size.height)*0.0226781,), - Container( - //color: Colors.white, - height: (MediaQuery.of(context).size.height)*0.055, - margin: EdgeInsets.only(top: 0, bottom: 0, left: (MediaQuery.of(context).size.width) *(45/428), right: (MediaQuery.of(context).size.width) *(45/428),), - decoration: BoxDecoration( - color: Colors.white, - borderRadius: BorderRadius.all(Radius.circular(10)), - border: Border.all( - color: Color(0xff757575), - width: 1, - ), - boxShadow: [ - BoxShadow( - color: Color(0xff0000004D), - ), - ], - ), - child: TextFormField( - obscureText: true, - decoration: InputDecoration( - hintText: _dataPreviouslyStored == null ? "Loading..." : (_dataPreviouslyStored ? _password : "Password"), - hintStyle: TextStyle(color: _dataPreviouslyStored ? Colors.black : Color(0xffAEAEAE), - fontSize: (MediaQuery.of(context).size.height)*(20/926), - fontFamily: 'Brandon-med',), - contentPadding: EdgeInsets.fromLTRB(20.0, (MediaQuery.of(context).size.height)*0.0037797, 20.0, (MediaQuery.of(context).size.height)*0.0037797), - enabledBorder: OutlineInputBorder( - borderSide: BorderSide( - color: Colors.transparent, - width: 0.0, - ), - borderRadius: BorderRadius.circular(10.0), - ), - focusedBorder: OutlineInputBorder( - borderSide: BorderSide( - color: Colors.transparent, - width: 0.0, - ), - ), - ), - //validator: (val) => val!.isEmpty ? "Please enter a Password." : null, - onChanged: (val) { - setState(() { - _dataPreviouslyStored == null ? val = "" : - (_dataPreviouslyStored ? val = _password : _password = val); - }); - }, - style: TextStyle( - color: Colors.black, - fontSize: (MediaQuery.of(context).size.height)*(20/926), - fontFamily: 'Brandon-med', - ), - ), - ), - SizedBox(height: (MediaQuery.of(context).size.height)*0.024838,), - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Row( - mainAxisAlignment: MainAxisAlignment.start, - children: [ - Container( - margin: EdgeInsets.only(top: 0, bottom: 0, left: (MediaQuery.of(context).size.width) *(45/428), right: 0,), - height: (MediaQuery.of(context).size.height)*0.0167, - width: (MediaQuery.of(context).size.height)*0.0167, - color: Colors.white, - child: Transform.scale( - scale: (MediaQuery.of(context).size.height)*0.001, - child: Checkbox( - side: BorderSide( - color: Color(0xffB0A6C2), - width: 0, - ), - checkColor: Colors.white, - value: _isChecked, - onChanged: (bool? value) { - setState(() { - _isChecked = value!; - }); - }, - ), - ), - ), - Container( - padding: EdgeInsets.only(top: 0, bottom: 0, left: (MediaQuery.of(context).size.width) *(5/428), right: 0,), - child: Text("Remember me!", - style: TextStyle( - color: Color.fromRGBO(255, 255, 255, 100), - fontFamily: 'Brandon-med', - fontSize: (MediaQuery.of(context).size.height)*0.0161987, - ),), - ), - ], - ), - Container( - padding: EdgeInsets.only(top: 0, bottom: 0, left: 0, right: (MediaQuery.of(context).size.width) *(45/428),), - child: Text("Forgot Password?", - style: TextStyle( - color: Color(0xffFFFEFE), - fontFamily: 'Brandon-med', - fontSize: (MediaQuery.of(context).size.height)*0.0161987, - ),), - ), - ], - ), - SizedBox(height: (MediaQuery.of(context).size.height) *0.0864,), - ], - ), - ), - SizedBox(height: (MediaQuery.of(context).size.height) *(25/926),), - ], - ), - GestureDetector( - child: Container(//Login button - child: Align( - alignment: Alignment.center, - child: SvgPicture.asset( - "assets/Images/login.svg", - height: (MediaQuery.of(context).size.height) *0.0486, - ), - ), - ), - onTap: () { - if(_formKey.currentState!.validate()) { - //_navigateAndDisplaySelection(context); - //print(_isChecked); - getUserData(context, _email, _password); - } - }, - ), - ], - ), - ), - ), - ), - AnimatedCrossFade( - crossFadeState: _loaded ? CrossFadeState.showFirst : CrossFadeState.showSecond, - duration: _duration, - secondChild: Container( - height: (MediaQuery.of(context).size.height) *0.183, - child: Text("")), - firstChild: Row( - mainAxisAlignment: MainAxisAlignment.end, - //crossAxisAlignment: CrossAxisAlignment.end, - children: [ - Stack( - //alignment: Alignment.centerRight, - children: [ - Positioned( - left: (MediaQuery.of(context).size.height) *(80/926), - top: (MediaQuery.of(context).size.height) *(50/926), - child: Align( - alignment: Alignment.bottomRight, - child: SvgPicture.asset( - "assets/Images/login_bottomRight.svg", - height: (MediaQuery.of(context).size.height) *0.183, - width: (MediaQuery.of(context).size.height) *0.183, - ), - ), - ), - Positioned(//Remove and add again - child: Align( - alignment: Alignment.bottomRight, - child: SvgPicture.asset( - "assets/Images/login_bottomRight.svg", - height: (MediaQuery.of(context).size.height) *0.183, - width: (MediaQuery.of(context).size.height) *0.183, - color: Colors.transparent, - ), - ), - ), - ], - ), - ], - ), - ), - ], - ), - ), - ), - ); - } -} +import 'dart:convert'; +import 'dart:io'; + +import 'package:flutter/material.dart'; +import 'package:flutter_svg/flutter_svg.dart'; +import 'package:http/http.dart' as http; +import 'package:path_provider/path_provider.dart'; +import 'package:shared_preferences/shared_preferences.dart'; +import 'package:testify/auth_storage.dart'; +import 'package:testify/models/user_model_successful_login.dart'; +import 'package:testify/models/user_model_unsuccessful_login.dart'; +import 'package:testify/screens/home.dart'; + +class Login extends StatefulWidget { + const Login({Key? key, required this.fromWhere}) : super(key: key); + + final String fromWhere; + @override + State createState() => _LoginState(); +} + +class _LoginState extends State { + //Data Fields: + final _formKey = GlobalKey(); + String _email = ""; + String _password = ""; + bool _isChecked = false; + //To start animation + bool _loaded = false; + var _duration = const Duration(milliseconds: 450); + var _dataPreviouslyStored = false; + late UserModelSuccessfulLogin _successfulUser; + late UserModelUnsuccessfulLogin _unsuccessfulUser; + var _invalidUsername = false; + var _invalidPassword = false; + + //The data gets stored to local storage. Continue from there. + AuthStorage storage = new AuthStorage(); + + @override + void initState() { + super.initState(); + //To delete the auth file when the user logs out. + if(widget.fromWhere == "Home") { + storage.deleteFile(); + print("Deleted + :" + storage.readAuth().toString()); + setState(() { + _email = ""; + _password = ""; + _isChecked = false; + _dataPreviouslyStored = false; + }); + } + else { + storage.readAuth().then((value) { + if(value.length != 0) { + var temp = value.split(" "); + print(temp); + setState(() { + _email = temp[0]; + _password = temp[1]; + _dataPreviouslyStored = true; + }); + print("Email + Password: " + _email + _password); + } + else { + + } + }); + } + Future.delayed(Duration(milliseconds: 1), () { + setState(() { + _loaded = true; + }); + }); + } + + //https://demo.pookidevs.com/auth/login + Future getUserData(BuildContext context, String email, String password) async { + SharedPreferences prefs = await SharedPreferences.getInstance(); + final String apiUrl = "https://demo.pookidevs.com/auth/login"; + http.post(Uri.parse(apiUrl), headers: { + 'Content-type': 'application/json; charset=UTF-8', + }, body: json.encode( + { + "user": + { + "user_email": email, + "user_pass": password + } + }) + ).then((response) { + if(response.statusCode == 200) { + //The entered credentials are correct. + if(json.decode(response.body).toString().substring(0,20) == "{data: {status: true") { + final responseString = (response.body); + var loginData = userModelSuccessfulLoginFromJson(responseString); + final UserModelSuccessfulLogin successfulUser = loginData; + setState(() { + _successfulUser = successfulUser; + }); + //Saves Token to use later. + prefs.setString('token', _successfulUser.data.token); + prefs.setInt("userId", _successfulUser.data.id); + _navigateAndDisplaySelection(context); + print(_successfulUser.data.status); + } + //Credentials are incorrect + else if(json.decode(response.body).toString().substring(0,21) == "{data: {status: false") { + final responseString = (response.body); + var loginData = userModelUnsuccessfulLoginFromJson(responseString); + final UserModelUnsuccessfulLogin unsuccessfulUser = loginData; + setState(() { + _unsuccessfulUser = unsuccessfulUser; + }); + print(_unsuccessfulUser.data.status); + ScaffoldMessenger.of(context) + ..removeCurrentSnackBar() + ..showSnackBar(SnackBar(content: Text(_unsuccessfulUser.data.message))); + _navigateAndDisplaySelection(context); + var splitMessage = (_unsuccessfulUser.data.message).split(" "); + print(splitMessage); + if(splitMessage.length == 4) { + setState(() { + _invalidPassword = true; + _invalidUsername = true; + }); + } + else if(splitMessage.length == 2) { + setState(() { + _invalidPassword = true; + }); + } + } + //loginData = userModelLoginFromJson(responseString); + } else { + + } + }); + + } + + //After form validation navigation to next screen. + void _navigateAndDisplaySelection(BuildContext context) async { + if(_successfulUser.data.status == true) { + if(_isChecked == true) { + storage.writeAuth(_email, _password); + print("Email + Password: " + _email + _password); + final result = await Navigator.push( + context, + MaterialPageRoute(builder: (context) => const Home()), + ); + } + else { + storage.writeAuth(_email, _password); + storage.deleteFile(); + print("Email + Password: " + _email + _password); + final result = await Navigator.push( + context, + MaterialPageRoute(builder: (context) => const Home()), + ); + } + } + /*ScaffoldMessenger.of(context) + ..removeCurrentSnackBar() + ..showSnackBar(SnackBar(content: Text(_unsuccessfulUser.data.message)));*/ + } + + @override + Widget build(BuildContext context) { + return WillPopScope( + onWillPop: () async { + // ScaffoldMessenger.of(context) + // ..removeCurrentSnackBar() + // ..showSnackBar(SnackBar(content: Text(""))); + return false; + }, + child: Scaffold( + backgroundColor: Color(0xff3F2668),//Color copied from xD=#3F2668 + body: SingleChildScrollView( + child: Container( + height: (MediaQuery.of(context).size.height), + child: Column( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + AnimatedCrossFade( + crossFadeState: _loaded ? CrossFadeState.showFirst : CrossFadeState.showSecond, + duration: _duration, + firstChild: Container( + height: (MediaQuery.of(context).size.height) *0.3, + color: Colors.transparent, + child: Align( + alignment: Alignment.topLeft, + child: Image( + image: AssetImage("assets/Images/login_topLeftBubble_1.png"), + ), + ), + ), + secondChild: Container( + height: (MediaQuery.of(context).size.height) *0.3, + color: Colors.transparent, + child: Text(""), + ), + ), + SizedBox(height: (MediaQuery.of(context).size.height) *0.02159,), + AnimatedCrossFade( + crossFadeState: _loaded ? CrossFadeState.showFirst : CrossFadeState.showSecond, + duration: _duration, + secondChild: Text(""), + firstChild: Container( + child: Form( + key: _formKey, + child: Stack( + alignment: Alignment.bottomCenter, + children: [ + Column(//Add extra space at the end of the container(the one that has TextFormField) so that the login button can be aligned. + children: [ + Container(//For Borders of lighter area //Main Container to add Welcome, TextFormFields and Login. + //tbd: Get the color right! + margin: EdgeInsets.only(top: 0, bottom: 0, left: (MediaQuery.of(context).size.width) *(31/428), right: (MediaQuery.of(context).size.width) *(31/428),), + padding: EdgeInsets.only(top: 0, bottom: (MediaQuery.of(context).size.height) *0.0179, left: 0, right: 0,), + decoration: BoxDecoration( + color: Color.fromRGBO(176, 166, 194, 210),//0xffB0A6C2, rgba(176, 166, 194, 1) + borderRadius: BorderRadius.all(Radius.circular(10)), + border: Border.all( + color: Color(0xff757575), + width: 0, + ), + boxShadow: [ + BoxShadow( + color: Color(0xff0000004D), + ), + ], + ), + child: Column( + children: [ + Container( + padding: EdgeInsets.only(top: (MediaQuery.of(context).size.height) *0.020518, bottom: 0, left: 0, right: 0,), + child: Text("Welcome!", + style: TextStyle( + color: Color(0xffFFFEFE), + fontFamily: 'Brandon-bld', + fontSize: (MediaQuery.of(context).size.height) *0.0410,//38, + ),), + ), + Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Container( + padding: EdgeInsets.only(top: 0, bottom: 0, left: 0, right: 0,), + child: Text("Don't have an account?", + style: TextStyle( + color: Color.fromRGBO(255, 255, 255, 100), + fontFamily: 'Brandon-med', + fontSize: (MediaQuery.of(context).size.height)*0.0194, + ),), + ), + Container( + padding: EdgeInsets.only(top: 0, bottom: 0, left: 0, right: 0,), + child: Text(" Sign Up", + style: TextStyle( + color: Color(0xffFFFEFE), + fontFamily: 'Brandon-med', + fontSize: (MediaQuery.of(context).size.height)*0.0194, + ),), + ), + ], + ), + SizedBox(height: (MediaQuery.of(context).size.height)*0.04535,), + Container( + //color: Colors.white, + height: (MediaQuery.of(context).size.height)*0.055, + //padding: EdgeInsets.fromLTRB(20.0, (MediaQuery.of(context).size.height - MediaQuery.of(context).padding.top)*0.0037797, 20.0, (MediaQuery.of(context).size.height - MediaQuery.of(context).padding.top)*0.0037797), + margin: EdgeInsets.only(top: 0, bottom: 0, left: (MediaQuery.of(context).size.width) *(45/428), right: (MediaQuery.of(context).size.width) *(45/428),), + decoration: BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.all(Radius.circular(10)), + border: Border.all( + color: _invalidUsername == true ? Colors.red : Color(0xff757575), + width: _invalidUsername == true ? 3 : 1, + ), + boxShadow: [ + BoxShadow( + color: Color(0xff0000004D), + ), + ], + ), + child: TextFormField( + decoration: InputDecoration( + suffixIcon: _invalidUsername == true ? Text("! ", + style: TextStyle( + color: Colors.red, + fontSize: (MediaQuery.of(context).size.height)*(20/926), + fontFamily: 'Brandon-med', + ),) : Text(""), + suffixIconConstraints: BoxConstraints(minWidth: 0, minHeight: 0), + hintText: _dataPreviouslyStored == null ? "Loading..." : (_dataPreviouslyStored ? _email : "Username"), + hintStyle: TextStyle(color: _dataPreviouslyStored ? Color(0xff171616) : Color(0xffAEAEAE), + fontSize: (MediaQuery.of(context).size.height)*(20/926), + fontFamily: 'Brandon-med',), + contentPadding: EdgeInsets.fromLTRB(20.0, (MediaQuery.of(context).size.height)*0.0037797, 20.0, (MediaQuery.of(context).size.height)*0.0037797), + enabledBorder: OutlineInputBorder( + borderSide: BorderSide( + color: Colors.transparent, + width: 0.0, + ), + borderRadius: BorderRadius.circular(10.0), + ), + focusedBorder: OutlineInputBorder( + borderSide: BorderSide( + color: Colors.transparent, + width: 0.0, + ), + ), + ), + //validator: (val) => val!.isEmpty ? "Please enter a Username." : null, + onChanged: (val) { + _dataPreviouslyStored == null ? val = "" : + (_dataPreviouslyStored ? val = _email : _email = val); + //_email = val; + }, + style: TextStyle( + color: Colors.black, + fontSize: (MediaQuery.of(context).size.height)*(20/926), + fontFamily: 'Brandon-med', + ), + ), + ), + SizedBox(height: (MediaQuery.of(context).size.height)*0.0226781,), + Container( + //color: Colors.white, + height: (MediaQuery.of(context).size.height)*0.055, + margin: EdgeInsets.only(top: 0, bottom: 0, left: (MediaQuery.of(context).size.width) *(45/428), right: (MediaQuery.of(context).size.width) *(45/428),), + decoration: BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.all(Radius.circular(10)), + border: Border.all( + color: _invalidPassword == true ? Colors.red : Color(0xff757575), + width: _invalidPassword == true ? 3 : 1, + ), + boxShadow: [ + BoxShadow( + color: Color(0xff0000004D), + ), + ], + ), + child: TextFormField( + obscureText: true, + decoration: InputDecoration( + suffixIcon: _invalidPassword == true ? Text("! ", + style: TextStyle( + color: Colors.red, + fontSize: (MediaQuery.of(context).size.height)*(20/926), + fontFamily: 'Brandon-med', + ),) : Text(""), + suffixIconConstraints: BoxConstraints(minWidth: 0, minHeight: 0), + hintText: _dataPreviouslyStored == null ? "Loading..." : (_dataPreviouslyStored ? _password : "Password"), + hintStyle: TextStyle(color: _dataPreviouslyStored ? Colors.black : Color(0xffAEAEAE), + fontSize: (MediaQuery.of(context).size.height)*(20/926), + fontFamily: 'Brandon-med',), + contentPadding: EdgeInsets.fromLTRB(20.0, (MediaQuery.of(context).size.height)*0.0037797, 20.0, (MediaQuery.of(context).size.height)*0.0037797), + enabledBorder: OutlineInputBorder( + borderSide: BorderSide( + color: Colors.transparent, + width: 0.0, + ), + borderRadius: BorderRadius.circular(10.0), + ), + focusedBorder: OutlineInputBorder( + borderSide: BorderSide( + color: Colors.transparent, + width: 0.0, + ), + ), + ), + //validator: (val) => val!.isEmpty ? "Please enter a Password." : null, + onChanged: (val) { + setState(() { + _dataPreviouslyStored == null ? val = "" : + (_dataPreviouslyStored ? val = _password : _password = val); + }); + }, + style: TextStyle( + color: Colors.black, + fontSize: (MediaQuery.of(context).size.height)*(20/926), + fontFamily: 'Brandon-med', + ), + ), + ), + SizedBox(height: (MediaQuery.of(context).size.height)*0.024838,), + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Container( + margin: EdgeInsets.only(top: 0, bottom: 0, left: (MediaQuery.of(context).size.width) *(45/428), right: 0,), + height: (MediaQuery.of(context).size.height)*0.0167, + width: (MediaQuery.of(context).size.height)*0.0167, + color: Colors.white, + child: Transform.scale( + scale: (MediaQuery.of(context).size.height)*0.001, + child: Checkbox( + side: BorderSide( + color: Color(0xffB0A6C2), + width: 0, + ), + checkColor: Colors.white, + value: _isChecked, + onChanged: (bool? value) { + setState(() { + _isChecked = value!; + }); + }, + ), + ), + ), + Container( + padding: EdgeInsets.only(top: 0, bottom: 0, left: (MediaQuery.of(context).size.width) *(5/428), right: 0,), + child: Text("Remember me!", + style: TextStyle( + color: Color.fromRGBO(255, 255, 255, 100), + fontFamily: 'Brandon-med', + fontSize: (MediaQuery.of(context).size.height)*0.0161987, + ),), + ), + ], + ), + Container( + padding: EdgeInsets.only(top: 0, bottom: 0, left: 0, right: (MediaQuery.of(context).size.width) *(45/428),), + child: Text("Forgot Password?", + style: TextStyle( + color: Color(0xffFFFEFE), + fontFamily: 'Brandon-med', + fontSize: (MediaQuery.of(context).size.height)*0.0161987, + ),), + ), + ], + ), + SizedBox(height: (MediaQuery.of(context).size.height) *0.0864,), + ], + ), + ), + SizedBox(height: (MediaQuery.of(context).size.height) *(25/926),), + ], + ), + GestureDetector( + child: Container(//Login button + child: Align( + alignment: Alignment.center, + child: SvgPicture.asset( + "assets/Images/login.svg", + height: (MediaQuery.of(context).size.height) *0.0486, + ), + ), + ), + onTap: () { + if(_formKey.currentState!.validate()) { + //_navigateAndDisplaySelection(context); + //print(_isChecked); + getUserData(context, _email, _password); + } + }, + ), + ], + ), + ), + ), + ), + AnimatedCrossFade( + crossFadeState: _loaded ? CrossFadeState.showFirst : CrossFadeState.showSecond, + duration: _duration, + secondChild: Container( + height: (MediaQuery.of(context).size.height) *0.183, + child: Text("")), + firstChild: Row( + mainAxisAlignment: MainAxisAlignment.end, + //crossAxisAlignment: CrossAxisAlignment.end, + children: [ + Stack( + //alignment: Alignment.centerRight, + children: [ + Positioned( + left: (MediaQuery.of(context).size.height) *(80/926), + top: (MediaQuery.of(context).size.height) *(50/926), + child: Align( + alignment: Alignment.bottomRight, + child: SvgPicture.asset( + "assets/Images/login_bottomRight.svg", + height: (MediaQuery.of(context).size.height) *0.183, + width: (MediaQuery.of(context).size.height) *0.183, + ), + ), + ), + Positioned(//Remove and add again + child: Align( + alignment: Alignment.bottomRight, + child: SvgPicture.asset( + "assets/Images/login_bottomRight.svg", + height: (MediaQuery.of(context).size.height) *0.183, + width: (MediaQuery.of(context).size.height) *0.183, + color: Colors.transparent, + ), + ), + ), + ], + ), + ], + ), + ), + ], + ), + ), + ), + ), + ); + } +} diff --git a/lib/screens/Welcome/GenerateQuiz/difficulty.dart b/lib/screens/Welcome/GenerateQuiz/difficulty.dart index 0a42723..cc6ca55 100644 --- a/lib/screens/Welcome/GenerateQuiz/difficulty.dart +++ b/lib/screens/Welcome/GenerateQuiz/difficulty.dart @@ -1,281 +1,281 @@ -import 'package:flutter/material.dart'; -import 'package:flutter_svg/flutter_svg.dart'; -import 'package:testify/screens/Authentication/login.dart'; -import 'package:testify/screens/Welcome/GenerateQuiz/generate_quiz_last.dart'; -import 'package:testify/screens/Welcome/GenerateQuiz/question_types.dart'; -import 'package:testify/screens/Welcome/side_menu_bar.dart'; - -class Difficulty extends StatefulWidget { - @override - State createState() => _DifficultyState(); -} - -class _DifficultyState extends State { - //Fields - - @override - Widget build(BuildContext context) { - return Scaffold( - backgroundColor: Color(0xffF8F9FB), - drawer: SideMenuBar(), - appBar: AppBar( - backgroundColor: Color(0xff3F2668), - elevation: 2, - centerTitle: true, - flexibleSpace: Container( - decoration: BoxDecoration( - gradient: LinearGradient( - begin: Alignment.topCenter, - end: Alignment.bottomCenter, - colors: [ - Color(0xff7F1AF1), - Color(0xff482384) - ]) - ), - ), - title: const Text("Generate Quiz", - style: TextStyle( - color: Color(0xffFFFEFE), - fontFamily: 'Brandon-bld', - ), - ), - actions: [ - TextButton( - onPressed: () async { - final result = await Navigator.push( - context, - MaterialPageRoute(builder: (context) => const Login(fromWhere:"Home")), - ); - }, - child: const Icon( - Icons.logout, - color: Colors.white, - ), - ), - ], - ), - body: Container( - padding: EdgeInsets.only(top:(MediaQuery.of(context).size.height) *(15/926), - bottom: (MediaQuery.of(context).size.height) *(8/926), - left: (MediaQuery.of(context).size.width) *(18/428), - right: (MediaQuery.of(context).size.width) *(18/428)), - child: Column( - children: [ - Row( - children: [ - Container( - width: (MediaQuery.of(context).size.width) *(221/428), - //height: (MediaQuery.of(context).size.height) *(91/926), - child: Column( - children: [ - Align( - alignment: Alignment.topLeft, - child: Text("Create Quiz", - style: TextStyle( - color: Color(0xff232323), - fontFamily: 'Brandon-bld', - fontSize: (MediaQuery.of(context).size.height) *(20/926),//38, - ),), - ), - SizedBox(height: (MediaQuery.of(context).size.height) *(2/926),), - Text("Lorem ipsum dolor sit amet, consectetur adipiscing elit. Cras imperdiet finibus elit non luctus. Morbi auctor mattis ante.", - style: TextStyle( - color: Color(0xFF483A3A), - fontFamily: 'Brandon-med', - fontSize: (MediaQuery.of(context).size.height) *(10/926),//38, - ),), - ], - ), - ), - SizedBox(width: (MediaQuery.of(context).size.width) *(39/428),), - Container( - //color: Colors.transparent, - child: SvgPicture.asset( - "assets/Images/create_quiz.svg", - height: (MediaQuery.of(context).size.height) *(100/926), - //width: (MediaQuery.of(context).size.width) *(132/428), - ), - ), - ], - ), - SizedBox(height: (MediaQuery.of(context).size.height) *(25/926),), - //a - Container( - height: (MediaQuery.of(context).size.height) *(35.32/926), - decoration: BoxDecoration( - color: Color(0xff3F2668),//0xffB0A6C2, rgba(176, 166, 194, 1) - borderRadius: BorderRadius.only(topLeft: Radius.circular(50), topRight: Radius.circular(50)), - boxShadow: [ - BoxShadow( - color: Colors.black12,//Color(0xff00000029), - spreadRadius: 5, - blurRadius: 5, - offset: Offset(0, 0), - ), - ], - ), - child: Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - SizedBox(width: (MediaQuery.of(context).size.width) *(28/428),), - Container( - padding: EdgeInsets.only(top: (MediaQuery.of(context).size.height) *(9/926), bottom: (MediaQuery.of(context).size.height) *(4/926)), - height: (MediaQuery.of(context).size.height) *(35.32/926), - width: (MediaQuery.of(context).size.width) *(113/428), - color: Color(0xFF3F2668), - child: Column( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Text(" Systems/Subjects/Topics ", - style: TextStyle( - color: Color(0xffFEFEFE), - fontFamily: 'Brandon-bld', - fontSize: (MediaQuery.of(context).size.height) *(12/926), - ),), - ], - ), - ), - Container( - padding: EdgeInsets.only(top: (MediaQuery.of(context).size.height) *(5/926), bottom: (MediaQuery.of(context).size.height) *(5/926)), - height: (MediaQuery.of(context).size.height) *(35.32/926), - width: (MediaQuery.of(context).size.width) *(80/428), - color: Color(0xFF3F2668), - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Text("Question Types", - style: TextStyle( - color: Color(0xffFEFEFE), - fontFamily: 'Brandon-bld', - fontSize: (MediaQuery.of(context).size.height) *(12/926), - ),), - ], - ), - ), - Container( - padding: EdgeInsets.only(top: (MediaQuery.of(context).size.height) *(5/926), bottom: (MediaQuery.of(context).size.height) *(5/926)), - height: (MediaQuery.of(context).size.height) *(35.32/926), - width: (MediaQuery.of(context).size.width) *(65/428), - color: Colors.white, - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Text("Difficulty", - style: TextStyle( - color: Color(0xFF3F2668),//0xFF3F2668 - fontFamily: 'Brandon-bld', - fontSize: (MediaQuery.of(context).size.height) *(12/926), - ),), - Container( - padding: EdgeInsets.only(left: (MediaQuery.of(context).size.width) *(13/428), right: (MediaQuery.of(context).size.width) *(13/428)), - //margin: EdgeInsets.only(top: (MediaQuery.of(context).size.height) *(1/926)), - child: Divider(height: 3, - thickness: 2, - color: Color(0xFF3F2668),), - ), - ], - ), - ), - Container( - padding: EdgeInsets.only(top: (MediaQuery.of(context).size.height) *(5/926), bottom: (MediaQuery.of(context).size.height) *(5/926)), - height: (MediaQuery.of(context).size.height) *(35.32/926), - width: (MediaQuery.of(context).size.width) *(75/428), - color: Color(0xFF3F2668), - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Text("Generate Quiz", - style: TextStyle( - color: Color(0xffFEFEFE), - fontFamily: 'Brandon-bld', - fontSize: (MediaQuery.of(context).size.height) *(12/926), - ),), - ], - ), - ), - SizedBox(width: (MediaQuery.of(context).size.width) *(28/428),), - ], - ), - ), - SizedBox(height: (MediaQuery.of(context).size.height) *(15.28/926),), - Container( - height: (MediaQuery.of(context).size.height) *(167.52/926), - color: Colors.red, - ), - SizedBox(height: (MediaQuery.of(context).size.height) *(10.74/926),), - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - InkWell( - child: Container( - height: (MediaQuery.of(context).size.height) *(42/926), - width: (MediaQuery.of(context).size.width) *(68/428), - decoration: BoxDecoration( - color: Color(0xff3F2668),//0xffB0A6C2, rgba(176, 166, 194, 1) - borderRadius: BorderRadius.all(Radius.circular(3)), - boxShadow: [ - BoxShadow( - color: Colors.black12,//Color(0xff00000029), - spreadRadius: 2, - blurRadius: 2, - offset: Offset(0, 0), - ), - ], - ), - child: TextButton( - onPressed: () { - Navigator.pop(context); - }, - child: Center( - child: Text("Back", - style: TextStyle( - color: Colors.white, - fontFamily: 'Brandon-med', - ), - ), - ), - ), - ), - ), - InkWell( - child: Container( - height: (MediaQuery.of(context).size.height) *(42/926), - width: (MediaQuery.of(context).size.width) *(68/428), - decoration: BoxDecoration( - color: Color(0xff3F2668),//0xffB0A6C2, rgba(176, 166, 194, 1) - borderRadius: BorderRadius.all(Radius.circular(3)), - boxShadow: [ - BoxShadow( - color: Colors.black12,//Color(0xff00000029), - spreadRadius: 2, - blurRadius: 2, - offset: Offset(0, 0), - ), - ], - ), - child: TextButton( - onPressed: () async { - final result = await Navigator.push( - context, - MaterialPageRoute(builder: (context) => GenerateQuizLast()), - ); - }, - child: Center( - child: Text("Next", - style: TextStyle( - color: Colors.white, - fontFamily: 'Brandon-med', - ), - ), - ), - ), - ), - ), - ], - ), - ], - ), - ), - ); - } +import 'package:flutter/material.dart'; +import 'package:flutter_svg/flutter_svg.dart'; +import 'package:testify/screens/Authentication/login.dart'; +import 'package:testify/screens/Welcome/GenerateQuiz/generate_quiz_last.dart'; +import 'package:testify/screens/Welcome/GenerateQuiz/question_types.dart'; +import 'package:testify/screens/Welcome/side_menu_bar.dart'; + +class Difficulty extends StatefulWidget { + @override + State createState() => _DifficultyState(); +} + +class _DifficultyState extends State { + //Fields + + @override + Widget build(BuildContext context) { + return Scaffold( + backgroundColor: Color(0xffF8F9FB), + drawer: SideMenuBar(), + appBar: AppBar( + backgroundColor: Color(0xff3F2668), + elevation: 2, + centerTitle: true, + flexibleSpace: Container( + decoration: BoxDecoration( + gradient: LinearGradient( + begin: Alignment.topCenter, + end: Alignment.bottomCenter, + colors: [ + Color(0xff7F1AF1), + Color(0xff482384) + ]) + ), + ), + title: const Text("Generate Quiz", + style: TextStyle( + color: Color(0xffFFFEFE), + fontFamily: 'Brandon-bld', + ), + ), + actions: [ + TextButton( + onPressed: () async { + final result = await Navigator.push( + context, + MaterialPageRoute(builder: (context) => const Login(fromWhere:"Home")), + ); + }, + child: const Icon( + Icons.logout, + color: Colors.white, + ), + ), + ], + ), + body: Container( + padding: EdgeInsets.only(top:(MediaQuery.of(context).size.height) *(15/926), + bottom: (MediaQuery.of(context).size.height) *(8/926), + left: (MediaQuery.of(context).size.width) *(18/428), + right: (MediaQuery.of(context).size.width) *(18/428)), + child: Column( + children: [ + Row( + children: [ + Container( + width: (MediaQuery.of(context).size.width) *(221/428), + //height: (MediaQuery.of(context).size.height) *(91/926), + child: Column( + children: [ + Align( + alignment: Alignment.topLeft, + child: Text("Create Quiz", + style: TextStyle( + color: Color(0xff232323), + fontFamily: 'Brandon-bld', + fontSize: (MediaQuery.of(context).size.height) *(20/926),//38, + ),), + ), + SizedBox(height: (MediaQuery.of(context).size.height) *(2/926),), + Text("Lorem ipsum dolor sit amet, consectetur adipiscing elit. Cras imperdiet finibus elit non luctus. Morbi auctor mattis ante.", + style: TextStyle( + color: Color(0xFF483A3A), + fontFamily: 'Brandon-med', + fontSize: (MediaQuery.of(context).size.height) *(10/926),//38, + ),), + ], + ), + ), + SizedBox(width: (MediaQuery.of(context).size.width) *(39/428),), + Container( + //color: Colors.transparent, + child: SvgPicture.asset( + "assets/Images/create_quiz.svg", + height: (MediaQuery.of(context).size.height) *(100/926), + //width: (MediaQuery.of(context).size.width) *(132/428), + ), + ), + ], + ), + SizedBox(height: (MediaQuery.of(context).size.height) *(25/926),), + //a + Container( + height: (MediaQuery.of(context).size.height) *(35.32/926), + decoration: BoxDecoration( + color: Color(0xff3F2668),//0xffB0A6C2, rgba(176, 166, 194, 1) + borderRadius: BorderRadius.only(topLeft: Radius.circular(50), topRight: Radius.circular(50)), + boxShadow: [ + BoxShadow( + color: Colors.black12,//Color(0xff00000029), + spreadRadius: 5, + blurRadius: 5, + offset: Offset(0, 0), + ), + ], + ), + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + SizedBox(width: (MediaQuery.of(context).size.width) *(28/428),), + Container( + padding: EdgeInsets.only(top: (MediaQuery.of(context).size.height) *(9/926), bottom: (MediaQuery.of(context).size.height) *(4/926)), + height: (MediaQuery.of(context).size.height) *(35.32/926), + width: (MediaQuery.of(context).size.width) *(113/428), + color: Color(0xFF3F2668), + child: Column( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text(" Systems/Subjects/Topics ", + style: TextStyle( + color: Color(0xffFEFEFE), + fontFamily: 'Brandon-bld', + fontSize: (MediaQuery.of(context).size.height) *(12/926), + ),), + ], + ), + ), + Container( + padding: EdgeInsets.only(top: (MediaQuery.of(context).size.height) *(5/926), bottom: (MediaQuery.of(context).size.height) *(5/926)), + height: (MediaQuery.of(context).size.height) *(35.32/926), + width: (MediaQuery.of(context).size.width) *(80/428), + color: Color(0xFF3F2668), + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Text("Question Types", + style: TextStyle( + color: Color(0xffFEFEFE), + fontFamily: 'Brandon-bld', + fontSize: (MediaQuery.of(context).size.height) *(12/926), + ),), + ], + ), + ), + Container( + padding: EdgeInsets.only(top: (MediaQuery.of(context).size.height) *(5/926), bottom: (MediaQuery.of(context).size.height) *(5/926)), + height: (MediaQuery.of(context).size.height) *(35.32/926), + width: (MediaQuery.of(context).size.width) *(65/428), + color: Colors.white, + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Text("Difficulty", + style: TextStyle( + color: Color(0xFF3F2668),//0xFF3F2668 + fontFamily: 'Brandon-bld', + fontSize: (MediaQuery.of(context).size.height) *(12/926), + ),), + Container( + padding: EdgeInsets.only(left: (MediaQuery.of(context).size.width) *(13/428), right: (MediaQuery.of(context).size.width) *(13/428)), + //margin: EdgeInsets.only(top: (MediaQuery.of(context).size.height) *(1/926)), + child: Divider(height: 3, + thickness: 2, + color: Color(0xFF3F2668),), + ), + ], + ), + ), + Container( + padding: EdgeInsets.only(top: (MediaQuery.of(context).size.height) *(5/926), bottom: (MediaQuery.of(context).size.height) *(5/926)), + height: (MediaQuery.of(context).size.height) *(35.32/926), + width: (MediaQuery.of(context).size.width) *(75/428), + color: Color(0xFF3F2668), + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Text("Generate Quiz", + style: TextStyle( + color: Color(0xffFEFEFE), + fontFamily: 'Brandon-bld', + fontSize: (MediaQuery.of(context).size.height) *(12/926), + ),), + ], + ), + ), + SizedBox(width: (MediaQuery.of(context).size.width) *(28/428),), + ], + ), + ), + SizedBox(height: (MediaQuery.of(context).size.height) *(15.28/926),), + Container( + height: (MediaQuery.of(context).size.height) *(167.52/926), + color: Colors.red, + ), + SizedBox(height: (MediaQuery.of(context).size.height) *(10.74/926),), + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + InkWell( + child: Container( + height: (MediaQuery.of(context).size.height) *(42/926), + width: (MediaQuery.of(context).size.width) *(68/428), + decoration: BoxDecoration( + color: Color(0xff3F2668),//0xffB0A6C2, rgba(176, 166, 194, 1) + borderRadius: BorderRadius.all(Radius.circular(3)), + boxShadow: [ + BoxShadow( + color: Colors.black12,//Color(0xff00000029), + spreadRadius: 2, + blurRadius: 2, + offset: Offset(0, 0), + ), + ], + ), + child: TextButton( + onPressed: () { + Navigator.pop(context); + }, + child: Center( + child: Text("Back", + style: TextStyle( + color: Colors.white, + fontFamily: 'Brandon-med', + ), + ), + ), + ), + ), + ), + InkWell( + child: Container( + height: (MediaQuery.of(context).size.height) *(42/926), + width: (MediaQuery.of(context).size.width) *(68/428), + decoration: BoxDecoration( + color: Color(0xff3F2668),//0xffB0A6C2, rgba(176, 166, 194, 1) + borderRadius: BorderRadius.all(Radius.circular(3)), + boxShadow: [ + BoxShadow( + color: Colors.black12,//Color(0xff00000029), + spreadRadius: 2, + blurRadius: 2, + offset: Offset(0, 0), + ), + ], + ), + child: TextButton( + onPressed: () async { + final result = await Navigator.push( + context, + MaterialPageRoute(builder: (context) => GenerateQuizLast()), + ); + }, + child: Center( + child: Text("Next", + style: TextStyle( + color: Colors.white, + fontFamily: 'Brandon-med', + ), + ), + ), + ), + ), + ), + ], + ), + ], + ), + ), + ); + } } \ No newline at end of file diff --git a/lib/screens/Welcome/GenerateQuiz/generate_quiz.dart b/lib/screens/Welcome/GenerateQuiz/generate_quiz.dart index cd4d420..fc730dc 100644 --- a/lib/screens/Welcome/GenerateQuiz/generate_quiz.dart +++ b/lib/screens/Welcome/GenerateQuiz/generate_quiz.dart @@ -1,259 +1,1634 @@ -import 'package:flutter/material.dart'; -import 'package:flutter_svg/flutter_svg.dart'; -import 'package:testify/screens/Authentication/login.dart'; -import 'package:testify/screens/Welcome/GenerateQuiz/question_types.dart'; -import 'package:testify/screens/Welcome/side_menu_bar.dart'; - -class GenerateQuiz extends StatefulWidget { - @override - State createState() => _GenerateQuizState(); -} - -class _GenerateQuizState extends State { - // This is the first Page - - @override - Widget build(BuildContext context) { - return Scaffold( - backgroundColor: Color(0xffF8F9FB), - drawer: SideMenuBar(), - appBar: AppBar( - backgroundColor: Color(0xff3F2668), - elevation: 2, - centerTitle: true, - flexibleSpace: Container( - decoration: BoxDecoration( - gradient: LinearGradient( - begin: Alignment.topCenter, - end: Alignment.bottomCenter, - colors: [ - Color(0xff7F1AF1), - Color(0xff482384) - ]) - ), - ), - title: const Text("Generate Quiz", - style: TextStyle( - color: Color(0xffFFFEFE), - fontFamily: 'Brandon-bld', - ), - ), - actions: [ - TextButton( - onPressed: () async { - final result = await Navigator.push( - context, - MaterialPageRoute(builder: (context) => const Login(fromWhere:"Home")), - ); - }, - child: const Icon( - Icons.logout, - color: Colors.white, - ), - ), - ], - ), - body: Container( - padding: EdgeInsets.only(top:(MediaQuery.of(context).size.height) *(15/926), - bottom: (MediaQuery.of(context).size.height) *(8/926), - left: (MediaQuery.of(context).size.width) *(18/428), - right: (MediaQuery.of(context).size.width) *(18/428)), - child: Column( - children: [ - Row( - children: [ - Container( - width: (MediaQuery.of(context).size.width) *(221/428), - //height: (MediaQuery.of(context).size.height) *(91/926), - child: Column( - children: [ - Align( - alignment: Alignment.topLeft, - child: Text("Create Quiz", - style: TextStyle( - color: Color(0xff232323), - fontFamily: 'Brandon-bld', - fontSize: (MediaQuery.of(context).size.height) *(20/926),//38, - ),), - ), - SizedBox(height: (MediaQuery.of(context).size.height) *(2/926),), - Text("Lorem ipsum dolor sit amet, consectetur adipiscing elit. Cras imperdiet finibus elit non luctus. Morbi auctor mattis ante.", - style: TextStyle( - color: Color(0xFF483A3A), - fontFamily: 'Brandon-med', - fontSize: (MediaQuery.of(context).size.height) *(10/926),//38, - ),), - ], - ), - ), - SizedBox(width: (MediaQuery.of(context).size.width) *(39/428),), - Container( - //color: Colors.transparent, - child: SvgPicture.asset( - "assets/Images/create_quiz.svg", - height: (MediaQuery.of(context).size.height) *(100/926), - //width: (MediaQuery.of(context).size.width) *(132/428), - ), - ), - ], - ), - SizedBox(height: (MediaQuery.of(context).size.height) *(25/926),), - //a - Container( - height: (MediaQuery.of(context).size.height) *(35.32/926), - decoration: BoxDecoration( - color: Color(0xff3F2668),//0xffB0A6C2, rgba(176, 166, 194, 1) - borderRadius: BorderRadius.only(topLeft: Radius.circular(50), topRight: Radius.circular(50)), - boxShadow: [ - BoxShadow( - color: Colors.black12,//Color(0xff00000029), - spreadRadius: 5, - blurRadius: 5, - offset: Offset(0, 0), - ), - ], - ), - child: Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - SizedBox(width: (MediaQuery.of(context).size.width) *(28/428),), - Container( - padding: EdgeInsets.only(top: (MediaQuery.of(context).size.height) *(9/926), bottom: (MediaQuery.of(context).size.height) *(4/926)), - height: (MediaQuery.of(context).size.height) *(35.32/926), - width: (MediaQuery.of(context).size.width) *(113/428), - color: Colors.white, - child: Column( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Text(" Systems/Subjects/Topics ", - style: TextStyle( - color: Color(0xFF3F2668), - fontFamily: 'Brandon-bld', - fontSize: (MediaQuery.of(context).size.height) *(12/926), - ),), - Container( - padding: EdgeInsets.only(left: (MediaQuery.of(context).size.width) *(17/428), right: (MediaQuery.of(context).size.width) *(17/428)), - //margin: EdgeInsets.only(top: (MediaQuery.of(context).size.height) *(1/926)), - child: Divider(height: 3, - thickness: 2, - color: Color(0xFF3F2668),), - ), - ], - ), - ), - Container( - padding: EdgeInsets.only(top: (MediaQuery.of(context).size.height) *(5/926), bottom: (MediaQuery.of(context).size.height) *(5/926)), - height: (MediaQuery.of(context).size.height) *(35.32/926), - width: (MediaQuery.of(context).size.width) *(80/428), - color: Color(0xFF3F2668), - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Text("Question Types", - style: TextStyle( - color: Color(0xffFEFEFE), - fontFamily: 'Brandon-bld', - fontSize: (MediaQuery.of(context).size.height) *(12/926), - ),), - ], - ), - ), - Container( - padding: EdgeInsets.only(top: (MediaQuery.of(context).size.height) *(5/926), bottom: (MediaQuery.of(context).size.height) *(5/926)), - height: (MediaQuery.of(context).size.height) *(35.32/926), - width: (MediaQuery.of(context).size.width) *(65/428), - color: Color(0xFF3F2668), - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Text("Difficulty", - style: TextStyle( - color: Color(0xffFEFEFE), - fontFamily: 'Brandon-bld', - fontSize: (MediaQuery.of(context).size.height) *(12/926), - ),), - ], - ), - ), - Container( - padding: EdgeInsets.only(top: (MediaQuery.of(context).size.height) *(5/926), bottom: (MediaQuery.of(context).size.height) *(5/926)), - height: (MediaQuery.of(context).size.height) *(35.32/926), - width: (MediaQuery.of(context).size.width) *(75/428), - color: Color(0xFF3F2668), - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Text("Generate Quiz", - style: TextStyle( - color: Color(0xffFEFEFE), - fontFamily: 'Brandon-bld', - fontSize: (MediaQuery.of(context).size.height) *(12/926), - ),), - ], - ), - ), - SizedBox(width: (MediaQuery.of(context).size.width) *(28/428),), - ], - ), - ), - SizedBox(height: (MediaQuery.of(context).size.height) *(15.28/926),), - Container( - height: (MediaQuery.of(context).size.height) *(167.52/926), - color: Colors.red, - ), - SizedBox(height: (MediaQuery.of(context).size.height) *(17.9/926),), - Container( - height: (MediaQuery.of(context).size.height) *(167.52/926), - color: Colors.red, - ), - SizedBox(height: (MediaQuery.of(context).size.height) *(17.9/926),), - Container( - height: (MediaQuery.of(context).size.height) *(167.52/926), - color: Colors.red, - ), - SizedBox(height: (MediaQuery.of(context).size.height) *(10.74/926),), - Row( - mainAxisAlignment: MainAxisAlignment.end, - children: [ - InkWell( - child: Container( - height: (MediaQuery.of(context).size.height) *(42/926), - width: (MediaQuery.of(context).size.width) *(68/428), - decoration: BoxDecoration( - color: Color(0xff3F2668),//0xffB0A6C2, rgba(176, 166, 194, 1) - borderRadius: BorderRadius.all(Radius.circular(3)), - boxShadow: [ - BoxShadow( - color: Colors.black12,//Color(0xff00000029), - spreadRadius: 2, - blurRadius: 2, - offset: Offset(0, 0), - ), - ], - ), - child: TextButton( - onPressed: () async { - final result = await Navigator.push( - context, - MaterialPageRoute(builder: (context) => QuestionTypes()), - ); - }, - child: Center( - child: Text("Next", - style: TextStyle( - color: Colors.white, - fontFamily: 'Brandon-med', - ), - ), - ), - ), - ), - ), - ], - ), - ], - ), - ), - ); - } +import 'dart:convert'; +import 'package:flutter/services.dart'; + +import 'package:flutter/cupertino.dart'; +import 'package:http/http.dart' as http; + +import 'package:flutter/material.dart'; +import 'package:flutter_svg/flutter_svg.dart'; +import 'package:shared_preferences/shared_preferences.dart'; +import 'package:testify/models/GenerateQuizModels/get_system_categories_successful.dart'; +import 'package:testify/models/GenerateQuizModels/get_system_categories_unsuccessful.dart'; +import 'package:testify/screens/Authentication/login.dart'; +import 'package:testify/screens/Welcome/QuizModule/quiz_module.dart'; +import 'package:testify/screens/Welcome/side_menu_bar.dart'; +import 'dart:math' as math; + +class GenerateQuiz extends StatefulWidget { + @override + State createState() => _GenerateQuizState(); +} + +class _GenerateQuizState extends State with SingleTickerProviderStateMixin { + late TabController _tabController; + + // Once the data is loaded only then it shows the containers. + bool _hasDataLoaded = false; + + //Total Questions returned by the API. + // First gets its value when getUserData is run and then gets updated as getQuestionCounts is run. + int _totalQuestions = 0; + List _questions = []; + + //Tab 1 Data: + //Not allowing Subjects or topics to be selected if Systems is empty + bool _systemsDisabled = true; + bool _topicsDisabled = true; + //Title, ID, questions(total questions available), isSelected(which checkbox is clicked), finalTitles(titles that work on getQuestionsCount). + var systemsEverything = { + "title": [], // Saves titles + "finalTitles": [], // Save the final titles that are to be sent to getQuestionsCount + "ID": [], // Saves IDs + "questions": [], // Saves questions + "isSelected": [] // Whichever checkbox is true that bool turns true. + }; + + // Tab 2 Data: + var subjectsEverything = { + "title": [], + "finalTitles": [], // Save the final titles that are to be sent to getQuestionsCount + "ID": [], + "questions": [], + "isSelected": [] + }; + + // Tab 3 Data: + var topicsEverything = { + "title": [], + "finalTitles": [], // Save the final titles that are to be sent to getQuestionsCount + "ID": [], + "questions": [], + "isSelected": [] + }; + + //Tab 4 Data: + //If no option is selected everything stays false and zero is sent. + /*None is not populated*/ + List _questionTypesTitle = ["None", "Unused Questions", "Incorrect Questions", "Correct Questions", "Omitted Questions", "Marked Questions", "All"]; + List _questionTypeSelectedBool = [true, false, false, false, false, false, false]; + int _questionTypeInt = 0; + + //Tab 5 Data: + List _difficultyLevelTitle = ["Very Easy", "Easy", "Medium", "Hard", "Very Hard"]; + List _difficultyLevelBool = [false, false, false, false, false]; + List _difficultyLevel = []; + //Generate Quiz + bool _tutorMode = true; + bool _timedMode = false; + // Just a form key for the questionCount + final _numberOfQuestionsKey = GlobalKey(); + var _questionsCount; + + //Shared Pref + var _token; + var _userId; + + // Token Valid + var _getSystemCategoriesSuccessful; + // Token Incorrect + var _getSystemCategoriesUnsuccessful; + + //When getQuestionCount is run(Just used to get the totalQuestions + var _getQuestionsCountCategoriesSuccessful; + var _getQuestionsCountCategoriesUnsuccessful; + + @override + void initState() { + super.initState(); + _tabController = TabController(vsync: this, length: 5); + getUserDataSST(); + } + + //This is run only once. + Future getUserDataSST() async { + SharedPreferences prefs = await SharedPreferences.getInstance(); + final String apiUrlSystemCategories = "https://demo.pookidevs.com/quiz/generator/getAllCategories"; + _token = prefs.getString('token')!; + _userId = prefs.getInt("userId")!; + http.get(Uri.parse(apiUrlSystemCategories), headers: { + 'Content-type': 'application/json; charset=UTF-8', 'Authorization' : _token.toString(), + },).then((response) { + // print(jsonDecode(response.body).toString()); + if(response.statusCode == 200) { + if(json.decode(response.body).toString().substring(0,20) == "{data: {status: true") { + final responseString = (response.body); + var systemCategoriesDataSuccessful = getSystemCategoriesSuccessfulModelFromJson(responseString); + final GetSystemCategoriesSuccessfulModel getSystemCategoriesSuccessful = systemCategoriesDataSuccessful; + setState(() { + _getSystemCategoriesSuccessful = getSystemCategoriesSuccessful; + _hasDataLoaded = true; + _totalQuestions = _getSystemCategoriesSuccessful.data.totalQuestions; + _questions = _getSystemCategoriesSuccessful.data.questions; + }); + // print(_questions); + } else { + + } + //Adds data to lists + categorizeUserData(); + } + else { // Status Code is 401 here that is why if written in the above if statement it would not work. + //Token is Invalid + if(json.decode(response.body).toString().substring(0,14) == "{status: false") { + final responseString = (response.body); + var systemCategoriesDataUnsuccessful = getSystemCategoriesUnsuccessfulModelFromJson(responseString); + final GetSystemCategoriesUnsuccessfulModel getSystemCategoriesUnsuccessful = systemCategoriesDataUnsuccessful; + setState(() { + _getSystemCategoriesUnsuccessful = getSystemCategoriesUnsuccessful; + }); + print(_getSystemCategoriesUnsuccessful.msg); + ScaffoldMessenger.of(context) + ..removeCurrentSnackBar() + ..showSnackBar(SnackBar(content: Text("Token Expired!"))); + final result = Navigator.push( + context, + MaterialPageRoute(builder: (context) => const Login(fromWhere:"Home")), + ); + } + else { + + } + } + } + ); + } + + Future getQuestionsCount() async { + // print(subjectsEverything["finalTitles"]); + // print(systemsEverything["finalTitles"]); + // print(topicsEverything["finalTitles"]); + // print(_userId); + // print(_questionTypeInt); + // print(_difficultyLevel); + + final String apiUrl = "https://demo.pookidevs.com/quiz/generator/getQuestionCounts"; + http.post(Uri.parse(apiUrl), headers: { + 'Content-type': 'application/json; charset=UTF-8', 'Authorization' : _token.toString(), + }, body: json.encode( + { + "data": + { + "subjects": subjectsEverything["finalTitles"], + "systems": systemsEverything["finalTitles"], + "topics": topicsEverything["finalTitles"], + "userId": _userId, // Add _userId here. + "statusLevels": _questionTypeInt, // Add _questionType here + "difficultyLevels": _difficultyLevel, // Add _difficultyLevels here + } + }) + ).then((response) { + if(response.statusCode == 200) { + // print("getQuestionsCount() : " + response.body.toString()); + if(json.decode(response.body).toString().substring(0,20) == "{data: {status: true") { + final responseString = (response.body); + var QuestionsCountCategoriesSuccessful = getSystemCategoriesSuccessfulModelFromJson(responseString); + final GetSystemCategoriesSuccessfulModel getQuestionsCountCategoriesSuccessful = QuestionsCountCategoriesSuccessful; + setState(() { + _getQuestionsCountCategoriesSuccessful = getQuestionsCountCategoriesSuccessful; + _totalQuestions = _getQuestionsCountCategoriesSuccessful.data.totalQuestions; + _questions = _getQuestionsCountCategoriesSuccessful.data.questions; + }); + // print(_getSystemCategoriesSuccessful); + print(_totalQuestions); + print(_questions); + } else { + + } + } else { + //Token is Invalid + if(json.decode(response.body).toString().substring(0,14) == "{status: false") { + final responseString = (response.body); + var QuestionsCountCategoriesDataUnsuccessful = getSystemCategoriesUnsuccessfulModelFromJson(responseString); + final GetSystemCategoriesUnsuccessfulModel getQuestionsCountCategoriesUnsuccessful = QuestionsCountCategoriesDataUnsuccessful; + setState(() { + _getQuestionsCountCategoriesUnsuccessful = getQuestionsCountCategoriesUnsuccessful; + }); + print(_getQuestionsCountCategoriesUnsuccessful.msg); + ScaffoldMessenger.of(context) + ..removeCurrentSnackBar() + ..showSnackBar(SnackBar(content: Text("Token Expired!"))); + final result = Navigator.push( + context, + MaterialPageRoute(builder: (context) => const Login(fromWhere:"Home")), + ); + } + else { + + } + } + }); + + } + + //Add data to lists. Only done the first time. + categorizeUserData() { + //To clear any past data + int c = 0; + while((c<_getSystemCategoriesSuccessful.data.categories.toList().length) & (_getSystemCategoriesSuccessful.data.categories.toList().length > 0)) { + var tempLength = _getSystemCategoriesSuccessful.data.categories.toList().length; + if(_getSystemCategoriesSuccessful.data.categories[c].subCategories != null) { + if(_getSystemCategoriesSuccessful.data.categories[c].parentCategory.toString() == "systems") { + //Gets the length of subjects(Number of Subjects) + var lenSystems = _getSystemCategoriesSuccessful.data.categories[c].subCategories.toList().length; + int i = 0; + setState(() { + while((lenSystems>0) & (i0) & (i0) & (i[ + Color(0xff7F1AF1), + Color(0xff482384) + ]) + ), + ), + title: const Text("Generate Quiz", + style: TextStyle( + color: Color(0xffFFFEFE), + fontFamily: 'Brandon-bld', + ), + ), + actions: [ + TextButton( + onPressed: () async { + final result = await Navigator.push( + context, + MaterialPageRoute(builder: (context) => const Login(fromWhere:"Home")), + ); + }, + child: SvgPicture.asset( + "assets/Images/logout.svg", + height: (MediaQuery.of(context).size.height) *(32/926), + ), + ), + ], + ), + body: SingleChildScrollView( + child: Container( + padding: EdgeInsets.only(top:(MediaQuery.of(context).size.height) *(15/926), + bottom: (MediaQuery.of(context).size.height) *(8/926), + left: (MediaQuery.of(context).size.width) *(18/428), + right: (MediaQuery.of(context).size.width) *(18/428)), + child: Column( + children: [ + Row( + children: [ + Container( + width: (MediaQuery.of(context).size.width) *(221/428), + //height: (MediaQuery.of(context).size.height) *(91/926), + child: Column( + children: [ + Align( + alignment: Alignment.topLeft, + child: Text("Create Quiz", + style: TextStyle( + color: Color(0xff232323), + fontFamily: 'Brandon-bld', + fontSize: (MediaQuery.of(context).size.height) *(25/926),//38, + ),), + ), + SizedBox(height: (MediaQuery.of(context).size.height) *(2/926),), + Text("Lorem ipsum dolor sit amet, consectetur adipiscing elit. Cras imperdiet finibus elit non luctus. Morbi auctor mattis ante.", + style: TextStyle( + color: Color(0xFF483A3A), + fontFamily: 'Brandon-med', + fontSize: (MediaQuery.of(context).size.height) *(13/926),//38, + ),), + ], + ), + ), + SizedBox(width: (MediaQuery.of(context).size.width) *(39/428),), + Container( + //color: Colors.transparent, + child: SvgPicture.asset( + "assets/Images/create_quiz.svg", + height: (MediaQuery.of(context).size.height) *(100/926), + //width: (MediaQuery.of(context).size.width) *(132/428), + ), + ), + ], + ), + SizedBox(height: (MediaQuery.of(context).size.height) *(25/926),), + Container( + // padding: EdgeInsets.only(left: (MediaQuery.of(context).size.width) *(28/428), right: (MediaQuery.of(context).size.width) *(28/428)), + height: (MediaQuery.of(context).size.height) *(35.32/926), + width: double.infinity, + // decoration: BoxDecoration( + // color: Color(0xff3F2668),//0xffB0A6C2, rgba(176, 166, 194, 1) + // ), + child: TabBar( + isScrollable: true, + controller: _tabController, + labelColor: Color(0xFF3F2668), + labelStyle: TextStyle( + color: Color(0xFF3F2668), + fontFamily: 'Brandon-bld', + fontSize: (MediaQuery.of(context).size.height) *(16/926), + ), + indicator: BoxDecoration( + color: Colors.transparent, + ), + indicatorColor: Color(0xFF3F2668), + unselectedLabelColor: Color(0xFFA1A1A1), + unselectedLabelStyle: TextStyle( + color: Color(0xFFA1A1A1), + fontFamily: 'Brandon-bld', + fontSize: (MediaQuery.of(context).size.height) *(16/926), + ), + labelPadding: EdgeInsets.only(top: (MediaQuery.of(context).size.height) *(0/926), bottom: (MediaQuery.of(context).size.height) *(0/926), + left: (MediaQuery.of(context).size.height) *(0/926), right: (MediaQuery.of(context).size.height) *(0/926)), + tabs: [ + Container( + width: (MediaQuery.of(context).size.width) *(5.5/43), + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Tab(text: "Subjects"), + ], + ), + ), + Container( + width: (MediaQuery.of(context).size.width) *(7.5/43), + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Container( + child: Icon(Icons.arrow_forward_ios, + size: (MediaQuery.of(context).size.width) *(15/428),),), + SizedBox(width: (MediaQuery.of(context).size.width) *(5/428)), + Tab(text: "Systems"), + ], + ) + ), + Container( + width: (MediaQuery.of(context).size.width) *(6.5/43), + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Container( + child: Icon(Icons.arrow_forward_ios, + size: (MediaQuery.of(context).size.width) *(15/428),),), + SizedBox(width: (MediaQuery.of(context).size.width) *(5/428)), + Tab(text: "Topics"), + ], + ) + ), + Container( + width: (MediaQuery.of(context).size.width) *(8.5/43), + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Container( + child: Icon(Icons.arrow_forward_ios, + size: (MediaQuery.of(context).size.width) *(15/428),),), + SizedBox(width: (MediaQuery.of(context).size.width) *(5/428)), + Tab(text: "Questions"), + ], + ) + ), + Container( + width: (MediaQuery.of(context).size.width) *(10.5/43), + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Container( + child: Icon(Icons.arrow_forward_ios, + size: (MediaQuery.of(context).size.width) *(15/428),),), + SizedBox(width: (MediaQuery.of(context).size.width) *(5/428)), + Tab(text: "Generate Quiz"), + ], + ) + ), + ], + ), + ), + SizedBox(height: (MediaQuery.of(context).size.height) *(13.28/926),), + Container( + height: (MediaQuery.of(context).size.height) *(596/926), + width: double.infinity, + child: TabBarView( + // physics: NeverScrollableScrollPhysics(), + controller: _tabController, + children: [ + //Tab1: Subjects + Column( + children: [ + Container( + height: (MediaQuery.of(context).size.height) *(40.32/926), + width: (MediaQuery.of(context).size.width) *(386/428), + decoration: BoxDecoration( + color: Color(0xFF3F2668), + borderRadius: BorderRadius.only(bottomLeft: Radius.circular(15.0), topRight: Radius.circular(15.0),), + boxShadow: [ + BoxShadow( + color: Colors.black12, + spreadRadius: 2, + blurRadius: 2, + offset: Offset(0, 0), + ), + ], + ), + child: Center( + child: Text("Select Subjects", + style: TextStyle( + color: Colors.white, + fontFamily: 'Brandon-bld', + fontSize: (MediaQuery.of(context).size.height) *(26.31/926),//38, + ),), + ), + ), + SizedBox(height: (MediaQuery.of(context).size.height) *(33/926)), + Container( + width: (MediaQuery.of(context).size.width) *(386/428), + child: _hasDataLoaded == false ? + Container(height: (MediaQuery.of(context).size.height) *(460/926),child: Center(child: CircularProgressIndicator(color: Color(0xFF3F2668),))) + : + Container( + height: (MediaQuery.of(context).size.height) *(460/926), + child: ListView( + scrollDirection: Axis.vertical, + children: [ + Container( + height: (MediaQuery.of(context).size.height) *(120.9/926), + child: GridView( + gridDelegate: SliverGridDelegateWithFixedCrossAxisCount( + crossAxisCount: 2, + crossAxisSpacing: (MediaQuery.of(context).size.width) *(30/428), + mainAxisExtent: (MediaQuery.of(context).size.height) *(40.224/926),), + children: [ + for(int i = 0; i 0) { + setState(() { + _systemsDisabled = false; + }); + } + + //Unchecking the previously checked boxes. + if(subjectsEverything["isSelected"]![i] == false) { + if(systemsEverything["isSelected"]!.length > 0) { + for(int i = 0; i 0) { + for(int i = 0; i[ + for(int i = 0; i 0) { + setState(() { + _topicsDisabled = false; + }); + } + + //Unchecking the previously checked boxes. + if(systemsEverything["isSelected"]![i] == false) { + // topicsEverything + if(topicsEverything["isSelected"]!.length > 0) { + for(int i = 0; i[ + for(int i = 0; i[ + FilteringTextInputFormatter.digitsOnly + ], // Only numbers can be entered + textAlign: TextAlign.center, + decoration: InputDecoration( + hintText: "4", + hintStyle: TextStyle(color: Color(0xffAEAEAE), + fontSize: (MediaQuery.of(context).size.height)*(15/926), + fontFamily: 'Brandon-med',), + contentPadding: EdgeInsets.fromLTRB(2.0, 1, 2.0, 1), + enabledBorder: OutlineInputBorder( + borderSide: BorderSide( + color: Color(0xFF7070709E), + width: 1.0, + ), + borderRadius: BorderRadius.circular(3.0), + ), + focusedBorder: OutlineInputBorder( + borderSide: BorderSide( + color: Colors.transparent, + width: 0.0, + ), + ), + ), + style: TextStyle( + color: Colors.black, + fontSize: (MediaQuery.of(context).size.height)*(15/926), + fontFamily: 'Brandon-med', + ), + onChanged: (val) { + final number = num.tryParse(val); + if(number != null) { + var totalQuestions; + try { + totalQuestions = _totalQuestions; + } catch (error) { + ScaffoldMessenger.of(context) + ..removeCurrentSnackBar() + ..showSnackBar(SnackBar(content: Text("Error"))); + } + if((int.parse(val)>totalQuestions) || (int.parse(val)>=40)) { + ScaffoldMessenger.of(context) + ..removeCurrentSnackBar() + ..showSnackBar(SnackBar(content: Text("Enter a smaller number"))); + setState(() { + _questionsCount = 0; + }); + } + else{ + setState(() { + _questionsCount = int.parse(val); + }); + } + } + }, + ), + ), + ), + Text(" /" + _totalQuestions.toString(), + style: TextStyle( + color: Color(0xFF98A4A4), + fontSize: (MediaQuery.of(context).size.height)*(15/926), + fontFamily: 'Brandon-med', + ),), + ], + ), + ), + ], + ), + ), + SizedBox(height: (MediaQuery.of(context).size.height) *(21/926),), + + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + InkWell( + child: Container( + height: (MediaQuery.of(context).size.height) *(42/926), + width: (MediaQuery.of(context).size.width) *(68/428), + decoration: BoxDecoration( + color: Color(0xff3F2668),//0xffB0A6C2, rgba(176, 166, 194, 1) + borderRadius: BorderRadius.all(Radius.circular(3)), + boxShadow: [ + BoxShadow( + color: Colors.black12,//Color(0xff00000029), + spreadRadius: 2, + blurRadius: 2, + offset: Offset(0, 0), + ), + ], + ), + child: TextButton( + onPressed: () { + //Animates to next tab + _backTab(); + }, + child: Center( + child: Text("Back", + style: TextStyle( + color: Colors.white, + fontFamily: 'Brandon-med', + ), + ), + ), + ), + ), + ), + InkWell( + child: Container( + height: (MediaQuery.of(context).size.height) *(42/926), + width: (MediaQuery.of(context).size.width) *(100/428), + decoration: BoxDecoration( + color: Color(0xff3F2668),//0xffB0A6C2, rgba(176, 166, 194, 1) + borderRadius: BorderRadius.all(Radius.circular(3)), + boxShadow: [ + BoxShadow( + color: Colors.black12,//Color(0xff00000029), + spreadRadius: 2, + blurRadius: 2, + offset: Offset(0, 0), + ), + ], + ), + child: TextButton( + onPressed: () { + print("adsdsa"); + // print(num.tryParse(_questionsCount)); + if(_questionsCount > 0) { + final result = Navigator.push( + context, + MaterialPageRoute(builder: (context) => QuizModule(totalQuestions: _questionsCount, questions: _questions)), + ); + } + }, + child: Center( + child: Text("Create Quiz", + style: TextStyle( + color: Colors.white, + fontFamily: 'Brandon-med', + ), + ), + ), + ), + ), + ), + ], + ), + ], + ), + ], + ), + ), + ], + ), + ), + ), + ); + } } \ No newline at end of file diff --git a/lib/screens/Welcome/GenerateQuiz/generate_quiz_last.dart b/lib/screens/Welcome/GenerateQuiz/generate_quiz_last.dart index 2a2f85e..61d6d5f 100644 --- a/lib/screens/Welcome/GenerateQuiz/generate_quiz_last.dart +++ b/lib/screens/Welcome/GenerateQuiz/generate_quiz_last.dart @@ -1,276 +1,276 @@ -import 'package:flutter/material.dart'; -import 'package:flutter_svg/flutter_svg.dart'; -import 'package:testify/screens/Authentication/login.dart'; -import 'package:testify/screens/Welcome/GenerateQuiz/difficulty.dart'; -import 'package:testify/screens/Welcome/GenerateQuiz/question_types.dart'; -import 'package:testify/screens/Welcome/side_menu_bar.dart'; - -class GenerateQuizLast extends StatefulWidget { - @override - State createState() => _GenerateQuizLastState(); -} - -class _GenerateQuizLastState extends State { - //Fields - - @override - Widget build(BuildContext context) { - return Scaffold( - backgroundColor: Color(0xffF8F9FB), - drawer: SideMenuBar(), - appBar: AppBar( - backgroundColor: Color(0xff3F2668), - elevation: 2, - centerTitle: true, - flexibleSpace: Container( - decoration: BoxDecoration( - gradient: LinearGradient( - begin: Alignment.topCenter, - end: Alignment.bottomCenter, - colors: [ - Color(0xff7F1AF1), - Color(0xff482384) - ]) - ), - ), - title: const Text("Generate Quiz", - style: TextStyle( - color: Color(0xffFFFEFE), - fontFamily: 'Brandon-bld', - ), - ), - actions: [ - TextButton( - onPressed: () async { - final result = await Navigator.push( - context, - MaterialPageRoute(builder: (context) => const Login(fromWhere:"Home")), - ); - }, - child: const Icon( - Icons.logout, - color: Colors.white, - ), - ), - ], - ), - body: Container( - padding: EdgeInsets.only(top:(MediaQuery.of(context).size.height) *(15/926), - bottom: (MediaQuery.of(context).size.height) *(8/926), - left: (MediaQuery.of(context).size.width) *(18/428), - right: (MediaQuery.of(context).size.width) *(18/428)), - child: Column( - children: [ - Row( - children: [ - Container( - width: (MediaQuery.of(context).size.width) *(221/428), - //height: (MediaQuery.of(context).size.height) *(91/926), - child: Column( - children: [ - Align( - alignment: Alignment.topLeft, - child: Text("Create Quiz", - style: TextStyle( - color: Color(0xff232323), - fontFamily: 'Brandon-bld', - fontSize: (MediaQuery.of(context).size.height) *(20/926),//38, - ),), - ), - SizedBox(height: (MediaQuery.of(context).size.height) *(2/926),), - Text("Lorem ipsum dolor sit amet, consectetur adipiscing elit. Cras imperdiet finibus elit non luctus. Morbi auctor mattis ante.", - style: TextStyle( - color: Color(0xFF483A3A), - fontFamily: 'Brandon-med', - fontSize: (MediaQuery.of(context).size.height) *(10/926),//38, - ),), - ], - ), - ), - SizedBox(width: (MediaQuery.of(context).size.width) *(39/428),), - Container( - //color: Colors.transparent, - child: SvgPicture.asset( - "assets/Images/create_quiz.svg", - height: (MediaQuery.of(context).size.height) *(100/926), - //width: (MediaQuery.of(context).size.width) *(132/428), - ), - ), - ], - ), - SizedBox(height: (MediaQuery.of(context).size.height) *(25/926),), - //a - Container( - height: (MediaQuery.of(context).size.height) *(35.32/926), - decoration: BoxDecoration( - color: Color(0xff3F2668),//0xffB0A6C2, rgba(176, 166, 194, 1) - borderRadius: BorderRadius.only(topLeft: Radius.circular(50), topRight: Radius.circular(50)), - boxShadow: [ - BoxShadow( - color: Colors.black12,//Color(0xff00000029), - spreadRadius: 5, - blurRadius: 5, - offset: Offset(0, 0), - ), - ], - ), - child: Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - SizedBox(width: (MediaQuery.of(context).size.width) *(28/428),), - Container( - padding: EdgeInsets.only(top: (MediaQuery.of(context).size.height) *(9/926), bottom: (MediaQuery.of(context).size.height) *(4/926)), - height: (MediaQuery.of(context).size.height) *(35.32/926), - width: (MediaQuery.of(context).size.width) *(113/428), - color: Color(0xFF3F2668), - child: Column( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Text(" Systems/Subjects/Topics ", - style: TextStyle( - color: Color(0xffFEFEFE), - fontFamily: 'Brandon-bld', - fontSize: (MediaQuery.of(context).size.height) *(12/926), - ),), - ], - ), - ), - Container( - padding: EdgeInsets.only(top: (MediaQuery.of(context).size.height) *(5/926), bottom: (MediaQuery.of(context).size.height) *(5/926)), - height: (MediaQuery.of(context).size.height) *(35.32/926), - width: (MediaQuery.of(context).size.width) *(80/428), - color: Color(0xFF3F2668), - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Text("Question Types", - style: TextStyle( - color: Color(0xffFEFEFE), - fontFamily: 'Brandon-bld', - fontSize: (MediaQuery.of(context).size.height) *(12/926), - ),), - ], - ), - ), - Container( - padding: EdgeInsets.only(top: (MediaQuery.of(context).size.height) *(5/926), bottom: (MediaQuery.of(context).size.height) *(5/926)), - height: (MediaQuery.of(context).size.height) *(35.32/926), - width: (MediaQuery.of(context).size.width) *(65/428), - color: Color(0xFF3F2668), - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Text("Difficulty", - style: TextStyle( - color: Color(0xffFEFEFE), - fontFamily: 'Brandon-bld', - fontSize: (MediaQuery.of(context).size.height) *(12/926), - ),), - ], - ), - ), - Container( - padding: EdgeInsets.only(top: (MediaQuery.of(context).size.height) *(5/926), bottom: (MediaQuery.of(context).size.height) *(5/926)), - height: (MediaQuery.of(context).size.height) *(35.32/926), - width: (MediaQuery.of(context).size.width) *(75/428), - color: Colors.white, - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Text("Generate Quiz", - style: TextStyle( - color: Color(0xFF3F2668),//0xFF3F2668 - fontFamily: 'Brandon-bld', - fontSize: (MediaQuery.of(context).size.height) *(12/926), - ),), - Container( - padding: EdgeInsets.only(left: (MediaQuery.of(context).size.width) *(13/428), right: (MediaQuery.of(context).size.width) *(13/428)), - //margin: EdgeInsets.only(top: (MediaQuery.of(context).size.height) *(1/926)), - child: Divider(height: 3, - thickness: 2, - color: Color(0xFF3F2668),), - ), - ], - ), - ), - SizedBox(width: (MediaQuery.of(context).size.width) *(28/428),), - ], - ), - ), - SizedBox(height: (MediaQuery.of(context).size.height) *(15.28/926),), - Container( - height: (MediaQuery.of(context).size.height) *(167.52/926), - color: Colors.red, - ), - SizedBox(height: (MediaQuery.of(context).size.height) *(10.74/926),), - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - InkWell( - child: Container( - height: (MediaQuery.of(context).size.height) *(42/926), - width: (MediaQuery.of(context).size.width) *(68/428), - decoration: BoxDecoration( - color: Color(0xff3F2668),//0xffB0A6C2, rgba(176, 166, 194, 1) - borderRadius: BorderRadius.all(Radius.circular(3)), - boxShadow: [ - BoxShadow( - color: Colors.black12,//Color(0xff00000029), - spreadRadius: 2, - blurRadius: 2, - offset: Offset(0, 0), - ), - ], - ), - child: TextButton( - onPressed: () { - Navigator.pop(context); - }, - child: Center( - child: Text("Back", - style: TextStyle( - color: Colors.white, - fontFamily: 'Brandon-med', - ), - ), - ), - ), - ), - ), - InkWell( - child: Container( - height: (MediaQuery.of(context).size.height) *(42/926), - width: (MediaQuery.of(context).size.width) *(100/428), - decoration: BoxDecoration( - color: Color(0xff3F2668),//0xffB0A6C2, rgba(176, 166, 194, 1) - borderRadius: BorderRadius.all(Radius.circular(3)), - boxShadow: [ - BoxShadow( - color: Colors.black12,//Color(0xff00000029), - spreadRadius: 2, - blurRadius: 2, - offset: Offset(0, 0), - ), - ], - ), - child: TextButton( - onPressed: () { }, - child: Center( - child: Text("Create Quiz", - style: TextStyle( - color: Colors.white, - fontFamily: 'Brandon-med', - ), - ), - ), - ), - ), - ), - ], - ), - ], - ), - ), - ); - } +import 'package:flutter/material.dart'; +import 'package:flutter_svg/flutter_svg.dart'; +import 'package:testify/screens/Authentication/login.dart'; +import 'package:testify/screens/Welcome/GenerateQuiz/difficulty.dart'; +import 'package:testify/screens/Welcome/GenerateQuiz/question_types.dart'; +import 'package:testify/screens/Welcome/side_menu_bar.dart'; + +class GenerateQuizLast extends StatefulWidget { + @override + State createState() => _GenerateQuizLastState(); +} + +class _GenerateQuizLastState extends State { + //Fields + + @override + Widget build(BuildContext context) { + return Scaffold( + backgroundColor: Color(0xffF8F9FB), + drawer: SideMenuBar(), + appBar: AppBar( + backgroundColor: Color(0xff3F2668), + elevation: 2, + centerTitle: true, + flexibleSpace: Container( + decoration: BoxDecoration( + gradient: LinearGradient( + begin: Alignment.topCenter, + end: Alignment.bottomCenter, + colors: [ + Color(0xff7F1AF1), + Color(0xff482384) + ]) + ), + ), + title: const Text("Generate Quiz", + style: TextStyle( + color: Color(0xffFFFEFE), + fontFamily: 'Brandon-bld', + ), + ), + actions: [ + TextButton( + onPressed: () async { + final result = await Navigator.push( + context, + MaterialPageRoute(builder: (context) => const Login(fromWhere:"Home")), + ); + }, + child: const Icon( + Icons.logout, + color: Colors.white, + ), + ), + ], + ), + body: Container( + padding: EdgeInsets.only(top:(MediaQuery.of(context).size.height) *(15/926), + bottom: (MediaQuery.of(context).size.height) *(8/926), + left: (MediaQuery.of(context).size.width) *(18/428), + right: (MediaQuery.of(context).size.width) *(18/428)), + child: Column( + children: [ + Row( + children: [ + Container( + width: (MediaQuery.of(context).size.width) *(221/428), + //height: (MediaQuery.of(context).size.height) *(91/926), + child: Column( + children: [ + Align( + alignment: Alignment.topLeft, + child: Text("Create Quiz", + style: TextStyle( + color: Color(0xff232323), + fontFamily: 'Brandon-bld', + fontSize: (MediaQuery.of(context).size.height) *(20/926),//38, + ),), + ), + SizedBox(height: (MediaQuery.of(context).size.height) *(2/926),), + Text("Lorem ipsum dolor sit amet, consectetur adipiscing elit. Cras imperdiet finibus elit non luctus. Morbi auctor mattis ante.", + style: TextStyle( + color: Color(0xFF483A3A), + fontFamily: 'Brandon-med', + fontSize: (MediaQuery.of(context).size.height) *(10/926),//38, + ),), + ], + ), + ), + SizedBox(width: (MediaQuery.of(context).size.width) *(39/428),), + Container( + //color: Colors.transparent, + child: SvgPicture.asset( + "assets/Images/create_quiz.svg", + height: (MediaQuery.of(context).size.height) *(100/926), + //width: (MediaQuery.of(context).size.width) *(132/428), + ), + ), + ], + ), + SizedBox(height: (MediaQuery.of(context).size.height) *(25/926),), + //a + Container( + height: (MediaQuery.of(context).size.height) *(35.32/926), + decoration: BoxDecoration( + color: Color(0xff3F2668),//0xffB0A6C2, rgba(176, 166, 194, 1) + borderRadius: BorderRadius.only(topLeft: Radius.circular(50), topRight: Radius.circular(50)), + boxShadow: [ + BoxShadow( + color: Colors.black12,//Color(0xff00000029), + spreadRadius: 5, + blurRadius: 5, + offset: Offset(0, 0), + ), + ], + ), + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + SizedBox(width: (MediaQuery.of(context).size.width) *(28/428),), + Container( + padding: EdgeInsets.only(top: (MediaQuery.of(context).size.height) *(9/926), bottom: (MediaQuery.of(context).size.height) *(4/926)), + height: (MediaQuery.of(context).size.height) *(35.32/926), + width: (MediaQuery.of(context).size.width) *(113/428), + color: Color(0xFF3F2668), + child: Column( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text(" Systems/Subjects/Topics ", + style: TextStyle( + color: Color(0xffFEFEFE), + fontFamily: 'Brandon-bld', + fontSize: (MediaQuery.of(context).size.height) *(12/926), + ),), + ], + ), + ), + Container( + padding: EdgeInsets.only(top: (MediaQuery.of(context).size.height) *(5/926), bottom: (MediaQuery.of(context).size.height) *(5/926)), + height: (MediaQuery.of(context).size.height) *(35.32/926), + width: (MediaQuery.of(context).size.width) *(80/428), + color: Color(0xFF3F2668), + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Text("Question Types", + style: TextStyle( + color: Color(0xffFEFEFE), + fontFamily: 'Brandon-bld', + fontSize: (MediaQuery.of(context).size.height) *(12/926), + ),), + ], + ), + ), + Container( + padding: EdgeInsets.only(top: (MediaQuery.of(context).size.height) *(5/926), bottom: (MediaQuery.of(context).size.height) *(5/926)), + height: (MediaQuery.of(context).size.height) *(35.32/926), + width: (MediaQuery.of(context).size.width) *(65/428), + color: Color(0xFF3F2668), + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Text("Difficulty", + style: TextStyle( + color: Color(0xffFEFEFE), + fontFamily: 'Brandon-bld', + fontSize: (MediaQuery.of(context).size.height) *(12/926), + ),), + ], + ), + ), + Container( + padding: EdgeInsets.only(top: (MediaQuery.of(context).size.height) *(5/926), bottom: (MediaQuery.of(context).size.height) *(5/926)), + height: (MediaQuery.of(context).size.height) *(35.32/926), + width: (MediaQuery.of(context).size.width) *(75/428), + color: Colors.white, + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Text("Generate Quiz", + style: TextStyle( + color: Color(0xFF3F2668),//0xFF3F2668 + fontFamily: 'Brandon-bld', + fontSize: (MediaQuery.of(context).size.height) *(12/926), + ),), + Container( + padding: EdgeInsets.only(left: (MediaQuery.of(context).size.width) *(13/428), right: (MediaQuery.of(context).size.width) *(13/428)), + //margin: EdgeInsets.only(top: (MediaQuery.of(context).size.height) *(1/926)), + child: Divider(height: 3, + thickness: 2, + color: Color(0xFF3F2668),), + ), + ], + ), + ), + SizedBox(width: (MediaQuery.of(context).size.width) *(28/428),), + ], + ), + ), + SizedBox(height: (MediaQuery.of(context).size.height) *(15.28/926),), + Container( + height: (MediaQuery.of(context).size.height) *(167.52/926), + color: Colors.red, + ), + SizedBox(height: (MediaQuery.of(context).size.height) *(10.74/926),), + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + InkWell( + child: Container( + height: (MediaQuery.of(context).size.height) *(42/926), + width: (MediaQuery.of(context).size.width) *(68/428), + decoration: BoxDecoration( + color: Color(0xff3F2668),//0xffB0A6C2, rgba(176, 166, 194, 1) + borderRadius: BorderRadius.all(Radius.circular(3)), + boxShadow: [ + BoxShadow( + color: Colors.black12,//Color(0xff00000029), + spreadRadius: 2, + blurRadius: 2, + offset: Offset(0, 0), + ), + ], + ), + child: TextButton( + onPressed: () { + Navigator.pop(context); + }, + child: Center( + child: Text("Back", + style: TextStyle( + color: Colors.white, + fontFamily: 'Brandon-med', + ), + ), + ), + ), + ), + ), + InkWell( + child: Container( + height: (MediaQuery.of(context).size.height) *(42/926), + width: (MediaQuery.of(context).size.width) *(100/428), + decoration: BoxDecoration( + color: Color(0xff3F2668),//0xffB0A6C2, rgba(176, 166, 194, 1) + borderRadius: BorderRadius.all(Radius.circular(3)), + boxShadow: [ + BoxShadow( + color: Colors.black12,//Color(0xff00000029), + spreadRadius: 2, + blurRadius: 2, + offset: Offset(0, 0), + ), + ], + ), + child: TextButton( + onPressed: () { }, + child: Center( + child: Text("Create Quiz", + style: TextStyle( + color: Colors.white, + fontFamily: 'Brandon-med', + ), + ), + ), + ), + ), + ), + ], + ), + ], + ), + ), + ); + } } \ No newline at end of file diff --git a/lib/screens/Welcome/GenerateQuiz/question_types.dart b/lib/screens/Welcome/GenerateQuiz/question_types.dart index 6ca3bf1..b0dc5f3 100644 --- a/lib/screens/Welcome/GenerateQuiz/question_types.dart +++ b/lib/screens/Welcome/GenerateQuiz/question_types.dart @@ -1,281 +1,281 @@ -import 'package:flutter/material.dart'; -import 'package:flutter_svg/flutter_svg.dart'; -import 'package:testify/screens/Authentication/login.dart'; -import 'package:testify/screens/Welcome/GenerateQuiz/difficulty.dart'; -import 'package:testify/screens/Welcome/GenerateQuiz/question_types.dart'; -import 'package:testify/screens/Welcome/side_menu_bar.dart'; - -class QuestionTypes extends StatefulWidget { - @override - State createState() => _QuestionTypesState(); -} - -class _QuestionTypesState extends State { - //Fields - - @override - Widget build(BuildContext context) { - return Scaffold( - backgroundColor: Color(0xffF8F9FB), - drawer: SideMenuBar(), - appBar: AppBar( - backgroundColor: Color(0xff3F2668), - elevation: 2, - centerTitle: true, - flexibleSpace: Container( - decoration: BoxDecoration( - gradient: LinearGradient( - begin: Alignment.topCenter, - end: Alignment.bottomCenter, - colors: [ - Color(0xff7F1AF1), - Color(0xff482384) - ]) - ), - ), - title: const Text("Generate Quiz", - style: TextStyle( - color: Color(0xffFFFEFE), - fontFamily: 'Brandon-bld', - ), - ), - actions: [ - TextButton( - onPressed: () async { - final result = await Navigator.push( - context, - MaterialPageRoute(builder: (context) => const Login(fromWhere:"Home")), - ); - }, - child: const Icon( - Icons.logout, - color: Colors.white, - ), - ), - ], - ), - body: Container( - padding: EdgeInsets.only(top:(MediaQuery.of(context).size.height) *(15/926), - bottom: (MediaQuery.of(context).size.height) *(8/926), - left: (MediaQuery.of(context).size.width) *(18/428), - right: (MediaQuery.of(context).size.width) *(18/428)), - child: Column( - children: [ - Row( - children: [ - Container( - width: (MediaQuery.of(context).size.width) *(221/428), - //height: (MediaQuery.of(context).size.height) *(91/926), - child: Column( - children: [ - Align( - alignment: Alignment.topLeft, - child: Text("Create Quiz", - style: TextStyle( - color: Color(0xff232323), - fontFamily: 'Brandon-bld', - fontSize: (MediaQuery.of(context).size.height) *(20/926),//38, - ),), - ), - SizedBox(height: (MediaQuery.of(context).size.height) *(2/926),), - Text("Lorem ipsum dolor sit amet, consectetur adipiscing elit. Cras imperdiet finibus elit non luctus. Morbi auctor mattis ante.", - style: TextStyle( - color: Color(0xFF483A3A), - fontFamily: 'Brandon-med', - fontSize: (MediaQuery.of(context).size.height) *(10/926),//38, - ),), - ], - ), - ), - SizedBox(width: (MediaQuery.of(context).size.width) *(39/428),), - Container( - //color: Colors.transparent, - child: SvgPicture.asset( - "assets/Images/create_quiz.svg", - height: (MediaQuery.of(context).size.height) *(100/926), - //width: (MediaQuery.of(context).size.width) *(132/428), - ), - ), - ], - ), - SizedBox(height: (MediaQuery.of(context).size.height) *(25/926),), - //a - Container( - height: (MediaQuery.of(context).size.height) *(35.32/926), - decoration: BoxDecoration( - color: Color(0xff3F2668),//0xffB0A6C2, rgba(176, 166, 194, 1) - borderRadius: BorderRadius.only(topLeft: Radius.circular(50), topRight: Radius.circular(50)), - boxShadow: [ - BoxShadow( - color: Colors.black12,//Color(0xff00000029), - spreadRadius: 5, - blurRadius: 5, - offset: Offset(0, 0), - ), - ], - ), - child: Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - SizedBox(width: (MediaQuery.of(context).size.width) *(28/428),), - Container( - padding: EdgeInsets.only(top: (MediaQuery.of(context).size.height) *(9/926), bottom: (MediaQuery.of(context).size.height) *(4/926)), - height: (MediaQuery.of(context).size.height) *(35.32/926), - width: (MediaQuery.of(context).size.width) *(113/428), - color: Color(0xFF3F2668), - child: Column( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Text(" Systems/Subjects/Topics ", - style: TextStyle( - color: Color(0xffFEFEFE), - fontFamily: 'Brandon-bld', - fontSize: (MediaQuery.of(context).size.height) *(12/926), - ),), - ], - ), - ), - Container( - padding: EdgeInsets.only(top: (MediaQuery.of(context).size.height) *(5/926), bottom: (MediaQuery.of(context).size.height) *(5/926)), - height: (MediaQuery.of(context).size.height) *(35.32/926), - width: (MediaQuery.of(context).size.width) *(80/428), - color: Colors.white, - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Text("Question Types", - style: TextStyle( - color: Color(0xFF3F2668), - fontFamily: 'Brandon-bld', - fontSize: (MediaQuery.of(context).size.height) *(12/926), - ),), - Container( - padding: EdgeInsets.only(left: (MediaQuery.of(context).size.width) *(13/428), right: (MediaQuery.of(context).size.width) *(13/428)), - //margin: EdgeInsets.only(top: (MediaQuery.of(context).size.height) *(1/926)), - child: Divider(height: 3, - thickness: 2, - color: Color(0xFF3F2668),), - ), - ], - ), - ), - Container( - padding: EdgeInsets.only(top: (MediaQuery.of(context).size.height) *(5/926), bottom: (MediaQuery.of(context).size.height) *(5/926)), - height: (MediaQuery.of(context).size.height) *(35.32/926), - width: (MediaQuery.of(context).size.width) *(65/428), - color: Color(0xFF3F2668), - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Text("Difficulty", - style: TextStyle( - color: Color(0xffFEFEFE), - fontFamily: 'Brandon-bld', - fontSize: (MediaQuery.of(context).size.height) *(12/926), - ),), - ], - ), - ), - Container( - padding: EdgeInsets.only(top: (MediaQuery.of(context).size.height) *(5/926), bottom: (MediaQuery.of(context).size.height) *(5/926)), - height: (MediaQuery.of(context).size.height) *(35.32/926), - width: (MediaQuery.of(context).size.width) *(75/428), - color: Color(0xFF3F2668), - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Text("Generate Quiz", - style: TextStyle( - color: Color(0xffFEFEFE), - fontFamily: 'Brandon-bld', - fontSize: (MediaQuery.of(context).size.height) *(12/926), - ),), - ], - ), - ), - SizedBox(width: (MediaQuery.of(context).size.width) *(28/428),), - ], - ), - ), - SizedBox(height: (MediaQuery.of(context).size.height) *(15.28/926),), - Container( - height: (MediaQuery.of(context).size.height) *(167.52/926), - color: Colors.red, - ), - SizedBox(height: (MediaQuery.of(context).size.height) *(10.74/926),), - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - InkWell( - child: Container( - height: (MediaQuery.of(context).size.height) *(42/926), - width: (MediaQuery.of(context).size.width) *(68/428), - decoration: BoxDecoration( - color: Color(0xff3F2668),//0xffB0A6C2, rgba(176, 166, 194, 1) - borderRadius: BorderRadius.all(Radius.circular(3)), - boxShadow: [ - BoxShadow( - color: Colors.black12,//Color(0xff00000029), - spreadRadius: 2, - blurRadius: 2, - offset: Offset(0, 0), - ), - ], - ), - child: TextButton( - onPressed: () { - Navigator.pop(context); - }, - child: Center( - child: Text("Back", - style: TextStyle( - color: Colors.white, - fontFamily: 'Brandon-med', - ), - ), - ), - ), - ), - ), - InkWell( - child: Container( - height: (MediaQuery.of(context).size.height) *(42/926), - width: (MediaQuery.of(context).size.width) *(68/428), - decoration: BoxDecoration( - color: Color(0xff3F2668),//0xffB0A6C2, rgba(176, 166, 194, 1) - borderRadius: BorderRadius.all(Radius.circular(3)), - boxShadow: [ - BoxShadow( - color: Colors.black12,//Color(0xff00000029), - spreadRadius: 2, - blurRadius: 2, - offset: Offset(0, 0), - ), - ], - ), - child: TextButton( - onPressed: () async { - final result = await Navigator.push( - context, - MaterialPageRoute(builder: (context) => Difficulty()), - ); - }, - child: Center( - child: Text("Next", - style: TextStyle( - color: Colors.white, - fontFamily: 'Brandon-med', - ), - ), - ), - ), - ), - ), - ], - ), - ], - ), - ), - ); - } +import 'package:flutter/material.dart'; +import 'package:flutter_svg/flutter_svg.dart'; +import 'package:testify/screens/Authentication/login.dart'; +import 'package:testify/screens/Welcome/GenerateQuiz/difficulty.dart'; +import 'package:testify/screens/Welcome/GenerateQuiz/question_types.dart'; +import 'package:testify/screens/Welcome/side_menu_bar.dart'; + +class QuestionTypes extends StatefulWidget { + @override + State createState() => _QuestionTypesState(); +} + +class _QuestionTypesState extends State { + //Fields + + @override + Widget build(BuildContext context) { + return Scaffold( + backgroundColor: Color(0xffF8F9FB), + drawer: SideMenuBar(), + appBar: AppBar( + backgroundColor: Color(0xff3F2668), + elevation: 2, + centerTitle: true, + flexibleSpace: Container( + decoration: BoxDecoration( + gradient: LinearGradient( + begin: Alignment.topCenter, + end: Alignment.bottomCenter, + colors: [ + Color(0xff7F1AF1), + Color(0xff482384) + ]) + ), + ), + title: const Text("Generate Quiz", + style: TextStyle( + color: Color(0xffFFFEFE), + fontFamily: 'Brandon-bld', + ), + ), + actions: [ + TextButton( + onPressed: () async { + final result = await Navigator.push( + context, + MaterialPageRoute(builder: (context) => const Login(fromWhere:"Home")), + ); + }, + child: const Icon( + Icons.logout, + color: Colors.white, + ), + ), + ], + ), + body: Container( + padding: EdgeInsets.only(top:(MediaQuery.of(context).size.height) *(15/926), + bottom: (MediaQuery.of(context).size.height) *(8/926), + left: (MediaQuery.of(context).size.width) *(18/428), + right: (MediaQuery.of(context).size.width) *(18/428)), + child: Column( + children: [ + Row( + children: [ + Container( + width: (MediaQuery.of(context).size.width) *(221/428), + //height: (MediaQuery.of(context).size.height) *(91/926), + child: Column( + children: [ + Align( + alignment: Alignment.topLeft, + child: Text("Create Quiz", + style: TextStyle( + color: Color(0xff232323), + fontFamily: 'Brandon-bld', + fontSize: (MediaQuery.of(context).size.height) *(20/926),//38, + ),), + ), + SizedBox(height: (MediaQuery.of(context).size.height) *(2/926),), + Text("Lorem ipsum dolor sit amet, consectetur adipiscing elit. Cras imperdiet finibus elit non luctus. Morbi auctor mattis ante.", + style: TextStyle( + color: Color(0xFF483A3A), + fontFamily: 'Brandon-med', + fontSize: (MediaQuery.of(context).size.height) *(10/926),//38, + ),), + ], + ), + ), + SizedBox(width: (MediaQuery.of(context).size.width) *(39/428),), + Container( + //color: Colors.transparent, + child: SvgPicture.asset( + "assets/Images/create_quiz.svg", + height: (MediaQuery.of(context).size.height) *(100/926), + //width: (MediaQuery.of(context).size.width) *(132/428), + ), + ), + ], + ), + SizedBox(height: (MediaQuery.of(context).size.height) *(25/926),), + //a + Container( + height: (MediaQuery.of(context).size.height) *(35.32/926), + decoration: BoxDecoration( + color: Color(0xff3F2668),//0xffB0A6C2, rgba(176, 166, 194, 1) + borderRadius: BorderRadius.only(topLeft: Radius.circular(50), topRight: Radius.circular(50)), + boxShadow: [ + BoxShadow( + color: Colors.black12,//Color(0xff00000029), + spreadRadius: 5, + blurRadius: 5, + offset: Offset(0, 0), + ), + ], + ), + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + SizedBox(width: (MediaQuery.of(context).size.width) *(28/428),), + Container( + padding: EdgeInsets.only(top: (MediaQuery.of(context).size.height) *(9/926), bottom: (MediaQuery.of(context).size.height) *(4/926)), + height: (MediaQuery.of(context).size.height) *(35.32/926), + width: (MediaQuery.of(context).size.width) *(113/428), + color: Color(0xFF3F2668), + child: Column( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text(" Systems/Subjects/Topics ", + style: TextStyle( + color: Color(0xffFEFEFE), + fontFamily: 'Brandon-bld', + fontSize: (MediaQuery.of(context).size.height) *(12/926), + ),), + ], + ), + ), + Container( + padding: EdgeInsets.only(top: (MediaQuery.of(context).size.height) *(5/926), bottom: (MediaQuery.of(context).size.height) *(5/926)), + height: (MediaQuery.of(context).size.height) *(35.32/926), + width: (MediaQuery.of(context).size.width) *(80/428), + color: Colors.white, + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Text("Question Types", + style: TextStyle( + color: Color(0xFF3F2668), + fontFamily: 'Brandon-bld', + fontSize: (MediaQuery.of(context).size.height) *(12/926), + ),), + Container( + padding: EdgeInsets.only(left: (MediaQuery.of(context).size.width) *(13/428), right: (MediaQuery.of(context).size.width) *(13/428)), + //margin: EdgeInsets.only(top: (MediaQuery.of(context).size.height) *(1/926)), + child: Divider(height: 3, + thickness: 2, + color: Color(0xFF3F2668),), + ), + ], + ), + ), + Container( + padding: EdgeInsets.only(top: (MediaQuery.of(context).size.height) *(5/926), bottom: (MediaQuery.of(context).size.height) *(5/926)), + height: (MediaQuery.of(context).size.height) *(35.32/926), + width: (MediaQuery.of(context).size.width) *(65/428), + color: Color(0xFF3F2668), + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Text("Difficulty", + style: TextStyle( + color: Color(0xffFEFEFE), + fontFamily: 'Brandon-bld', + fontSize: (MediaQuery.of(context).size.height) *(12/926), + ),), + ], + ), + ), + Container( + padding: EdgeInsets.only(top: (MediaQuery.of(context).size.height) *(5/926), bottom: (MediaQuery.of(context).size.height) *(5/926)), + height: (MediaQuery.of(context).size.height) *(35.32/926), + width: (MediaQuery.of(context).size.width) *(75/428), + color: Color(0xFF3F2668), + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Text("Generate Quiz", + style: TextStyle( + color: Color(0xffFEFEFE), + fontFamily: 'Brandon-bld', + fontSize: (MediaQuery.of(context).size.height) *(12/926), + ),), + ], + ), + ), + SizedBox(width: (MediaQuery.of(context).size.width) *(28/428),), + ], + ), + ), + SizedBox(height: (MediaQuery.of(context).size.height) *(15.28/926),), + Container( + height: (MediaQuery.of(context).size.height) *(167.52/926), + color: Colors.red, + ), + SizedBox(height: (MediaQuery.of(context).size.height) *(10.74/926),), + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + InkWell( + child: Container( + height: (MediaQuery.of(context).size.height) *(42/926), + width: (MediaQuery.of(context).size.width) *(68/428), + decoration: BoxDecoration( + color: Color(0xff3F2668),//0xffB0A6C2, rgba(176, 166, 194, 1) + borderRadius: BorderRadius.all(Radius.circular(3)), + boxShadow: [ + BoxShadow( + color: Colors.black12,//Color(0xff00000029), + spreadRadius: 2, + blurRadius: 2, + offset: Offset(0, 0), + ), + ], + ), + child: TextButton( + onPressed: () { + Navigator.pop(context); + }, + child: Center( + child: Text("Back", + style: TextStyle( + color: Colors.white, + fontFamily: 'Brandon-med', + ), + ), + ), + ), + ), + ), + InkWell( + child: Container( + height: (MediaQuery.of(context).size.height) *(42/926), + width: (MediaQuery.of(context).size.width) *(68/428), + decoration: BoxDecoration( + color: Color(0xff3F2668),//0xffB0A6C2, rgba(176, 166, 194, 1) + borderRadius: BorderRadius.all(Radius.circular(3)), + boxShadow: [ + BoxShadow( + color: Colors.black12,//Color(0xff00000029), + spreadRadius: 2, + blurRadius: 2, + offset: Offset(0, 0), + ), + ], + ), + child: TextButton( + onPressed: () async { + final result = await Navigator.push( + context, + MaterialPageRoute(builder: (context) => Difficulty()), + ); + }, + child: Center( + child: Text("Next", + style: TextStyle( + color: Colors.white, + fontFamily: 'Brandon-med', + ), + ), + ), + ), + ), + ), + ], + ), + ], + ), + ), + ); + } } \ No newline at end of file diff --git a/lib/screens/Welcome/side_menu_bar.dart b/lib/screens/Welcome/side_menu_bar.dart index 4f7d3ab..9c9444a 100644 --- a/lib/screens/Welcome/side_menu_bar.dart +++ b/lib/screens/Welcome/side_menu_bar.dart @@ -1,46 +1,47 @@ -import 'package:flutter/material.dart'; -import 'package:testify/screens/Welcome/GenerateQuiz/generate_quiz.dart'; - -class SideMenuBar extends StatelessWidget { - @override - Widget build(BuildContext context) { - return Container( - width: (MediaQuery.of(context).size.width) *0.7, - child: Drawer( - child: ListView( - // Remove padding - padding: EdgeInsets.zero, - children: [ - Container( - padding: EdgeInsets.only(top: MediaQuery.of(context).padding.top), - height: (MediaQuery.of(context).size.height), - color: Color(0xffB0A6C2), - width: (MediaQuery.of(context).size.width) *0.7, - child: Column( - children: [ - ListTile( - leading: Icon(Icons.arrow_back), - title: Text('Back'), - onTap: () => Navigator.pop(context), - ), - Divider(), - ListTile( - leading: Icon(Icons.quiz_outlined), - title: Text('Generate Quiz'), - onTap: () async { - final result = await Navigator.push( - context, - MaterialPageRoute(builder: (context) => GenerateQuiz()), - ); - }, - ), - ], - ), - ), - //Divider(), - ], - ), - ), - ); - } +import 'package:flutter/material.dart'; +import 'package:testify/screens/Welcome/GenerateQuiz/generate_quiz.dart'; + +class SideMenuBar extends StatelessWidget { + @override + Widget build(BuildContext context) { + return Container( + width: (MediaQuery.of(context).size.width) *0.7, + child: Drawer( + child: ListView( + // Remove padding + padding: EdgeInsets.zero, + children: [ + Container( + padding: EdgeInsets.only(top: MediaQuery.of(context).padding.top), + height: (MediaQuery.of(context).size.height), + color: Color(0xffB0A6C2), + width: (MediaQuery.of(context).size.width) *0.7, + child: Column( + children: [ + ListTile( + leading: Icon(Icons.arrow_back), + title: Text('Close'), + onTap: () => Navigator.pop(context), + ), + Divider(), + ListTile( + leading: Icon(Icons.quiz_outlined), + title: Text('Generate Quiz'), + onTap: () async { + Navigator.of(context).pop(); + final result = await Navigator.push( + context, + MaterialPageRoute(builder: (context) => GenerateQuiz()), + ); + }, + ), + ], + ), + ), + //Divider(), + ], + ), + ), + ); + } } \ No newline at end of file diff --git a/lib/screens/home.dart b/lib/screens/home.dart index 9edd147..162f0b4 100644 --- a/lib/screens/home.dart +++ b/lib/screens/home.dart @@ -1,57 +1,66 @@ -import 'package:flutter/material.dart'; -import 'package:testify/auth_storage.dart'; -import 'package:testify/screens/Authentication/login.dart'; -import 'package:testify/screens/Welcome/side_menu_bar.dart'; - -class Home extends StatefulWidget { - const Home({Key? key}) : super(key: key); - - @override - _HomeState createState() => _HomeState(); -} - -class _HomeState extends State { - @override - Widget build(BuildContext context) { - return Scaffold( - backgroundColor: Colors.white, - drawer: SideMenuBar(), - appBar: AppBar( - backgroundColor: Color(0xff3F2668), - elevation: 2, - centerTitle: true, - flexibleSpace: Container( - decoration: BoxDecoration( - gradient: LinearGradient( - begin: Alignment.topCenter, - end: Alignment.bottomCenter, - colors: [ - Color(0xff7F1AF1), - Color(0xff482384) - ]) - ), - ), - title: const Text("Home", - style: TextStyle( - color: Color(0xffFFFEFE), - fontFamily: 'Brandon-bld', - ), - ), - actions: [ - TextButton( - onPressed: () async { - final result = await Navigator.push( - context, - MaterialPageRoute(builder: (context) => const Login(fromWhere:"Home")), - ); - }, - child: const Icon( - Icons.logout, - color: Colors.white, - ), - ), - ], - ), - ); - } -} +import 'package:flutter/material.dart'; +import 'package:flutter_svg/svg.dart'; +import 'package:testify/auth_storage.dart'; +import 'package:testify/screens/Authentication/login.dart'; +import 'package:testify/screens/Welcome/side_menu_bar.dart'; + +class Home extends StatefulWidget { + const Home({Key? key}) : super(key: key); + + @override + _HomeState createState() => _HomeState(); +} + +class _HomeState extends State { + @override + Widget build(BuildContext context) { + return WillPopScope( + onWillPop: () async { + ScaffoldMessenger.of(context) + ..removeCurrentSnackBar() + ..showSnackBar(SnackBar(content: Text("Press Logout Button"))); + return false; + }, + child: Scaffold( + backgroundColor: Colors.white, + drawer: SideMenuBar(), + appBar: AppBar( + backgroundColor: Color(0xff3F2668), + elevation: 2, + centerTitle: true, + flexibleSpace: Container( + decoration: BoxDecoration( + gradient: LinearGradient( + begin: Alignment.topCenter, + end: Alignment.bottomCenter, + colors: [ + Color(0xff7F1AF1), + Color(0xff482384) + ]) + ), + ), + title: const Text("Home", + style: TextStyle( + color: Color(0xffFFFEFE), + fontFamily: 'Brandon-bld', + ), + ), + actions: [ + TextButton( + onPressed: () async { + final result = await Navigator.push( + context, + MaterialPageRoute(builder: (context) => const Login(fromWhere:"Home")), + ); + }, + child: SvgPicture.asset( + "assets/Images/logout.svg", + height: (MediaQuery.of(context).size.height) *(32/926), + ), + ), + ], + ), + ), + ); + } +} diff --git a/pubspec.yaml b/pubspec.yaml index 61fd2a9..f2066ba 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,107 +1,114 @@ -name: testify -description: A Self-assessment System deployed in the medical industry to prepare fresh graduates for their next big step as practitioners. - -# The following line prevents the package from being accidentally published to -# pub.dev using `flutter pub publish`. This is preferred for private packages. -publish_to: 'none' # Remove this line if you wish to publish to pub.dev - -# The following defines the version and build number for your application. -# A version number is three numbers separated by dots, like 1.2.43 -# followed by an optional build number separated by a +. -# Both the version and the builder number may be overridden in flutter -# build by specifying --build-name and --build-number, respectively. -# In Android, build-name is used as versionName while build-number used as versionCode. -# Read more about Android versioning at https://developer.android.com/studio/publish/versioning -# In iOS, build-name is used as CFBundleShortVersionString while build-number used as CFBundleVersion. -# Read more about iOS versioning at -# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html -version: 1.0.0+1 - -environment: - sdk: ">=2.15.1 <3.0.0" - -# Dependencies specify other packages that your package needs in order to work. -# To automatically upgrade your package dependencies to the latest versions -# consider running `flutter pub upgrade --major-versions`. Alternatively, -# dependencies can be manually updated by changing the version numbers below to -# the latest version available on pub.dev. To see which dependencies have newer -# versions available, run `flutter pub outdated`. -dependencies: - flutter: - sdk: flutter - - - # The following adds the Cupertino Icons font to your application. - # Use with the CupertinoIcons class for iOS style icons. - cupertino_icons: ^1.0.2 - flutter_svg: ^1.0.2 - http: ^0.13.4 - path_provider: ^2.0.8 - -dev_dependencies: - flutter_test: - sdk: flutter - - # The "flutter_lints" package below contains a set of recommended lints to - # encourage good coding practices. The lint set provided by the package is - # activated in the `analysis_options.yaml` file located at the root of your - # package. See that file for information about deactivating specific lint - # rules and activating additional ones. - flutter_lints: ^1.0.0 - -# For information on the generic Dart part of this file, see the -# following page: https://dart.dev/tools/pub/pubspec - -# The following section is specific to Flutter. -flutter: - - # The following line ensures that the Material Icons font is - # included with your application, so that you can use the icons in - # the material Icons class. - uses-material-design: true - - # To add assets to your application, add an assets section, like this: - # assets: - # - images/a_dot_burr.jpeg - # - images/a_dot_ham.jpeg - assets: - - assets/Images/login_topLeftBubble_1.png - - assets/Images/login.svg - - assets/Images/login_bottomRight.svg - - assets/Images/login_bottomRight_png.png - - assets/Images/create_quiz.svg - -fonts: - - family: Brandon-bld - fonts: - - asset: assets/Fonts/Brandon_bld.otf - - family: Brandon-med - fonts: - - asset: assets/Fonts/Brandon_med.otf - - - # An image asset can refer to one or more resolution-specific "variants", see - # https://flutter.dev/assets-and-images/#resolution-aware. - - # For details regarding adding assets from package dependencies, see - # https://flutter.dev/assets-and-images/#from-packages - - # To add custom fonts to your application, add a fonts section here, - # in this "flutter" section. Each entry in this list should have a - # "family" key with the font family name, and a "fonts" key with a - # list giving the asset and other descriptors for the font. For - # example: - # fonts: - # - family: Schyler - # fonts: - # - asset: fonts/Schyler-Regular.ttf - # - asset: fonts/Schyler-Italic.ttf - # style: italic - # - family: Trajan Pro - # fonts: - # - asset: fonts/TrajanPro.ttf - # - asset: fonts/TrajanPro_Bold.ttf - # weight: 700 - # - # For details regarding fonts from package dependencies, - # see https://flutter.dev/custom-fonts/#from-packages +name: testify +description: A new Flutter project. + +# The following line prevents the package from being accidentally published to +# pub.dev using `flutter pub publish`. This is preferred for private packages. +publish_to: 'none' # Remove this line if you wish to publish to pub.dev + +# The following defines the version and build number for your application. +# A version number is three numbers separated by dots, like 1.2.43 +# followed by an optional build number separated by a +. +# Both the version and the builder number may be overridden in flutter +# build by specifying --build-name and --build-number, respectively. +# In Android, build-name is used as versionName while build-number used as versionCode. +# Read more about Android versioning at https://developer.android.com/studio/publish/versioning +# In iOS, build-name is used as CFBundleShortVersionString while build-number used as CFBundleVersion. +# Read more about iOS versioning at +# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html +version: 1.0.0+1 + +environment: + sdk: ">=2.12.0 <3.0.0" + +# Dependencies specify other packages that your package needs in order to work. +# To automatically upgrade your package dependencies to the latest versions +# consider running `flutter pub upgrade --major-versions`. Alternatively, +# dependencies can be manually updated by changing the version numbers below to +# the latest version available on pub.dev. To see which dependencies have newer +# versions available, run `flutter pub outdated`. +dependencies: + flutter: + sdk: flutter + + + # The following adds the Cupertino Icons font to your application. + # Use with the CupertinoIcons class for iOS style icons. + cupertino_icons: ^1.0.2 + flutter_svg: ^1.0.2 + http: ^0.13.4 + path_provider: ^2.0.8 + shared_preferences: ^2.0.12 + flutter_countdown_timer: ^4.1.0 + + +dev_dependencies: + flutter_test: + sdk: flutter + + # The "flutter_lints" package below contains a set of recommended lints to + # encourage good coding practices. The lint set provided by the package is + # activated in the `analysis_options.yaml` file located at the root of your + # package. See that file for information about deactivating specific lint + # rules and activating additional ones. + flutter_lints: ^1.0.0 + +# For information on the generic Dart part of this file, see the +# following page: https://dart.dev/tools/pub/pubspec + +# The following section is specific to Flutter. +flutter: + + # The following line ensures that the Material Icons font is + # included with your application, so that you can use the icons in + # the material Icons class. + uses-material-design: true + + # To add assets to your application, add an assets section, like this: + # assets: + # - images/a_dot_burr.jpeg + # - images/a_dot_ham.jpeg + assets: + - assets/Images/login_topLeftBubble_1.png + - assets/Images/login.svg + - assets/Images/login_bottomRight.svg + - assets/Images/login_bottomRight_png.png + - assets/Images/create_quiz.svg + - assets/Images/logout.svg + - assets/Images/lab.svg + - assets/Images/zoom.svg + - assets/Images/calculator.svg + - assets/Images/notes.svg + + fonts: + - family: Brandon-bld + fonts: + - asset: assets/Fonts/Brandon_bld.otf + - family: Brandon-med + fonts: + - asset: assets/Fonts/Brandon_med.otf + + # An image asset can refer to one or more resolution-specific "variants", see + # https://flutter.dev/assets-and-images/#resolution-aware. + + # For details regarding adding assets from package dependencies, see + # https://flutter.dev/assets-and-images/#from-packages + + # To add custom fonts to your application, add a fonts section here, + # in this "flutter" section. Each entry in this list should have a + # "family" key with the font family name, and a "fonts" key with a + # list giving the asset and other descriptors for the font. For + # example: + # fonts: + # - family: Schyler + # fonts: + # - asset: fonts/Schyler-Regular.ttf + # - asset: fonts/Schyler-Italic.ttf + # style: italic + # - family: Trajan Pro + # fonts: + # - asset: fonts/TrajanPro.ttf + # - asset: fonts/TrajanPro_Bold.ttf + # weight: 700 + # + # For details regarding fonts from package dependencies, + # see https://flutter.dev/custom-fonts/#from-packages diff --git a/test/widget_test.dart b/test/widget_test.dart index 6f150a5..1e86a3a 100644 --- a/test/widget_test.dart +++ b/test/widget_test.dart @@ -1,30 +1,30 @@ -// This is a basic Flutter widget test. -// -// To perform an interaction with a widget in your test, use the WidgetTester -// utility that Flutter provides. For example, you can send tap and scroll -// gestures. You can also use WidgetTester to find child widgets in the widget -// tree, read text, and verify that the values of widget properties are correct. - -import 'package:flutter/material.dart'; -import 'package:flutter_test/flutter_test.dart'; - -import 'package:testify/main.dart'; - -void main() { - testWidgets('Counter increments smoke test', (WidgetTester tester) async { - // Build our app and trigger a frame. - await tester.pumpWidget(MyApp()); - - // Verify that our counter starts at 0. - expect(find.text('0'), findsOneWidget); - expect(find.text('1'), findsNothing); - - // Tap the '+' icon and trigger a frame. - await tester.tap(find.byIcon(Icons.add)); - await tester.pump(); - - // Verify that our counter has incremented. - expect(find.text('0'), findsNothing); - expect(find.text('1'), findsOneWidget); - }); -} +// This is a basic Flutter widget test. +// +// To perform an interaction with a widget in your test, use the WidgetTester +// utility that Flutter provides. For example, you can send tap and scroll +// gestures. You can also use WidgetTester to find child widgets in the widget +// tree, read text, and verify that the values of widget properties are correct. + +import 'package:flutter/material.dart'; +import 'package:flutter_test/flutter_test.dart'; + +import 'package:testify/main.dart'; + +void main() { + testWidgets('Counter increments smoke test', (WidgetTester tester) async { + // Build our app and trigger a frame. + await tester.pumpWidget(MyApp()); + + // Verify that our counter starts at 0. + expect(find.text('0'), findsOneWidget); + expect(find.text('1'), findsNothing); + + // Tap the '+' icon and trigger a frame. + await tester.tap(find.byIcon(Icons.add)); + await tester.pump(); + + // Verify that our counter has incremented. + expect(find.text('0'), findsNothing); + expect(find.text('1'), findsOneWidget); + }); +} diff --git a/web/index.html b/web/index.html index ece6821..9c42991 100644 --- a/web/index.html +++ b/web/index.html @@ -1,104 +1,104 @@ - - - - - - - - - - - - - - - - - - - - testify - - - - - - - + + + + + + + + + + + + + + + + + + + + testify + + + + + + + diff --git a/web/manifest.json b/web/manifest.json index 318a589..a086e94 100644 --- a/web/manifest.json +++ b/web/manifest.json @@ -1,35 +1,35 @@ -{ - "name": "testify", - "short_name": "testify", - "start_url": ".", - "display": "standalone", - "background_color": "#0175C2", - "theme_color": "#0175C2", - "description": "A new Flutter project.", - "orientation": "portrait-primary", - "prefer_related_applications": false, - "icons": [ - { - "src": "icons/Icon-192.png", - "sizes": "192x192", - "type": "image/png" - }, - { - "src": "icons/Icon-512.png", - "sizes": "512x512", - "type": "image/png" - }, - { - "src": "icons/Icon-maskable-192.png", - "sizes": "192x192", - "type": "image/png", - "purpose": "maskable" - }, - { - "src": "icons/Icon-maskable-512.png", - "sizes": "512x512", - "type": "image/png", - "purpose": "maskable" - } - ] -} +{ + "name": "testify", + "short_name": "testify", + "start_url": ".", + "display": "standalone", + "background_color": "#0175C2", + "theme_color": "#0175C2", + "description": "A new Flutter project.", + "orientation": "portrait-primary", + "prefer_related_applications": false, + "icons": [ + { + "src": "icons/Icon-192.png", + "sizes": "192x192", + "type": "image/png" + }, + { + "src": "icons/Icon-512.png", + "sizes": "512x512", + "type": "image/png" + }, + { + "src": "icons/Icon-maskable-192.png", + "sizes": "192x192", + "type": "image/png", + "purpose": "maskable" + }, + { + "src": "icons/Icon-maskable-512.png", + "sizes": "512x512", + "type": "image/png", + "purpose": "maskable" + } + ] +} From d349f158c9dfa1164f0da3968c4ebcfa73b39e82 Mon Sep 17 00:00:00 2001 From: TheYoungWolf-Productions Date: Sun, 10 Apr 2022 11:27:31 +0500 Subject: [PATCH 13/23] Add assets --- assets/Images/calculator.svg | 3 ++ assets/Images/lab.svg | 3 ++ assets/Images/logout.svg | 3 ++ assets/Images/notes.svg | 6 ++++ assets/Images/prevQuiz.svg | 50 ++++++++++++++++++++++++++++++++++ assets/Images/testAnalysis.svg | 3 ++ assets/Images/testResults.svg | 3 ++ assets/Images/zoom.svg | 3 ++ 8 files changed, 74 insertions(+) create mode 100644 assets/Images/calculator.svg create mode 100644 assets/Images/lab.svg create mode 100644 assets/Images/logout.svg create mode 100644 assets/Images/notes.svg create mode 100644 assets/Images/prevQuiz.svg create mode 100644 assets/Images/testAnalysis.svg create mode 100644 assets/Images/testResults.svg create mode 100644 assets/Images/zoom.svg diff --git a/assets/Images/calculator.svg b/assets/Images/calculator.svg new file mode 100644 index 0000000..e988fff --- /dev/null +++ b/assets/Images/calculator.svg @@ -0,0 +1,3 @@ + + + diff --git a/assets/Images/lab.svg b/assets/Images/lab.svg new file mode 100644 index 0000000..4e9920a --- /dev/null +++ b/assets/Images/lab.svg @@ -0,0 +1,3 @@ + + + diff --git a/assets/Images/logout.svg b/assets/Images/logout.svg new file mode 100644 index 0000000..2f532a5 --- /dev/null +++ b/assets/Images/logout.svg @@ -0,0 +1,3 @@ + + + diff --git a/assets/Images/notes.svg b/assets/Images/notes.svg new file mode 100644 index 0000000..00038ae --- /dev/null +++ b/assets/Images/notes.svg @@ -0,0 +1,6 @@ + + + + Notes + + diff --git a/assets/Images/prevQuiz.svg b/assets/Images/prevQuiz.svg new file mode 100644 index 0000000..e1ed78f --- /dev/null +++ b/assets/Images/prevQuiz.svg @@ -0,0 +1,50 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/Images/testAnalysis.svg b/assets/Images/testAnalysis.svg new file mode 100644 index 0000000..4602d15 --- /dev/null +++ b/assets/Images/testAnalysis.svg @@ -0,0 +1,3 @@ + + + diff --git a/assets/Images/testResults.svg b/assets/Images/testResults.svg new file mode 100644 index 0000000..8c4e652 --- /dev/null +++ b/assets/Images/testResults.svg @@ -0,0 +1,3 @@ + + + diff --git a/assets/Images/zoom.svg b/assets/Images/zoom.svg new file mode 100644 index 0000000..6a928a9 --- /dev/null +++ b/assets/Images/zoom.svg @@ -0,0 +1,3 @@ + + + From 94dac3174c6e1dd595a0e16fba68fbd10b4108fb Mon Sep 17 00:00:00 2001 From: TheYoungWolf-Productions Date: Sun, 10 Apr 2022 11:28:25 +0500 Subject: [PATCH 14/23] Add packages --- pubspec.yaml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/pubspec.yaml b/pubspec.yaml index f2066ba..6cebda2 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -39,6 +39,7 @@ dependencies: path_provider: ^2.0.8 shared_preferences: ^2.0.12 flutter_countdown_timer: ^4.1.0 + math_expressions: ^2.0.0 dev_dependencies: @@ -78,6 +79,9 @@ flutter: - assets/Images/zoom.svg - assets/Images/calculator.svg - assets/Images/notes.svg + - assets/Images/testResults.svg + - assets/Images/testAnalysis.svg + - assets/Images/prevQuiz.svg fonts: - family: Brandon-bld From ee9824e813118dc839259a6697f30fedc196a582 Mon Sep 17 00:00:00 2001 From: TheYoungWolf-Productions Date: Sun, 10 Apr 2022 11:29:28 +0500 Subject: [PATCH 15/23] Add components --- lib/main.dart | 12 +- .../QuizModuleModels/generate_quiz_model.dart | 97 ++ .../get_system_categories_successful.dart | 97 ++ .../get_system_categories_unsuccessful.dart | 29 + .../get_previous_quizzes_model.dart | 97 ++ lib/screens/Authentication/login.dart | 124 +- .../Welcome/GenerateQuiz/generate_quiz.dart | 192 +-- .../Welcome/PreviousQuiz/previous_quiz.dart | 609 +++++++ .../Welcome/PreviousQuiz/test_details.dart | 386 +++++ lib/screens/Welcome/PreviousQuiz/tile.dart | 137 ++ lib/screens/Welcome/QuizModule/buttons.dart | 55 + .../Welcome/QuizModule/calculator.dart | 179 +++ .../QuizModule/question_explanation.dart | 372 +++++ .../Welcome/QuizModule/quiz_module.dart | 1402 +++++++++++++++++ .../Welcome/QuizModule/search_bar.dart | 861 ++++++++++ lib/screens/Welcome/side_menu_bar.dart | 45 +- lib/screens/home.dart | 66 +- 17 files changed, 4581 insertions(+), 179 deletions(-) create mode 100644 lib/models/GenerateQuizModels/QuizModuleModels/generate_quiz_model.dart create mode 100644 lib/models/GenerateQuizModels/get_system_categories_successful.dart create mode 100644 lib/models/GenerateQuizModels/get_system_categories_unsuccessful.dart create mode 100644 lib/models/GetPreviousQuizzesModel/get_previous_quizzes_model.dart create mode 100644 lib/screens/Welcome/PreviousQuiz/previous_quiz.dart create mode 100644 lib/screens/Welcome/PreviousQuiz/test_details.dart create mode 100644 lib/screens/Welcome/PreviousQuiz/tile.dart create mode 100644 lib/screens/Welcome/QuizModule/buttons.dart create mode 100644 lib/screens/Welcome/QuizModule/calculator.dart create mode 100644 lib/screens/Welcome/QuizModule/question_explanation.dart create mode 100644 lib/screens/Welcome/QuizModule/quiz_module.dart create mode 100644 lib/screens/Welcome/QuizModule/search_bar.dart diff --git a/lib/main.dart b/lib/main.dart index 0f01647..1e0f65d 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -2,6 +2,8 @@ import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:testify/auth_storage.dart'; import 'package:testify/screens/Authentication/login.dart'; +import 'package:testify/screens/Welcome/GenerateQuiz/generate_quiz.dart'; +import 'package:testify/screens/Welcome/QuizModule/quiz_module.dart'; import 'package:testify/screens/home.dart'; void main() async { @@ -25,6 +27,14 @@ class _MyAppState extends State { @override Widget build(BuildContext context) { return MaterialApp( - home: Login(fromWhere: "main",)); + initialRoute: '/', + routes: { + // When navigating to the "/" route, build the FirstScreen widget. + '/': (context) => Login(fromWhere: "main",), + // When navigating to the "/second" route, build the SecondScreen widget. + '/home': (context) => Home(), + }, + // home: Login(fromWhere: "main",) + ); } } \ No newline at end of file diff --git a/lib/models/GenerateQuizModels/QuizModuleModels/generate_quiz_model.dart b/lib/models/GenerateQuizModels/QuizModuleModels/generate_quiz_model.dart new file mode 100644 index 0000000..f030c46 --- /dev/null +++ b/lib/models/GenerateQuizModels/QuizModuleModels/generate_quiz_model.dart @@ -0,0 +1,97 @@ +// To parse this JSON data, do +// +// final generateQuizSuccessful = generateQuizSuccessfulFromJson(jsonString); + +import 'dart:convert'; + +GenerateQuizSuccessful generateQuizSuccessfulFromJson(String str) => GenerateQuizSuccessful.fromJson(json.decode(str)); + +String generateQuizSuccessfulToJson(GenerateQuizSuccessful data) => json.encode(data.toJson()); + +class GenerateQuizSuccessful { + GenerateQuizSuccessful({ + required this.data, + }); + + Data data; + + factory GenerateQuizSuccessful.fromJson(Map json) => GenerateQuizSuccessful( + data: Data.fromJson(json["data"]), + ); + + Map toJson() => { + "data": data.toJson(), + }; +} + +class Data { + Data({ + required this.status, + required this.questions, + required this.totalQuestions, + required this.quizId, + }); + + bool status; + List questions; + int totalQuestions; + int quizId; + + factory Data.fromJson(Map json) => Data( + status: json["status"], + questions: List.from(json["questions"].map((x) => Question.fromJson(x))), + totalQuestions: json["totalQuestions"], + quizId: json["quizId"], + ); + + Map toJson() => { + "status": status, + "questions": List.from(questions.map((x) => x.toJson())), + "totalQuestions": totalQuestions, + "quizId": quizId, + }; +} + +class Question { + Question({ + required this.id, + required this.title, + required this.question, + required this.correctMsg, + required this.answerType, + required this.postId, + required this.options, + required this.statistics, + }); + + int id; + String title; + String question; + String correctMsg; + String answerType; + int postId; + List options; + List statistics; + + factory Question.fromJson(Map json) => Question( + id: json["id"], + title: json["title"], + question: json["question"], + correctMsg: json["correct_msg"], + answerType: json["answer_type"], + postId: json["postId"], + options: List.from(json["options"].map((x) => x)), + statistics: List.from(json["statistics"].map((x) => x)), + ); + + Map toJson() => { + "id": id, + "title": title, + "question": question, + "correct_msg": correctMsg, + "answer_type": answerType, + "postId": postId, + "options": List.from(options.map((x) => x)), + "statistics": List.from(statistics.map((x) => x)), + }; +} diff --git a/lib/models/GenerateQuizModels/get_system_categories_successful.dart b/lib/models/GenerateQuizModels/get_system_categories_successful.dart new file mode 100644 index 0000000..03fc4a3 --- /dev/null +++ b/lib/models/GenerateQuizModels/get_system_categories_successful.dart @@ -0,0 +1,97 @@ +// To parse this JSON data, do +// +// final getSystemCategoriesSuccessfulModel = getSystemCategoriesSuccessfulModelFromJson(jsonString); + +import 'dart:convert'; + +GetSystemCategoriesSuccessfulModel getSystemCategoriesSuccessfulModelFromJson(String str) => GetSystemCategoriesSuccessfulModel.fromJson(json.decode(str)); + +String getSystemCategoriesSuccessfulModelToJson(GetSystemCategoriesSuccessfulModel data) => json.encode(data.toJson()); + +class GetSystemCategoriesSuccessfulModel { + GetSystemCategoriesSuccessfulModel({ + required this.data, + }); + + Data data; + + factory GetSystemCategoriesSuccessfulModel.fromJson(Map json) => GetSystemCategoriesSuccessfulModel( + data: Data.fromJson(json["data"]), + ); + + Map toJson() => { + "data": data.toJson(), + }; +} + +class Data { + Data({ + required this.status, + required this.categories, + required this.totalQuestions, + required this.questions, + }); + + bool status; + List categories; + int totalQuestions; + List questions; + + factory Data.fromJson(Map json) => Data( + status: json["status"], + categories: List.from(json["categories"].map((x) => Category.fromJson(x))), + totalQuestions: json["totalQuestions"], + questions: List.from(json["questions"].map((x) => x)), + ); + + Map toJson() => { + "status": status, + "categories": List.from(categories.map((x) => x.toJson())), + "totalQuestions": totalQuestions, + "questions": List.from(questions.map((x) => x)), + }; +} + +class Category { + Category({ + required this.parentCategory, + required this.subCategories, + }); + + String parentCategory; + List subCategories; + + factory Category.fromJson(Map json) => Category( + parentCategory: json["parentCategory"], + subCategories: List.from(json["subCategories"].map((x) => SubCategory.fromJson(x))), + ); + + Map toJson() => { + "parentCategory": parentCategory, + "subCategories": List.from(subCategories.map((x) => x.toJson())), + }; +} + +class SubCategory { + SubCategory({ + required this.id, + required this.title, + required this.questions, + }); + + String id; + String title; + int questions; + + factory SubCategory.fromJson(Map json) => SubCategory( + id: json["ID"], + title: json["Title"], + questions: json["Questions"], + ); + + Map toJson() => { + "ID": id, + "Title": title, + "Questions": questions, + }; +} diff --git a/lib/models/GenerateQuizModels/get_system_categories_unsuccessful.dart b/lib/models/GenerateQuizModels/get_system_categories_unsuccessful.dart new file mode 100644 index 0000000..64a3ec0 --- /dev/null +++ b/lib/models/GenerateQuizModels/get_system_categories_unsuccessful.dart @@ -0,0 +1,29 @@ +// To parse this JSON data, do +// +// final getSystemCategoriesUnsuccessfulModel = getSystemCategoriesUnsuccessfulModelFromJson(jsonString); + +import 'dart:convert'; + +GetSystemCategoriesUnsuccessfulModel getSystemCategoriesUnsuccessfulModelFromJson(String str) => GetSystemCategoriesUnsuccessfulModel.fromJson(json.decode(str)); + +String getSystemCategoriesUnsuccessfulModelToJson(GetSystemCategoriesUnsuccessfulModel data) => json.encode(data.toJson()); + +class GetSystemCategoriesUnsuccessfulModel { + GetSystemCategoriesUnsuccessfulModel({ + required this.status, + required this.msg, + }); + + bool status; + String msg; + + factory GetSystemCategoriesUnsuccessfulModel.fromJson(Map json) => GetSystemCategoriesUnsuccessfulModel( + status: json["status"], + msg: json["msg"], + ); + + Map toJson() => { + "status": status, + "msg": msg, + }; +} diff --git a/lib/models/GetPreviousQuizzesModel/get_previous_quizzes_model.dart b/lib/models/GetPreviousQuizzesModel/get_previous_quizzes_model.dart new file mode 100644 index 0000000..f665ea8 --- /dev/null +++ b/lib/models/GetPreviousQuizzesModel/get_previous_quizzes_model.dart @@ -0,0 +1,97 @@ +// To parse this JSON data, do +// +// final getPreviousQuizzesModel = getPreviousQuizzesModelFromJson(jsonString); + +import 'dart:convert'; + +GetPreviousQuizzesModel getPreviousQuizzesModelFromJson(String str) => GetPreviousQuizzesModel.fromJson(json.decode(str)); + +String getPreviousQuizzesModelToJson(GetPreviousQuizzesModel data) => json.encode(data.toJson()); + +class GetPreviousQuizzesModel { + GetPreviousQuizzesModel({ + required this.data, + }); + + Data data; + + factory GetPreviousQuizzesModel.fromJson(Map json) => GetPreviousQuizzesModel( + data: Data.fromJson(json["data"]), + ); + + Map toJson() => { + "data": data.toJson(), + }; +} + +class Data { + Data({ + required this.status, + required this.quizzes, + }); + + bool status; + List quizzes; + + factory Data.fromJson(Map json) => Data( + status: json["status"], + quizzes: List.from(json["quizzes"].map((x) => Quiz.fromJson(x))), + ); + + Map toJson() => { + "status": status, + "quizzes": List.from(quizzes.map((x) => x.toJson())), + }; +} + +class Quiz { + Quiz({ + required this.quizId, + required this.name, + required this.score, + required this.date, + required this.status, + required this.questions, + required this.totalQuestions, + required this.subjects, + required this.systems, + required this.topics, + }); + + int quizId; + String name; + String score; + String date; + String status; + List questions; + String totalQuestions; + List subjects; + List systems; + List topics; + + factory Quiz.fromJson(Map json) => Quiz( + quizId: json["quizId"], + name: json["name"], + score: json["score"], + date: json["date"], + status: json["status"], + questions: List.from(json["questions"].map((x) => x)), + totalQuestions: json["totalQuestions"], + subjects: List.from(json["subjects"].map((x) => x)), + systems: List.from(json["systems"].map((x) => x)), + topics: List.from(json["topics"].map((x) => x)), + ); + + Map toJson() => { + "quizId": quizId, + "name": name, + "score": score, + "date": date, + "status": status, + "questions": List.from(questions.map((x) => x)), + "totalQuestions": totalQuestions, + "subjects": List.from(subjects.map((x) => x)), + "systems": List.from(systems.map((x) => x)), + "topics": List.from(topics.map((x) => x)), + }; +} diff --git a/lib/screens/Authentication/login.dart b/lib/screens/Authentication/login.dart index b554aa3..f2c6e83 100644 --- a/lib/screens/Authentication/login.dart +++ b/lib/screens/Authentication/login.dart @@ -146,19 +146,21 @@ class _LoginState extends State { if(_isChecked == true) { storage.writeAuth(_email, _password); print("Email + Password: " + _email + _password); - final result = await Navigator.push( - context, - MaterialPageRoute(builder: (context) => const Home()), - ); + // final result = await Navigator.push( + // context, + // MaterialPageRoute(builder: (context) => const Home()), + // ); + Navigator.pushNamed(context, '/home'); } else { storage.writeAuth(_email, _password); storage.deleteFile(); print("Email + Password: " + _email + _password); - final result = await Navigator.push( - context, - MaterialPageRoute(builder: (context) => const Home()), - ); + // final result = await Navigator.push( + // context, + // MaterialPageRoute(builder: (context) => const Home()), + // ); + Navigator.pushNamed(context, '/home'); } } /*ScaffoldMessenger.of(context) @@ -388,55 +390,67 @@ class _LoginState extends State { ), ), SizedBox(height: (MediaQuery.of(context).size.height)*0.024838,), - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Row( - mainAxisAlignment: MainAxisAlignment.start, - children: [ - Container( - margin: EdgeInsets.only(top: 0, bottom: 0, left: (MediaQuery.of(context).size.width) *(45/428), right: 0,), - height: (MediaQuery.of(context).size.height)*0.0167, - width: (MediaQuery.of(context).size.height)*0.0167, - color: Colors.white, - child: Transform.scale( - scale: (MediaQuery.of(context).size.height)*0.001, - child: Checkbox( - side: BorderSide( - color: Color(0xffB0A6C2), - width: 0, + GestureDetector( + onTap: () { + if(_isChecked == false) + setState(() { + _isChecked = true; + }); + else if(_isChecked == true) + setState(() { + _isChecked = false; + }); + }, + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Container( + margin: EdgeInsets.only(top: 0, bottom: 0, left: (MediaQuery.of(context).size.width) *(45/428), right: 0,), + height: (MediaQuery.of(context).size.height)*0.0167, + width: (MediaQuery.of(context).size.height)*0.0167, + color: Colors.white, + child: Transform.scale( + scale: (MediaQuery.of(context).size.height)*0.001, + child: Checkbox( + side: BorderSide( + color: Color(0xffB0A6C2), + width: 0, + ), + checkColor: Colors.white, + value: _isChecked, + onChanged: (bool? value) { + setState(() { + _isChecked = value!; + }); + }, ), - checkColor: Colors.white, - value: _isChecked, - onChanged: (bool? value) { - setState(() { - _isChecked = value!; - }); - }, ), - ), - ), - Container( - padding: EdgeInsets.only(top: 0, bottom: 0, left: (MediaQuery.of(context).size.width) *(5/428), right: 0,), - child: Text("Remember me!", - style: TextStyle( - color: Color.fromRGBO(255, 255, 255, 100), - fontFamily: 'Brandon-med', - fontSize: (MediaQuery.of(context).size.height)*0.0161987, - ),), - ), - ], - ), - Container( - padding: EdgeInsets.only(top: 0, bottom: 0, left: 0, right: (MediaQuery.of(context).size.width) *(45/428),), - child: Text("Forgot Password?", - style: TextStyle( - color: Color(0xffFFFEFE), - fontFamily: 'Brandon-med', - fontSize: (MediaQuery.of(context).size.height)*0.0161987, - ),), - ), - ], + ), + Container( + padding: EdgeInsets.only(top: 0, bottom: 0, left: (MediaQuery.of(context).size.width) *(5/428), right: 0,), + child: Text("Remember me!", + style: TextStyle( + color: Color.fromRGBO(255, 255, 255, 100), + fontFamily: 'Brandon-med', + fontSize: (MediaQuery.of(context).size.height)*0.0161987, + ),), + ), + ], + ), + Container( + padding: EdgeInsets.only(top: 0, bottom: 0, left: 0, right: (MediaQuery.of(context).size.width) *(45/428),), + child: Text("Forgot Password?", + style: TextStyle( + color: Color(0xffFFFEFE), + fontFamily: 'Brandon-med', + fontSize: (MediaQuery.of(context).size.height)*0.0161987, + ),), + ), + ], + ), ), SizedBox(height: (MediaQuery.of(context).size.height) *0.0864,), ], diff --git a/lib/screens/Welcome/GenerateQuiz/generate_quiz.dart b/lib/screens/Welcome/GenerateQuiz/generate_quiz.dart index fc730dc..17cc89c 100644 --- a/lib/screens/Welcome/GenerateQuiz/generate_quiz.dart +++ b/lib/screens/Welcome/GenerateQuiz/generate_quiz.dart @@ -423,99 +423,6 @@ class _GenerateQuizState extends State with SingleTickerProviderSt ], ), SizedBox(height: (MediaQuery.of(context).size.height) *(25/926),), - Container( - // padding: EdgeInsets.only(left: (MediaQuery.of(context).size.width) *(28/428), right: (MediaQuery.of(context).size.width) *(28/428)), - height: (MediaQuery.of(context).size.height) *(35.32/926), - width: double.infinity, - // decoration: BoxDecoration( - // color: Color(0xff3F2668),//0xffB0A6C2, rgba(176, 166, 194, 1) - // ), - child: TabBar( - isScrollable: true, - controller: _tabController, - labelColor: Color(0xFF3F2668), - labelStyle: TextStyle( - color: Color(0xFF3F2668), - fontFamily: 'Brandon-bld', - fontSize: (MediaQuery.of(context).size.height) *(16/926), - ), - indicator: BoxDecoration( - color: Colors.transparent, - ), - indicatorColor: Color(0xFF3F2668), - unselectedLabelColor: Color(0xFFA1A1A1), - unselectedLabelStyle: TextStyle( - color: Color(0xFFA1A1A1), - fontFamily: 'Brandon-bld', - fontSize: (MediaQuery.of(context).size.height) *(16/926), - ), - labelPadding: EdgeInsets.only(top: (MediaQuery.of(context).size.height) *(0/926), bottom: (MediaQuery.of(context).size.height) *(0/926), - left: (MediaQuery.of(context).size.height) *(0/926), right: (MediaQuery.of(context).size.height) *(0/926)), - tabs: [ - Container( - width: (MediaQuery.of(context).size.width) *(5.5/43), - child: Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Tab(text: "Subjects"), - ], - ), - ), - Container( - width: (MediaQuery.of(context).size.width) *(7.5/43), - child: Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Container( - child: Icon(Icons.arrow_forward_ios, - size: (MediaQuery.of(context).size.width) *(15/428),),), - SizedBox(width: (MediaQuery.of(context).size.width) *(5/428)), - Tab(text: "Systems"), - ], - ) - ), - Container( - width: (MediaQuery.of(context).size.width) *(6.5/43), - child: Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Container( - child: Icon(Icons.arrow_forward_ios, - size: (MediaQuery.of(context).size.width) *(15/428),),), - SizedBox(width: (MediaQuery.of(context).size.width) *(5/428)), - Tab(text: "Topics"), - ], - ) - ), - Container( - width: (MediaQuery.of(context).size.width) *(8.5/43), - child: Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Container( - child: Icon(Icons.arrow_forward_ios, - size: (MediaQuery.of(context).size.width) *(15/428),),), - SizedBox(width: (MediaQuery.of(context).size.width) *(5/428)), - Tab(text: "Questions"), - ], - ) - ), - Container( - width: (MediaQuery.of(context).size.width) *(10.5/43), - child: Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Container( - child: Icon(Icons.arrow_forward_ios, - size: (MediaQuery.of(context).size.width) *(15/428),),), - SizedBox(width: (MediaQuery.of(context).size.width) *(5/428)), - Tab(text: "Generate Quiz"), - ], - ) - ), - ], - ), - ), SizedBox(height: (MediaQuery.of(context).size.height) *(13.28/926),), Container( height: (MediaQuery.of(context).size.height) *(596/926), @@ -553,7 +460,8 @@ class _GenerateQuizState extends State with SingleTickerProviderSt ), SizedBox(height: (MediaQuery.of(context).size.height) *(33/926)), Container( - width: (MediaQuery.of(context).size.width) *(386/428), + padding: EdgeInsets.only(left: (MediaQuery.of(context).size.width) *(10/428), right: (MediaQuery.of(context).size.width) *(10/428)), + width: (MediaQuery.of(context).size.width) *(366/428), child: _hasDataLoaded == false ? Container(height: (MediaQuery.of(context).size.height) *(460/926),child: Center(child: CircularProgressIndicator(color: Color(0xFF3F2668),))) : @@ -580,7 +488,7 @@ class _GenerateQuizState extends State with SingleTickerProviderSt style: TextStyle( color: subjectsEverything["isSelected"]![i] == true ? Colors.white : Color(0xFF3F3D56), fontFamily: 'Brandon-med', - fontSize: (MediaQuery.of(context).size.height)*(19/926), + fontSize: (MediaQuery.of(context).size.height)*(15/926), ),), onPressed: () { setState(() { @@ -732,7 +640,8 @@ class _GenerateQuizState extends State with SingleTickerProviderSt ), SizedBox(height: (MediaQuery.of(context).size.height) *(33/926)), Container( - width: (MediaQuery.of(context).size.width) *(386/428), + padding: EdgeInsets.only(left: (MediaQuery.of(context).size.width) *(10/428), right: (MediaQuery.of(context).size.width) *(10/428)), + width: (MediaQuery.of(context).size.width) *(366/428), child: Container( height: (MediaQuery.of(context).size.height) *(460/926), child: _hasDataLoaded == false ? Text("") : ListView( @@ -756,7 +665,7 @@ class _GenerateQuizState extends State with SingleTickerProviderSt style: TextStyle( color: systemsEverything["isSelected"]![i] == true ? Colors.white : Color(0xFF3F3D56), fontFamily: 'Brandon-med', - fontSize: (MediaQuery.of(context).size.height)*(19/926), + fontSize: (MediaQuery.of(context).size.height)*(15/926), ),), onPressed: () { if(_systemsDisabled == false) { @@ -819,9 +728,34 @@ class _GenerateQuizState extends State with SingleTickerProviderSt getQuestionsCount(); } else { - ScaffoldMessenger.of(context) - ..removeCurrentSnackBar() - ..showSnackBar(SnackBar(content: Text("Select Subjects First!"))); + showDialog( + context: context, + builder: (context) => AlertDialog( + content: Text( + 'Select Subjects First!', + style: TextStyle( + color: Color(0xffA1A1A1), + fontFamily: 'Brandon-bld', + fontSize: (MediaQuery.of(context).size.height) * (21 / 926), + ), + ), + actions: [ + Divider(), + TextButton( + onPressed: () { + Navigator.of(context).pop(); + }, + child: Text('Okay', + style: TextStyle( + color: Color(0xff3F2668), + fontFamily: 'Brandon-bld', + fontSize: + (MediaQuery.of(context).size.height) * (21 / 926), + )), + ), + ], + ), + ); } }, ), @@ -911,7 +845,7 @@ class _GenerateQuizState extends State with SingleTickerProviderSt children: [ Container( height: (MediaQuery.of(context).size.height) *(40.32/926), - width: (MediaQuery.of(context).size.width) *(386/428), + width: (MediaQuery.of(context).size.width) *(366/428), //color: Colors.red, decoration: BoxDecoration( color: Color(0xFF3F2668),//0xffB0A6C2, rgba(176, 166, 194, 1) @@ -936,7 +870,8 @@ class _GenerateQuizState extends State with SingleTickerProviderSt ), SizedBox(height: (MediaQuery.of(context).size.height) *(33/926)), Container( - width: (MediaQuery.of(context).size.width) *(386/428), + padding: EdgeInsets.only(left: (MediaQuery.of(context).size.width) *(10/428), right: (MediaQuery.of(context).size.width) *(10/428)), + width: (MediaQuery.of(context).size.width) *(366/428), child: Container( height: (MediaQuery.of(context).size.height) *(460/926), child: _hasDataLoaded == false ? Text("") : ListView( @@ -960,7 +895,7 @@ class _GenerateQuizState extends State with SingleTickerProviderSt style: TextStyle( color: topicsEverything["isSelected"]![i] == true ? Colors.white : Color(0xFF3F3D56), fontFamily: 'Brandon-med', - fontSize: (MediaQuery.of(context).size.height)*(19/926), + fontSize: (MediaQuery.of(context).size.height)*(15/926), ),), onPressed: () { if((_systemsDisabled == false) & (_topicsDisabled == false)) { @@ -986,9 +921,34 @@ class _GenerateQuizState extends State with SingleTickerProviderSt }); } else { - ScaffoldMessenger.of(context) - ..removeCurrentSnackBar() - ..showSnackBar(SnackBar(content: Text("Select Systems First!"))); + showDialog( + context: context, + builder: (context) => AlertDialog( + content: Text( + 'Select Systems First!', + style: TextStyle( + color: Color(0xffA1A1A1), + fontFamily: 'Brandon-bld', + fontSize: (MediaQuery.of(context).size.height) * (21 / 926), + ), + ), + actions: [ + Divider(), + TextButton( + onPressed: () { + Navigator.of(context).pop(); + }, + child: Text('Okay', + style: TextStyle( + color: Color(0xff3F2668), + fontFamily: 'Brandon-bld', + fontSize: + (MediaQuery.of(context).size.height) * (21 / 926), + )), + ), + ], + ), + ); } // print(subjectsEverything["finalTitles"]); // print(systemsEverything["finalTitles"]); @@ -1107,7 +1067,8 @@ class _GenerateQuizState extends State with SingleTickerProviderSt ), SizedBox(height: (MediaQuery.of(context).size.height) *(33/926)), Container( - width: (MediaQuery.of(context).size.width) *(386/428), + padding: EdgeInsets.only(left: (MediaQuery.of(context).size.width) *(10/428), right: (MediaQuery.of(context).size.width) *(10/428)), + width: (MediaQuery.of(context).size.width) *(366/428), height: (MediaQuery.of(context).size.height) *(460/926), child: Column( children: [ @@ -1119,7 +1080,7 @@ class _GenerateQuizState extends State with SingleTickerProviderSt children: [ Container( height: (MediaQuery.of(context).size.height) *(40.224/926), - width: (MediaQuery.of(context).size.width) *(312/428), + width: (MediaQuery.of(context).size.width) *(302/428), color: _questionTypeSelectedBool[i] == false ? Colors.white : Color(0xFF3F2668), child: TextButton( style: TextButton.styleFrom( @@ -1128,7 +1089,7 @@ class _GenerateQuizState extends State with SingleTickerProviderSt style: TextStyle( color: _questionTypeSelectedBool[i] == false ? Color(0xFF3F3D56) : Colors.white, fontFamily: 'Brandon-med', - fontSize: (MediaQuery.of(context).size.height)*(19/926), + fontSize: (MediaQuery.of(context).size.height)*(15/926), ),), onPressed: () { _questionTypesLogic(i); @@ -1144,7 +1105,8 @@ class _GenerateQuizState extends State with SingleTickerProviderSt }, child: Container( height: (MediaQuery.of(context).size.height) *(34.224/926), - width: (MediaQuery.of(context).size.width) *(29.224/428), + width: (MediaQuery.of(context).size.height) *(34.224/926), + // width: (MediaQuery.of(context).size.width) *(29.224/428), decoration: BoxDecoration( border: Border.all(width: 9, color: Color(0xFFA1A1A1)), borderRadius: BorderRadius.all(Radius.circular(50)), @@ -1374,6 +1336,7 @@ class _GenerateQuizState extends State with SingleTickerProviderSt if(_tutorMode == false) { setState(() { _tutorMode = true; + print(_tutorMode); }); } }, @@ -1404,6 +1367,7 @@ class _GenerateQuizState extends State with SingleTickerProviderSt if(_tutorMode == true) { setState(() { _tutorMode = false; + // print(_tutorMode); }); } }, @@ -1423,7 +1387,7 @@ class _GenerateQuizState extends State with SingleTickerProviderSt Row( children: [ Transform.scale( - scale: 0.82, + scale: 1, child: Container( height: (MediaQuery.of(context).size.height) *(20/926), child: Switch( @@ -1431,7 +1395,7 @@ class _GenerateQuizState extends State with SingleTickerProviderSt onChanged: (value) { setState(() { _timedMode = value; - print(_timedMode); + // print(_timedMode); }); }, activeColor: Color(0xff3F2668), @@ -1443,7 +1407,7 @@ class _GenerateQuizState extends State with SingleTickerProviderSt style: TextStyle( color: Color(0xff483A3A), fontFamily: 'Brandon-med', - fontSize: (MediaQuery.of(context).size.height) *(13/926) + fontSize: (MediaQuery.of(context).size.height) *(15/926) ), ), ), @@ -1603,7 +1567,7 @@ class _GenerateQuizState extends State with SingleTickerProviderSt if(_questionsCount > 0) { final result = Navigator.push( context, - MaterialPageRoute(builder: (context) => QuizModule(totalQuestions: _questionsCount, questions: _questions)), + MaterialPageRoute(builder: (context) => QuizModule(totalQuestions: _questionsCount, questions: _questions, timedMode: _timedMode,)), ); } }, diff --git a/lib/screens/Welcome/PreviousQuiz/previous_quiz.dart b/lib/screens/Welcome/PreviousQuiz/previous_quiz.dart new file mode 100644 index 0000000..69042d7 --- /dev/null +++ b/lib/screens/Welcome/PreviousQuiz/previous_quiz.dart @@ -0,0 +1,609 @@ + +import 'package:flutter/material.dart'; +import 'package:flutter_svg/flutter_svg.dart'; +import 'package:shared_preferences/shared_preferences.dart'; +import 'package:testify/models/GenerateQuizModels/get_system_categories_successful.dart'; +import 'package:testify/models/GenerateQuizModels/get_system_categories_unsuccessful.dart'; +import 'package:testify/models/GetPreviousQuizzesModel/get_previous_quizzes_model.dart'; +import 'package:testify/screens/Authentication/login.dart'; +import 'package:testify/screens/Welcome/PreviousQuiz/test_details.dart'; +import 'package:testify/screens/Welcome/PreviousQuiz/tile.dart'; +import '../side_menu_bar.dart'; +import 'package:http/http.dart' as http; +import 'dart:convert'; + +class PreviousQuiz extends StatefulWidget { + @override + _PreviousQuizState createState() => _PreviousQuizState(); +} + +class _PreviousQuizState extends State { + final filterList=['Filter By','Subjects','Systems','Topics']; + int filterIndex = 0; + String _currentfilter='Filter By'; + String _currentsubfilter='Filter By'; + int subFilterIndex = 0; + List subFilterList=['option1','option2']; + List subjectsSubFilterList = ["Select"]; + List systemsSubFilterList = ["Select"]; + List topicsSubFilterList = ["Select"]; + List filterSubFilterSelected = ["",""]; // 0: Filter, 1: SubFilter. + double? _swipeStartX; + String? _swipeDirection; + + bool hasPreviousQuizzesDataLoaded = false; + var previousQuizzesData = { + "quizId": [], + "name": [], + "score": [], + "date": [], + "status": [], + "questions": [], + "totalQuestions": [], + "subjects": [], + "systems": [], + "topics": [], + }; + + var previousQuizzesDataFiltered = { + "quizId": [], + "name": [], + "score": [], + "date": [], + "status": [], + "questions": [], + "totalQuestions": [], + "subjects": [], + "systems": [], + "topics": [], + }; + + //Shared Pref + var _token; + var _userId; + + // Token Valid + var _getSystemCategoriesSuccessful; + // Token Incorrect + var _getSystemCategoriesUnsuccessful; + + //Get Previous Quizzes + var _getPreviousQuizzesSuccessful; + + @override + void initState() { + super.initState(); + getPreviousQuizzes(); + getUserDataSST(); + } + + Future getPreviousQuizzes() async { + SharedPreferences prefs = await SharedPreferences.getInstance(); + final String apiUrlSystemCategories = "https://demo.pookidevs.com/quiz/generator/getPreviousQuizzes"; + _token = prefs.getString('token')!; + _userId = prefs.getInt("userId")!; + http.get(Uri.parse(apiUrlSystemCategories), headers: { + 'Content-type': 'application/json; charset=UTF-8', 'Authorization' : _token.toString(), + },).then((response) { + // print(jsonDecode(response.body)); + if(response.statusCode == 200) { + if(json.decode(response.body).toString().substring(0,20) == "{data: {status: true"){ + final responseString = (response.body); + var getPrevQuiz = getPreviousQuizzesModelFromJson(responseString); + final GetPreviousQuizzesModel getPreviousQuizzesSuccessful = getPrevQuiz; + setState(() { + _getPreviousQuizzesSuccessful = getPreviousQuizzesSuccessful; + }); + // print(_getPreviousQuizzesSuccessful.data.quizzes[0].quizId); + categorizePreviousQuizzesData(); + } + } + else { + //Token is Invalid + ScaffoldMessenger.of(context) + ..removeCurrentSnackBar() + ..showSnackBar(SnackBar(content: Text("Token Expired!"))); + final result = Navigator.push( + context, + MaterialPageRoute(builder: (context) => const Login(fromWhere:"Home")), + ); + } + } + ); + } + + categorizePreviousQuizzesData() { + int c = 0; + while((c<_getPreviousQuizzesSuccessful.data.quizzes.toList().length) & (_getPreviousQuizzesSuccessful.data.quizzes.toList().length > 0)) { + setState(() { + previousQuizzesData["quizId"]!.add(_getPreviousQuizzesSuccessful.data.quizzes[c].quizId); + previousQuizzesData["name"]!.add(_getPreviousQuizzesSuccessful.data.quizzes[c].name); + previousQuizzesData["score"]!.add(_getPreviousQuizzesSuccessful.data.quizzes[c].score); + previousQuizzesData["date"]!.add(_getPreviousQuizzesSuccessful.data.quizzes[c].date); + previousQuizzesData["status"]!.add(_getPreviousQuizzesSuccessful.data.quizzes[c].status); + previousQuizzesData["questions"]!.add(_getPreviousQuizzesSuccessful.data.quizzes[c].questions); + previousQuizzesData["totalQuestions"]!.add(_getPreviousQuizzesSuccessful.data.quizzes[c].totalQuestions); + previousQuizzesData["subjects"]!.add(_getPreviousQuizzesSuccessful.data.quizzes[c].subjects); + previousQuizzesData["systems"]!.add(_getPreviousQuizzesSuccessful.data.quizzes[c].systems); + previousQuizzesData["topics"]!.add(_getPreviousQuizzesSuccessful.data.quizzes[c].topics); + }); + c++; + } + setState(() { + hasPreviousQuizzesDataLoaded = true; + }); + print(previousQuizzesData); + } + + applyingPreviousQuizzesFilters() { + setState(() { + previousQuizzesDataFiltered["quizId"] = []; + previousQuizzesDataFiltered["name"] = []; + previousQuizzesDataFiltered["score"] = []; + previousQuizzesDataFiltered["date"] = []; + previousQuizzesDataFiltered["status"] = []; + previousQuizzesDataFiltered["questions"] = []; + previousQuizzesDataFiltered["totalQuestions"] = []; + previousQuizzesDataFiltered["subjects"] = []; + previousQuizzesDataFiltered["systems"] = []; + previousQuizzesDataFiltered["topics"] = []; + }); + if(filterSubFilterSelected[0] == "Subjects") { + for(int j = 0; j getUserDataSST() async { + SharedPreferences prefs = await SharedPreferences.getInstance(); + final String apiUrlSystemCategories = "https://demo.pookidevs.com/quiz/generator/getAllCategories"; + _token = prefs.getString('token')!; + _userId = prefs.getInt("userId")!; + // print(_userId); + // print(_token); + http.get(Uri.parse(apiUrlSystemCategories), headers: { + 'Content-type': 'application/json; charset=UTF-8', 'Authorization' : _token.toString(), + },).then((response) { + // print(jsonDecode(response.body).toString()); + if(response.statusCode == 200) { + if(json.decode(response.body).toString().substring(0,20) == "{data: {status: true") { + final responseString = (response.body); + var systemCategoriesDataSuccessful = getSystemCategoriesSuccessfulModelFromJson(responseString); + final GetSystemCategoriesSuccessfulModel getSystemCategoriesSuccessful = systemCategoriesDataSuccessful; + setState(() { + _getSystemCategoriesSuccessful = getSystemCategoriesSuccessful; + }); + // print(_questions); + } else { + + } + //Adds data to lists + categorizeUserData(); + } + else { // Status Code is 401 here that is why if written in the above if statement it would not work. + //Token is Invalid + if(json.decode(response.body).toString().substring(0,14) == "{status: false") { + final responseString = (response.body); + var systemCategoriesDataUnsuccessful = getSystemCategoriesUnsuccessfulModelFromJson(responseString); + final GetSystemCategoriesUnsuccessfulModel getSystemCategoriesUnsuccessful = systemCategoriesDataUnsuccessful; + setState(() { + _getSystemCategoriesUnsuccessful = getSystemCategoriesUnsuccessful; + }); + print(_getSystemCategoriesUnsuccessful.msg); + ScaffoldMessenger.of(context) + ..removeCurrentSnackBar() + ..showSnackBar(SnackBar(content: Text("Token Expired!"))); + final result = Navigator.push( + context, + MaterialPageRoute(builder: (context) => const Login(fromWhere:"Home")), + ); + } + else { + + } + } + } + ); + } + + //Add data to lists. Only done the first time. + categorizeUserData() { + //To clear any past data + int c = 0; + while((c<_getSystemCategoriesSuccessful.data.categories.toList().length) & (_getSystemCategoriesSuccessful.data.categories.toList().length > 0)) { + var tempLength = _getSystemCategoriesSuccessful.data.categories.toList().length; + if(_getSystemCategoriesSuccessful.data.categories[c].subCategories != null) { + if(_getSystemCategoriesSuccessful.data.categories[c].parentCategory.toString() == "systems") { + //Gets the length of subjects(Number of Subjects) + var lenSystems = _getSystemCategoriesSuccessful.data.categories[c].subCategories.toList().length; + int i = 0; + setState(() { + while((lenSystems>0) & (i0) & (i0) & (i[ + Color(0xff7F1AF1), + Color(0xff482384) + ]) + ), + ), + title: const Text("Previous Quiz", + style: TextStyle( + color: Color(0xffFFFEFE), + fontFamily: 'Brandon-bld', + ), + ), + actions: [ + TextButton( + onPressed: () async { + final result = await Navigator.push( + context, + MaterialPageRoute(builder: (context) => const Login(fromWhere:"Home")), + ); + }, + child: SvgPicture.asset( + "assets/Images/logout.svg", + height: (MediaQuery.of(context).size.height) *(32/926), + ), + ), + ], + ), + body: SingleChildScrollView( + child: Container( + padding: EdgeInsets.only(top:(MediaQuery.of(context).size.height) *(15/926), + bottom: (MediaQuery.of(context).size.height) *(8/926), + left: (MediaQuery.of(context).size.width) *(18/428), + right: (MediaQuery.of(context).size.width) *(18/428)), + child: Column( + children: [ + Row( + children: [ + Container( + width: (MediaQuery.of(context).size.width) *(221/428), + //height: (MediaQuery.of(context).size.height) *(91/926), + child: Column( + children: [ + Align( + alignment: Alignment.topLeft, + child: Text("Previous Quiz", + style: TextStyle( + color: Color(0xff232323), + fontFamily: 'Brandon-bld', + fontSize: (MediaQuery.of(context).size.height) *(25/926),//38, + ),), + ), + SizedBox(height: (MediaQuery.of(context).size.height) *(2/926),), + Text("Lorem ipsum dolor sit amet, consectetur adipiscing elit. Cras imperdiet finibus elit non luctus. Morbi auctor mattis ante.", + style: TextStyle( + color: Color(0xFF483A3A), + fontFamily: 'Brandon-med', + fontSize: (MediaQuery.of(context).size.height) *(13/926),//38, + ),), + ], + ), + ), + SizedBox(width: (MediaQuery.of(context).size.width) *(39/428),), + Container( + //color: Colors.transparent, + child: SvgPicture.asset( + "assets/Images/prevQuiz.svg", + height: (MediaQuery.of(context).size.height) *(100/926), + //width: (MediaQuery.of(context).size.width) *(132/428), + ), + ), + ], + ), + SizedBox(height: (MediaQuery.of(context).size.height)*(30/926),), + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Row( + children: [ + Text("Filter By: ", + style: TextStyle( + color: Color(0xFF483A3A), + fontFamily: 'Brandon-med', + fontSize: (MediaQuery.of(context).size.height) *(16/926),//38, + ),), + DropdownButton( + value: filterList[filterIndex], + underline: Container(), + iconEnabledColor: Color(0xff3F2668), + dropdownColor:Colors.white , + onChanged: (newValue) { + setState(() { + // print(newValue); + _currentfilter = newValue as String; + if(_currentfilter == filterList[1]){ + filterIndex = 1; + subFilterIndex = 0; + subFilterList = subjectsSubFilterList;} + else if(_currentfilter == filterList[2]){ + filterIndex = 2; + subFilterIndex = 0; + subFilterList = systemsSubFilterList;} + else if(_currentfilter == filterList[3]){ + filterIndex = 3; + subFilterIndex = 0; + subFilterList = topicsSubFilterList;} + else if(_currentfilter == filterList[0]){ + filterIndex = 0; + subFilterIndex = 0;} + filterSubFilterSelected[0] = _currentfilter; + applyingPreviousQuizzesFilters(); + // print(filterSubFilterSelected); + }); + }, + items: filterList.map((filter){ + return DropdownMenuItem( + child: Text(filter,style: TextStyle( + color: Color(0xff3F2668), + fontFamily: 'Brandon-bld', + fontSize: + (MediaQuery.of(context).size.height) * (16 / 926), + ),), + value: filter, + ); + }).toList(), + + + ), + ], + ), + // This below row is just for the if statement + if(_currentfilter != "Filter By") + Row( + children: [ + //SizedBox(width: (MediaQuery.of(context).size.width)*(40/428),), + Text(_currentfilter + ": ", + style: TextStyle( + color: Color(0xFF483A3A), + fontFamily: 'Brandon-med', + fontSize: (MediaQuery.of(context).size.height) *(16/926),//38, + ),), + DropdownButton( + value: (subFilterList.length<(subFilterIndex+1)) ? subFilterList[0] : subFilterList[subFilterIndex], + underline: Container(), + iconEnabledColor: Color(0xff3F2668), + dropdownColor:Colors.white , + onChanged: (newValue) { + setState(() { + // print(newValue); + subFilterIndex = 0; + _currentsubfilter = newValue as String; + for(int i = 0; i _swipeStartX!) ? "Right" : "Left"; + }, + onHorizontalDragEnd: (e) async { + if (_swipeDirection == "Right") + print("left"); + else if (_swipeDirection == "Left") { + print(previousQuizzesDataFiltered["system"]![i].toString()); + // final result = await Navigator.push( + // context, + // MaterialPageRoute( + // builder: (context) => TestDetails( + // quizId: previousQuizzesData["quizId"]![i], + // system: previousQuizzesData["system"]![i], + // subject: previousQuizzesData["subject"]![i], + // topic: previousQuizzesData["topic"]![i], + // score: previousQuizzesData["score"]![i], + // status: previousQuizzesData["status"]![i]))); + } + },), + ], + ) : + Column( + children: [ + SizedBox(height: (MediaQuery.of(context).size.height)*(30/926),), + GestureDetector(child: Tile( + name: previousQuizzesData["name"]![i], + quizId: previousQuizzesData["quizId"]![i], + status: previousQuizzesData["status"]![i], + score: previousQuizzesData["score"]![i], + systems: previousQuizzesData["systems"]![i], + questions: previousQuizzesData["questions"]![i], + date: previousQuizzesData["date"]![i], + topics: previousQuizzesData["topics"]![i], + subjects: previousQuizzesData["subjects"]![i], + totalQuestions: previousQuizzesData["totalQuestions"]![i],), + onHorizontalDragStart: (e) { + _swipeStartX = e.globalPosition.dx; + }, + onHorizontalDragUpdate: (e) { + _swipeDirection = + (e.globalPosition.dx > _swipeStartX!) ? "Right" : "Left"; + }, + onHorizontalDragEnd: (e) async { + if (_swipeDirection == "Right") + print("left"); + else if (_swipeDirection == "Left") { + print(previousQuizzesData["system"]![i].toString()); + // final result = await Navigator.push( + // context, + // MaterialPageRoute( + // builder: (context) => TestDetails( + // quizId: previousQuizzesData["quizId"]![i], + // system: previousQuizzesData["system"]![i], + // subject: previousQuizzesData["subject"]![i], + // topic: previousQuizzesData["topic"]![i], + // score: previousQuizzesData["score"]![i], + // status: previousQuizzesData["status"]![i]))); + } + },), + ], + ), + SizedBox(height: (MediaQuery.of(context).size.height)*(30/926),), + + ], + ), + ), + ), + ); + } +} diff --git a/lib/screens/Welcome/PreviousQuiz/test_details.dart b/lib/screens/Welcome/PreviousQuiz/test_details.dart new file mode 100644 index 0000000..d1960ef --- /dev/null +++ b/lib/screens/Welcome/PreviousQuiz/test_details.dart @@ -0,0 +1,386 @@ +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_svg/svg.dart'; + +import '../../Authentication/login.dart'; +import '../side_menu_bar.dart'; + +class TestDetails extends StatelessWidget { + final int quizId; + final List system; + final List subject; + final List topic; + final String status; + final String score; + TestDetails( + {required this.quizId, + required this.system, + required this.subject, + required this.topic, + required this.status, + required this.score}); + @override + Widget build(BuildContext context) { + return Scaffold( + backgroundColor: Color(0xffF8F9FB), + drawer: SideMenuBar(), + appBar: AppBar( + toolbarHeight: (MediaQuery.of(context).size.height) * (73.52 / 926), + backgroundColor: Color(0xff3F2668), + elevation: 2, + centerTitle: true, + flexibleSpace: Container( + decoration: const BoxDecoration( + gradient: LinearGradient( + begin: Alignment.topCenter, + end: Alignment.bottomCenter, + colors: [Color(0xff7F1AF1), Color(0xff482384)])), + ), + title: const Text( + "Test Details", + style: TextStyle( + color: Color(0xffFFFEFE), + fontFamily: 'Brandon-bld', + ), + ), + actions: [ + TextButton( + onPressed: () async { + final result = await Navigator.push( + context, + MaterialPageRoute( + builder: (context) => const Login(fromWhere: "Home")), + ); + }, + child: SvgPicture.asset( + "assets/Images/logout.svg", + height: (MediaQuery.of(context).size.height) * (32 / 926), + ), + ), + ], + ), + body: SingleChildScrollView( + child: Padding( + padding: const EdgeInsets.symmetric(vertical: 100), + child: Column( + children: [ + Center( + child: Container( + height: (MediaQuery.of(context).size.height) * (488 / 926), + width: (MediaQuery.of(context).size.width) * (385 / 428), + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(2), + color: Colors.white, + boxShadow: [ + BoxShadow(color: Colors.grey, offset: Offset(0, 4), blurRadius: 6) + ], + ), + child: Column( + children: [ + + Container( + height: (MediaQuery.of(context).size.height) * (59 / 926), + width: (MediaQuery.of(context).size.width) * (385 / 428), + color: Color(0xff6D5A8D), + child: Center( + child: Text( + 'Test Details', + style: TextStyle( + color: Colors.white, + fontFamily: 'Brandon-bld', + fontSize: (MediaQuery.of(context).size.height) * (20 / 926), + ), + ), + ), + ), + Container( + height: (MediaQuery.of(context).size.height) * (310 / 926), + width: (MediaQuery.of(context).size.width) * (385 / 428), + padding: EdgeInsets.all(25), + child: Table( + columnWidths: {0:FixedColumnWidth((MediaQuery.of(context).size.width) * (25 / 428)), + 1:FixedColumnWidth((MediaQuery.of(context).size.width) * (200 / 428))}, + border: TableBorder.all(color: Colors.transparent), + children: [ + TableRow(children: [ + Padding( + padding: const EdgeInsets.only(top:8.0), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + 'Quiz ID:', + style: TextStyle( + color: Color(0xff3F2668), + fontFamily: 'Brandon-bld', + fontSize: (MediaQuery.of(context).size.height) * + (16 / 926), + ), + ), + ], + ), + ), + Padding( + padding: const EdgeInsets.only(top:8.0), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text(quizId.toString(), + textAlign: TextAlign.start, + style: TextStyle( + color: Colors.black, + fontFamily: 'Brandon-med', + fontSize: (MediaQuery.of(context).size.height) * + (16 / 926), + )) + ], + ), + ) + ]), + TableRow(children: [ + Padding( + padding: const EdgeInsets.only(top:8.0), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + 'System:', + style: TextStyle( + color: Color(0xff3F2668), + fontFamily: 'Brandon-bld', + fontSize: (MediaQuery.of(context).size.height) * + (16 / 926), + ), + ), + ], + ), + ), + Padding( + padding: const EdgeInsets.only(top:8.0), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text(system.toString().substring(1, system.toString().length-1) == "" ? "-" : system.toString().substring(1, system.toString().length-1), + style: TextStyle( + color: Colors.black, + fontFamily: 'Brandon-med', + fontSize: (MediaQuery.of(context).size.height) * + (16 / 926), + )) + ], + ), + ) + ]), + TableRow(children: [ + Padding( + padding: const EdgeInsets.only(top:8.0), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + 'Subject:', + style: TextStyle( + color: Color(0xff3F2668), + fontFamily: 'Brandon-bld', + fontSize: (MediaQuery.of(context).size.height) * + (16 / 926), + ), + ), + ], + ), + ), + Padding( + padding: const EdgeInsets.only(top:8.0), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text(subject.toString().substring(1, subject.toString().length-1) == "" ? "-" : subject.toString().substring(1, subject.toString().length-1), + style: TextStyle( + color: Colors.black, + fontFamily: 'Brandon-med', + fontSize: (MediaQuery.of(context).size.height) * + (16 / 926), + )) + ], + ), + ) + ]), + TableRow(children: [ + Padding( + padding: const EdgeInsets.only(top:8.0), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + 'Topic:', + style: TextStyle( + color: Color(0xff3F2668), + fontFamily: 'Brandon-bld', + fontSize: (MediaQuery.of(context).size.height) * + (16 / 926), + ), + ), + ], + ), + ), + Padding( + padding: const EdgeInsets.only(top:8.0), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text(topic.toString().substring(1, topic.toString().length-1) == "" ? "-" : topic.toString().substring(1, topic.toString().length-1), + style: TextStyle( + color: Colors.black, + fontFamily: 'Brandon-med', + fontSize: (MediaQuery.of(context).size.height) * + (16 / 926), + )) + ], + ), + ) + ]), + TableRow(children: [ + Padding( + padding: const EdgeInsets.only(top:8.0), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + 'Score:', + style: TextStyle( + color: Color(0xff3F2668), + fontFamily: 'Brandon-bld', + fontSize: (MediaQuery.of(context).size.height) * + (16 / 926), + ), + ), + ], + ), + ), + Padding( + padding: const EdgeInsets.only(top:8.0), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text(score, + style: TextStyle( + color: Colors.black, + fontFamily: 'Brandon-med', + fontSize: (MediaQuery.of(context).size.height) * + (16 / 926), + )) + ], + ), + ) + ]), + TableRow(children: [ + Padding( + padding: const EdgeInsets.only(top:8.0), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + 'Status:', + style: TextStyle( + color: Color(0xff3F2668), + fontFamily: 'Brandon-bld', + fontSize: (MediaQuery.of(context).size.height) * + (16 / 926), + ), + ), + ], + ), + ), + Padding( + padding: const EdgeInsets.only(top:8.0), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text(status, + style: TextStyle( + color: Colors.black, + fontFamily: 'Brandon-med', + fontSize: (MediaQuery.of(context).size.height) * + (16 / 926), + )) + ], + ), + ) + ]) + ], + ), + ), + + Container( + height: (MediaQuery.of(context).size.height) * (70 / 926), + width: (MediaQuery.of(context).size.width) * (385 / 428), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + children: [ + Column( + children: [ + Container(height:40,width:40,decoration: BoxDecoration(color: Color(0xff7F1AF1),borderRadius: BorderRadius.circular(20)), + child: Icon(Icons.show_chart_outlined,size: 20,color:Colors.white)) + ,Text('Test Analysis',style: TextStyle( + color: Color(0xff7F1AF1), + fontFamily: 'Brandon-med', + fontSize: (MediaQuery.of(context).size.height) * (15 / 926), + ),) + ], + ), + Column( + children: [ + Container(height:40,width:40,decoration: BoxDecoration(color: Color(0xff7F1AF1),borderRadius: BorderRadius.circular(20)), + child: Icon(Icons.event_note_outlined,size: 20,color:Colors.white)) + ,Text('Test Results',style: TextStyle( + color: Color(0xff7F1AF1), + fontFamily: 'Brandon-med', + fontSize: (MediaQuery.of(context).size.height) * (15 / 926), + ),) + ], + ), + Column( + children: [ + Container(height:40,width:40,decoration: BoxDecoration(color: Color(0xff7F1AF1),borderRadius: BorderRadius.circular(20)), + child: Icon(Icons.arrow_right,size: 40,color:Colors.white)) + ,Text('Resume',style: TextStyle( + color: Color(0xff7F1AF1), + fontFamily: 'Brandon-med', + fontSize: (MediaQuery.of(context).size.height) * (15 / 926), + ),) + ], + ), + ], + ), + ) + + ], + ), + ), + ), + Padding( + padding: const EdgeInsets.all(20.0), + child: InkWell( + onTap:(){ + Navigator.of(context).pop(); + }, + child:Container( + child: Row( + children: [Icon(Icons.arrow_back,color: Color(0xff7F1AF1),size: 15,),Text('Back',style: TextStyle( + color: Color(0xff7F1AF1), + fontFamily: 'Brandon-bld', + fontSize: (MediaQuery.of(context).size.height) * + (13 / 926), + ),)], + + ), + )), + ) + ], + ), + ), + ), + ); + + } +} diff --git a/lib/screens/Welcome/PreviousQuiz/tile.dart b/lib/screens/Welcome/PreviousQuiz/tile.dart new file mode 100644 index 0000000..5f59667 --- /dev/null +++ b/lib/screens/Welcome/PreviousQuiz/tile.dart @@ -0,0 +1,137 @@ +import 'package:flutter/material.dart'; +import 'package:testify/screens/Welcome/PreviousQuiz/test_details.dart'; + +class Tile extends StatelessWidget { + final String name; + final int quizId; + final String status; + final String score; + final String date; + final List questions; + final String totalQuestions; + final List subjects; + final List systems; + final List topics; + Tile({required this.name, required this.quizId, required this.status, required this.score, required this.totalQuestions, required this.questions, required this.date, required this.subjects, required this.systems, required this.topics}); + @override + Widget build(BuildContext context) { + return Container( + height: (MediaQuery.of(context).size.height) * (84 / 926), + width: (MediaQuery.of(context).size.width) * (385 / 428), + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(2), + color: Colors.white, + boxShadow: [ + BoxShadow(color: Colors.grey, offset: Offset(0, 4), blurRadius: 6) + ], + ), + child: Row( + children: [ + Container( + height: (MediaQuery.of(context).size.height) * (84 / 926), + width: (MediaQuery.of(context).size.width) * (87 / 428), + color: Color(0xff6D5A8D), + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Text( + 'Quiz ID', + style: TextStyle( + color: Colors.white, + fontFamily: 'Brandon-bld', + fontSize: + (MediaQuery.of(context).size.height) * (18 / 926), + ), + ), + Text(quizId.toString(), + style: TextStyle( + color: Colors.white, + fontFamily: 'Brandon-med', + fontSize: + (MediaQuery.of(context).size.height) * (17 / 926), + )) + ], + )), + Container( + height: (MediaQuery.of(context).size.height) * (84 / 926), + width: (MediaQuery.of(context).size.width) * (248 / 428), + color: Colors.white, + padding: EdgeInsets.all( + (MediaQuery.of(context).size.height) * (16 / 926)), + child: Column( + children: [ + Row( + children: [ + Icon( + Icons.sticky_note_2_rounded, + color: Colors.grey, + ), + SizedBox( + width: (MediaQuery.of(context).size.width) * (12 / 428), + ), + Text( + name, + style: TextStyle( + color: Colors.black, + fontFamily: 'Brandon-med', + fontSize: + (MediaQuery.of(context).size.height) * (18 / 926), + ), + ) + ], + ), + Divider( + height: 1.5, + ), + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + score + ' / 100', + style: TextStyle( + color: Color(0xff6C63FF), + fontFamily: 'Brandon-med', + fontSize: + (MediaQuery.of(context).size.height) * (14 / 926), + ), + ), + Text( + status, + style: TextStyle( + color: Color(0xff6C63FF), + fontFamily: 'Brandon-med', + fontSize: + (MediaQuery.of(context).size.height) * (14 / 926), + ), + ), + ], + ) + ], + ), + ), + Container( + height: (MediaQuery.of(context).size.height) * (84 / 926), + width: (MediaQuery.of(context).size.width) * (50 / 428), + color: Colors.white, + child: IconButton( + icon: Icon(Icons.arrow_right, + color: Color(0xff6D5A8D), + size: (MediaQuery.of(context).size.height) * (60 / 926)), + onPressed: () async { + Navigator.of(context).pop(); + final result = await Navigator.push( + context, + MaterialPageRoute( + builder: (context) => TestDetails( + quizId: quizId, + system: systems, + subject: subjects, + topic: topics, + score: score, + status: status))); + })), + ], + ), + ); + } +} diff --git a/lib/screens/Welcome/QuizModule/buttons.dart b/lib/screens/Welcome/QuizModule/buttons.dart new file mode 100644 index 0000000..c702dde --- /dev/null +++ b/lib/screens/Welcome/QuizModule/buttons.dart @@ -0,0 +1,55 @@ +import 'package:flutter/material.dart'; + +// creating Stateless Widget for buttons +class MyButton extends StatelessWidget { + +// declaring variables + final color; + final textColor; + final String buttonText; + final buttontapped; + +//Constructor + MyButton({this.color, this.textColor, required this.buttonText, this.buttontapped}); + + @override + Widget build(BuildContext context) { + return Scaffold( + body: GestureDetector( + onTap: buttontapped, + child: Center( + child: Container( + height: 35, + width: 35, + decoration: BoxDecoration( + color: Colors.white, + boxShadow: [ + BoxShadow( + offset: Offset(0, 4), + blurRadius: 6, + color: Colors.black45//Color(0xFFF9F8F9), // background color + ), + ], + borderRadius: BorderRadius.circular(5), + ), + + child: Center( + child: Text( + buttonText, + style: TextStyle( + color: Colors.black, + fontFamily: 'Brandon-bld', + fontSize: (MediaQuery.of(context).size.height*(20/926)), + fontWeight: FontWeight.bold, + ), + ), + ), + ), + ), + ), + + + ); + } +} + diff --git a/lib/screens/Welcome/QuizModule/calculator.dart b/lib/screens/Welcome/QuizModule/calculator.dart new file mode 100644 index 0000000..b46b9d0 --- /dev/null +++ b/lib/screens/Welcome/QuizModule/calculator.dart @@ -0,0 +1,179 @@ +import 'package:flutter/material.dart'; +import 'buttons.dart'; +import 'package:math_expressions/math_expressions.dart'; +class Calculator extends StatefulWidget { + @override + _CalculatorState createState() => _CalculatorState(); +} + +class _CalculatorState extends State { + var userInput = ''; + var answer = ''; + final List buttons = [ + '7', + '8', + '9', + '%', + 'C', + '4', + '5', + '6', + 'x', + 'DEL', + '1', + '2', + '3', + '+', + '/', + '.', + '0', + '=', + '-', + + ]; + bool isOperator(String x) { + if (x == '/' || x == 'x' || x == '-' || x == '+' || x == '=') { + return true; + } + return false; + } +// function to calculate the input operation + void equalPressed() { + String finaluserinput = userInput; + finaluserinput = userInput.replaceAll('x', '*'); + + Parser p = Parser(); + Expression exp = p.parse(finaluserinput); + ContextModel cm = ContextModel(); + double eval = exp.evaluate(EvaluationType.REAL, cm); + answer = eval.toString(); + } + @override + Widget build(BuildContext context) { + return AlertDialog( + content: SizedBox( + height: (MediaQuery.of(context).size.height)*(310/926), + width: (MediaQuery.of(context).size.width)*(237/428), + child: Container( + padding: EdgeInsets.all(0), + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(5), + color: Colors.white + ), + child: Column( + children: [ + + Container( + width: (MediaQuery.of(context).size.width)*(237/428), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Container( + alignment: Alignment.centerLeft, + child: Text( + userInput, + style: TextStyle( + color: Color(0xff7F1AF1), + fontFamily: 'Brandon-bld', + fontSize: (MediaQuery.of(context).size.height) * (20 / 926), + ), + ),), + Spacer(), + Container( + alignment: Alignment.centerRight, + child: Text( + answer, + style: TextStyle( + color: Color(0xff7F1AF1), + fontFamily: 'Brandon-bld', + fontSize: (MediaQuery.of(context).size.height) * (29 / 926), + ), + ), + ), + + ]), + ), + Divider(), + Container( + height: (MediaQuery.of(context).size.height)*(237/926), + width: (MediaQuery.of(context).size.width)*(310/428), + padding: EdgeInsets.all(8), + child: GridView.builder(itemCount: buttons.length,gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 5, crossAxisSpacing: 2.0, + mainAxisSpacing: 2.0,mainAxisExtent: 40), itemBuilder: (BuildContext context, int index) { + // Clear Button + if (index == 4) { + return MyButton( + buttontapped: () { + setState(() { + userInput = ''; + answer = '0'; + }); + }, + buttonText: buttons[index], + + ); + } + + // % Button + else if (index == 3) { + return MyButton( + buttontapped: () { + setState(() { + userInput += buttons[index]; + }); + }, + buttonText: buttons[index], + + ); + } + // Delete Button + else if (index == 9) { + return MyButton( + buttontapped: () { + setState(() { + userInput = + userInput.substring(0, userInput.length - 1); + }); + }, + buttonText: buttons[index], + + );} + // Equal_to Button + else if (index == 17) { + return MyButton( + buttontapped: () { + setState(() { + equalPressed(); + }); + }, + buttonText: buttons[index], + + ); + } + // other buttons + else { + return MyButton( + buttontapped: () { + setState(() { + userInput += buttons[index]; + }); + }, + buttonText: buttons[index], + + ); + } + }), + ) + + ], + ), + ), + ), + ); + } + + + } + + + diff --git a/lib/screens/Welcome/QuizModule/question_explanation.dart b/lib/screens/Welcome/QuizModule/question_explanation.dart new file mode 100644 index 0000000..f86203c --- /dev/null +++ b/lib/screens/Welcome/QuizModule/question_explanation.dart @@ -0,0 +1,372 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_countdown_timer/flutter_countdown_timer.dart'; +import 'package:flutter_svg/svg.dart'; +import 'package:testify/screens/Welcome/side_menu_bar.dart'; + +class QuestionExplanation extends StatefulWidget { + const QuestionExplanation({Key? key, required this.questionId, required this.question, required this.correctAnswer, required this.explanation}) : super(key: key); + + final int questionId; + final String question; + final String correctAnswer; + final String explanation; + + @override + State createState() => _QuestionExplanationState(); +} + +class _QuestionExplanationState extends State { + int endTime = DateTime.now().millisecondsSinceEpoch + 1000 * 30; + + void onEnd() { + print('onEnd'); + } + + @override + Widget build(BuildContext context) { + // print(widget.questionId); + // print(widget.question); + // print(widget.correctAnswer); + // print(widget.explanation); + return Scaffold( + backgroundColor: Color(0xffF8F9FB), + drawer: SideMenuBar(), + // drawer: moreMenu(), + appBar: AppBar( + toolbarHeight: (MediaQuery.of(context).size.height) * (73.52 / 926), + backgroundColor: Color(0xff3F2668), + elevation: 2, + centerTitle: true, + title: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Text( + 'Question ', + style: TextStyle( + color: Color(0xffffffff), + fontFamily: 'Brandon-bld', + fontSize: (MediaQuery.of(context).size.height) * (20 / 926), + ), + ), + ], + ), + flexibleSpace: Container( + decoration: const BoxDecoration( + gradient: LinearGradient( + begin: Alignment.topCenter, + end: Alignment.bottomCenter, + colors: [Color(0xff7F1AF1), Color(0xff482384)])), + ), + actions: [ + TextButton( + onPressed: () async { + }, + child: SvgPicture.asset( + "assets/Images/logout.svg", + height: (MediaQuery.of(context).size.height) *(32/926), + ), + ), + ], + ), + body: Column( + children: [ + Container( + height: ((MediaQuery.of(context).size.height) * ((926-73.52-50.88-(MediaQuery.of(context).padding.top)-8.1) / 926)), + child: ListView( + scrollDirection: Axis.vertical, + children: [ + Container( + padding: EdgeInsets.only( + top: (MediaQuery.of(context).size.height) * (15 / 926), + bottom: (MediaQuery.of(context).size.height) * (8 / 926), + left: (MediaQuery.of(context).size.width) * (18 / 428), + right: (MediaQuery.of(context).size.width) * (18 / 428)), + child: Column( + children: [ + Row( + children: [ + Container( + width: (MediaQuery.of(context).size.width) * (221 / 428), + //height: (MediaQuery.of(context).size.height) *(91/926), + child: Column( + children: [ + Align( + alignment: Alignment.topLeft, + child: Text( + "Attempt Your Quiz", + style: TextStyle( + color: Color(0xff232323), + fontFamily: 'Brandon-bld', + fontSize: (MediaQuery.of(context).size.height) * + (20 / 926), //38, + ), + ), + ), + SizedBox( + height: (MediaQuery.of(context).size.height) * + (2 / 926), + ), + Align( + alignment: Alignment.topLeft, + child: Text( + "Question ID: " + widget.questionId.toString(), // questionNumber + style: TextStyle( + color: Color(0xFF7F1AF1), + fontFamily: 'Brandon-med', + fontSize: (MediaQuery.of(context).size.height) * + (13 / 926), //38, + ), + ), + ) + ], + ), + ), + SizedBox( + width: (MediaQuery.of(context).size.width) * (39 / 428), + ), + // for timer + Container( + height: (MediaQuery.of(context).size.height) * (25 / 926), + width: (MediaQuery.of(context).size.width) * (107 / 428), + color: Color(0xFF3F2668), + child: Row( + children: [ + Text(' Time Left ', + style: TextStyle( + color: Color(0xFFFFFFFF), + fontFamily: 'Brandon-med', + fontSize: (MediaQuery.of(context).size.height) * + (7 / 926), + )), + CountdownTimer( + textStyle: TextStyle( + color: Color(0xFFFFFFFF), + fontFamily: 'Brandon-med', + fontSize: (MediaQuery.of(context).size.height) * + (13 / 926), + ), + endTime: endTime, + onEnd: onEnd, + endWidget: Text( + "00 : 00 : 00", + style: TextStyle( + color: Color(0xFFFFFFFF), + fontFamily: 'Brandon-med', + fontSize: (MediaQuery.of(context).size.height) * + (13 / 926), + ), + ), + ), + ], + ), + ) + ], + ), + SizedBox( + height: (MediaQuery.of(context).size.height) * (35.47 / 926), + ), + Text( + widget.question, + style: TextStyle( + color: Color(0xFF483A3A), + fontFamily: 'Brandon-med', + fontSize: + (MediaQuery.of(context).size.height) * (18 / 926), //38, + ), + ), + SizedBox( + height: (MediaQuery.of(context).size.height) * (25 / 926), + ), + Align( + alignment: Alignment.topLeft, + child: Text( + "Correct Answer: ", // questionNumber + style: TextStyle( + color: Color(0xFF7F1AF1), + fontFamily: 'Brandon-med', + fontSize: (MediaQuery.of(context).size.height) * + (13 / 926), //38, + ), + ), + ), + SizedBox( + height: (MediaQuery.of(context).size.height) * (10.75 / 926), + ), + Container( + // height: (MediaQuery.of(context).size.height) * (50 / 926), + // width: (MediaQuery.of(context).size.width) * (385 / 428), + padding: EdgeInsets.only( + top: (MediaQuery.of(context).size.height) * (8 / 928), + left: (MediaQuery.of(context).size.width) * (13 / 428), + bottom: (MediaQuery.of(context).size.height) * (8 / 928), + ), + decoration: BoxDecoration( + color: Color(0xFF3F2668), + border: Border.all( + color: Color(0xFF3F2668), + ), + borderRadius: BorderRadius.all(Radius.circular(0)) + ), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Container( + width: (MediaQuery.of(context).size.width) * (300 / 428), + child: Text(widget.correctAnswer, + style: TextStyle( + color: Colors.white, + fontFamily: 'Brandon-med', + fontSize: (MediaQuery.of(context).size.height) * + (18 / 926), //38, + )), + ), + ], + )), + SizedBox( + height: (MediaQuery.of(context).size.height) * (20.2 / 926), + ), + Align( + alignment: Alignment.topLeft, + child: Text( + "Explanation: ", // questionNumber + style: TextStyle( + color: Color(0xFF7F1AF1), + fontFamily: 'Brandon-med', + fontSize: (MediaQuery.of(context).size.height) * + (13 / 926), //38, + ), + ), + ), + SizedBox( + height: (MediaQuery.of(context).size.height) * (10.75 / 926), + ), + Text( + widget.explanation, + style: TextStyle( + color: Color(0xFF483A3A), + fontFamily: 'Brandon-med', + fontSize: + (MediaQuery.of(context).size.height) * (18 / 926), //38, + ), + ), + SizedBox( + height: (MediaQuery.of(context).size.height) * (20.75 / 926), + ), + TextButton( + onPressed: () { + Navigator.of(context).pop(); + }, + style: TextButton.styleFrom( + padding: EdgeInsets.zero,), + child: Row( + children: [ + Container( + child: Icon(Icons.arrow_back, + color: Color(0xFF7F1AF1), + size: (MediaQuery.of(context).size.height) * + (15 / 926),), + ), + SizedBox(width: (MediaQuery.of(context).size.width) * + (3 / 428),), + Text( + "Back to Question", // questionNumber + style: TextStyle( + color: Color(0xFF7F1AF1), + fontFamily: 'Brandon-med', + fontSize: (MediaQuery.of(context).size.height) * + (13 / 926), //38, + ), + ), + ], + ), + ), + ], + )), + ], + ), + ) , + Align( + alignment: Alignment.bottomCenter, + child: Container( + height: ((MediaQuery.of(context).size.height) * (51 / 926)), + color: Colors.grey, + // decoration: const BoxDecoration( + // gradient: LinearGradient( + // begin: Alignment.topCenter, + // end: Alignment.bottomCenter, + // colors: [Color(0xff7F1AF1), Color(0xff482384)])), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + TextButton( + onPressed: null, + style: TextButton.styleFrom( + padding: EdgeInsets.zero,), + child: Row( + children: [ + SizedBox(width: (MediaQuery.of(context).size.width) * (16 / 428)), + Container( + child: Icon(Icons.arrow_back_ios_outlined, + color: Color(0xFFE4E4E4), + size: ((MediaQuery.of(context).size.width) * (23.1 / 428)),), + ), + ], + ), + ), + TextButton( + onPressed: null, + style: TextButton.styleFrom( + padding: EdgeInsets.zero,), + child: Row( + children: [ + Container( + width: ((MediaQuery.of(context).size.height) * (15 / 926)), + decoration: BoxDecoration( + color: Color(0xFFE4E4E4), + shape: BoxShape.circle + ), + ), + SizedBox(width: (MediaQuery.of(context).size.width) * (6 / 428)), + Container( + width: ((MediaQuery.of(context).size.height) * (15 / 926)), + decoration: BoxDecoration( + color: Color(0xFFE4E4E4), + shape: BoxShape.circle + ), + ), + SizedBox(width: (MediaQuery.of(context).size.width) * (6 / 428)), + Container( + width: ((MediaQuery.of(context).size.height) * (15 / 926)), + decoration: BoxDecoration( + color: Color(0xFFE4E4E4), + shape: BoxShape.circle + ), + ), + ], + ), + ), + TextButton( + onPressed: null, + style: TextButton.styleFrom( + padding: EdgeInsets.zero,), + child: Row( + children: [ + Container( + child: Icon(Icons.arrow_forward_ios_outlined, + color: Color(0xFFE4E4E4), + size: ((MediaQuery.of(context).size.width) * (23.1 / 428)),), + ), + SizedBox(width: (MediaQuery.of(context).size.width) * (16 / 428)), + ], + ), + ), + ], + ), + ), + ) + ], + ), + ); + } +} diff --git a/lib/screens/Welcome/QuizModule/quiz_module.dart b/lib/screens/Welcome/QuizModule/quiz_module.dart new file mode 100644 index 0000000..6224bc3 --- /dev/null +++ b/lib/screens/Welcome/QuizModule/quiz_module.dart @@ -0,0 +1,1402 @@ +import 'dart:async'; +import 'dart:convert'; +import 'dart:math' as math; + +import 'package:flutter/material.dart'; +import 'package:flutter_countdown_timer/current_remaining_time.dart'; +import 'package:flutter_countdown_timer/flutter_countdown_timer.dart'; +import 'package:http/http.dart' as http; +import 'package:testify/models/GenerateQuizModels/QuizModuleModels/generate_quiz_model.dart'; +import 'package:testify/screens/Authentication/login.dart'; +import 'package:testify/screens/Welcome/QuizModule/question_explanation.dart'; +import 'package:testify/screens/Welcome/QuizModule/search_bar.dart'; +import 'package:testify/screens/Welcome/side_menu_bar.dart'; +import 'package:testify/screens/Welcome//QuizModule/calculator.dart'; +import 'package:flutter_svg/flutter_svg.dart'; +import 'package:shared_preferences/shared_preferences.dart'; +import 'package:flutter/cupertino.dart'; + +class QuizModule extends StatefulWidget { + const QuizModule({Key? key, required this.totalQuestions, required this.questions, required this.timedMode}) : super(key: key); + + final int totalQuestions; + final List questions; + final bool timedMode; + @override + _QuizModuleState createState() => _QuizModuleState(); +} + +class _QuizModuleState extends State { + int endTime = DateTime.now().millisecondsSinceEpoch + 1000 * 30; + List _questions = ['1', '2', '3', '4']; + String _currentQuestion = '1'; + int _currentSelected = 0; + String _labValues="Lorem ipsum dolor sit amet, consectetur adipiscing elit. Cras imperdiet finibus elit non luctus. Morbi auctor mattis ante. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Cras imperdiet finibus elit non luctus. Morbi auctor mattis ante."; + String _note="Lorem ipsum dolor sit amet, consectetur adipiscing elit. Cras imperdiet finibus elit non luctus. Morbi auctor mattis ante. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Cras imperdiet finibus elit non luctus. Morbi auctor mattis ante."; + late TextEditingController _textController; + double _fontSize = 18; // To change font size + bool _showTextZoom = false; // To show ths slider + + int timeElapsed = 0; + /// declare a timer + Timer? timer; + // Timer? saveQuiz; // Saves quiz every few seconds. + + //BottomNavBar + int _selectedIndex = 0; + + // This key is used to open the side drawer + final GlobalKey _scaffoldKey = new GlobalKey(); + + //Shared Pref + var _token; + var _userId; + + //Model Data + var _getGenerateQuizSuccessful; + var _quizId; + + //Changing quiz questions + // This changes the array index which in turn changes the rest. + int questionNumber = 0; + + //To change Icon and color + int whichOption = 0; + + // To void null safety error + bool hasDataLoaded = false; + bool ranSaveQuizAtTheStart = false; // To auto save the quiz at the start and avoid the quizzes from being suspended + // if(hasDataLoaded = true) { + // if(ranSaveQuizAtTheStart = false) { + // SaveQuizAPI(); + // setState(() { + // ranSaveQuizAtTheStart = true; + // }); + // } + // } + + //Storing the data required to display quiz questions and store their answers + var questionsData = { + "title": [], + "ID": [], + "question": [], + "correct_msg": [], // This is the explanation + "options": [], // A list would be added to this list + "statistics": [], // [1, 0, 0] + "answeredCorrectly": [], // Stores string and turns true if answered correctly. Can't be a bool since values are correct/incorrect/notAnswered + "optionSelectedInt": [], //To change Icon and color + // "isSelected": [] + }; + + @override + void initState() { + super.initState(); + _textController = TextEditingController(); + GenerateQuizAPI(); + timer = Timer.periodic( + const Duration(seconds: 1), + (timer) { + setState(() { + timeElapsed++; + }); + }, + ); + + // saveQuiz = Timer.periodic( + // const Duration(seconds: 10), + // (timer) { + // SaveQuizAPI(); + // }, + // ); + } + + Future submitAnswerAPI(int? indexOfOptionThatIsActuallyCorrect, int? correct, int? optionIndexSelected) async { + final String apiUrlGenerateQuiz = "https://demo.pookidevs.com/quiz/solver/submitAnswer"; + + // print("user id: "+ _userId.toString()); + // print("questionId: "+ questionsData["id"]![questionNumber].toString()); + // print("quizId: "+ _getGenerateQuizSuccessful.data.quizId.toString()); + // print("indexOfOptionThatIsActuallyCorrect: " + indexOfOptionThatIsActuallyCorrect.toString()); + // print("correct: " + correct.toString()); + // print("optionIndexSelected: " + optionIndexSelected.toString()); + + + + http.post(Uri.parse(apiUrlGenerateQuiz), headers: { + 'Content-type': 'application/json; charset=UTF-8', 'Authorization' : _token.toString(), + }, body: json.encode( + { + "data":{ + "userId": _userId.toString(), + "questionId": questionsData["id"]![questionNumber].toString(), + "quizId": _getGenerateQuizSuccessful.data.quizId.toString(), + "answerMeta":{ + "index": questionsData["id"]![questionNumber].toString(), + "Correctanswerindex": indexOfOptionThatIsActuallyCorrect.toString(), // indexOfOptionThatIsActuallyCorrect + "correct": correct.toString(), // Correct = 1 if answer is correct, -1 if answer is omitted and 0 if answer is incorrect + "optionIndexSelected": optionIndexSelected.toString() + } + } + }) + ).then((response) { + // print(jsonDecode(response.body).toString()); + if((response.statusCode == 200)) { + print(jsonDecode(response.body).toString()); + if(jsonDecode(response.body) == "{data: {status: true, message: Answer Submitted}}") { + + } else { + ScaffoldMessenger.of(context) + ..removeCurrentSnackBar() + ..showSnackBar(SnackBar(content: Text("Error! Answer not Saved!"))); + } + } + else { // Token Invalid + + } + } + ); + } + + + Future SaveQuizAPI() async { + SharedPreferences prefs = await SharedPreferences.getInstance(); + prefs.setInt("quizId", _getGenerateQuizSuccessful.data.quizId); + final String apiUrlGenerateQuiz = "https://demo.pookidevs.com/quiz/solver/saveQuiz"; + + var date = new DateTime.now().toString().split("."); + int quizScore = 0; + bool allQuestionsAreAnswered = true; + int totalQuizTime = timeElapsed; + for(int i = 0; i{ + 'Content-type': 'application/json; charset=UTF-8', 'Authorization' : _token.toString(), + }, body: json.encode( + { + "data": + { + "quiz" : { + "quizId": _getGenerateQuizSuccessful.data.quizId, + "quizTitle": "Custom Quiz" + date[0].toString(), // "Custom Quiz" + Date.now() + "quizDate": date[0].toString(), // "Custom Quiz" + "quizScore": quizScore.toString(), // total correct + "quizTotalQuestions": widget.totalQuestions, + "quizStatus": allQuestionsAreAnswered ? "completed" : "suspended", // "completed", "suspended" + "quizQuestions": widget.questions.toString(), // Question IDs + "quizMode":"tutor", // "tutor", "exam" + "quizTime": totalQuizTime.toString(), // total quiz time in seconds + "isTimed": widget.timedMode, // bool true or false + "omittedQuestions": [], // Don't send anything here + "SelectedOptionsArray": [] // Don't send anything here + }, + "userId": _userId + } + } + + ) + ).then((response) { + print(jsonDecode(response.body).toString()); + if((response.statusCode == 200) & (json.decode(response.body).toString().substring(0,14) != "{status: false")) { + + } + else { // Token Invalid + + } + } + ); + } + + Future GenerateQuizAPI() async { + SharedPreferences prefs = await SharedPreferences.getInstance(); + final String apiUrlGenerateQuiz = "https://demo.pookidevs.com/quiz/generator/generateQuiz"; + _token = prefs.getString('token')!; + _userId = prefs.getInt("userId")!; + http.post(Uri.parse(apiUrlGenerateQuiz), headers: { + 'Content-type': 'application/json; charset=UTF-8', 'Authorization' : _token.toString(), + }, body: json.encode( + { + "data": + { + "questionIds": widget.questions, + "count": widget.totalQuestions + } + }) + ).then((response) { + // print("This is: " + jsonDecode(response.body).toString()); + if((response.statusCode == 200) & (json.decode(response.body).toString().substring(0,14) != "{status: false")) { + final responseString = (response.body); + var generateQuizSuccessful = generateQuizSuccessfulFromJson(responseString); + final GenerateQuizSuccessful getGenerateQuizSuccessful = generateQuizSuccessful; + setState(() { + _getGenerateQuizSuccessful = getGenerateQuizSuccessful; + _quizId = _getGenerateQuizSuccessful.data.quizId; + print(_quizId); + }); + categoriesGenerateQuizData(); + } + else { // Token Invalid + + } + } + ); + } + + Future BookmarkQuestionAPI() async { + final String apiUrlGenerateQuiz = "https://demo.pookidevs.com/quiz/solver/markQuestion"; + http.post(Uri.parse(apiUrlGenerateQuiz), headers: { + 'Content-type': 'application/json; charset=UTF-8', 'Authorization' : _token.toString(), + }, body: json.encode( + { + "data": { + "userId": _userId, + "questionId": questionsData["id"]![questionNumber].toString(), + "tableName": "marked_questions", + "isMarked": true + } + }) + ).then((response) { + print(jsonDecode(response.body).toString()); + if((response.statusCode == 200) & (json.decode(response.body).toString().substring(0,14) != "{status: false")) { + + } + else { // Token Invalid + + } + } + ); + } + + Future addNotesAPI() async { + // print(_userId); + // print(questionsData["id"]![questionNumber].toString()); + // print(_quizId); + // print(_note); + final String apiUrlGenerateQuiz = "https://demo.pookidevs.com/quiz/notes/addNotes"; + http.post(Uri.parse(apiUrlGenerateQuiz), headers: { + 'Content-type': 'application/json; charset=UTF-8', 'Authorization' : _token.toString(), + }, body: json.encode( + { + "data": { + "userId": _userId, + "questionId": questionsData["id"]![questionNumber].toString(), + "quizId": _quizId, + "note": _note, + "tableName": "notes" + } + } + ) + ).then((response) { + // print(jsonDecode(response.body).toString()); + // print(json.decode(response.body).toString().substring(json.decode(response.body).toString().length-12,json.decode(response.body).toString().length)); + if((response.statusCode == 200) & (json.decode(response.body).toString().substring(json.decode(response.body).toString().length-12,json.decode(response.body).toString().length) == "Note Added}}")) { + ScaffoldMessenger.of(context) + ..removeCurrentSnackBar() + ..showSnackBar(SnackBar(content: Text("Note Added!"))); + } + else if((response.statusCode == 200) & (json.decode(response.body).toString().substring(0,14) == "{status: false")) { // Token Invalid + ScaffoldMessenger.of(context) + ..removeCurrentSnackBar() + ..showSnackBar(SnackBar(content: Text("Token Expired!"))); + final result = Navigator.push( + context, + MaterialPageRoute(builder: (context) => const Login(fromWhere:"Home")), + ); + } + else { + ScaffoldMessenger.of(context) + ..removeCurrentSnackBar() + ..showSnackBar(SnackBar(content: Text("Note not Added!"))); + } + } + ); + } + + void categoriesGenerateQuizData() async { + setState(() { + questionsData["id"] = []; + questionsData["question"] = []; + questionsData["options"] = []; + questionsData["statistics"] = []; + questionsData["correct_msg"] = []; + questionsData["answeredCorrectly"] = []; + questionsData["optionSelectedInt"] = []; + _questions = []; + }); + int c = 0; + if(_getGenerateQuizSuccessful != null) { + while ((c < _getGenerateQuizSuccessful.data.questions + .toList() + .length) & (_getGenerateQuizSuccessful.data.questions + .toList() + .length > 0)) { + // questionsData + setState(() { + questionsData["id"]!.add( + _getGenerateQuizSuccessful.data.questions[c].id); + questionsData["question"]!.add( + _getGenerateQuizSuccessful.data.questions[c].question); + questionsData["options"]!.add( + _getGenerateQuizSuccessful.data.questions[c].options); + questionsData["statistics"]!.add( + _getGenerateQuizSuccessful.data.questions[c].statistics); + questionsData["correct_msg"]!.add( + _getGenerateQuizSuccessful.data.questions[c] + .correctMsg); //answeredCorrectly + questionsData["answeredCorrectly"]!.add("notAnswered"); + questionsData["optionSelectedInt"]!.add(0); + _questions.add((c+1).toString()); + }); + c++; + } + setState(() { + hasDataLoaded = true; + }); + if(hasDataLoaded == true) { + if(ranSaveQuizAtTheStart == false) { + SaveQuizAPI(); + setState(() { + ranSaveQuizAtTheStart = true; + }); + } + } + } + // print(questionsData); + } + + // To change text size - text zoom + Widget _textZoom(BuildContext context) { + return GestureDetector( + onTap: () { + }, + child: Container( + height: ((MediaQuery.of(context).size.height) * (51 / 926)), + decoration: const BoxDecoration( + gradient: LinearGradient( + begin: Alignment.topCenter, + end: Alignment.bottomCenter, + colors: [Color(0xff7F1AF1), Color(0xff482384)])), + child: new Slider( + value: _fontSize, + activeColor: Colors.white, + inactiveColor: Colors.red, + onChanged: (double value) { + setState(() { + _fontSize = value; + print(_fontSize); + }); + }, + divisions: 4, + min: 14.0, + max: 22.0, + ), + ), + ); + } + + + void onEnd() { + print('onEnd'); + } + + Widget bookmarkQuestion(BuildContext context) { + return SizedBox( + child: AlertDialog( + contentPadding: EdgeInsets.all(MediaQuery.of(context).size.width*(15/428)), + content: Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + 'Bookmark', + style: TextStyle( + color: Color(0xffB0A6C2), + fontFamily: 'Brandon-bld', + fontSize: (MediaQuery.of(context).size.height) * (18 / 926), + ), + ), + IconButton(icon:Icon(Icons.cancel),iconSize:23,color: Color(0xFF3F2668),onPressed: () { + Navigator.of(context).pop(); + },), + ], + ), + Divider(), + Text("Are you sure you want to bookmark this question", + ), + ], + ), + actions: [ + Divider(), + Row( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + TextButton( + onPressed: () { + Navigator.of(context).pop(); + }, + child: Text('No', + style: TextStyle( + color: Color(0xff3F2668), + fontFamily: 'Brandon-bld', + fontSize: + (MediaQuery.of(context).size.height) * (21 / 926), + )), + ), + Divider(), + TextButton( + onPressed: () { + Navigator.of(context).pop(); + print(questionsData["id"]![questionNumber].toString()); + BookmarkQuestionAPI(); + }, + child: Text('Yes', + style: TextStyle( + color: Color(0xff3F2668), + fontFamily: 'Brandon-bld', + fontSize: + (MediaQuery.of(context).size.height) * (21 / 926), + )), + ), + ], + ), + ], + ), + ); + } + + Widget labValues(BuildContext context) { + return SizedBox( + child: AlertDialog( + contentPadding: EdgeInsets.all(MediaQuery.of(context).size.width*(15/428)), + content: Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + 'Lab Values', + style: TextStyle( + color: Color(0xffB0A6C2), + fontFamily: 'Brandon-bld', + fontSize: (MediaQuery.of(context).size.height) * (18 / 926), + ), + ), + IconButton(icon:Icon(Icons.cancel),iconSize:23,color: Color(0xFF3F2668),onPressed: () { + Navigator.of(context).pop(); + },), + ], + ), + Divider(), + Text(_labValues), + ], + ), + ), + ); + } + Widget moreMenu() { + return Container( + width: (MediaQuery.of(context).size.width) * 0.3, + child: Drawer( + child: Container( + decoration: const BoxDecoration( + gradient: LinearGradient( + begin: Alignment.topRight, + end: Alignment.bottomLeft, + colors: [Color(0xff3F2668), Color(0xff482384)])), + child: ListView( + // Remove padding + padding: EdgeInsets.zero, + children: [ + Container( + padding: EdgeInsets.only( + top: MediaQuery.of(context).padding.top), + height: (MediaQuery.of(context).size.height), + color: Colors.transparent, + child: Column( + children: [ + ListTile( + leading: Icon( + Icons.close, + color: Colors.white, + ), + onTap: () => Navigator.pop(context), + ), + SizedBox( + height: + (MediaQuery.of(context).size.height) * (47 / 926), + ), + InkWell( + onTap: () { + Navigator.of(context).pop(); + // showDialog( + // context: context, + // builder: (BuildContext context) => + // labValues(context), + // ); + final result = Navigator.push( + context, + MaterialPageRoute(builder: (context) => SearchListExample()), + ); + }, + child: Container( + alignment: Alignment.center, + child: Column( + children: [ + SvgPicture.asset( + 'assets/Images/lab.svg', + height: (MediaQuery.of(context).size.height) * + (37 / 926), + color: Colors.white, + ), + SizedBox( + height: (MediaQuery.of(context).size.height) * + (10 / 926), + ), + Text( + 'Lab Values', + style: TextStyle( + color: Colors.white, + fontFamily: 'Brandon-bld', + fontSize: + (MediaQuery.of(context).size.height) * + (15 / 926), + ), + ) + ], + ), + ) + + //Divider(), + ), + SizedBox( + height: + (MediaQuery.of(context).size.height) * (47 / 926), + ), + InkWell( + onTap: () { + Navigator.of(context).pop(); + // bookmarkQuestion + showDialog( + context: context, + builder: (BuildContext context) => + bookmarkQuestion(context), + ); + }, + child: Container( + alignment: Alignment.center, + child: Column( + children: [ + Icon( + Icons.bookmark, + size: 37, + color: Colors.white, + ), + SizedBox( + height: (MediaQuery.of(context).size.height) * + (10 / 926), + ), + Text( + 'Bookmarks', + style: TextStyle( + color: Colors.white, + fontFamily: 'Brandon-bld', + fontSize: + (MediaQuery.of(context).size.height) * + (15 / 926), + ), + ) + ], + ), + ) + + //Divider(), + ), + SizedBox( + height: + (MediaQuery.of(context).size.height) * (47 / 926), + ), + InkWell( + onTap: () { + Navigator.of(context).pop(); + showDialog( + context: context, + builder: (BuildContext context) => + notes(context), + ); + }, + child: Container( + alignment: Alignment.center, + child: Column( + children: [ + Icon( + Icons.note_rounded, + size: 37, + color: Colors.white, + ), + SizedBox( + height: + (MediaQuery.of(context).size.height) * + (10 / 926), + ), + Text( + 'Notes', + style: TextStyle( + color: Colors.white, + fontFamily: 'Brandon-bld', + fontSize: + (MediaQuery.of(context).size.height) * + (15 / 926), + ), + ) + ], + ), + ) + + //Divider(), + ), + SizedBox( + height: + (MediaQuery.of(context).size.height) * (47 / 926), + ), + InkWell( + onTap:() {Navigator.of(context).pop(); + showDialog( + context: context, + builder: (BuildContext context) => + Calculator(), + );}, + child: Container( + alignment: Alignment.center, + child: Column( + children: [ + SvgPicture.asset('assets/Images/calculator.svg', + height: (MediaQuery.of(context).size.height) * + (37 / 926)), + SizedBox( + height: (MediaQuery.of(context).size.height) * + (10 / 926), + ), + Text( + 'Calculator', + style: TextStyle( + color: Colors.white, + fontFamily: 'Brandon-bld', + fontSize: + (MediaQuery.of(context).size.height) * + (15 / 926), + ), + ) + ], + ), + )), + SizedBox( + height: + (MediaQuery.of(context).size.height) * (47 / 926), + ), + InkWell( + onTap: () { + Navigator.of(context).pop(); + setState(() { + _showTextZoom = true; + }); + }, + child: Container( + alignment: Alignment.center, + child: Column( + children: [ + SvgPicture.asset('assets/Images/zoom.svg', + height: (MediaQuery.of(context).size.height) * + (37 / 926)), + SizedBox( + height: (MediaQuery.of(context).size.height) * + (10 / 926), + ), + Text( + 'Text Zoom', + style: TextStyle( + color: Colors.white, + fontFamily: 'Brandon-bld', + fontSize: + (MediaQuery.of(context).size.height) * + (15 / 926), + ), + ) + ], + ), + )) + ], + ), + ), + ]), + ))); + } + Widget notes(BuildContext context) { + return SizedBox( + child: AlertDialog( + contentPadding: EdgeInsets.all(MediaQuery.of(context).size.width*(15/428)), + content: Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + 'Take Notes', + style: TextStyle( + color: Color(0xffB0A6C2), + fontFamily: 'Brandon-bld', + fontSize: (MediaQuery.of(context).size.height) * (18 / 926), + ), + ), + IconButton(icon:Icon(Icons.cancel),iconSize:23,color: Color(0xFF3F2668),onPressed: () { + Navigator.of(context).pop(); + },), + ], + ), + Divider(), + TextField( + controller: _textController, + keyboardType: TextInputType.multiline, + minLines: 1,//Normal textInputField will be displayed + maxLines: 5,// when user presses enter it will adapt to it + decoration: InputDecoration( + hintText: "Add notes here...", + hintStyle: TextStyle(color: Color(0xffAEAEAE), + fontSize: (MediaQuery.of(context).size.height)*(15/926), + fontFamily: 'Brandon-med',), + contentPadding: EdgeInsets.fromLTRB(2.0, 1, 2.0, 1), + focusedBorder: OutlineInputBorder( + borderSide: BorderSide( + color: Colors.transparent, + width: 0.0, + ), + ), + ), + style: TextStyle( + color: Colors.black, + fontSize: (MediaQuery.of(context).size.height)*(15/926), + fontFamily: 'Brandon-med', + ), + onChanged: (String value) { + setState(() { + _note = value; + }); + }, + ), + Row( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + IconButton(onPressed:(){ + setState((){ + _note=''; + _textController.clear(); + } + ); + } , iconSize: 21 ,icon: Icon(Icons.refresh,color: Color(0xFF3F2668))), + TextButton( + onPressed: () { + addNotesAPI(); + _textController.clear(); + Navigator.of(context).pop(); + }, + style: TextButton.styleFrom( + padding: EdgeInsets.zero,), + child: Container( + height: (MediaQuery.of(context).size.height) * (31 / 926), + width:(MediaQuery.of(context).size.width) * (97 / 428), + decoration: BoxDecoration(borderRadius:BorderRadius.circular(4),color: Color(0xFFDDDAE2),), + child:Row( + mainAxisAlignment: MainAxisAlignment.center, + children:[ + Icon(Icons.save,color: Color(0xFF3F2668),), + SizedBox( + height: (MediaQuery.of(context).size.width) * + (14 / 428), + ), + Text( + 'Save', + style: TextStyle( + color: Color(0xff3F2668), + fontFamily: 'Brandon-bld', + fontSize: (MediaQuery.of(context).size.height) * (19 / 926), + ), + ), + ]) + ),) + ], + ) + ], + ), + ),);} + Future _onQuit() async { + return (await showDialog( + context: context, + builder: (context) => AlertDialog( + content: Text( + 'Do you want to quit the quiz', + style: TextStyle( + color: Color(0xffA1A1A1), + fontFamily: 'Brandon-bld', + fontSize: (MediaQuery.of(context).size.height) * (21 / 926), + ), + ), + actions: [ + TextButton( + onPressed: () => Navigator.of(context).pop(false), + child: Text('No', + style: TextStyle( + color: Color(0xff3F2668), + fontFamily: 'Brandon-bld', + fontSize: + (MediaQuery.of(context).size.height) * (21 / 926), + )), + ), + TextButton( + onPressed: () { + SaveQuizAPI(); + ScaffoldMessenger.of(context) + ..removeCurrentSnackBar() + ..showSnackBar(SnackBar(content: Text("The Quiz has been saved!"))); + Navigator.of(context).pop(true); + Navigator.of(context).pop(); + }, + child: Text('Yes', + style: TextStyle( + color: Color(0xff3F2668), + fontFamily: 'Brandon-bld', + fontSize: + (MediaQuery.of(context).size.height) * (21 / 926), + )), + ), + ], + ), + )) ?? + false; + } + + @override + void dispose() { + _textController.dispose(); + timer?.cancel(); + // saveQuiz?.cancel(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + return WillPopScope( + onWillPop: () async { + ScaffoldMessenger.of(context) + ..removeCurrentSnackBar() + ..showSnackBar(SnackBar(content: Text("Click on Quit Quiz!"))); + return false; + }, + child: Scaffold( + resizeToAvoidBottomInset: false, + backgroundColor: Color(0xffF8F9FB), + drawer: SideMenuBar(), + // drawer: moreMenu(), + endDrawer: moreMenu(), + appBar: AppBar( + toolbarHeight: (MediaQuery.of(context).size.height) * (73.52 / 926), + backgroundColor: Color(0xff3F2668), + elevation: 2, + centerTitle: true, + title: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Text( + 'Question ', + style: TextStyle( + color: Color(0xffffffff), + fontFamily: 'Brandon-bld', + fontSize: (MediaQuery.of(context).size.height) * (20 / 926), + ), + ), + DropdownButton( + value: (questionNumber + 1).toString(), + underline: Container(), + iconEnabledColor: Colors.white, + dropdownColor: Color(0xff3F2668), + onChanged: (newValue) { + setState(() { + print(newValue); + _currentQuestion = newValue as String; + questionNumber = int.parse(newValue) - 1; + }); + }, + items: _questions.map((question) { + return DropdownMenuItem( + child: new Text( + question + ' / ' + widget.totalQuestions.toString(), + style: TextStyle( + color: Colors.white, + fontFamily: 'Brandon-bld', + fontSize: + (MediaQuery.of(context).size.height) * (20 / 926), + ), + ), + value: question, + ); + }).toList(), + ), + ], + ), + flexibleSpace: Container( + decoration: const BoxDecoration( + gradient: LinearGradient( + begin: Alignment.topCenter, + end: Alignment.bottomCenter, + colors: [Color(0xff7F1AF1), Color(0xff482384)])), + ), + actions: [ + TextButton( + onPressed: () async { + SaveQuizAPI(); + }, + child: SvgPicture.asset( + "assets/Images/logout.svg", + height: (MediaQuery.of(context).size.height) *(32/926), + ), + ), + ], + ), + body: hasDataLoaded == false ? Center(child: CircularProgressIndicator()) : Column( + children: [ + GestureDetector( + onTap: () { + setState(() { + _showTextZoom = false; + }); + }, + child: Container( + height: ((MediaQuery.of(context).size.height) * ((926-73.52-50.88-(MediaQuery.of(context).padding.top)-8.1) / 926)), + child: ListView( + scrollDirection: Axis.vertical, + children: [ + Container( + padding: EdgeInsets.only( + top: (MediaQuery.of(context).size.height) * (15 / 926), + bottom: (MediaQuery.of(context).size.height) * (8 / 926), + left: (MediaQuery.of(context).size.width) * (18 / 428), + right: (MediaQuery.of(context).size.width) * (18 / 428)), + child: Column( + children: [ + Row( + children: [ + Container( + width: (MediaQuery.of(context).size.width) * (221 / 428), + //height: (MediaQuery.of(context).size.height) *(91/926), + child: Column( + children: [ + Align( + alignment: Alignment.topLeft, + child: Text( + "Attempt Your Quiz", + style: TextStyle( + color: Color(0xff232323), + fontFamily: 'Brandon-bld', + fontSize: (MediaQuery.of(context).size.height) * + (20 / 926), //38, + ), + ), + ), + SizedBox( + height: (MediaQuery.of(context).size.height) * + (2 / 926), + ), + Align( + alignment: Alignment.topLeft, + child: Text( + "Question ID: " + questionsData["id"]![questionNumber].toString(), // questionNumber + style: TextStyle( + color: Color(0xFF7F1AF1), + fontFamily: 'Brandon-med', + fontSize: (MediaQuery.of(context).size.height) * + (13 / 926), //38, + ), + ), + ) + ], + ), + ), + SizedBox( + width: (MediaQuery.of(context).size.width) * (39 / 428), + ), + // for timer + Container( + height: (MediaQuery.of(context).size.height) * (25 / 926), + width: (MediaQuery.of(context).size.width) * (87 / 428), + color: Color(0xFF3F2668), + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Text('', + style: TextStyle( + color: Color(0xFFFFFFFF), + fontFamily: 'Brandon-med', + fontSize: (MediaQuery.of(context).size.height) * + (7 / 926), + )), + CountdownTimer( + textStyle: TextStyle( + color: Color(0xFFFFFFFF), + fontFamily: 'Brandon-med', + fontSize: (MediaQuery.of(context).size.height) * + (13 / 926), + ), + endTime: endTime, + onEnd: onEnd, + endWidget: Text( + "00 : 00 : 00", + style: TextStyle( + color: Color(0xFFFFFFFF), + fontFamily: 'Brandon-med', + fontSize: (MediaQuery.of(context).size.height) * + (13 / 926), + ), + ), + ), + ], + ), + ) + ], + ), + SizedBox( + height: (MediaQuery.of(context).size.height) * (25 / 926), + ), + Text( + questionsData["question"]![questionNumber].toString(), + style: TextStyle( + color: Color(0xFF483A3A), + fontFamily: 'Brandon-med', + fontSize: + (MediaQuery.of(context).size.height) * (_fontSize / 926), //38, + ), + ), + SizedBox( + height: (MediaQuery.of(context).size.height) * (25 / 926), + ), + if(questionsData["options"] != null) + for(int i = 0; i QuestionExplanation(question: questionsData["question"]![questionNumber].toString(), correctAnswer: correctAns.toString(), questionId: questionsData["id"]![questionNumber], explanation: questionsData["correct_msg"]![questionNumber].toString(),)), + ); + }, + child: Container( + alignment: Alignment.topRight, + child: Text( + "See Explanation", + style: TextStyle( + color: Color(0xFF7F1AF1), + fontFamily: 'Brandon-med', + fontSize: (MediaQuery.of(context).size.height) * + (13 / 926), //38, + ), + ), + ), + ) : Container(), + SizedBox( + height: (MediaQuery.of(context).size.height) * (20 / 926), + ), + ], + ), + SizedBox( + height: (MediaQuery.of(context).size.height) * (5 / 926), + ), + SizedBox( + height: (MediaQuery.of(context).size.height) * (96 / 926), + ), + Row( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + Container( + alignment: Alignment.bottomRight, + child: InkWell( + child: Icon(Icons.power_settings_new, + color: Color(0xFF7F1AF1), + size: (MediaQuery.of(context).size.height) * + (23 / 926),), + ), + ), + SizedBox( + width: (MediaQuery.of(context).size.width) * (5 / 428), + ), + Container( + alignment: Alignment.bottomRight, + child: InkWell( + child: Text( + "Quit Quiz", + style: TextStyle( + color: Color(0xFF7F1AF1), + fontFamily: 'Brandon-bld', + fontSize: (MediaQuery.of(context).size.height) * + (13 / 926), //38, + ), + ), + onTap: () => _onQuit())), + ], + ), + SizedBox( + height: (MediaQuery.of(context).size.height) * (26 / 926), + ), + ], + )), + ], + ), + ), + ) , + Align( + alignment: Alignment.bottomCenter, + child: Container( + height: ((MediaQuery.of(context).size.height) * (51 / 926)), + decoration: const BoxDecoration( + gradient: LinearGradient( + begin: Alignment.topCenter, + end: Alignment.bottomCenter, + colors: [Color(0xff7F1AF1), Color(0xff482384)])), + child: _showTextZoom == true ? _textZoom(context) : Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + TextButton( + onPressed: () { + if(questionNumber > 0) { + setState(() { + questionNumber--; + }); + } + }, + style: TextButton.styleFrom( + padding: EdgeInsets.zero,), + child: Row( + children: [ + SizedBox(width: (MediaQuery.of(context).size.width) * (16 / 428)), + Container( + child: Icon(Icons.arrow_back_ios_outlined, + color: Colors.white, + size: ((MediaQuery.of(context).size.width) * (23.1 / 428)),), + ), + ], + ), + ), + Builder( + builder: (context) => TextButton( + onPressed: () { Scaffold.of(context).openEndDrawer(); }, + style: TextButton.styleFrom( + padding: EdgeInsets.zero,), + child: Row( + children: [ + Container( + width: ((MediaQuery.of(context).size.height) * (15 / 926)), + decoration: BoxDecoration( + color: Colors.white, + shape: BoxShape.circle + ), + ), + SizedBox(width: (MediaQuery.of(context).size.width) * (6 / 428)), + Container( + width: ((MediaQuery.of(context).size.height) * (15 / 926)), + decoration: BoxDecoration( + color: Colors.white, + shape: BoxShape.circle + ), + ), + SizedBox(width: (MediaQuery.of(context).size.width) * (6 / 428)), + Container( + width: ((MediaQuery.of(context).size.height) * (15 / 926)), + decoration: BoxDecoration( + color: Colors.white, + shape: BoxShape.circle + ), + ), + ], + ), + ), + ), + TextButton( + onPressed: () { + if(questionNumber < (widget.totalQuestions - 1)) { + setState(() { + questionNumber++; + }); + } + }, + style: TextButton.styleFrom( + padding: EdgeInsets.zero,), + child: Row( + children: [ + Container( + child: Icon(Icons.arrow_forward_ios_outlined, + color: Colors.white, + size: ((MediaQuery.of(context).size.width) * (23.1 / 428)),), + ), + SizedBox(width: (MediaQuery.of(context).size.width) * (16 / 428)), + ], + ), + ), + ], + ), + ), + ) + ], + ), + ), + ); + } +} diff --git a/lib/screens/Welcome/QuizModule/search_bar.dart b/lib/screens/Welcome/QuizModule/search_bar.dart new file mode 100644 index 0000000..29dcac1 --- /dev/null +++ b/lib/screens/Welcome/QuizModule/search_bar.dart @@ -0,0 +1,861 @@ +import 'package:flutter/material.dart'; + +class SearchListExample extends StatefulWidget { + @override + _SearchListExampleState createState() => new _SearchListExampleState(); +} + +class _SearchListExampleState extends State with SingleTickerProviderStateMixin { + + final bloodLabValues = [ + {"title": 'Alanine aminotransferase (ALT), serum', "value": '8-40 U/L', "siValue": '8-40 U/L', + "subtitle": [{"title": '', "value": ''}] + }, + {"title": 'Alkaline phosphatase, serum ', "value": '', "siValue": '', + "subtitle": [ + {"title": 'Male', "value": '30-100 U/L', "siValue": '30-100 U/L'}, + {"title": 'Female', "value": '45-115 U/L', "siValue": '45-115 U/L'}, + ] + }, + {"title": 'Amylase, serum', "value": '25-125 U/L', "subtitle": [], "siValue": '25-125 U/L' }, + {"title": 'Aspartate aminotransferase (AST), serum', "value": '8-40 U/L', "subtitle": [], "siValue": '8-40 U/L'}, + {"title": 'Bilirubin, serum (adult)' , "value": '', "siValue": '', + "subtitle": [ + {"title": 'Total', "value": '0.1-1.0 mg/dL', "siValue": '2-17 μmol/L'}, + {"title": 'Direct', "value": '0.0-0.3 mg/dL', "siValue": '0.0-0.05 μmol/L'}, + ] + }, + {"title": 'Calcium, serum (total)', "value": '8.4-10.2 mg/dL', "subtitle": [], "siValue": '2.1-2.8 mmol/L'}, + {"title": 'Cholesterol, serum' , "value": '', "siValue": '', + "subtitle": [ + {"title": 'Total', "value": '150-240 mg/dL', "siValue": '3.9-6.2 mmol/L'}, + {"title": 'HDL', "value": '0-70 mg/dL', "siValue": '0.8-1.8 mmol/L'}, + {"title": 'LDL', "value": '<160 mg/dL', "siValue": '<4.2 mmol/L'}, + ] + }, + {"title": 'Cortisol, serum', "value": '', "siValue": '', + "subtitle": [ + {"title": '0800 h', "value": '5-23 μg/dL', "siValue": '138-635 nmol/L'}, + {"title": '1600 h', "value": '3-15 μg/dL', "siValue": '82-413 nmol/L'}, + {"title": '2000 h', "value": '50% of 0800 h', "siValue": 'Fraction of 0800 h: ≤0.50'}, + ] + }, + {"title": 'Creatine kinase, serum', "value": '', "siValue": 'L', + "subtitle": [ + {"title": 'Male', "value": '25-90 U/L', "siValue": '25-90 U/L'}, + {"title": 'Female', "value": '10-70 U/L', "siValue": '10-70 U/L'}, + ] + }, + {"title": 'Creatinine, serum', "value": '0.6-1.2 mg/dL', "subtitle": [], "siValue": '53-106 μmol/L'}, + {"title": 'Electrolytes, serum', "value": '', "siValue": '', + "subtitle": [ + {"title": 'Sodium (Na+)', "value": '136-145 mEq/L', "siValue": '136-145 mEq/L'}, + {"title": 'Potassium (K+)', "value": '3.5-5.0 mEq/L', "siValue": '95-105 mmol/L'}, + {"title": 'Chloride (Cl-)', "value": '95-105 mEq/L', "siValue": '3.5-5.0 mmol/L'}, + {"title": 'Bicarbonate (HCO3-)', "value": '22-28 mEq/L', "siValue": '22-28 mEq/L'}, + {"title": 'Magnesium (Mg2+)', "value": '1.5-2.0 mEq/L', "siValue": '0.75-1.0 mmol/L'}, + ] + }, + {"title": 'Estriol, total, serum (in pregnancy)', "value": '', "siValue": '', + "subtitle": [ + {"title": '24-28 wks', "value": '30-170 ng/mL', "siValue": '104-590 nmol/L'}, + {"title": '28-32 wks', "value": '40-220 ng/mL', "siValue": '140-760 nmol/L'}, + {"title": '32-36 wks', "value": '60-280 ng/mL', "siValue": '208-970 nmol/L'}, + {"title": '36-40 wks', "value": '80-350 ng/mL', "siValue": '280-1210 nmol/L'}, + ] + }, + + {"title": 'Ferritin, serum', "value": '', "siValue": '', + "subtitle": [ + {"title": 'Male', "value": '15-200 ng/mL', "siValue": '15-200 ng/mL'}, + {"title": 'Female', "value": '12-150 ng/mL', "siValue": '12-150 ng/mL'}, + ] + }, + {"title": 'Follicle-stimulating hormone, serum/plasma', "value": '', "siValue": '', + "subtitle": [ + {"title": 'Male', "value": '4-25 mIU/mL', "siValue": '4-25 mIU/mL'}, + {"title": 'Female', "value": '', "siValue": ''}, + {"title": 'premenopause', "value": '4-30 mIU/mL', "siValue": '4-30 mIU/mL'}, + {"title": 'midcycle peak', "value": '10-90 mIU/mLL', "siValue": '10-90 mIU/mLL'}, + {"title": 'postmenopause', "value": '40-250 mIU/mL', "siValue": '40-250 mIU/mL'}, + ] + }, + {"title": 'Gases, arterial blood (room air)', "value": '', "siValue": '', + "subtitle": [ + {"title": 'pH', "value": '7.35-7.45', "siValue": '[H+] 36-44 nmol/L'}, + {"title": 'Pco2', "value": '33-45 mm Hg', "siValue": '4.4-5.9 kPa'}, + {"title": 'Po2', "value": '75-105 mm Hg', "siValue": '10.0-14.0 kPa'}, + ] + }, + {"title": 'Glucose, serum', "value": '', "siValue": '', + "subtitle": [ + {"title": 'Fasting', "value": '70-110 mg/dL', "siValue": '3.8-6.1 mmol/L'}, + {"title": '2-h postprandial', "value": '<120 mg/dL', "siValue": '<6.6 mmol/L'}, + ] + }, + {"title": 'Growth hormone- arginine stimulation', "value": '', "siValue": '', + "subtitle": [ + {"title": 'Fasting', "value": '<5 ng/mL', "siValue": '<5 ng/mL'}, + {"title": 'Provocative stimuli', "value": '>7 ng/mL', "siValue": '>7 μg/L'}, + ] + }, + {"title": 'Immunoglobulins, serum', "value": '', "siValue": '', + "subtitle": [ + {"title": 'IgA', "value": '76-390 mg/dL', "siValue": '0.76-3.90 g/L'}, + {"title": 'IgE', "value": '0-380 IU/mL', "siValue": '0-380 kIU/L'}, + {"title": 'IgG', "value": '650-1,500 mg/dL', "siValue": '6.5-15 g/L'}, + {"title": 'IgM', "value": '40-345 mg/dL', "siValue": '0.4-3.45 g/L'}, + ] + }, + {"title": 'Iron', "value": '50-170 μg/dL', "subtitle": [], "siValue": '9-30 μmol/LL'}, + {"title": 'Lactate dehydrogenase, serum', "value": '45-90 U/L (100-250 IU/L)', "siValue": '45-90 U/L (100-250 IU/L)', + "subtitle": [] + }, + {"title": 'Luteinizing hormone, serum/plasma', "value": '', "siValue": '', + "subtitle": [ + {"title": 'Male', "value": '6-23 mIU/mL', "siValue": '6-23 U/L'}, + {"title": 'Female', "value": '', "siValue": ''}, + {"title": 'follicular phase', "value": '5-30 mIU/mL', "siValue": '5-30 U/L'}, + {"title": 'midcycle', "value": '75-150 mIU/mL', "siValue": '75-150 U/L'}, + {"title": 'postmenopause', "value": '30-200 mIU/mL', "siValue": '30-200 U/L'}, + ] + }, + {"title": 'Osmolality, serum', "value": '275-295 mOsmol/kg H2O', "siValue": '275-295 mOsmol/kg H2O', + "subtitle": [] + }, + {"title": 'Parathyroid hormone, serum, N-terminal', "value": '10-65 pg/mL', "siValue": '10-65 pg/mL', + "subtitle": [] + }, + {"title": 'Phosphate (alkaline), serum (p-NPP at 30° C)', "value": '20-70 U/L', "siValue": '20-70 U/L', + "subtitle": [] + }, + {"title": 'Phosphorus (inorganic), serum', "value": '3.0-4.5 mg/dL', "siValue": '1.0-1.5 mmol/L', + "subtitle": [] + }, + + {"title": 'Prolactin, serum (hPRL) ', "value": '<20 ng/mL', "siValue": '<20 ng/mL', + "subtitle": [] + }, + {"title": 'Proteins, serum', "value": '', "siValue": '', + "subtitle": [ + {"title": 'Total (recumbent)', "value": '6.0-7.8 g/dL', "siValue": '60-78 g/L'}, + {"title": 'Albumin', "value": '3.5-5.5 g/dL', "siValue": '35-55 g/L'}, + {"title": 'Globulin', "value": '2.3-3.5 g/dL', "siValue": '23-35 g/L'}, + ] + }, + {"title": 'Thyroid-stimulating hormone (TSH), serum', "value": '0.5-5.0 μU/mL', "siValue": '0.5-5.0 μU/mL', + "subtitle": [] + }, + {"title": 'Thyroidal iodine (123I) uptake', "value": '8%-30% of administered dose/24 h', "siValue": '0.08-0.30 fraction of administered dose/24 h', + "subtitle": [] + }, + {"title": 'Thyroxine (T4), serum', "value": '5-12 μg/dL', "siValue": '64-155 nmol/L', + "subtitle": [] + }, + {"title": 'Triglycerides, serum', "value": '35-160 mg/dL', "siValue": '0.4-1.81 mmol/L', + "subtitle": [] + }, + {"title": 'Triiodothyronine (T3), serum (RIA)', "value": '115-190 ng/dL', "siValue": '1.8-2.9 nmol/L', + "subtitle": [] + }, + {"title": 'Triiodothyronine (T3) resin uptake', "value": '25%-35%', "siValue": '0.25-0.35', + "subtitle": [] + }, + {"title": 'Urea nitrogen, serum (BUN)', "value": '7-18 mg/dL', "siValue": '1.2-3.0 mmol/L', + "subtitle": [] + }, + {"title": 'Uric acid, serum', "value": '3.0-8.2 mg/dL', "siValue": '0.18-0.48 mmol/L', + "subtitle": [] + }, + + ]; + final HematologicLabValues = [ + {"title": 'Bleeding time (template)', "value": '2-7 minutes', "siValue": '2-7 minutes', + "subtitle": [] + }, + {"title": 'CD4+ T-lymphocyte count', "value": '>500 mm^3', "siValue": '>500 x 106/L', + "subtitle": [] + }, + {"title": 'Erythrocyte count', "value": '', "siValue": '', + "subtitle": [ + {"title": 'Male', "value": '4.3-5.9 million/mm^3', "siValue": '4.3-5.9 x 10^12/L'}, + {"title": 'Female', "value": '3.5-5.5 million/mm^3', "siValue": '3.5-5.5 x 10^12/L'}, + ] + }, + {"title": 'Erythrocyte sedimentation rate (Westergren)', "value": '', "siValue": '', + "subtitle": [ + {"title": 'Male', "value": '0-15 mm/h', "siValue": '0-15 mm/h'}, + {"title": 'Female', "value": '0-20 mm/h', "siValue": '0-20 mm/h'}, + ] + }, + {"title": 'Hematocrit', "value": '', "siValue": '', + "subtitle": [ + {"title": 'Male', "value": '41%-53%', "siValue": '0.41-0.53'}, + {"title": 'Female', "value": '36%-46%', "siValue": '0.36-0.46'}, + ] + }, + {"title": 'Hemoglobin A1c', "value": '≤6%', "siValue": '≤0.06', + "subtitle": [] + }, + {"title": 'Hemoglobin, blood', "value": '', "siValue": '', + "subtitle": [ + {"title": 'Male', "value": '13.5-17.5 g/dL', "siValue": '2.09-2.71 mmol/L'}, + {"title": 'Female', "value": '12.0-16.0 g/dL', "siValue": '1.86-2.48 mmol/L'}, + ] + }, + {"title": 'Leukocyte count and differential', "value": '', "siValue": '', + "subtitle": [ + {"title": 'Leukocyte count', "value": '4,500-11,000/mm^3', "siValue": '4.5-11.0 x 10^9/L'}, + {"title": 'Neutrophils, segmented', "value": '54%-62%', "siValue": '0.54-0.62'}, + {"title": 'Neutrophils, banded', "value": '3%-5%', "siValue": '0.03-0.05'}, + {"title": 'Eosinophils', "value": '1%-3%', "siValue": '0.01-0.03'}, + {"title": 'Basophils', "value": '0%-0.75%', "siValue": '0-0.0075'}, + {"title": 'Lymphocytes', "value": '25%-33%', "siValue": '0.25-0.33'}, + {"title": 'Monocytes', "value": '3%-7%', "siValue": '0.03-0.07'}, + ] + }, + {"title": 'Mean corpuscular hemoglobin (MCH)', "value": '25.4-34.6 pg/cell', "siValue": '0.39-0.54 fmol/cell', + "subtitle": [] + }, + {"title": 'Mean corpuscular hemoglobin concentration (MCHC)', "value": '31%-36% Hb/cell', "siValue": '4.81-5.58 mmol Hb/L', + "subtitle": [] + }, + {"title": 'Mean corpuscular volume (MCV)', "value": '80-100 μm3', "siValue": '80-100 fL', + "subtitle": [] + }, + {"title": 'Partial thromboplastin time (activated)', "value": '25-40 seconds', "siValue": '25-40 seconds', + "subtitle": [] + }, + {"title": 'Platelet count', "value": '150,000-400,000/mm^3', "siValue": '150-400 x 10^9/L', + "subtitle": [] + }, + {"title": 'Prothrombin time', "value": '11-15 seconds', "siValue": '11-15 seconds', + "subtitle": [] + }, + {"title": 'Reticulocyte count', "value": '0.5%-1.5% of red cells', "siValue": '0.005-0.015 fraction of red cells', + "subtitle": [] + }, + {"title": 'Thrombin time', "value": '<2 seconds deviation from control', "siValue": '<2 seconds deviation from control', + "subtitle": [] + }, + {"title": 'Volume', "value": '', "siValue": '', + "subtitle": [ + {"title": 'Plasma', "value": '', "siValue": ''}, + {"title": 'Male', "value": '25-43 mL/kg', "siValue": '0.005-0.015 fraction of red cells' }, + {"title": 'Female', "value": '28-45 mL/kg', "siValue": '0.028-0.045 L/kg'}, + {"title": 'Red cell', "value": '', "siValue": ''}, + {"title": 'Male', "value": '20-36 mL/kg', "siValue": '0.020-0.036 L/kg'}, + {"title": 'Female', "value": '19-31 mL/kg', "siValue": '0.019-0.031 L/kg'}, + ] + }, + + + ]; + final CerebrospinalLabValues = [ + {"title": 'Cell count', "value": '0-5/mm^3', "siValue": '0-5 x 10^6/L', + "subtitle": [] + }, + {"title": 'Chloride', "value": '118-132 mEq/L', "siValue": '118-132 mmol/L', + "subtitle": [] + }, + {"title": 'Gamma globulin', "value": '3%-12% of total proteins', "siValue": '0.03-0.12 of total proteins', + "subtitle": [] + }, + {"title": 'Glucose', "value": '40-70 mg/dL', "siValue": '2.2-3.9 mmol/L', + "subtitle": [] + }, + {"title": 'Pressure', "value": '70-180 mm H2O', "siValue": '70-180 mm H2O', + "subtitle": [] + }, + {"title": 'Proteins, total', "value": '<40 mg/dL', "siValue": '<0.40 g/L', + "subtitle": [] + }, + ]; + final sweatLabValues = [ + {"title": 'Calcium', "value": '100-300 mg/24 h', "siValue": '2.5-7.5 mmol/24 h', + "subtitle": [] + }, + {"title": 'Chloride', "value": '1Varies with intake', "siValue": '1Varies with intake', + "subtitle": [] + }, + {"title": 'Creatine clearance', "value": '', "siValue": '', + "subtitle": [ + {"title": 'Male', "value": '97-137 mL/min', "siValue": '1.62-2.29 mL/s'}, + {"title": 'Female', "value": '88-128 mL/min', "siValue": '1.47-2.14 mL/s'}, + ] + }, + {"title": 'Estriol, total (in pregnancy)', "value": '', "siValue": '', + "subtitle": [ + {"title": '30 wks', "value": '6-18 mg/24 h', "siValue": '21-62 μmol/24 h'}, + {"title": '35 wks', "value": '9-28 mg/24 h', "siValue": '31-97 μmol/24 h'}, + {"title": '40 wks', "value": '13-42 mg/24 h', "siValue": '45-146 μmol/24 h'}, + ] + }, + {"title": '17-hydroxycorticosteroids', "value": '', "siValue": '', + "subtitle": [ + {"title": 'Male', "value": '3.0-10.0 mg/24 h', "siValue": '8.2-27.6 μmol/24 h'}, + {"title": 'Female', "value": '2.0-8.0 mg/24 h', "siValue": '5.5-22.0 μmol/24 h'}, + ] + }, + {"title": '17-ketosteroids, total', "value": '', "siValue": '', + "subtitle": [ + {"title": 'Male', "value": '8-20 mg/24 h', "siValue": '28-70 μmol/24 h'}, + {"title": 'Female', "value": '6-15 mg/24 h', "siValue": '21-52 μmol/24 h'}, + ] + }, + {"title": 'Osmolality', "value": '50-1,400 mOsmol/kg H2O', "siValue": '50-1,400 mmol/kg', + "subtitle": [] + }, + {"title": 'Oxalate', "value": '8-40 μg/mL', "siValue": '90-445 μmol/L', + "subtitle": [] + }, + {"title": 'Proteins, total', "value": '<150 mg/24 h', "siValue": '<0.15 g/24 h', + "subtitle": [] + }, + {"title": 'Sodium, total', "value": 'varies with diet', "siValue": 'varies with diet', + "subtitle": [] + }, + {"title": 'Uric acid', "value": 'varies with diet', "siValue": 'varies with diet', + "subtitle": [] + }, + {"title": 'Body Mass Index (Adult)', "value": '19-25 kg/m^2', "siValue": '19-25 kg/m^2', + "subtitle": [] + }, + ]; + + + + Widget appBarTitle = new Text( + "Search Values", + style: new TextStyle(color: Colors.white), + ); + Icon icon = new Icon( + Icons.search, + color: Colors.white, + ); + final globalKey = new GlobalKey(); + final TextEditingController _controller = new TextEditingController(); + List _list = []; // = ["Indian rupee", "United States dollar", "Australian dollar", "Euro", "British pound", "Yemeni rial", "Japanese yen", "Hong Kong dollar"]; + bool _isSearching = false; + String _searchText = ""; + List searchresult = []; + bool _siValues = false; + late TabController _tabController; + + var bloodLabValuesData = { + "title" : [], + "value" : [], + "siValue" : [] + }; + var HematologicLabValuesData = { + "title" : [], + "value" : [], + "siValue" : [] + }; + var CerebrospinalLabValuesData = { + "title" : [], + "value" : [], + "siValue" : [] + }; + var sweatLabValuesData = { + "title" : [], + "value" : [], + "siValue" : [] + }; + + var LabValuesList = { + "title" : [], + "value" : [], + "siValue" : [] + }; + + categorizebloodLabValues() { + for(int i = 0; i; + }); + // print(CerebrospinalLabValuesData["title"]); + // print(_list); + } + + _SearchListExampleState() { + _controller.addListener(() { + if (_controller.text.isEmpty) { + setState(() { + _isSearching = false; + _searchText = ""; + }); + } else { + setState(() { + _isSearching = true; + _searchText = _controller.text; + }); + } + }); + } + + @override + void initState() { + super.initState(); + _tabController = TabController(vsync: this, length: 4) + ..addListener(() { + setState(() { + if(_tabController.index == 0){ + // print(_tabController.index); + setState(() { + _handleSearchEnd(); + if(bloodLabValuesData["title"] != null) + _list = bloodLabValuesData["title"] as List; + _isSearching = false; + _searchText = ""; + searchOperation(""); + }); + } + else if(_tabController.index == 1){ + // print(_tabController.index); + setState(() { + _handleSearchEnd(); + if(HematologicLabValuesData["title"] != null) + _list = HematologicLabValuesData["title"] as List; + _isSearching = false; + _searchText = ""; + searchOperation(""); + }); + } + else if(_tabController.index == 2){ + // print(_tabController.index); + setState(() { + _handleSearchEnd(); + if(CerebrospinalLabValuesData["title"] != null) + _list = CerebrospinalLabValuesData["title"] as List; + _isSearching = false; + _searchText = ""; + searchOperation(""); + }); + } + else if(_tabController.index == 3){ + // print(_tabController.index); + setState(() { + _handleSearchEnd(); + if(sweatLabValuesData["title"] != null) + _list = sweatLabValuesData["title"] as List; + _isSearching = false; + _searchText = ""; + searchOperation(""); + }); + } + }); + }); + categorizebloodLabValues(); + _isSearching = false; + } + + @override + void dispose() { + _tabController.dispose(); + super.dispose(); + } + + Widget listTiles() { + return Container( // _tabController.index == 0 + child: ListView( + scrollDirection: Axis.vertical, + children: [ + Container( + child: searchresult.length != 0 || _controller.text.isNotEmpty + ? Column( + children: [ + for(int j = 0; j<_list.length;j++) + for(int i = 0; i[ + Color(0xff7F1AF1), + Color(0xff482384) + ]) + ), + ), + title: appBarTitle, actions: [ + new IconButton( + icon: icon, + onPressed: () { + setState(() { + if (this.icon.icon == Icons.search) { + this.icon = new Icon( + Icons.close, + color: Colors.white, + ); + this.appBarTitle = new TextField( + controller: _controller, + style: new TextStyle( + color: Colors.white, + ), + decoration: new InputDecoration( + prefixIcon: new Icon(Icons.search, color: Colors.white), + hintText: "Search...", + hintStyle: new TextStyle(color: Colors.white)), + onChanged: searchOperation, + ); + _handleSearchStart(); + } else { + _handleSearchEnd(); + } + }); + }, + ), + ]), + body: SingleChildScrollView( + child: Column( + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Container( + padding: EdgeInsets.only(top: (MediaQuery.of(context).size.height) * (30 / 926), bottom: (MediaQuery.of(context).size.height) * (20 / 926), + left: (MediaQuery.of(context).size.width) * (20 / 428)), + alignment: Alignment.center, + child: Text( + "Lab Values", + style: TextStyle( + color: Color(0xff232323), + fontFamily: 'Brandon-bld', + fontSize: (MediaQuery.of(context).size.height) * + (20 / 926), //38, + ), + ), + ), + Row( + children: [ + Transform.scale( + scale: 1, + child: Container( + height: (MediaQuery.of(context).size.height) *(15/926), + child: Switch( + value: _siValues, + onChanged: (value) { + setState(() { + _siValues = value; + // print(_siValues); + }); + }, + activeColor: Color(0xff3F2668), + ), + ), + ), + Container( + child: Text("Si Reference Intervals", + style: TextStyle( + color: Color(0xff483A3A), + fontFamily: 'Brandon-med', + fontSize: (MediaQuery.of(context).size.height) *(15/926) + ), + ), + ), + SizedBox(width: (MediaQuery.of(context).size.width) *(10/428)), + + ], + ), + ], + ), + Container( + margin: EdgeInsets.only(left: (MediaQuery.of(context).size.width) * (15 / 428), right: (MediaQuery.of(context).size.width) * (15 / 428)), + // padding: EdgeInsets.only(left: (MediaQuery.of(context).size.width) * (10 / 428), right: (MediaQuery.of(context).size.width) * (10 / 428)), + decoration: BoxDecoration( + border: Border(bottom: BorderSide(color: Colors.grey, width: 2)) + ), + child: TabBar( + padding: EdgeInsets.zero, + indicatorPadding: EdgeInsets.zero, + labelPadding: EdgeInsets.zero, + controller: _tabController, + tabs: [ + Tab(icon: Text( + "Blood", + style: TextStyle( + color: Color(0xff232323), + fontFamily: 'Brandon-bld', + fontSize: (MediaQuery.of(context).size.height) * + (15 / 926), //38, + ), + ),), + Tab(icon: Text( + "Hematologic", + style: TextStyle( + color: Color(0xff232323), + fontFamily: 'Brandon-bld', + fontSize: (MediaQuery.of(context).size.height) * + (15 / 926), //38, + ), + ),), + Tab(icon: Text( + "Cerebrospinal", + style: TextStyle( + color: Color(0xff232323), + fontFamily: 'Brandon-bld', + fontSize: (MediaQuery.of(context).size.height) * + (15 / 926), //38, + ), + ),), + Tab(icon: Text( + "Sweat", + style: TextStyle( + color: Color(0xff232323), + fontFamily: 'Brandon-bld', + fontSize: (MediaQuery.of(context).size.height) * + (15 / 926), //38, + ), + ),), + ], + ), + ), + SizedBox(height: (MediaQuery.of(context).size.height) * + (8 / 926),), + Row( + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Container( + width: ((MediaQuery.of(context).size.width)*(2/3)), + padding: EdgeInsets.only(left: (MediaQuery.of(context).size.width) * + (20 / 428)), + child: Text( + _tabController.index == 0 ? "Blood, Plasma, Serum" : + _tabController.index == 1 ? "Serum" : + _tabController.index == 2 ? "Cerebrospinal Fluid" : + _tabController.index == 3 ? "Urine" : "Urine", + style: TextStyle( + color: Color(0xff232323), + fontFamily: 'Brandon-bld', + fontSize: (MediaQuery.of(context).size.height) * + (15 / 926), //38, + ), + ), + ), + Container( + padding: EdgeInsets.only(right: (MediaQuery.of(context).size.width) * + (20 / 428)), + child: Text( + _siValues == true ? "Si Reference Interval" : "Reference Range", + style: TextStyle( + color: Color(0xff232323), + fontFamily: 'Brandon-bld', + fontSize: (MediaQuery.of(context).size.height) * + (15 / 926), //38, + ), + ), + ), + ], + ), + Container( + padding: EdgeInsets.only(left: (MediaQuery.of(context).size.width) * (15 / 428), right: (MediaQuery.of(context).size.width) * (15 / 428)), + child: Divider(thickness: 0.4, color: Colors.grey,)), + Container( + padding: EdgeInsets.only(left: (MediaQuery.of(context).size.width) * (15 / 428), right: (MediaQuery.of(context).size.width) * (15 / 428)), + height: MediaQuery.of(context).size.height * 0.6, + child: TabBarView( + controller: _tabController, + children: [ + //Tab 1 + listTiles(), + //Tab 2 + listTiles(), + //Tab 3 + listTiles(), + //Tab 4 + listTiles(), + ], + ), + ), + ], + ), + )), + ); + } + + + void _handleSearchStart() { + setState(() { + _isSearching = true; + }); + } + + void _handleSearchEnd() { + setState(() { + this.icon = new Icon( + Icons.search, + color: Colors.white, + ); + this.appBarTitle = new Text( + "Search Values", + style: new TextStyle(color: Colors.white), + ); + _isSearching = false; + _controller.clear(); + }); + } + + void searchOperation(String searchText) { + searchresult.clear(); + if (_isSearching != null) { + for (int i = 0; i < _list.length; i++) { + String data = _list[i]; + if (data.toLowerCase().contains(searchText.toLowerCase())) { + searchresult.add(data); + } + } + } + } +} diff --git a/lib/screens/Welcome/side_menu_bar.dart b/lib/screens/Welcome/side_menu_bar.dart index 9c9444a..0112a3f 100644 --- a/lib/screens/Welcome/side_menu_bar.dart +++ b/lib/screens/Welcome/side_menu_bar.dart @@ -1,6 +1,8 @@ import 'package:flutter/material.dart'; import 'package:testify/screens/Welcome/GenerateQuiz/generate_quiz.dart'; +import 'PreviousQuiz/previous_quiz.dart'; + class SideMenuBar extends StatelessWidget { @override Widget build(BuildContext context) { @@ -14,25 +16,56 @@ class SideMenuBar extends StatelessWidget { Container( padding: EdgeInsets.only(top: MediaQuery.of(context).padding.top), height: (MediaQuery.of(context).size.height), - color: Color(0xffB0A6C2), + decoration: const BoxDecoration( + gradient: LinearGradient( + begin: Alignment.topRight, + end: Alignment.bottomLeft, + colors: [Color(0xff3F2668), Color(0xff482384)])), width: (MediaQuery.of(context).size.width) *0.7, child: Column( children: [ ListTile( - leading: Icon(Icons.arrow_back), - title: Text('Close'), + leading: Icon(Icons.arrow_back, color: Colors.white,), + title: Text('Close', style: TextStyle(color: Colors.white),), onTap: () => Navigator.pop(context), ), Divider(), ListTile( - leading: Icon(Icons.quiz_outlined), - title: Text('Generate Quiz'), + leading: Icon(Icons.quiz_outlined, color: Colors.white,), + title: Text('Generate Quiz', style: TextStyle(color: Colors.white),), onTap: () async { - Navigator.of(context).pop(); + // Navigator.of(context).pop(); + Navigator.of(context) + .popUntil(ModalRoute.withName("/home")); final result = await Navigator.push( context, MaterialPageRoute(builder: (context) => GenerateQuiz()), ); + // final result = Navigator.pushAndRemoveUntil( + // context, + // MaterialPageRoute(builder: (BuildContext context) => GenerateQuiz()), + // ModalRoute.withName('/home'), + // ); + }, + ), + ListTile( + leading: Icon(Icons.quiz_outlined, color: Colors.white,), + title: Text('Previous Quiz', style: TextStyle(color: Colors.white),), + onTap: () async { + // Navigator.of(context).pop(); + + Navigator.of(context) + .popUntil(ModalRoute.withName("/home")); + final result = await Navigator.push( + context, + MaterialPageRoute(builder: (context) => PreviousQuiz()), + ); + + // final result = Navigator.pushAndRemoveUntil( + // context, + // MaterialPageRoute(builder: (BuildContext context) => PreviousQuiz()), + // ModalRoute.withName('/home'), + // ); }, ), ], diff --git a/lib/screens/home.dart b/lib/screens/home.dart index 162f0b4..5f0caf9 100644 --- a/lib/screens/home.dart +++ b/lib/screens/home.dart @@ -1,8 +1,14 @@ +import 'dart:async'; +import 'dart:convert'; + import 'package:flutter/material.dart'; import 'package:flutter_svg/svg.dart'; +import 'package:shared_preferences/shared_preferences.dart'; import 'package:testify/auth_storage.dart'; import 'package:testify/screens/Authentication/login.dart'; import 'package:testify/screens/Welcome/side_menu_bar.dart'; +import 'package:testify/screens/Welcome/QuizModule/search_bar.dart'; +import 'package:http/http.dart' as http; class Home extends StatefulWidget { const Home({Key? key}) : super(key: key); @@ -48,11 +54,14 @@ class _HomeState extends State { actions: [ TextButton( onPressed: () async { - final result = await Navigator.push( + // Use this where ever Navigated to Login + final result = Navigator.pushAndRemoveUntil( context, - MaterialPageRoute(builder: (context) => const Login(fromWhere:"Home")), + MaterialPageRoute(builder: (BuildContext context) => const Login(fromWhere:"Home")), + ModalRoute.withName('/'), ); - }, + + }, child: SvgPicture.asset( "assets/Images/logout.svg", height: (MediaQuery.of(context).size.height) *(32/926), @@ -60,6 +69,57 @@ class _HomeState extends State { ), ], ), + body: TextButton( + onPressed: () async { + final result = Navigator.push( + context, + MaterialPageRoute(builder: (context) => SearchListExample()), + ); + + + // SharedPreferences prefs = await SharedPreferences.getInstance(); + // var quizID = prefs.getInt("quizId"); + // var _token = prefs.getString('token')!; + // // print(quizID); + // final String apiUrlGenerateQuiz = "https://demo.pookidevs.com/quiz/solver/saveQuiz"; + // http.post(Uri.parse(apiUrlGenerateQuiz), headers: { + // 'Content-type': 'application/json; charset=UTF-8', 'Authorization' : _token.toString(), + // }, body: json.encode( + // { + // "data": + // { + // "quiz" : { + // "quizId": 387145, + // "quizTitle": "First Quiz", // "Custom Quiz" + Date.now() + // "quizDate": " ", // "Custom Quiz" + // "quizScore": "20", // total correct + // "quizTotalQuestions": "20", + // "quizStatus": "completed", // "completed", "suspended" + // "quizQuestions": "[15,18]", // Question IDs + // "quizMode":"tutor", // "tutor", "exam" + // "quizTime": "900", // total quiz time in seconds + // "isTimed": false, // bool true or false + // "omittedQuestions": [], // Don't send anything here + // "SelectedOptionsArray": [] // Don't send anything here + // }, + // "userId": 7 + // } + // }) + // ).then((response) { + // print(jsonDecode(response.body).toString()); + // if((response.statusCode == 200) & (json.decode(response.body).toString().substring(0,14) != "{status: false")) { + // + // } + // else { // Token Invalid + // + // } + // } + // ); + + + }, + child: Text("Search Bar"), + ), ), ); } From 4d461b442ad61427e6fa1cfc220427b7d09105f1 Mon Sep 17 00:00:00 2001 From: TheYoungWolf-Productions Date: Mon, 11 Apr 2022 15:21:25 +0500 Subject: [PATCH 16/23] Add resume quiz sprint --- .../QuizModuleModels/generate_quiz_model.dart | 194 +- .../get_system_categories_successful.dart | 194 +- .../get_system_categories_unsuccessful.dart | 58 +- .../ResumeQuiz/resume_quiz_model.dart | 226 ++ .../get_previous_quizzes_model.dart | 194 +- lib/screens/Authentication/login.dart | 590 +-- .../Welcome/GenerateQuiz/generate_quiz.dart | 2 +- .../Welcome/PreviousQuiz/previous_quiz.dart | 1218 +++---- .../Welcome/PreviousQuiz/test_details.dart | 864 +++-- lib/screens/Welcome/PreviousQuiz/tile.dart | 274 +- lib/screens/Welcome/QuizModule/buttons.dart | 110 +- .../Welcome/QuizModule/calculator.dart | 358 +- .../QuizModule/question_explanation.dart | 744 ++-- .../Welcome/QuizModule/quiz_final.dart | 10 + .../Welcome/QuizModule/quiz_module.dart | 3169 +++++++++-------- .../Welcome/QuizModule/search_bar.dart | 1722 ++++----- lib/screens/home.dart | 146 +- 17 files changed, 5437 insertions(+), 4636 deletions(-) create mode 100644 lib/models/GetPreviousQuizzesModel/ResumeQuiz/resume_quiz_model.dart create mode 100644 lib/screens/Welcome/QuizModule/quiz_final.dart diff --git a/lib/models/GenerateQuizModels/QuizModuleModels/generate_quiz_model.dart b/lib/models/GenerateQuizModels/QuizModuleModels/generate_quiz_model.dart index f030c46..562990a 100644 --- a/lib/models/GenerateQuizModels/QuizModuleModels/generate_quiz_model.dart +++ b/lib/models/GenerateQuizModels/QuizModuleModels/generate_quiz_model.dart @@ -1,97 +1,97 @@ -// To parse this JSON data, do -// -// final generateQuizSuccessful = generateQuizSuccessfulFromJson(jsonString); - -import 'dart:convert'; - -GenerateQuizSuccessful generateQuizSuccessfulFromJson(String str) => GenerateQuizSuccessful.fromJson(json.decode(str)); - -String generateQuizSuccessfulToJson(GenerateQuizSuccessful data) => json.encode(data.toJson()); - -class GenerateQuizSuccessful { - GenerateQuizSuccessful({ - required this.data, - }); - - Data data; - - factory GenerateQuizSuccessful.fromJson(Map json) => GenerateQuizSuccessful( - data: Data.fromJson(json["data"]), - ); - - Map toJson() => { - "data": data.toJson(), - }; -} - -class Data { - Data({ - required this.status, - required this.questions, - required this.totalQuestions, - required this.quizId, - }); - - bool status; - List questions; - int totalQuestions; - int quizId; - - factory Data.fromJson(Map json) => Data( - status: json["status"], - questions: List.from(json["questions"].map((x) => Question.fromJson(x))), - totalQuestions: json["totalQuestions"], - quizId: json["quizId"], - ); - - Map toJson() => { - "status": status, - "questions": List.from(questions.map((x) => x.toJson())), - "totalQuestions": totalQuestions, - "quizId": quizId, - }; -} - -class Question { - Question({ - required this.id, - required this.title, - required this.question, - required this.correctMsg, - required this.answerType, - required this.postId, - required this.options, - required this.statistics, - }); - - int id; - String title; - String question; - String correctMsg; - String answerType; - int postId; - List options; - List statistics; - - factory Question.fromJson(Map json) => Question( - id: json["id"], - title: json["title"], - question: json["question"], - correctMsg: json["correct_msg"], - answerType: json["answer_type"], - postId: json["postId"], - options: List.from(json["options"].map((x) => x)), - statistics: List.from(json["statistics"].map((x) => x)), - ); - - Map toJson() => { - "id": id, - "title": title, - "question": question, - "correct_msg": correctMsg, - "answer_type": answerType, - "postId": postId, - "options": List.from(options.map((x) => x)), - "statistics": List.from(statistics.map((x) => x)), - }; -} +// To parse this JSON data, do +// +// final generateQuizSuccessful = generateQuizSuccessfulFromJson(jsonString); + +import 'dart:convert'; + +GenerateQuizSuccessful generateQuizSuccessfulFromJson(String str) => GenerateQuizSuccessful.fromJson(json.decode(str)); + +String generateQuizSuccessfulToJson(GenerateQuizSuccessful data) => json.encode(data.toJson()); + +class GenerateQuizSuccessful { + GenerateQuizSuccessful({ + required this.data, + }); + + Data data; + + factory GenerateQuizSuccessful.fromJson(Map json) => GenerateQuizSuccessful( + data: Data.fromJson(json["data"]), + ); + + Map toJson() => { + "data": data.toJson(), + }; +} + +class Data { + Data({ + required this.status, + required this.questions, + required this.totalQuestions, + required this.quizId, + }); + + bool status; + List questions; + int totalQuestions; + int quizId; + + factory Data.fromJson(Map json) => Data( + status: json["status"], + questions: List.from(json["questions"].map((x) => Question.fromJson(x))), + totalQuestions: json["totalQuestions"], + quizId: json["quizId"], + ); + + Map toJson() => { + "status": status, + "questions": List.from(questions.map((x) => x.toJson())), + "totalQuestions": totalQuestions, + "quizId": quizId, + }; +} + +class Question { + Question({ + required this.id, + required this.title, + required this.question, + required this.correctMsg, + required this.answerType, + required this.postId, + required this.options, + required this.statistics, + }); + + int id; + String title; + String question; + String correctMsg; + String answerType; + int postId; + List options; + List statistics; + + factory Question.fromJson(Map json) => Question( + id: json["id"], + title: json["title"], + question: json["question"], + correctMsg: json["correct_msg"], + answerType: json["answer_type"], + postId: json["postId"], + options: List.from(json["options"].map((x) => x)), + statistics: List.from(json["statistics"].map((x) => x)), + ); + + Map toJson() => { + "id": id, + "title": title, + "question": question, + "correct_msg": correctMsg, + "answer_type": answerType, + "postId": postId, + "options": List.from(options.map((x) => x)), + "statistics": List.from(statistics.map((x) => x)), + }; +} diff --git a/lib/models/GenerateQuizModels/get_system_categories_successful.dart b/lib/models/GenerateQuizModels/get_system_categories_successful.dart index 03fc4a3..6ec60af 100644 --- a/lib/models/GenerateQuizModels/get_system_categories_successful.dart +++ b/lib/models/GenerateQuizModels/get_system_categories_successful.dart @@ -1,97 +1,97 @@ -// To parse this JSON data, do -// -// final getSystemCategoriesSuccessfulModel = getSystemCategoriesSuccessfulModelFromJson(jsonString); - -import 'dart:convert'; - -GetSystemCategoriesSuccessfulModel getSystemCategoriesSuccessfulModelFromJson(String str) => GetSystemCategoriesSuccessfulModel.fromJson(json.decode(str)); - -String getSystemCategoriesSuccessfulModelToJson(GetSystemCategoriesSuccessfulModel data) => json.encode(data.toJson()); - -class GetSystemCategoriesSuccessfulModel { - GetSystemCategoriesSuccessfulModel({ - required this.data, - }); - - Data data; - - factory GetSystemCategoriesSuccessfulModel.fromJson(Map json) => GetSystemCategoriesSuccessfulModel( - data: Data.fromJson(json["data"]), - ); - - Map toJson() => { - "data": data.toJson(), - }; -} - -class Data { - Data({ - required this.status, - required this.categories, - required this.totalQuestions, - required this.questions, - }); - - bool status; - List categories; - int totalQuestions; - List questions; - - factory Data.fromJson(Map json) => Data( - status: json["status"], - categories: List.from(json["categories"].map((x) => Category.fromJson(x))), - totalQuestions: json["totalQuestions"], - questions: List.from(json["questions"].map((x) => x)), - ); - - Map toJson() => { - "status": status, - "categories": List.from(categories.map((x) => x.toJson())), - "totalQuestions": totalQuestions, - "questions": List.from(questions.map((x) => x)), - }; -} - -class Category { - Category({ - required this.parentCategory, - required this.subCategories, - }); - - String parentCategory; - List subCategories; - - factory Category.fromJson(Map json) => Category( - parentCategory: json["parentCategory"], - subCategories: List.from(json["subCategories"].map((x) => SubCategory.fromJson(x))), - ); - - Map toJson() => { - "parentCategory": parentCategory, - "subCategories": List.from(subCategories.map((x) => x.toJson())), - }; -} - -class SubCategory { - SubCategory({ - required this.id, - required this.title, - required this.questions, - }); - - String id; - String title; - int questions; - - factory SubCategory.fromJson(Map json) => SubCategory( - id: json["ID"], - title: json["Title"], - questions: json["Questions"], - ); - - Map toJson() => { - "ID": id, - "Title": title, - "Questions": questions, - }; -} +// To parse this JSON data, do +// +// final getSystemCategoriesSuccessfulModel = getSystemCategoriesSuccessfulModelFromJson(jsonString); + +import 'dart:convert'; + +GetSystemCategoriesSuccessfulModel getSystemCategoriesSuccessfulModelFromJson(String str) => GetSystemCategoriesSuccessfulModel.fromJson(json.decode(str)); + +String getSystemCategoriesSuccessfulModelToJson(GetSystemCategoriesSuccessfulModel data) => json.encode(data.toJson()); + +class GetSystemCategoriesSuccessfulModel { + GetSystemCategoriesSuccessfulModel({ + required this.data, + }); + + Data data; + + factory GetSystemCategoriesSuccessfulModel.fromJson(Map json) => GetSystemCategoriesSuccessfulModel( + data: Data.fromJson(json["data"]), + ); + + Map toJson() => { + "data": data.toJson(), + }; +} + +class Data { + Data({ + required this.status, + required this.categories, + required this.totalQuestions, + required this.questions, + }); + + bool status; + List categories; + int totalQuestions; + List questions; + + factory Data.fromJson(Map json) => Data( + status: json["status"], + categories: List.from(json["categories"].map((x) => Category.fromJson(x))), + totalQuestions: json["totalQuestions"], + questions: List.from(json["questions"].map((x) => x)), + ); + + Map toJson() => { + "status": status, + "categories": List.from(categories.map((x) => x.toJson())), + "totalQuestions": totalQuestions, + "questions": List.from(questions.map((x) => x)), + }; +} + +class Category { + Category({ + required this.parentCategory, + required this.subCategories, + }); + + String parentCategory; + List subCategories; + + factory Category.fromJson(Map json) => Category( + parentCategory: json["parentCategory"], + subCategories: List.from(json["subCategories"].map((x) => SubCategory.fromJson(x))), + ); + + Map toJson() => { + "parentCategory": parentCategory, + "subCategories": List.from(subCategories.map((x) => x.toJson())), + }; +} + +class SubCategory { + SubCategory({ + required this.id, + required this.title, + required this.questions, + }); + + String id; + String title; + int questions; + + factory SubCategory.fromJson(Map json) => SubCategory( + id: json["ID"], + title: json["Title"], + questions: json["Questions"], + ); + + Map toJson() => { + "ID": id, + "Title": title, + "Questions": questions, + }; +} diff --git a/lib/models/GenerateQuizModels/get_system_categories_unsuccessful.dart b/lib/models/GenerateQuizModels/get_system_categories_unsuccessful.dart index 64a3ec0..fbea9f6 100644 --- a/lib/models/GenerateQuizModels/get_system_categories_unsuccessful.dart +++ b/lib/models/GenerateQuizModels/get_system_categories_unsuccessful.dart @@ -1,29 +1,29 @@ -// To parse this JSON data, do -// -// final getSystemCategoriesUnsuccessfulModel = getSystemCategoriesUnsuccessfulModelFromJson(jsonString); - -import 'dart:convert'; - -GetSystemCategoriesUnsuccessfulModel getSystemCategoriesUnsuccessfulModelFromJson(String str) => GetSystemCategoriesUnsuccessfulModel.fromJson(json.decode(str)); - -String getSystemCategoriesUnsuccessfulModelToJson(GetSystemCategoriesUnsuccessfulModel data) => json.encode(data.toJson()); - -class GetSystemCategoriesUnsuccessfulModel { - GetSystemCategoriesUnsuccessfulModel({ - required this.status, - required this.msg, - }); - - bool status; - String msg; - - factory GetSystemCategoriesUnsuccessfulModel.fromJson(Map json) => GetSystemCategoriesUnsuccessfulModel( - status: json["status"], - msg: json["msg"], - ); - - Map toJson() => { - "status": status, - "msg": msg, - }; -} +// To parse this JSON data, do +// +// final getSystemCategoriesUnsuccessfulModel = getSystemCategoriesUnsuccessfulModelFromJson(jsonString); + +import 'dart:convert'; + +GetSystemCategoriesUnsuccessfulModel getSystemCategoriesUnsuccessfulModelFromJson(String str) => GetSystemCategoriesUnsuccessfulModel.fromJson(json.decode(str)); + +String getSystemCategoriesUnsuccessfulModelToJson(GetSystemCategoriesUnsuccessfulModel data) => json.encode(data.toJson()); + +class GetSystemCategoriesUnsuccessfulModel { + GetSystemCategoriesUnsuccessfulModel({ + required this.status, + required this.msg, + }); + + bool status; + String msg; + + factory GetSystemCategoriesUnsuccessfulModel.fromJson(Map json) => GetSystemCategoriesUnsuccessfulModel( + status: json["status"], + msg: json["msg"], + ); + + Map toJson() => { + "status": status, + "msg": msg, + }; +} diff --git a/lib/models/GetPreviousQuizzesModel/ResumeQuiz/resume_quiz_model.dart b/lib/models/GetPreviousQuizzesModel/ResumeQuiz/resume_quiz_model.dart new file mode 100644 index 0000000..52e5145 --- /dev/null +++ b/lib/models/GetPreviousQuizzesModel/ResumeQuiz/resume_quiz_model.dart @@ -0,0 +1,226 @@ +// To parse this JSON data, do +// +// final resumeQuizModel = resumeQuizModelFromJson(jsonString); + +import 'dart:convert'; + +ResumeQuizModel resumeQuizModelFromJson(String str) => ResumeQuizModel.fromJson(json.decode(str)); + +String resumeQuizModelToJson(ResumeQuizModel data) => json.encode(data.toJson()); + +class ResumeQuizModel { + ResumeQuizModel({ + required this.data, + }); + + Data data; + + factory ResumeQuizModel.fromJson(Map json) => ResumeQuizModel( + data: Data.fromJson(json["data"]), + ); + + Map toJson() => { + "data": data.toJson(), + }; +} + +class Data { + Data({ + required this.status, + required this.questions, + required this.previousQuizzes, + }); + + bool status; + List questions; + List previousQuizzes; + + factory Data.fromJson(Map json) => Data( + status: json["status"], + questions: List.from(json["questions"].map((x) => Question.fromJson(x))), + previousQuizzes: List.from(json["previousQuizzes"].map((x) => PreviousQuizz.fromJson(x))), + ); + + Map toJson() => { + "status": status, + "questions": List.from(questions.map((x) => x.toJson())), + "previousQuizzes": List.from(previousQuizzes.map((x) => x.toJson())), + }; +} + +class PreviousQuizz { + PreviousQuizz({ + required this.quizId, + required this.userId, + required this.quizMeta, + required this.sortId, + this.examId, + }); + + int quizId; + int userId; + QuizMeta quizMeta; + DateTime sortId; + dynamic examId; + + factory PreviousQuizz.fromJson(Map json) => PreviousQuizz( + quizId: json["quiz_id"], + userId: json["user_id"], + quizMeta: QuizMeta.fromJson(json["quiz_meta"]), + sortId: DateTime.parse(json["sortId"]), + examId: json["exam_id"], + ); + + Map toJson() => { + "quiz_id": quizId, + "user_id": userId, + "quiz_meta": quizMeta.toJson(), + "sortId": sortId.toIso8601String(), + "exam_id": examId, + }; +} + +class QuizMeta { + QuizMeta({ + required this.quizId, + required this.quizTitle, + required this.quizDate, + required this.quizScore, + required this.quizTotalQuestions, + required this.quizStatus, + required this.quizQuestions, + required this.quizMode, + required this.quizTime, + required this.isTimed, + required this.omittedQuestions, + required this.selectedOptionsArray, + }); + + // int quizId; + // String quizTitle; + // DateTime quizDate; + // String quizScore; + // int quizTotalQuestions; + // String quizStatus; + // String quizQuestions; + // String quizMode; + // String quizTime; + // bool isTimed; + // List omittedQuestions; + // List selectedOptionsArray; + + dynamic quizId; // Problem + String quizTitle; + DateTime quizDate; + dynamic quizScore; // Problem + int quizTotalQuestions; + String quizStatus; + String quizQuestions; + String quizMode; + String quizTime; + bool isTimed; + List omittedQuestions; + List selectedOptionsArray; + + factory QuizMeta.fromJson(Map json) => QuizMeta( + quizId: json["quizId"], + quizTitle: json["quizTitle"], + quizDate: DateTime.parse(json["quizDate"]), + quizScore: json["quizScore"], + quizTotalQuestions: json["quizTotalQuestions"], + quizStatus: json["quizStatus"], + quizQuestions: json["quizQuestions"], + quizMode: json["quizMode"], + quizTime: json["quizTime"], + isTimed: json["isTimed"], + omittedQuestions: List.from(json["omittedQuestions"].map((x) => x)), + selectedOptionsArray: List.from(json["selectedOptionsArray"].map((x) => x)), + ); + + Map toJson() => { + "quizId": quizId, + "quizTitle": quizTitle, + "quizDate": quizDate.toIso8601String(), + "quizScore": quizScore, + "quizTotalQuestions": quizTotalQuestions, + "quizStatus": quizStatus, + "quizQuestions": quizQuestions, + "quizMode": quizMode, + "quizTime": quizTime, + "isTimed": isTimed, + "omittedQuestions": List.from(omittedQuestions.map((x) => x)), + "selectedOptionsArray": List.from(selectedOptionsArray.map((x) => x)), + }; +} + +class Question { + Question({ + required this.id, + required this.title, + required this.question, + required this.correctMsg, + required this.answerType, + required this.postId, + this.userId, + this.submitData, + this.notes, + this.questionId, + this.noteId, + this.noteMeta, + required this.marked, + required this.options, + required this.statistics, + }); + + int id; + String title; + String question; + String correctMsg; + String answerType; + int postId; + dynamic userId; + dynamic submitData; + dynamic notes; + dynamic questionId; + dynamic noteId; + dynamic noteMeta; + int marked; + List options; + List statistics; + + factory Question.fromJson(Map json) => Question( + id: json["id"], + title: json["title"], + question: json["question"], + correctMsg: json["correct_msg"], + answerType: json["answer_type"], + postId: json["postId"], + userId: json["user_id"] == null ? null : json["user_id"], + submitData: json["submitData"] == null ? null : json["submitData"], + notes: json["notes"] == null ? null : json["notes"], + questionId: json["questionId"] == null ? null : json["questionId"], + noteId: json["noteId"] == null ? null : json["noteId"], + noteMeta: json["note_meta"] == null ? null : json["note_meta"], + marked: json["marked"], + options: List.from(json["options"].map((x) => x)), + statistics: List.from(json["statistics"].map((x) => x)), + ); + + Map toJson() => { + "id": id, + "title": title, + "question": question, + "correct_msg": correctMsg, + "answer_type": answerType, + "postId": postId, + "user_id": userId == null ? null : userId, + "submitData": submitData == null ? null : submitData, + "notes": notes, + "questionId": questionId, + "noteId": noteId, + "note_meta": noteMeta, + "marked": marked, + "options": List.from(options.map((x) => x)), + "statistics": List.from(statistics.map((x) => x)), + }; +} diff --git a/lib/models/GetPreviousQuizzesModel/get_previous_quizzes_model.dart b/lib/models/GetPreviousQuizzesModel/get_previous_quizzes_model.dart index f665ea8..a3aa346 100644 --- a/lib/models/GetPreviousQuizzesModel/get_previous_quizzes_model.dart +++ b/lib/models/GetPreviousQuizzesModel/get_previous_quizzes_model.dart @@ -1,97 +1,97 @@ -// To parse this JSON data, do -// -// final getPreviousQuizzesModel = getPreviousQuizzesModelFromJson(jsonString); - -import 'dart:convert'; - -GetPreviousQuizzesModel getPreviousQuizzesModelFromJson(String str) => GetPreviousQuizzesModel.fromJson(json.decode(str)); - -String getPreviousQuizzesModelToJson(GetPreviousQuizzesModel data) => json.encode(data.toJson()); - -class GetPreviousQuizzesModel { - GetPreviousQuizzesModel({ - required this.data, - }); - - Data data; - - factory GetPreviousQuizzesModel.fromJson(Map json) => GetPreviousQuizzesModel( - data: Data.fromJson(json["data"]), - ); - - Map toJson() => { - "data": data.toJson(), - }; -} - -class Data { - Data({ - required this.status, - required this.quizzes, - }); - - bool status; - List quizzes; - - factory Data.fromJson(Map json) => Data( - status: json["status"], - quizzes: List.from(json["quizzes"].map((x) => Quiz.fromJson(x))), - ); - - Map toJson() => { - "status": status, - "quizzes": List.from(quizzes.map((x) => x.toJson())), - }; -} - -class Quiz { - Quiz({ - required this.quizId, - required this.name, - required this.score, - required this.date, - required this.status, - required this.questions, - required this.totalQuestions, - required this.subjects, - required this.systems, - required this.topics, - }); - - int quizId; - String name; - String score; - String date; - String status; - List questions; - String totalQuestions; - List subjects; - List systems; - List topics; - - factory Quiz.fromJson(Map json) => Quiz( - quizId: json["quizId"], - name: json["name"], - score: json["score"], - date: json["date"], - status: json["status"], - questions: List.from(json["questions"].map((x) => x)), - totalQuestions: json["totalQuestions"], - subjects: List.from(json["subjects"].map((x) => x)), - systems: List.from(json["systems"].map((x) => x)), - topics: List.from(json["topics"].map((x) => x)), - ); - - Map toJson() => { - "quizId": quizId, - "name": name, - "score": score, - "date": date, - "status": status, - "questions": List.from(questions.map((x) => x)), - "totalQuestions": totalQuestions, - "subjects": List.from(subjects.map((x) => x)), - "systems": List.from(systems.map((x) => x)), - "topics": List.from(topics.map((x) => x)), - }; -} +// To parse this JSON data, do +// +// final getPreviousQuizzesModel = getPreviousQuizzesModelFromJson(jsonString); + +import 'dart:convert'; + +GetPreviousQuizzesModel getPreviousQuizzesModelFromJson(String str) => GetPreviousQuizzesModel.fromJson(json.decode(str)); + +String getPreviousQuizzesModelToJson(GetPreviousQuizzesModel data) => json.encode(data.toJson()); + +class GetPreviousQuizzesModel { + GetPreviousQuizzesModel({ + required this.data, + }); + + Data data; + + factory GetPreviousQuizzesModel.fromJson(Map json) => GetPreviousQuizzesModel( + data: Data.fromJson(json["data"]), + ); + + Map toJson() => { + "data": data.toJson(), + }; +} + +class Data { + Data({ + required this.status, + required this.quizzes, + }); + + bool status; + List quizzes; + + factory Data.fromJson(Map json) => Data( + status: json["status"], + quizzes: List.from(json["quizzes"].map((x) => Quiz.fromJson(x))), + ); + + Map toJson() => { + "status": status, + "quizzes": List.from(quizzes.map((x) => x.toJson())), + }; +} + +class Quiz { + Quiz({ + required this.quizId, + required this.name, + required this.score, + required this.date, + required this.status, + required this.questions, + required this.totalQuestions, + required this.subjects, + required this.systems, + required this.topics, + }); + + int quizId; + String name; + String score; + String date; + String status; + List questions; + String totalQuestions; + List subjects; + List systems; + List topics; + + factory Quiz.fromJson(Map json) => Quiz( + quizId: json["quizId"], + name: json["name"], + score: json["score"], + date: json["date"], + status: json["status"], + questions: List.from(json["questions"].map((x) => x)), + totalQuestions: json["totalQuestions"], + subjects: List.from(json["subjects"].map((x) => x)), + systems: List.from(json["systems"].map((x) => x)), + topics: List.from(json["topics"].map((x) => x)), + ); + + Map toJson() => { + "quizId": quizId, + "name": name, + "score": score, + "date": date, + "status": status, + "questions": List.from(questions.map((x) => x)), + "totalQuestions": totalQuestions, + "subjects": List.from(subjects.map((x) => x)), + "systems": List.from(systems.map((x) => x)), + "topics": List.from(topics.map((x) => x)), + }; +} diff --git a/lib/screens/Authentication/login.dart b/lib/screens/Authentication/login.dart index f2c6e83..3687098 100644 --- a/lib/screens/Authentication/login.dart +++ b/lib/screens/Authentication/login.dart @@ -33,6 +33,7 @@ class _LoginState extends State { late UserModelUnsuccessfulLogin _unsuccessfulUser; var _invalidUsername = false; var _invalidPassword = false; + bool _isLoggingIn = false; // To start and finish CircularProgress Indicator //The data gets stored to local storage. Continue from there. AuthStorage storage = new AuthStorage(); @@ -68,7 +69,12 @@ class _LoginState extends State { } }); } - Future.delayed(Duration(milliseconds: 1), () { + // Future.delayed(Duration(milliseconds: 1), () { + // setState(() { + // _loaded = true; + // }); + // }); + Future.delayed(Duration(microseconds: 0), () { setState(() { _loaded = true; }); @@ -77,6 +83,9 @@ class _LoginState extends State { //https://demo.pookidevs.com/auth/login Future getUserData(BuildContext context, String email, String password) async { + setState(() { + _isLoggingIn = true; + }); SharedPreferences prefs = await SharedPreferences.getInstance(); final String apiUrl = "https://demo.pookidevs.com/auth/login"; http.post(Uri.parse(apiUrl), headers: { @@ -98,6 +107,7 @@ class _LoginState extends State { final UserModelSuccessfulLogin successfulUser = loginData; setState(() { _successfulUser = successfulUser; + _isLoggingIn = false; }); //Saves Token to use later. prefs.setString('token', _successfulUser.data.token); @@ -177,109 +187,64 @@ class _LoginState extends State { // ..showSnackBar(SnackBar(content: Text(""))); return false; }, - child: Scaffold( - backgroundColor: Color(0xff3F2668),//Color copied from xD=#3F2668 - body: SingleChildScrollView( - child: Container( - height: (MediaQuery.of(context).size.height), - child: Column( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - AnimatedCrossFade( - crossFadeState: _loaded ? CrossFadeState.showFirst : CrossFadeState.showSecond, - duration: _duration, - firstChild: Container( - height: (MediaQuery.of(context).size.height) *0.3, - color: Colors.transparent, - child: Align( - alignment: Alignment.topLeft, - child: Image( - image: AssetImage("assets/Images/login_topLeftBubble_1.png"), + child: GestureDetector( + onTap: () { + FocusScopeNode currentFocus = FocusScope.of(context); + + if (!currentFocus.hasPrimaryFocus) { + currentFocus.unfocus(); + } + }, + child: Scaffold( + backgroundColor: Color(0xff3F2668),//Color copied from xD=#3F2668 + body: SingleChildScrollView( + child: Container( + height: (MediaQuery.of(context).size.height), + child: Column( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + AnimatedCrossFade( + crossFadeState: _loaded ? CrossFadeState.showFirst : CrossFadeState.showSecond, + duration: _duration, + firstChild: Container( + height: (MediaQuery.of(context).size.height) *0.3, + color: Colors.transparent, + child: Align( + alignment: Alignment.topLeft, + child: Image( + image: AssetImage("assets/Images/login_topLeftBubble_1.png"), + ), ), ), + secondChild: Container( + height: (MediaQuery.of(context).size.height) *0.3, + color: Colors.transparent, + child: Text(""), + ), ), - secondChild: Container( - height: (MediaQuery.of(context).size.height) *0.3, - color: Colors.transparent, - child: Text(""), - ), - ), - SizedBox(height: (MediaQuery.of(context).size.height) *0.02159,), - AnimatedCrossFade( - crossFadeState: _loaded ? CrossFadeState.showFirst : CrossFadeState.showSecond, - duration: _duration, - secondChild: Text(""), - firstChild: Container( - child: Form( - key: _formKey, - child: Stack( - alignment: Alignment.bottomCenter, - children: [ - Column(//Add extra space at the end of the container(the one that has TextFormField) so that the login button can be aligned. - children: [ - Container(//For Borders of lighter area //Main Container to add Welcome, TextFormFields and Login. - //tbd: Get the color right! - margin: EdgeInsets.only(top: 0, bottom: 0, left: (MediaQuery.of(context).size.width) *(31/428), right: (MediaQuery.of(context).size.width) *(31/428),), - padding: EdgeInsets.only(top: 0, bottom: (MediaQuery.of(context).size.height) *0.0179, left: 0, right: 0,), - decoration: BoxDecoration( - color: Color.fromRGBO(176, 166, 194, 210),//0xffB0A6C2, rgba(176, 166, 194, 1) - borderRadius: BorderRadius.all(Radius.circular(10)), - border: Border.all( - color: Color(0xff757575), - width: 0, - ), - boxShadow: [ - BoxShadow( - color: Color(0xff0000004D), - ), - ], - ), - child: Column( - children: [ - Container( - padding: EdgeInsets.only(top: (MediaQuery.of(context).size.height) *0.020518, bottom: 0, left: 0, right: 0,), - child: Text("Welcome!", - style: TextStyle( - color: Color(0xffFFFEFE), - fontFamily: 'Brandon-bld', - fontSize: (MediaQuery.of(context).size.height) *0.0410,//38, - ),), - ), - Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Container( - padding: EdgeInsets.only(top: 0, bottom: 0, left: 0, right: 0,), - child: Text("Don't have an account?", - style: TextStyle( - color: Color.fromRGBO(255, 255, 255, 100), - fontFamily: 'Brandon-med', - fontSize: (MediaQuery.of(context).size.height)*0.0194, - ),), - ), - Container( - padding: EdgeInsets.only(top: 0, bottom: 0, left: 0, right: 0,), - child: Text(" Sign Up", - style: TextStyle( - color: Color(0xffFFFEFE), - fontFamily: 'Brandon-med', - fontSize: (MediaQuery.of(context).size.height)*0.0194, - ),), - ), - ], - ), - SizedBox(height: (MediaQuery.of(context).size.height)*0.04535,), - Container( - //color: Colors.white, - height: (MediaQuery.of(context).size.height)*0.055, - //padding: EdgeInsets.fromLTRB(20.0, (MediaQuery.of(context).size.height - MediaQuery.of(context).padding.top)*0.0037797, 20.0, (MediaQuery.of(context).size.height - MediaQuery.of(context).padding.top)*0.0037797), - margin: EdgeInsets.only(top: 0, bottom: 0, left: (MediaQuery.of(context).size.width) *(45/428), right: (MediaQuery.of(context).size.width) *(45/428),), + SizedBox(height: (MediaQuery.of(context).size.height) *0.02159,), + AnimatedCrossFade( + crossFadeState: _loaded ? CrossFadeState.showFirst : CrossFadeState.showSecond, + duration: _duration, + secondChild: Text(""), + firstChild: Container( + child: Form( + key: _formKey, + child: Stack( + alignment: Alignment.bottomCenter, + children: [ + Column(//Add extra space at the end of the container(the one that has TextFormField) so that the login button can be aligned. + children: [ + Container(//For Borders of lighter area //Main Container to add Welcome, TextFormFields and Login. + //tbd: Get the color right! + margin: EdgeInsets.only(top: 0, bottom: 0, left: (MediaQuery.of(context).size.width) *(31/428), right: (MediaQuery.of(context).size.width) *(31/428),), + padding: EdgeInsets.only(top: 0, bottom: (MediaQuery.of(context).size.height) *0.0179, left: 0, right: 0,), decoration: BoxDecoration( - color: Colors.white, + color: Color.fromRGBO(176, 166, 194, 210),//0xffB0A6C2, rgba(176, 166, 194, 1) borderRadius: BorderRadius.all(Radius.circular(10)), border: Border.all( - color: _invalidUsername == true ? Colors.red : Color(0xff757575), - width: _invalidUsername == true ? 3 : 1, + color: Color(0xff757575), + width: 0, ), boxShadow: [ BoxShadow( @@ -287,58 +252,52 @@ class _LoginState extends State { ), ], ), - child: TextFormField( - decoration: InputDecoration( - suffixIcon: _invalidUsername == true ? Text("! ", - style: TextStyle( - color: Colors.red, - fontSize: (MediaQuery.of(context).size.height)*(20/926), - fontFamily: 'Brandon-med', - ),) : Text(""), - suffixIconConstraints: BoxConstraints(minWidth: 0, minHeight: 0), - hintText: _dataPreviouslyStored == null ? "Loading..." : (_dataPreviouslyStored ? _email : "Username"), - hintStyle: TextStyle(color: _dataPreviouslyStored ? Color(0xff171616) : Color(0xffAEAEAE), - fontSize: (MediaQuery.of(context).size.height)*(20/926), - fontFamily: 'Brandon-med',), - contentPadding: EdgeInsets.fromLTRB(20.0, (MediaQuery.of(context).size.height)*0.0037797, 20.0, (MediaQuery.of(context).size.height)*0.0037797), - enabledBorder: OutlineInputBorder( - borderSide: BorderSide( - color: Colors.transparent, - width: 0.0, + child: Column( + children: [ + Container( + padding: EdgeInsets.only(top: (MediaQuery.of(context).size.height) *0.020518, bottom: 0, left: 0, right: 0,), + child: Text("Welcome!", + style: TextStyle( + color: Color(0xffFFFEFE), + fontFamily: 'Brandon-bld', + fontSize: (MediaQuery.of(context).size.height) *0.0410,//38, + ),), + ), + Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Container( + padding: EdgeInsets.only(top: 0, bottom: 0, left: 0, right: 0,), + child: Text("Don't have an account?", + style: TextStyle( + color: Color.fromRGBO(255, 255, 255, 100), + fontFamily: 'Brandon-med', + fontSize: (MediaQuery.of(context).size.height)*0.0194, + ),), ), - borderRadius: BorderRadius.circular(10.0), - ), - focusedBorder: OutlineInputBorder( - borderSide: BorderSide( - color: Colors.transparent, - width: 0.0, + Container( + padding: EdgeInsets.only(top: 0, bottom: 0, left: 0, right: 0,), + child: Text(" Sign Up", + style: TextStyle( + color: Color(0xffFFFEFE), + fontFamily: 'Brandon-med', + fontSize: (MediaQuery.of(context).size.height)*0.0194, + ),), ), - ), - ), - //validator: (val) => val!.isEmpty ? "Please enter a Username." : null, - onChanged: (val) { - _dataPreviouslyStored == null ? val = "" : - (_dataPreviouslyStored ? val = _email : _email = val); - //_email = val; - }, - style: TextStyle( - color: Colors.black, - fontSize: (MediaQuery.of(context).size.height)*(20/926), - fontFamily: 'Brandon-med', + ], ), - ), - ), - SizedBox(height: (MediaQuery.of(context).size.height)*0.0226781,), + SizedBox(height: (MediaQuery.of(context).size.height)*0.04535,), Container( //color: Colors.white, height: (MediaQuery.of(context).size.height)*0.055, + //padding: EdgeInsets.fromLTRB(20.0, (MediaQuery.of(context).size.height - MediaQuery.of(context).padding.top)*0.0037797, 20.0, (MediaQuery.of(context).size.height - MediaQuery.of(context).padding.top)*0.0037797), margin: EdgeInsets.only(top: 0, bottom: 0, left: (MediaQuery.of(context).size.width) *(45/428), right: (MediaQuery.of(context).size.width) *(45/428),), decoration: BoxDecoration( color: Colors.white, borderRadius: BorderRadius.all(Radius.circular(10)), border: Border.all( - color: _invalidPassword == true ? Colors.red : Color(0xff757575), - width: _invalidPassword == true ? 3 : 1, + color: _invalidUsername == true ? Colors.red : Color(0xff757575), + width: _invalidUsername == true ? 3 : 1, ), boxShadow: [ BoxShadow( @@ -347,17 +306,17 @@ class _LoginState extends State { ], ), child: TextFormField( - obscureText: true, + keyboardType: TextInputType.emailAddress, decoration: InputDecoration( - suffixIcon: _invalidPassword == true ? Text("! ", + suffixIcon: _invalidUsername == true ? Text("! ", style: TextStyle( color: Colors.red, fontSize: (MediaQuery.of(context).size.height)*(20/926), fontFamily: 'Brandon-med', ),) : Text(""), suffixIconConstraints: BoxConstraints(minWidth: 0, minHeight: 0), - hintText: _dataPreviouslyStored == null ? "Loading..." : (_dataPreviouslyStored ? _password : "Password"), - hintStyle: TextStyle(color: _dataPreviouslyStored ? Colors.black : Color(0xffAEAEAE), + hintText: _dataPreviouslyStored == null ? "Loading..." : (_dataPreviouslyStored ? _email : "Username"), + hintStyle: TextStyle(color: _dataPreviouslyStored ? Color(0xff171616) : Color(0xffAEAEAE), fontSize: (MediaQuery.of(context).size.height)*(20/926), fontFamily: 'Brandon-med',), contentPadding: EdgeInsets.fromLTRB(20.0, (MediaQuery.of(context).size.height)*0.0037797, 20.0, (MediaQuery.of(context).size.height)*0.0037797), @@ -375,12 +334,11 @@ class _LoginState extends State { ), ), ), - //validator: (val) => val!.isEmpty ? "Please enter a Password." : null, + //validator: (val) => val!.isEmpty ? "Please enter a Username." : null, onChanged: (val) { - setState(() { - _dataPreviouslyStored == null ? val = "" : - (_dataPreviouslyStored ? val = _password : _password = val); - }); + _dataPreviouslyStored == null ? val = "" : + (_dataPreviouslyStored ? val = _email : _email = val); + //_email = val; }, style: TextStyle( color: Colors.black, @@ -389,141 +347,249 @@ class _LoginState extends State { ), ), ), - SizedBox(height: (MediaQuery.of(context).size.height)*0.024838,), - GestureDetector( - onTap: () { - if(_isChecked == false) - setState(() { - _isChecked = true; - }); - else if(_isChecked == true) - setState(() { - _isChecked = false; - }); - }, - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Row( - mainAxisAlignment: MainAxisAlignment.start, - children: [ - Container( - margin: EdgeInsets.only(top: 0, bottom: 0, left: (MediaQuery.of(context).size.width) *(45/428), right: 0,), - height: (MediaQuery.of(context).size.height)*0.0167, - width: (MediaQuery.of(context).size.height)*0.0167, - color: Colors.white, - child: Transform.scale( - scale: (MediaQuery.of(context).size.height)*0.001, - child: Checkbox( - side: BorderSide( - color: Color(0xffB0A6C2), - width: 0, - ), - checkColor: Colors.white, - value: _isChecked, - onChanged: (bool? value) { - setState(() { - _isChecked = value!; - }); - }, - ), - ), - ), - Container( - padding: EdgeInsets.only(top: 0, bottom: 0, left: (MediaQuery.of(context).size.width) *(5/428), right: 0,), - child: Text("Remember me!", - style: TextStyle( - color: Color.fromRGBO(255, 255, 255, 100), - fontFamily: 'Brandon-med', - fontSize: (MediaQuery.of(context).size.height)*0.0161987, - ),), - ), - ], + SizedBox(height: (MediaQuery.of(context).size.height)*0.0226781,), + Container( + //color: Colors.white, + height: (MediaQuery.of(context).size.height)*0.055, + margin: EdgeInsets.only(top: 0, bottom: 0, left: (MediaQuery.of(context).size.width) *(45/428), right: (MediaQuery.of(context).size.width) *(45/428),), + decoration: BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.all(Radius.circular(10)), + border: Border.all( + color: _invalidPassword == true ? Colors.red : Color(0xff757575), + width: _invalidPassword == true ? 3 : 1, ), - Container( - padding: EdgeInsets.only(top: 0, bottom: 0, left: 0, right: (MediaQuery.of(context).size.width) *(45/428),), - child: Text("Forgot Password?", + boxShadow: [ + BoxShadow( + color: Color(0xff0000004D), + ), + ], + ), + child: TextFormField( + //keyboardType: TextInputType.visiblePassword, + obscureText: true, + decoration: InputDecoration( + suffixIcon: _invalidPassword == true ? Text("! ", style: TextStyle( - color: Color(0xffFFFEFE), + color: Colors.red, + fontSize: (MediaQuery.of(context).size.height)*(20/926), fontFamily: 'Brandon-med', - fontSize: (MediaQuery.of(context).size.height)*0.0161987, - ),), + ),) : Text(""), + suffixIconConstraints: BoxConstraints(minWidth: 0, minHeight: 0), + hintText: _dataPreviouslyStored == null ? "Loading..." : (_dataPreviouslyStored ? _password : "Password"), + hintStyle: TextStyle(color: _dataPreviouslyStored ? Colors.black : Color(0xffAEAEAE), + fontSize: (MediaQuery.of(context).size.height)*(20/926), + fontFamily: 'Brandon-med',), + contentPadding: EdgeInsets.fromLTRB(20.0, (MediaQuery.of(context).size.height)*0.0037797, 20.0, (MediaQuery.of(context).size.height)*0.0037797), + enabledBorder: OutlineInputBorder( + borderSide: BorderSide( + color: Colors.transparent, + width: 0.0, + ), + borderRadius: BorderRadius.circular(10.0), + ), + focusedBorder: OutlineInputBorder( + borderSide: BorderSide( + color: Colors.transparent, + width: 0.0, + ), + ), ), - ], + //validator: (val) => val!.isEmpty ? "Please enter a Password." : null, + onChanged: (val) { + setState(() { + _dataPreviouslyStored == null ? val = "" : + (_dataPreviouslyStored ? val = _password : _password = val); + }); + }, + style: TextStyle( + color: Colors.black, + fontSize: (MediaQuery.of(context).size.height)*(20/926), + fontFamily: 'Brandon-med', + ), + ), ), - ), - SizedBox(height: (MediaQuery.of(context).size.height) *0.0864,), - ], + SizedBox(height: (MediaQuery.of(context).size.height)*0.024838,), + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + GestureDetector( + onTap: () { + if(_isChecked == false) + setState(() { + _isChecked = true; + }); + else if(_isChecked == true) + setState(() { + _isChecked = false; + }); + }, + child: Row( + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Container( + margin: EdgeInsets.only(top: 0, bottom: 0, left: (MediaQuery.of(context).size.width) *(45/428), right: 0,), + height: (MediaQuery.of(context).size.height)*0.0167, + width: (MediaQuery.of(context).size.height)*0.0167, + color: Colors.white, + child: Transform.scale( + scale: (MediaQuery.of(context).size.height)*0.001, + child: Checkbox( + side: BorderSide( + color: Color(0xffB0A6C2), + width: 0, + ), + checkColor: Colors.white, + value: _isChecked, + onChanged: (bool? value) { + setState(() { + _isChecked = value!; + }); + }, + ), + ), + ), + Container( + padding: EdgeInsets.only(top: 0, bottom: 0, left: (MediaQuery.of(context).size.width) *(5/428), right: 0,), + child: Text("Remember me!", + style: TextStyle( + color: Color.fromRGBO(255, 255, 255, 100), + fontFamily: 'Brandon-med', + fontSize: (MediaQuery.of(context).size.height)*0.0161987, + ),), + ), + ], + ), + ), + Container( + padding: EdgeInsets.only(top: 0, bottom: 0, left: 0, right: (MediaQuery.of(context).size.width) *(45/428),), + child: Text("Forgot Password?", + style: TextStyle( + color: Color(0xffFFFEFE), + fontFamily: 'Brandon-med', + fontSize: (MediaQuery.of(context).size.height)*0.0161987, + ),), + ), + ], + ), + _isLoggingIn ? Container() : SizedBox(height: (MediaQuery.of(context).size.height) *0.0864,), + _isLoggingIn ? Container( + height: (MediaQuery.of(context).size.height) *0.0864, + child: Container( + alignment: Alignment.center, + height: (MediaQuery.of(context).size.height) *0.0664, + child: CircularProgressIndicator(color: Colors.white,)), + ) : Container(), + ], + ), + ), + SizedBox(height: (MediaQuery.of(context).size.height) *(25/926),), + ], + ), + // GestureDetector( + // child: Container(//Login button + // child: Align( + // alignment: Alignment.center, + // child: SvgPicture.asset( + // "assets/Images/login.svg", + // height: (MediaQuery.of(context).size.height) *0.0486, + // ), + // ), + // ), + // onTap: () { + // if(_formKey.currentState!.validate()) { + // //_navigateAndDisplaySelection(context); + // //print(_isChecked); + // getUserData(context, _email, _password); + // } + // }, + // ), + Container( + height: (MediaQuery.of(context).size.height) *(45/926), + width: (MediaQuery.of(context).size.width) *(150/428), + decoration: BoxDecoration( + gradient: LinearGradient( + begin: Alignment.centerLeft, + end: Alignment.centerRight, + colors: [ + Color(0xff7F1AF1), + Color(0xff482384) + ]), + borderRadius: new BorderRadius.only( + bottomLeft: const Radius.circular(20.0), + topRight: const Radius.circular(20.0), + ) ), - ), - SizedBox(height: (MediaQuery.of(context).size.height) *(25/926),), - ], - ), - GestureDetector( - child: Container(//Login button - child: Align( - alignment: Alignment.center, - child: SvgPicture.asset( - "assets/Images/login.svg", - height: (MediaQuery.of(context).size.height) *0.0486, + child: TextButton( + style: TextButton.styleFrom( + padding: EdgeInsets.zero, ), + onPressed: () { + // setState(() { + // _isLoggingIn = !_isLoggingIn; + // }); + if(_formKey.currentState!.validate()) { + //_navigateAndDisplaySelection(context); + // print(_isChecked); + getUserData(context, _email, _password); + } + }, + child: Text("Login", + style: TextStyle( + color: Color(0xffFFFEFE), + fontFamily: 'Brandon-bld', + fontSize: (MediaQuery.of(context).size.height)*(25/926), + ),), ), ), - onTap: () { - if(_formKey.currentState!.validate()) { - //_navigateAndDisplaySelection(context); - //print(_isChecked); - getUserData(context, _email, _password); - } - }, - ), - ], + ], + ), ), ), ), - ), - AnimatedCrossFade( - crossFadeState: _loaded ? CrossFadeState.showFirst : CrossFadeState.showSecond, - duration: _duration, - secondChild: Container( - height: (MediaQuery.of(context).size.height) *0.183, - child: Text("")), - firstChild: Row( - mainAxisAlignment: MainAxisAlignment.end, - //crossAxisAlignment: CrossAxisAlignment.end, - children: [ - Stack( - //alignment: Alignment.centerRight, - children: [ - Positioned( - left: (MediaQuery.of(context).size.height) *(80/926), - top: (MediaQuery.of(context).size.height) *(50/926), - child: Align( - alignment: Alignment.bottomRight, - child: SvgPicture.asset( - "assets/Images/login_bottomRight.svg", - height: (MediaQuery.of(context).size.height) *0.183, - width: (MediaQuery.of(context).size.height) *0.183, - ), - ), - ), - Positioned(//Remove and add again + AnimatedCrossFade( + crossFadeState: _loaded ? CrossFadeState.showFirst : CrossFadeState.showSecond, + duration: _duration, + secondChild: Container( + height: (MediaQuery.of(context).size.height) *0.183, + child: Text("")), + firstChild: Row( + mainAxisAlignment: MainAxisAlignment.end, + //crossAxisAlignment: CrossAxisAlignment.end, + children: [ + Stack( + //alignment: Alignment.centerRight, + children: [ + Positioned( + left: (MediaQuery.of(context).size.height) *(80/926), + top: (MediaQuery.of(context).size.height) *(50/926), child: Align( alignment: Alignment.bottomRight, child: SvgPicture.asset( "assets/Images/login_bottomRight.svg", height: (MediaQuery.of(context).size.height) *0.183, width: (MediaQuery.of(context).size.height) *0.183, - color: Colors.transparent, ), ), - ), - ], - ), - ], + ), + Positioned(//Remove and add again + child: Align( + alignment: Alignment.bottomRight, + child: SvgPicture.asset( + "assets/Images/login_bottomRight.svg", + height: (MediaQuery.of(context).size.height) *0.183, + width: (MediaQuery.of(context).size.height) *0.183, + color: Colors.transparent, + ), + ), + ), + ], + ), + ], + ), ), - ), - ], + ], + ), ), ), ), diff --git a/lib/screens/Welcome/GenerateQuiz/generate_quiz.dart b/lib/screens/Welcome/GenerateQuiz/generate_quiz.dart index 17cc89c..0326fc7 100644 --- a/lib/screens/Welcome/GenerateQuiz/generate_quiz.dart +++ b/lib/screens/Welcome/GenerateQuiz/generate_quiz.dart @@ -1567,7 +1567,7 @@ class _GenerateQuizState extends State with SingleTickerProviderSt if(_questionsCount > 0) { final result = Navigator.push( context, - MaterialPageRoute(builder: (context) => QuizModule(totalQuestions: _questionsCount, questions: _questions, timedMode: _timedMode,)), + MaterialPageRoute(builder: (context) => QuizModule(totalQuestions: _questionsCount, questions: _questions, timedMode: _timedMode, mode: _tutorMode ? "tutor" : "exam", whatsDone: "new",)), ); } }, diff --git a/lib/screens/Welcome/PreviousQuiz/previous_quiz.dart b/lib/screens/Welcome/PreviousQuiz/previous_quiz.dart index 69042d7..6523ef5 100644 --- a/lib/screens/Welcome/PreviousQuiz/previous_quiz.dart +++ b/lib/screens/Welcome/PreviousQuiz/previous_quiz.dart @@ -1,609 +1,609 @@ - -import 'package:flutter/material.dart'; -import 'package:flutter_svg/flutter_svg.dart'; -import 'package:shared_preferences/shared_preferences.dart'; -import 'package:testify/models/GenerateQuizModels/get_system_categories_successful.dart'; -import 'package:testify/models/GenerateQuizModels/get_system_categories_unsuccessful.dart'; -import 'package:testify/models/GetPreviousQuizzesModel/get_previous_quizzes_model.dart'; -import 'package:testify/screens/Authentication/login.dart'; -import 'package:testify/screens/Welcome/PreviousQuiz/test_details.dart'; -import 'package:testify/screens/Welcome/PreviousQuiz/tile.dart'; -import '../side_menu_bar.dart'; -import 'package:http/http.dart' as http; -import 'dart:convert'; - -class PreviousQuiz extends StatefulWidget { - @override - _PreviousQuizState createState() => _PreviousQuizState(); -} - -class _PreviousQuizState extends State { - final filterList=['Filter By','Subjects','Systems','Topics']; - int filterIndex = 0; - String _currentfilter='Filter By'; - String _currentsubfilter='Filter By'; - int subFilterIndex = 0; - List subFilterList=['option1','option2']; - List subjectsSubFilterList = ["Select"]; - List systemsSubFilterList = ["Select"]; - List topicsSubFilterList = ["Select"]; - List filterSubFilterSelected = ["",""]; // 0: Filter, 1: SubFilter. - double? _swipeStartX; - String? _swipeDirection; - - bool hasPreviousQuizzesDataLoaded = false; - var previousQuizzesData = { - "quizId": [], - "name": [], - "score": [], - "date": [], - "status": [], - "questions": [], - "totalQuestions": [], - "subjects": [], - "systems": [], - "topics": [], - }; - - var previousQuizzesDataFiltered = { - "quizId": [], - "name": [], - "score": [], - "date": [], - "status": [], - "questions": [], - "totalQuestions": [], - "subjects": [], - "systems": [], - "topics": [], - }; - - //Shared Pref - var _token; - var _userId; - - // Token Valid - var _getSystemCategoriesSuccessful; - // Token Incorrect - var _getSystemCategoriesUnsuccessful; - - //Get Previous Quizzes - var _getPreviousQuizzesSuccessful; - - @override - void initState() { - super.initState(); - getPreviousQuizzes(); - getUserDataSST(); - } - - Future getPreviousQuizzes() async { - SharedPreferences prefs = await SharedPreferences.getInstance(); - final String apiUrlSystemCategories = "https://demo.pookidevs.com/quiz/generator/getPreviousQuizzes"; - _token = prefs.getString('token')!; - _userId = prefs.getInt("userId")!; - http.get(Uri.parse(apiUrlSystemCategories), headers: { - 'Content-type': 'application/json; charset=UTF-8', 'Authorization' : _token.toString(), - },).then((response) { - // print(jsonDecode(response.body)); - if(response.statusCode == 200) { - if(json.decode(response.body).toString().substring(0,20) == "{data: {status: true"){ - final responseString = (response.body); - var getPrevQuiz = getPreviousQuizzesModelFromJson(responseString); - final GetPreviousQuizzesModel getPreviousQuizzesSuccessful = getPrevQuiz; - setState(() { - _getPreviousQuizzesSuccessful = getPreviousQuizzesSuccessful; - }); - // print(_getPreviousQuizzesSuccessful.data.quizzes[0].quizId); - categorizePreviousQuizzesData(); - } - } - else { - //Token is Invalid - ScaffoldMessenger.of(context) - ..removeCurrentSnackBar() - ..showSnackBar(SnackBar(content: Text("Token Expired!"))); - final result = Navigator.push( - context, - MaterialPageRoute(builder: (context) => const Login(fromWhere:"Home")), - ); - } - } - ); - } - - categorizePreviousQuizzesData() { - int c = 0; - while((c<_getPreviousQuizzesSuccessful.data.quizzes.toList().length) & (_getPreviousQuizzesSuccessful.data.quizzes.toList().length > 0)) { - setState(() { - previousQuizzesData["quizId"]!.add(_getPreviousQuizzesSuccessful.data.quizzes[c].quizId); - previousQuizzesData["name"]!.add(_getPreviousQuizzesSuccessful.data.quizzes[c].name); - previousQuizzesData["score"]!.add(_getPreviousQuizzesSuccessful.data.quizzes[c].score); - previousQuizzesData["date"]!.add(_getPreviousQuizzesSuccessful.data.quizzes[c].date); - previousQuizzesData["status"]!.add(_getPreviousQuizzesSuccessful.data.quizzes[c].status); - previousQuizzesData["questions"]!.add(_getPreviousQuizzesSuccessful.data.quizzes[c].questions); - previousQuizzesData["totalQuestions"]!.add(_getPreviousQuizzesSuccessful.data.quizzes[c].totalQuestions); - previousQuizzesData["subjects"]!.add(_getPreviousQuizzesSuccessful.data.quizzes[c].subjects); - previousQuizzesData["systems"]!.add(_getPreviousQuizzesSuccessful.data.quizzes[c].systems); - previousQuizzesData["topics"]!.add(_getPreviousQuizzesSuccessful.data.quizzes[c].topics); - }); - c++; - } - setState(() { - hasPreviousQuizzesDataLoaded = true; - }); - print(previousQuizzesData); - } - - applyingPreviousQuizzesFilters() { - setState(() { - previousQuizzesDataFiltered["quizId"] = []; - previousQuizzesDataFiltered["name"] = []; - previousQuizzesDataFiltered["score"] = []; - previousQuizzesDataFiltered["date"] = []; - previousQuizzesDataFiltered["status"] = []; - previousQuizzesDataFiltered["questions"] = []; - previousQuizzesDataFiltered["totalQuestions"] = []; - previousQuizzesDataFiltered["subjects"] = []; - previousQuizzesDataFiltered["systems"] = []; - previousQuizzesDataFiltered["topics"] = []; - }); - if(filterSubFilterSelected[0] == "Subjects") { - for(int j = 0; j getUserDataSST() async { - SharedPreferences prefs = await SharedPreferences.getInstance(); - final String apiUrlSystemCategories = "https://demo.pookidevs.com/quiz/generator/getAllCategories"; - _token = prefs.getString('token')!; - _userId = prefs.getInt("userId")!; - // print(_userId); - // print(_token); - http.get(Uri.parse(apiUrlSystemCategories), headers: { - 'Content-type': 'application/json; charset=UTF-8', 'Authorization' : _token.toString(), - },).then((response) { - // print(jsonDecode(response.body).toString()); - if(response.statusCode == 200) { - if(json.decode(response.body).toString().substring(0,20) == "{data: {status: true") { - final responseString = (response.body); - var systemCategoriesDataSuccessful = getSystemCategoriesSuccessfulModelFromJson(responseString); - final GetSystemCategoriesSuccessfulModel getSystemCategoriesSuccessful = systemCategoriesDataSuccessful; - setState(() { - _getSystemCategoriesSuccessful = getSystemCategoriesSuccessful; - }); - // print(_questions); - } else { - - } - //Adds data to lists - categorizeUserData(); - } - else { // Status Code is 401 here that is why if written in the above if statement it would not work. - //Token is Invalid - if(json.decode(response.body).toString().substring(0,14) == "{status: false") { - final responseString = (response.body); - var systemCategoriesDataUnsuccessful = getSystemCategoriesUnsuccessfulModelFromJson(responseString); - final GetSystemCategoriesUnsuccessfulModel getSystemCategoriesUnsuccessful = systemCategoriesDataUnsuccessful; - setState(() { - _getSystemCategoriesUnsuccessful = getSystemCategoriesUnsuccessful; - }); - print(_getSystemCategoriesUnsuccessful.msg); - ScaffoldMessenger.of(context) - ..removeCurrentSnackBar() - ..showSnackBar(SnackBar(content: Text("Token Expired!"))); - final result = Navigator.push( - context, - MaterialPageRoute(builder: (context) => const Login(fromWhere:"Home")), - ); - } - else { - - } - } - } - ); - } - - //Add data to lists. Only done the first time. - categorizeUserData() { - //To clear any past data - int c = 0; - while((c<_getSystemCategoriesSuccessful.data.categories.toList().length) & (_getSystemCategoriesSuccessful.data.categories.toList().length > 0)) { - var tempLength = _getSystemCategoriesSuccessful.data.categories.toList().length; - if(_getSystemCategoriesSuccessful.data.categories[c].subCategories != null) { - if(_getSystemCategoriesSuccessful.data.categories[c].parentCategory.toString() == "systems") { - //Gets the length of subjects(Number of Subjects) - var lenSystems = _getSystemCategoriesSuccessful.data.categories[c].subCategories.toList().length; - int i = 0; - setState(() { - while((lenSystems>0) & (i0) & (i0) & (i[ - Color(0xff7F1AF1), - Color(0xff482384) - ]) - ), - ), - title: const Text("Previous Quiz", - style: TextStyle( - color: Color(0xffFFFEFE), - fontFamily: 'Brandon-bld', - ), - ), - actions: [ - TextButton( - onPressed: () async { - final result = await Navigator.push( - context, - MaterialPageRoute(builder: (context) => const Login(fromWhere:"Home")), - ); - }, - child: SvgPicture.asset( - "assets/Images/logout.svg", - height: (MediaQuery.of(context).size.height) *(32/926), - ), - ), - ], - ), - body: SingleChildScrollView( - child: Container( - padding: EdgeInsets.only(top:(MediaQuery.of(context).size.height) *(15/926), - bottom: (MediaQuery.of(context).size.height) *(8/926), - left: (MediaQuery.of(context).size.width) *(18/428), - right: (MediaQuery.of(context).size.width) *(18/428)), - child: Column( - children: [ - Row( - children: [ - Container( - width: (MediaQuery.of(context).size.width) *(221/428), - //height: (MediaQuery.of(context).size.height) *(91/926), - child: Column( - children: [ - Align( - alignment: Alignment.topLeft, - child: Text("Previous Quiz", - style: TextStyle( - color: Color(0xff232323), - fontFamily: 'Brandon-bld', - fontSize: (MediaQuery.of(context).size.height) *(25/926),//38, - ),), - ), - SizedBox(height: (MediaQuery.of(context).size.height) *(2/926),), - Text("Lorem ipsum dolor sit amet, consectetur adipiscing elit. Cras imperdiet finibus elit non luctus. Morbi auctor mattis ante.", - style: TextStyle( - color: Color(0xFF483A3A), - fontFamily: 'Brandon-med', - fontSize: (MediaQuery.of(context).size.height) *(13/926),//38, - ),), - ], - ), - ), - SizedBox(width: (MediaQuery.of(context).size.width) *(39/428),), - Container( - //color: Colors.transparent, - child: SvgPicture.asset( - "assets/Images/prevQuiz.svg", - height: (MediaQuery.of(context).size.height) *(100/926), - //width: (MediaQuery.of(context).size.width) *(132/428), - ), - ), - ], - ), - SizedBox(height: (MediaQuery.of(context).size.height)*(30/926),), - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Row( - children: [ - Text("Filter By: ", - style: TextStyle( - color: Color(0xFF483A3A), - fontFamily: 'Brandon-med', - fontSize: (MediaQuery.of(context).size.height) *(16/926),//38, - ),), - DropdownButton( - value: filterList[filterIndex], - underline: Container(), - iconEnabledColor: Color(0xff3F2668), - dropdownColor:Colors.white , - onChanged: (newValue) { - setState(() { - // print(newValue); - _currentfilter = newValue as String; - if(_currentfilter == filterList[1]){ - filterIndex = 1; - subFilterIndex = 0; - subFilterList = subjectsSubFilterList;} - else if(_currentfilter == filterList[2]){ - filterIndex = 2; - subFilterIndex = 0; - subFilterList = systemsSubFilterList;} - else if(_currentfilter == filterList[3]){ - filterIndex = 3; - subFilterIndex = 0; - subFilterList = topicsSubFilterList;} - else if(_currentfilter == filterList[0]){ - filterIndex = 0; - subFilterIndex = 0;} - filterSubFilterSelected[0] = _currentfilter; - applyingPreviousQuizzesFilters(); - // print(filterSubFilterSelected); - }); - }, - items: filterList.map((filter){ - return DropdownMenuItem( - child: Text(filter,style: TextStyle( - color: Color(0xff3F2668), - fontFamily: 'Brandon-bld', - fontSize: - (MediaQuery.of(context).size.height) * (16 / 926), - ),), - value: filter, - ); - }).toList(), - - - ), - ], - ), - // This below row is just for the if statement - if(_currentfilter != "Filter By") - Row( - children: [ - //SizedBox(width: (MediaQuery.of(context).size.width)*(40/428),), - Text(_currentfilter + ": ", - style: TextStyle( - color: Color(0xFF483A3A), - fontFamily: 'Brandon-med', - fontSize: (MediaQuery.of(context).size.height) *(16/926),//38, - ),), - DropdownButton( - value: (subFilterList.length<(subFilterIndex+1)) ? subFilterList[0] : subFilterList[subFilterIndex], - underline: Container(), - iconEnabledColor: Color(0xff3F2668), - dropdownColor:Colors.white , - onChanged: (newValue) { - setState(() { - // print(newValue); - subFilterIndex = 0; - _currentsubfilter = newValue as String; - for(int i = 0; i _swipeStartX!) ? "Right" : "Left"; - }, - onHorizontalDragEnd: (e) async { - if (_swipeDirection == "Right") - print("left"); - else if (_swipeDirection == "Left") { - print(previousQuizzesDataFiltered["system"]![i].toString()); - // final result = await Navigator.push( - // context, - // MaterialPageRoute( - // builder: (context) => TestDetails( - // quizId: previousQuizzesData["quizId"]![i], - // system: previousQuizzesData["system"]![i], - // subject: previousQuizzesData["subject"]![i], - // topic: previousQuizzesData["topic"]![i], - // score: previousQuizzesData["score"]![i], - // status: previousQuizzesData["status"]![i]))); - } - },), - ], - ) : - Column( - children: [ - SizedBox(height: (MediaQuery.of(context).size.height)*(30/926),), - GestureDetector(child: Tile( - name: previousQuizzesData["name"]![i], - quizId: previousQuizzesData["quizId"]![i], - status: previousQuizzesData["status"]![i], - score: previousQuizzesData["score"]![i], - systems: previousQuizzesData["systems"]![i], - questions: previousQuizzesData["questions"]![i], - date: previousQuizzesData["date"]![i], - topics: previousQuizzesData["topics"]![i], - subjects: previousQuizzesData["subjects"]![i], - totalQuestions: previousQuizzesData["totalQuestions"]![i],), - onHorizontalDragStart: (e) { - _swipeStartX = e.globalPosition.dx; - }, - onHorizontalDragUpdate: (e) { - _swipeDirection = - (e.globalPosition.dx > _swipeStartX!) ? "Right" : "Left"; - }, - onHorizontalDragEnd: (e) async { - if (_swipeDirection == "Right") - print("left"); - else if (_swipeDirection == "Left") { - print(previousQuizzesData["system"]![i].toString()); - // final result = await Navigator.push( - // context, - // MaterialPageRoute( - // builder: (context) => TestDetails( - // quizId: previousQuizzesData["quizId"]![i], - // system: previousQuizzesData["system"]![i], - // subject: previousQuizzesData["subject"]![i], - // topic: previousQuizzesData["topic"]![i], - // score: previousQuizzesData["score"]![i], - // status: previousQuizzesData["status"]![i]))); - } - },), - ], - ), - SizedBox(height: (MediaQuery.of(context).size.height)*(30/926),), - - ], - ), - ), - ), - ); - } -} + +import 'package:flutter/material.dart'; +import 'package:flutter_svg/flutter_svg.dart'; +import 'package:shared_preferences/shared_preferences.dart'; +import 'package:testify/models/GenerateQuizModels/get_system_categories_successful.dart'; +import 'package:testify/models/GenerateQuizModels/get_system_categories_unsuccessful.dart'; +import 'package:testify/models/GetPreviousQuizzesModel/get_previous_quizzes_model.dart'; +import 'package:testify/screens/Authentication/login.dart'; +import 'package:testify/screens/Welcome/PreviousQuiz/test_details.dart'; +import 'package:testify/screens/Welcome/PreviousQuiz/tile.dart'; +import '../side_menu_bar.dart'; +import 'package:http/http.dart' as http; +import 'dart:convert'; + +class PreviousQuiz extends StatefulWidget { + @override + _PreviousQuizState createState() => _PreviousQuizState(); +} + +class _PreviousQuizState extends State { + final filterList=['Filter By','Subjects','Systems','Topics']; + int filterIndex = 0; + String _currentfilter='Filter By'; + String _currentsubfilter='Filter By'; + int subFilterIndex = 0; + List subFilterList=['option1','option2']; + List subjectsSubFilterList = ["Select"]; + List systemsSubFilterList = ["Select"]; + List topicsSubFilterList = ["Select"]; + List filterSubFilterSelected = ["",""]; // 0: Filter, 1: SubFilter. + double? _swipeStartX; + String? _swipeDirection; + + bool hasPreviousQuizzesDataLoaded = false; + var previousQuizzesData = { + "quizId": [], + "name": [], + "score": [], + "date": [], + "status": [], + "questions": [], + "totalQuestions": [], + "subjects": [], + "systems": [], + "topics": [], + }; + + var previousQuizzesDataFiltered = { + "quizId": [], + "name": [], + "score": [], + "date": [], + "status": [], + "questions": [], + "totalQuestions": [], + "subjects": [], + "systems": [], + "topics": [], + }; + + //Shared Pref + var _token; + var _userId; + + // Token Valid + var _getSystemCategoriesSuccessful; + // Token Incorrect + var _getSystemCategoriesUnsuccessful; + + //Get Previous Quizzes + var _getPreviousQuizzesSuccessful; + + @override + void initState() { + super.initState(); + getPreviousQuizzes(); + getUserDataSST(); + } + + Future getPreviousQuizzes() async { + SharedPreferences prefs = await SharedPreferences.getInstance(); + final String apiUrlSystemCategories = "https://demo.pookidevs.com/quiz/generator/getPreviousQuizzes"; + _token = prefs.getString('token')!; + _userId = prefs.getInt("userId")!; + http.get(Uri.parse(apiUrlSystemCategories), headers: { + 'Content-type': 'application/json; charset=UTF-8', 'Authorization' : _token.toString(), + },).then((response) { + // print(jsonDecode(response.body)); + if(response.statusCode == 200) { + if(json.decode(response.body).toString().substring(0,20) == "{data: {status: true"){ + final responseString = (response.body); + var getPrevQuiz = getPreviousQuizzesModelFromJson(responseString); + final GetPreviousQuizzesModel getPreviousQuizzesSuccessful = getPrevQuiz; + setState(() { + _getPreviousQuizzesSuccessful = getPreviousQuizzesSuccessful; + }); + // print(_getPreviousQuizzesSuccessful.data.quizzes[0].quizId); + categorizePreviousQuizzesData(); + } + } + else { + //Token is Invalid + ScaffoldMessenger.of(context) + ..removeCurrentSnackBar() + ..showSnackBar(SnackBar(content: Text("Token Expired!"))); + final result = Navigator.push( + context, + MaterialPageRoute(builder: (context) => const Login(fromWhere:"Home")), + ); + } + } + ); + } + + categorizePreviousQuizzesData() { + int c = 0; + while((c<_getPreviousQuizzesSuccessful.data.quizzes.toList().length) & (_getPreviousQuizzesSuccessful.data.quizzes.toList().length > 0)) { + setState(() { + previousQuizzesData["quizId"]!.add(_getPreviousQuizzesSuccessful.data.quizzes[c].quizId); + previousQuizzesData["name"]!.add(_getPreviousQuizzesSuccessful.data.quizzes[c].name); + previousQuizzesData["score"]!.add(_getPreviousQuizzesSuccessful.data.quizzes[c].score); + previousQuizzesData["date"]!.add(_getPreviousQuizzesSuccessful.data.quizzes[c].date); + previousQuizzesData["status"]!.add(_getPreviousQuizzesSuccessful.data.quizzes[c].status); + previousQuizzesData["questions"]!.add(_getPreviousQuizzesSuccessful.data.quizzes[c].questions); + previousQuizzesData["totalQuestions"]!.add(_getPreviousQuizzesSuccessful.data.quizzes[c].totalQuestions); + previousQuizzesData["subjects"]!.add(_getPreviousQuizzesSuccessful.data.quizzes[c].subjects); + previousQuizzesData["systems"]!.add(_getPreviousQuizzesSuccessful.data.quizzes[c].systems); + previousQuizzesData["topics"]!.add(_getPreviousQuizzesSuccessful.data.quizzes[c].topics); + }); + c++; + } + setState(() { + hasPreviousQuizzesDataLoaded = true; + }); + // print(previousQuizzesData); + } + + applyingPreviousQuizzesFilters() { + setState(() { + previousQuizzesDataFiltered["quizId"] = []; + previousQuizzesDataFiltered["name"] = []; + previousQuizzesDataFiltered["score"] = []; + previousQuizzesDataFiltered["date"] = []; + previousQuizzesDataFiltered["status"] = []; + previousQuizzesDataFiltered["questions"] = []; + previousQuizzesDataFiltered["totalQuestions"] = []; + previousQuizzesDataFiltered["subjects"] = []; + previousQuizzesDataFiltered["systems"] = []; + previousQuizzesDataFiltered["topics"] = []; + }); + if(filterSubFilterSelected[0] == "Subjects") { + for(int j = 0; j getUserDataSST() async { + SharedPreferences prefs = await SharedPreferences.getInstance(); + final String apiUrlSystemCategories = "https://demo.pookidevs.com/quiz/generator/getAllCategories"; + _token = prefs.getString('token')!; + _userId = prefs.getInt("userId")!; + // print(_userId); + // print(_token); + http.get(Uri.parse(apiUrlSystemCategories), headers: { + 'Content-type': 'application/json; charset=UTF-8', 'Authorization' : _token.toString(), + },).then((response) { + // print(jsonDecode(response.body).toString()); + if(response.statusCode == 200) { + if(json.decode(response.body).toString().substring(0,20) == "{data: {status: true") { + final responseString = (response.body); + var systemCategoriesDataSuccessful = getSystemCategoriesSuccessfulModelFromJson(responseString); + final GetSystemCategoriesSuccessfulModel getSystemCategoriesSuccessful = systemCategoriesDataSuccessful; + setState(() { + _getSystemCategoriesSuccessful = getSystemCategoriesSuccessful; + }); + // print(_questions); + } else { + + } + //Adds data to lists + categorizeUserData(); + } + else { // Status Code is 401 here that is why if written in the above if statement it would not work. + //Token is Invalid + if(json.decode(response.body).toString().substring(0,14) == "{status: false") { + final responseString = (response.body); + var systemCategoriesDataUnsuccessful = getSystemCategoriesUnsuccessfulModelFromJson(responseString); + final GetSystemCategoriesUnsuccessfulModel getSystemCategoriesUnsuccessful = systemCategoriesDataUnsuccessful; + setState(() { + _getSystemCategoriesUnsuccessful = getSystemCategoriesUnsuccessful; + }); + print(_getSystemCategoriesUnsuccessful.msg); + ScaffoldMessenger.of(context) + ..removeCurrentSnackBar() + ..showSnackBar(SnackBar(content: Text("Token Expired!"))); + final result = Navigator.push( + context, + MaterialPageRoute(builder: (context) => const Login(fromWhere:"Home")), + ); + } + else { + + } + } + } + ); + } + + //Add data to lists. Only done the first time. + categorizeUserData() { + //To clear any past data + int c = 0; + while((c<_getSystemCategoriesSuccessful.data.categories.toList().length) & (_getSystemCategoriesSuccessful.data.categories.toList().length > 0)) { + var tempLength = _getSystemCategoriesSuccessful.data.categories.toList().length; + if(_getSystemCategoriesSuccessful.data.categories[c].subCategories != null) { + if(_getSystemCategoriesSuccessful.data.categories[c].parentCategory.toString() == "systems") { + //Gets the length of subjects(Number of Subjects) + var lenSystems = _getSystemCategoriesSuccessful.data.categories[c].subCategories.toList().length; + int i = 0; + setState(() { + while((lenSystems>0) & (i0) & (i0) & (i[ + Color(0xff7F1AF1), + Color(0xff482384) + ]) + ), + ), + title: const Text("Previous Quiz", + style: TextStyle( + color: Color(0xffFFFEFE), + fontFamily: 'Brandon-bld', + ), + ), + actions: [ + TextButton( + onPressed: () async { + final result = await Navigator.push( + context, + MaterialPageRoute(builder: (context) => const Login(fromWhere:"Home")), + ); + }, + child: SvgPicture.asset( + "assets/Images/logout.svg", + height: (MediaQuery.of(context).size.height) *(32/926), + ), + ), + ], + ), + body: SingleChildScrollView( + child: Container( + padding: EdgeInsets.only(top:(MediaQuery.of(context).size.height) *(15/926), + bottom: (MediaQuery.of(context).size.height) *(8/926), + left: (MediaQuery.of(context).size.width) *(18/428), + right: (MediaQuery.of(context).size.width) *(18/428)), + child: Column( + children: [ + Row( + children: [ + Container( + width: (MediaQuery.of(context).size.width) *(221/428), + //height: (MediaQuery.of(context).size.height) *(91/926), + child: Column( + children: [ + Align( + alignment: Alignment.topLeft, + child: Text("Previous Quiz", + style: TextStyle( + color: Color(0xff232323), + fontFamily: 'Brandon-bld', + fontSize: (MediaQuery.of(context).size.height) *(25/926),//38, + ),), + ), + SizedBox(height: (MediaQuery.of(context).size.height) *(2/926),), + Text("Lorem ipsum dolor sit amet, consectetur adipiscing elit. Cras imperdiet finibus elit non luctus. Morbi auctor mattis ante.", + style: TextStyle( + color: Color(0xFF483A3A), + fontFamily: 'Brandon-med', + fontSize: (MediaQuery.of(context).size.height) *(13/926),//38, + ),), + ], + ), + ), + SizedBox(width: (MediaQuery.of(context).size.width) *(39/428),), + Container( + //color: Colors.transparent, + child: SvgPicture.asset( + "assets/Images/prevQuiz.svg", + height: (MediaQuery.of(context).size.height) *(100/926), + //width: (MediaQuery.of(context).size.width) *(132/428), + ), + ), + ], + ), + SizedBox(height: (MediaQuery.of(context).size.height)*(30/926),), + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Row( + children: [ + Text("Filter By: ", + style: TextStyle( + color: Color(0xFF483A3A), + fontFamily: 'Brandon-med', + fontSize: (MediaQuery.of(context).size.height) *(16/926),//38, + ),), + DropdownButton( + value: filterList[filterIndex], + underline: Container(), + iconEnabledColor: Color(0xff3F2668), + dropdownColor:Colors.white , + onChanged: (newValue) { + setState(() { + // print(newValue); + _currentfilter = newValue as String; + if(_currentfilter == filterList[1]){ + filterIndex = 1; + subFilterIndex = 0; + subFilterList = subjectsSubFilterList;} + else if(_currentfilter == filterList[2]){ + filterIndex = 2; + subFilterIndex = 0; + subFilterList = systemsSubFilterList;} + else if(_currentfilter == filterList[3]){ + filterIndex = 3; + subFilterIndex = 0; + subFilterList = topicsSubFilterList;} + else if(_currentfilter == filterList[0]){ + filterIndex = 0; + subFilterIndex = 0;} + filterSubFilterSelected[0] = _currentfilter; + applyingPreviousQuizzesFilters(); + // print(filterSubFilterSelected); + }); + }, + items: filterList.map((filter){ + return DropdownMenuItem( + child: Text(filter,style: TextStyle( + color: Color(0xff3F2668), + fontFamily: 'Brandon-bld', + fontSize: + (MediaQuery.of(context).size.height) * (16 / 926), + ),), + value: filter, + ); + }).toList(), + + + ), + ], + ), + // This below row is just for the if statement + if(_currentfilter != "Filter By") + Row( + children: [ + //SizedBox(width: (MediaQuery.of(context).size.width)*(40/428),), + Text(_currentfilter + ": ", + style: TextStyle( + color: Color(0xFF483A3A), + fontFamily: 'Brandon-med', + fontSize: (MediaQuery.of(context).size.height) *(16/926),//38, + ),), + DropdownButton( + value: (subFilterList.length<(subFilterIndex+1)) ? subFilterList[0] : subFilterList[subFilterIndex], + underline: Container(), + iconEnabledColor: Color(0xff3F2668), + dropdownColor:Colors.white , + onChanged: (newValue) { + setState(() { + // print(newValue); + subFilterIndex = 0; + _currentsubfilter = newValue as String; + for(int i = 0; i _swipeStartX!) ? "Right" : "Left"; + }, + onHorizontalDragEnd: (e) async { + if (_swipeDirection == "Right") + print("left"); + else if (_swipeDirection == "Left") { + print(previousQuizzesDataFiltered["system"]![i].toString()); + // final result = await Navigator.push( + // context, + // MaterialPageRoute( + // builder: (context) => TestDetails( + // quizId: previousQuizzesData["quizId"]![i], + // system: previousQuizzesData["system"]![i], + // subject: previousQuizzesData["subject"]![i], + // topic: previousQuizzesData["topic"]![i], + // score: previousQuizzesData["score"]![i], + // status: previousQuizzesData["status"]![i]))); + } + },), + ], + ) : + Column( + children: [ + SizedBox(height: (MediaQuery.of(context).size.height)*(30/926),), + GestureDetector(child: Tile( + name: previousQuizzesData["name"]![i], + quizId: previousQuizzesData["quizId"]![i], + status: previousQuizzesData["status"]![i], + score: previousQuizzesData["score"]![i], + systems: previousQuizzesData["systems"]![i], + questions: previousQuizzesData["questions"]![i], + date: previousQuizzesData["date"]![i], + topics: previousQuizzesData["topics"]![i], + subjects: previousQuizzesData["subjects"]![i], + totalQuestions: previousQuizzesData["totalQuestions"]![i],), + onHorizontalDragStart: (e) { + _swipeStartX = e.globalPosition.dx; + }, + onHorizontalDragUpdate: (e) { + _swipeDirection = + (e.globalPosition.dx > _swipeStartX!) ? "Right" : "Left"; + }, + onHorizontalDragEnd: (e) async { + if (_swipeDirection == "Right") + print("left"); + else if (_swipeDirection == "Left") { + print(previousQuizzesData["system"]![i].toString()); + // final result = await Navigator.push( + // context, + // MaterialPageRoute( + // builder: (context) => TestDetails( + // quizId: previousQuizzesData["quizId"]![i], + // system: previousQuizzesData["system"]![i], + // subject: previousQuizzesData["subject"]![i], + // topic: previousQuizzesData["topic"]![i], + // score: previousQuizzesData["score"]![i], + // status: previousQuizzesData["status"]![i]))); + } + },), + ], + ), + SizedBox(height: (MediaQuery.of(context).size.height)*(30/926),), + + ], + ), + ), + ), + ); + } +} diff --git a/lib/screens/Welcome/PreviousQuiz/test_details.dart b/lib/screens/Welcome/PreviousQuiz/test_details.dart index d1960ef..697e1aa 100644 --- a/lib/screens/Welcome/PreviousQuiz/test_details.dart +++ b/lib/screens/Welcome/PreviousQuiz/test_details.dart @@ -1,386 +1,478 @@ -import 'package:flutter/cupertino.dart'; -import 'package:flutter/material.dart'; -import 'package:flutter_svg/svg.dart'; - -import '../../Authentication/login.dart'; -import '../side_menu_bar.dart'; - -class TestDetails extends StatelessWidget { - final int quizId; - final List system; - final List subject; - final List topic; - final String status; - final String score; - TestDetails( - {required this.quizId, - required this.system, - required this.subject, - required this.topic, - required this.status, - required this.score}); - @override - Widget build(BuildContext context) { - return Scaffold( - backgroundColor: Color(0xffF8F9FB), - drawer: SideMenuBar(), - appBar: AppBar( - toolbarHeight: (MediaQuery.of(context).size.height) * (73.52 / 926), - backgroundColor: Color(0xff3F2668), - elevation: 2, - centerTitle: true, - flexibleSpace: Container( - decoration: const BoxDecoration( - gradient: LinearGradient( - begin: Alignment.topCenter, - end: Alignment.bottomCenter, - colors: [Color(0xff7F1AF1), Color(0xff482384)])), - ), - title: const Text( - "Test Details", - style: TextStyle( - color: Color(0xffFFFEFE), - fontFamily: 'Brandon-bld', - ), - ), - actions: [ - TextButton( - onPressed: () async { - final result = await Navigator.push( - context, - MaterialPageRoute( - builder: (context) => const Login(fromWhere: "Home")), - ); - }, - child: SvgPicture.asset( - "assets/Images/logout.svg", - height: (MediaQuery.of(context).size.height) * (32 / 926), - ), - ), - ], - ), - body: SingleChildScrollView( - child: Padding( - padding: const EdgeInsets.symmetric(vertical: 100), - child: Column( - children: [ - Center( - child: Container( - height: (MediaQuery.of(context).size.height) * (488 / 926), - width: (MediaQuery.of(context).size.width) * (385 / 428), - decoration: BoxDecoration( - borderRadius: BorderRadius.circular(2), - color: Colors.white, - boxShadow: [ - BoxShadow(color: Colors.grey, offset: Offset(0, 4), blurRadius: 6) - ], - ), - child: Column( - children: [ - - Container( - height: (MediaQuery.of(context).size.height) * (59 / 926), - width: (MediaQuery.of(context).size.width) * (385 / 428), - color: Color(0xff6D5A8D), - child: Center( - child: Text( - 'Test Details', - style: TextStyle( - color: Colors.white, - fontFamily: 'Brandon-bld', - fontSize: (MediaQuery.of(context).size.height) * (20 / 926), - ), - ), - ), - ), - Container( - height: (MediaQuery.of(context).size.height) * (310 / 926), - width: (MediaQuery.of(context).size.width) * (385 / 428), - padding: EdgeInsets.all(25), - child: Table( - columnWidths: {0:FixedColumnWidth((MediaQuery.of(context).size.width) * (25 / 428)), - 1:FixedColumnWidth((MediaQuery.of(context).size.width) * (200 / 428))}, - border: TableBorder.all(color: Colors.transparent), - children: [ - TableRow(children: [ - Padding( - padding: const EdgeInsets.only(top:8.0), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - 'Quiz ID:', - style: TextStyle( - color: Color(0xff3F2668), - fontFamily: 'Brandon-bld', - fontSize: (MediaQuery.of(context).size.height) * - (16 / 926), - ), - ), - ], - ), - ), - Padding( - padding: const EdgeInsets.only(top:8.0), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text(quizId.toString(), - textAlign: TextAlign.start, - style: TextStyle( - color: Colors.black, - fontFamily: 'Brandon-med', - fontSize: (MediaQuery.of(context).size.height) * - (16 / 926), - )) - ], - ), - ) - ]), - TableRow(children: [ - Padding( - padding: const EdgeInsets.only(top:8.0), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - 'System:', - style: TextStyle( - color: Color(0xff3F2668), - fontFamily: 'Brandon-bld', - fontSize: (MediaQuery.of(context).size.height) * - (16 / 926), - ), - ), - ], - ), - ), - Padding( - padding: const EdgeInsets.only(top:8.0), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text(system.toString().substring(1, system.toString().length-1) == "" ? "-" : system.toString().substring(1, system.toString().length-1), - style: TextStyle( - color: Colors.black, - fontFamily: 'Brandon-med', - fontSize: (MediaQuery.of(context).size.height) * - (16 / 926), - )) - ], - ), - ) - ]), - TableRow(children: [ - Padding( - padding: const EdgeInsets.only(top:8.0), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - 'Subject:', - style: TextStyle( - color: Color(0xff3F2668), - fontFamily: 'Brandon-bld', - fontSize: (MediaQuery.of(context).size.height) * - (16 / 926), - ), - ), - ], - ), - ), - Padding( - padding: const EdgeInsets.only(top:8.0), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text(subject.toString().substring(1, subject.toString().length-1) == "" ? "-" : subject.toString().substring(1, subject.toString().length-1), - style: TextStyle( - color: Colors.black, - fontFamily: 'Brandon-med', - fontSize: (MediaQuery.of(context).size.height) * - (16 / 926), - )) - ], - ), - ) - ]), - TableRow(children: [ - Padding( - padding: const EdgeInsets.only(top:8.0), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - 'Topic:', - style: TextStyle( - color: Color(0xff3F2668), - fontFamily: 'Brandon-bld', - fontSize: (MediaQuery.of(context).size.height) * - (16 / 926), - ), - ), - ], - ), - ), - Padding( - padding: const EdgeInsets.only(top:8.0), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text(topic.toString().substring(1, topic.toString().length-1) == "" ? "-" : topic.toString().substring(1, topic.toString().length-1), - style: TextStyle( - color: Colors.black, - fontFamily: 'Brandon-med', - fontSize: (MediaQuery.of(context).size.height) * - (16 / 926), - )) - ], - ), - ) - ]), - TableRow(children: [ - Padding( - padding: const EdgeInsets.only(top:8.0), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - 'Score:', - style: TextStyle( - color: Color(0xff3F2668), - fontFamily: 'Brandon-bld', - fontSize: (MediaQuery.of(context).size.height) * - (16 / 926), - ), - ), - ], - ), - ), - Padding( - padding: const EdgeInsets.only(top:8.0), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text(score, - style: TextStyle( - color: Colors.black, - fontFamily: 'Brandon-med', - fontSize: (MediaQuery.of(context).size.height) * - (16 / 926), - )) - ], - ), - ) - ]), - TableRow(children: [ - Padding( - padding: const EdgeInsets.only(top:8.0), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - 'Status:', - style: TextStyle( - color: Color(0xff3F2668), - fontFamily: 'Brandon-bld', - fontSize: (MediaQuery.of(context).size.height) * - (16 / 926), - ), - ), - ], - ), - ), - Padding( - padding: const EdgeInsets.only(top:8.0), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text(status, - style: TextStyle( - color: Colors.black, - fontFamily: 'Brandon-med', - fontSize: (MediaQuery.of(context).size.height) * - (16 / 926), - )) - ], - ), - ) - ]) - ], - ), - ), - - Container( - height: (MediaQuery.of(context).size.height) * (70 / 926), - width: (MediaQuery.of(context).size.width) * (385 / 428), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceEvenly, - children: [ - Column( - children: [ - Container(height:40,width:40,decoration: BoxDecoration(color: Color(0xff7F1AF1),borderRadius: BorderRadius.circular(20)), - child: Icon(Icons.show_chart_outlined,size: 20,color:Colors.white)) - ,Text('Test Analysis',style: TextStyle( - color: Color(0xff7F1AF1), - fontFamily: 'Brandon-med', - fontSize: (MediaQuery.of(context).size.height) * (15 / 926), - ),) - ], - ), - Column( - children: [ - Container(height:40,width:40,decoration: BoxDecoration(color: Color(0xff7F1AF1),borderRadius: BorderRadius.circular(20)), - child: Icon(Icons.event_note_outlined,size: 20,color:Colors.white)) - ,Text('Test Results',style: TextStyle( - color: Color(0xff7F1AF1), - fontFamily: 'Brandon-med', - fontSize: (MediaQuery.of(context).size.height) * (15 / 926), - ),) - ], - ), - Column( - children: [ - Container(height:40,width:40,decoration: BoxDecoration(color: Color(0xff7F1AF1),borderRadius: BorderRadius.circular(20)), - child: Icon(Icons.arrow_right,size: 40,color:Colors.white)) - ,Text('Resume',style: TextStyle( - color: Color(0xff7F1AF1), - fontFamily: 'Brandon-med', - fontSize: (MediaQuery.of(context).size.height) * (15 / 926), - ),) - ], - ), - ], - ), - ) - - ], - ), - ), - ), - Padding( - padding: const EdgeInsets.all(20.0), - child: InkWell( - onTap:(){ - Navigator.of(context).pop(); - }, - child:Container( - child: Row( - children: [Icon(Icons.arrow_back,color: Color(0xff7F1AF1),size: 15,),Text('Back',style: TextStyle( - color: Color(0xff7F1AF1), - fontFamily: 'Brandon-bld', - fontSize: (MediaQuery.of(context).size.height) * - (13 / 926), - ),)], - - ), - )), - ) - ], - ), - ), - ), - ); - - } -} +import 'dart:convert'; + +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_svg/svg.dart'; +import 'package:shared_preferences/shared_preferences.dart'; +import 'package:testify/models/GetPreviousQuizzesModel/ResumeQuiz/resume_quiz_model.dart'; +import 'package:testify/screens/Welcome/PreviousQuiz/previous_quiz.dart'; +import 'package:http/http.dart' as http; +import 'package:testify/screens/Welcome/QuizModule/quiz_module.dart'; +import '../../Authentication/login.dart'; +import '../side_menu_bar.dart'; + +class TestDetails extends StatefulWidget { + final int quizId; + final List system; + final List subject; + final List topic; + final String status; + final String score; + TestDetails( + {required this.quizId, + required this.system, + required this.subject, + required this.topic, + required this.status, + required this.score}); + + @override + State createState() => _TestDetailsState(); +} + +class _TestDetailsState extends State { + var _token; + var _userId; + var _resumeQuizSuccessful; + + @override + void initState() { + super.initState(); + ResumeQuizAPI(); + } + + Future ResumeQuizAPI() async { + SharedPreferences prefs = await SharedPreferences.getInstance(); + final String apiUrlGenerateQuiz = "https://demo.pookidevs.com/quiz/solver/resumeQuiz"; + _token = prefs.getString('token')!; + print(_token); + _userId = prefs.getInt("userId")!; + http.post(Uri.parse(apiUrlGenerateQuiz), headers: { + 'Content-type': 'application/json; charset=UTF-8', 'Authorization' : _token.toString(), + }, body: json.encode( + { + "quizId": widget.quizId + }) + ).then((response) { + // print(jsonDecode(response.body).toString()); + if((response.statusCode == 200) & (json.decode(response.body).toString().substring(0,14) != "{status: false")) { + final responseString = (response.body); + var resumeQuizSuccessful1 = resumeQuizModelFromJson(responseString); + final ResumeQuizModel resumeQuizSuccessful = resumeQuizSuccessful1; + setState(() { + _resumeQuizSuccessful = resumeQuizSuccessful; + // print(_resumeQuizSuccessful.data.previousQuizzes[0].quizMeta.quizMode); + // print(_resumeQuizSuccessful.data.previousQuizzes[0].quizMeta.quizTotalQuestions); + // print(_resumeQuizSuccessful.data.previousQuizzes[0].quizMeta.quizQuestions); + // print(_resumeQuizSuccessful.data.previousQuizzes[0].quizMeta.quizStatus); + // print(_resumeQuizSuccessful.data.previousQuizzes[0].quizMeta.isTimed); + // print(_resumeQuizSuccessful.data.previousQuizzes[0].quizMeta.quizId.runtimeType); + // print(_resumeQuizSuccessful.data.previousQuizzes[0].quizMeta.quizScore.runtimeType); + // _quizId = _getGenerateQuizSuccessful.data.quizId; + // print(_quizId); + }); + // categoriesGenerateQuizData(); + } + else { // Token Invalid + + } + } + ); + } + + @override + Widget build(BuildContext context) { + return Scaffold( + backgroundColor: Color(0xffF8F9FB), + drawer: SideMenuBar(), + appBar: AppBar( + toolbarHeight: (MediaQuery.of(context).size.height) * (73.52 / 926), + backgroundColor: Color(0xff3F2668), + elevation: 2, + centerTitle: true, + flexibleSpace: Container( + decoration: const BoxDecoration( + gradient: LinearGradient( + begin: Alignment.topCenter, + end: Alignment.bottomCenter, + colors: [Color(0xff7F1AF1), Color(0xff482384)])), + ), + title: const Text( + "Test Details", + style: TextStyle( + color: Color(0xffFFFEFE), + fontFamily: 'Brandon-bld', + ), + ), + actions: [ + TextButton( + onPressed: () async { + final result = await Navigator.push( + context, + MaterialPageRoute( + builder: (context) => const Login(fromWhere: "Home")), + ); + }, + child: SvgPicture.asset( + "assets/Images/logout.svg", + height: (MediaQuery.of(context).size.height) * (32 / 926), + ), + ), + ], + ), + body: SingleChildScrollView( + child: Padding( + padding: const EdgeInsets.symmetric(vertical: 100), + child: Column( + children: [ + Center( + child: Container( + // height: (MediaQuery.of(context).size.height) * (488 / 926), + width: (MediaQuery.of(context).size.width) * (385 / 428), + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(2), + color: Colors.white, + boxShadow: [ + BoxShadow(color: Colors.grey, offset: Offset(0, 4), blurRadius: 6) + ], + ), + child: Column( + children: [ + + Container( + height: (MediaQuery.of(context).size.height) * (59 / 926), + width: (MediaQuery.of(context).size.width) * (385 / 428), + color: Color(0xff6D5A8D), + child: Center( + child: Text( + 'Test Details', + style: TextStyle( + color: Colors.white, + fontFamily: 'Brandon-bld', + fontSize: (MediaQuery.of(context).size.height) * (20 / 926), + ), + ), + ), + ), + Container( + // height: (MediaQuery.of(context).size.height) * (310 / 926), + width: (MediaQuery.of(context).size.width) * (385 / 428), + padding: EdgeInsets.all(25), + child: Table( + columnWidths: {0:FixedColumnWidth((MediaQuery.of(context).size.width) * (25 / 428)), + 1:FixedColumnWidth((MediaQuery.of(context).size.width) * (200 / 428))}, + border: TableBorder.all(color: Colors.transparent), + children: [ + TableRow(children: [ + Padding( + padding: const EdgeInsets.only(top:8.0), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + 'Quiz ID:', + style: TextStyle( + color: Color(0xff3F2668), + fontFamily: 'Brandon-bld', + fontSize: (MediaQuery.of(context).size.height) * + (16 / 926), + ), + ), + ], + ), + ), + Padding( + padding: const EdgeInsets.only(top:8.0), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text(widget.quizId.toString(), + textAlign: TextAlign.start, + style: TextStyle( + color: Colors.black, + fontFamily: 'Brandon-med', + fontSize: (MediaQuery.of(context).size.height) * + (16 / 926), + )) + ], + ), + ) + ]), + TableRow(children: [ + Padding( + padding: const EdgeInsets.only(top:8.0), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + 'System:', + style: TextStyle( + color: Color(0xff3F2668), + fontFamily: 'Brandon-bld', + fontSize: (MediaQuery.of(context).size.height) * + (16 / 926), + ), + ), + ], + ), + ), + Padding( + padding: const EdgeInsets.only(top:8.0), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text(widget.system.toString().substring(1, widget.system.toString().length-1) == "" ? "-" : widget.system.toString().substring(1, widget.system.toString().length-1), + style: TextStyle( + color: Colors.black, + fontFamily: 'Brandon-med', + fontSize: (MediaQuery.of(context).size.height) * + (16 / 926), + )) + ], + ), + ) + ]), + TableRow(children: [ + Padding( + padding: const EdgeInsets.only(top:8.0), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + 'Subject:', + style: TextStyle( + color: Color(0xff3F2668), + fontFamily: 'Brandon-bld', + fontSize: (MediaQuery.of(context).size.height) * + (16 / 926), + ), + ), + ], + ), + ), + Padding( + padding: const EdgeInsets.only(top:8.0), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text(widget.subject.toString().substring(1, widget.subject.toString().length-1) == "" ? "-" : widget.subject.toString().substring(1, widget.subject.toString().length-1), + style: TextStyle( + color: Colors.black, + fontFamily: 'Brandon-med', + fontSize: (MediaQuery.of(context).size.height) * + (16 / 926), + )) + ], + ), + ) + ]), + TableRow(children: [ + Padding( + padding: const EdgeInsets.only(top:8.0), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + 'Topic:', + style: TextStyle( + color: Color(0xff3F2668), + fontFamily: 'Brandon-bld', + fontSize: (MediaQuery.of(context).size.height) * + (16 / 926), + ), + ), + ], + ), + ), + Padding( + padding: const EdgeInsets.only(top:8.0), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text(widget.topic.toString().substring(1, widget.topic.toString().length-1) == "" ? "-" : widget.topic.toString().substring(1, widget.topic.toString().length-1), + style: TextStyle( + color: Colors.black, + fontFamily: 'Brandon-med', + fontSize: (MediaQuery.of(context).size.height) * + (16 / 926), + )) + ], + ), + ) + ]), + TableRow(children: [ + Padding( + padding: const EdgeInsets.only(top:8.0), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + 'Score:', + style: TextStyle( + color: Color(0xff3F2668), + fontFamily: 'Brandon-bld', + fontSize: (MediaQuery.of(context).size.height) * + (16 / 926), + ), + ), + ], + ), + ), + Padding( + padding: const EdgeInsets.only(top:8.0), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text(widget.score, + style: TextStyle( + color: Colors.black, + fontFamily: 'Brandon-med', + fontSize: (MediaQuery.of(context).size.height) * + (16 / 926), + )) + ], + ), + ) + ]), + TableRow(children: [ + Padding( + padding: const EdgeInsets.only(top:8.0), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + 'Status:', + style: TextStyle( + color: Color(0xff3F2668), + fontFamily: 'Brandon-bld', + fontSize: (MediaQuery.of(context).size.height) * + (16 / 926), + ), + ), + ], + ), + ), + Padding( + padding: const EdgeInsets.only(top:8.0), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text(widget.status, + style: TextStyle( + color: Colors.black, + fontFamily: 'Brandon-med', + fontSize: (MediaQuery.of(context).size.height) * + (16 / 926), + )) + ], + ), + ) + ]) + ], + ), + ), + + Container( + height: (MediaQuery.of(context).size.height) * (70 / 926), + width: (MediaQuery.of(context).size.width) * (385 / 428), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + children: [ + Column( + children: [ + Container(height:40,width:40,decoration: BoxDecoration(color: Color(0xff7F1AF1),borderRadius: BorderRadius.circular(20)), + child: Icon(Icons.show_chart_outlined,size: 20,color:Colors.white)) + ,Text('Test Analysis',style: TextStyle( + color: Color(0xff7F1AF1), + fontFamily: 'Brandon-med', + fontSize: (MediaQuery.of(context).size.height) * (15 / 926), + ),) + ], + ), + Column( + children: [ + Container(height:40,width:40,decoration: BoxDecoration(color: Color(0xff7F1AF1),borderRadius: BorderRadius.circular(20)), + child: Icon(Icons.event_note_outlined,size: 20,color:Colors.white)) + ,Text('Test Results',style: TextStyle( + color: Color(0xff7F1AF1), + fontFamily: 'Brandon-med', + fontSize: (MediaQuery.of(context).size.height) * (15 / 926), + ),) + ], + ), + GestureDetector( + onTap: () async { + // print(_resumeQuizSuccessful.data.previousQuizzes[0].quizMeta.quizMode); + // print(_resumeQuizSuccessful.data.previousQuizzes[0].quizMeta.quizTotalQuestions); + // print(_resumeQuizSuccessful.data.previousQuizzes[0].quizMeta.quizQuestions); + // print(_resumeQuizSuccessful.data.previousQuizzes[0].quizMeta.isTimed); + SharedPreferences prefs = await SharedPreferences.getInstance(); + prefs.setInt("quizId", widget.quizId); + List _quizQuestions = []; + for(int i = 0; i<_resumeQuizSuccessful.data.questions.length; i++) { + _quizQuestions.add(_resumeQuizSuccessful.data.questions[i].id); + } + + // Navigator.of(context) + // .popUntil(ModalRoute.withName("/home")); + final result = Navigator.push( + context, + MaterialPageRoute(builder: (context) => QuizModule(totalQuestions: _resumeQuizSuccessful.data.previousQuizzes[0].quizMeta.quizTotalQuestions, + questions: _quizQuestions, + timedMode: _resumeQuizSuccessful.data.previousQuizzes[0].quizMeta.isTimed, + mode: _resumeQuizSuccessful.data.previousQuizzes[0].quizMeta.quizMode.toString(), + whatsDone: "resumed",)), + ); + }, + child: Column( + children: [ + Container(height:40,width:40,decoration: BoxDecoration(color: Color(0xff7F1AF1),borderRadius: BorderRadius.circular(20)), + child: Icon(Icons.arrow_right,size: 40,color:Colors.white)) + ,Text('Resume',style: TextStyle( + color: Color(0xff7F1AF1), + fontFamily: 'Brandon-med', + fontSize: (MediaQuery.of(context).size.height) * (15 / 926), + ),) + ], + ), + ), + ], + ), + ) + + ], + ), + ), + ), + Padding( + padding: const EdgeInsets.all(20.0), + child: InkWell( + onTap:() async { + // Navigator.of(context).pop(); + Navigator.of(context) + .popUntil(ModalRoute.withName("/home")); + final result = await Navigator.push( + context, + MaterialPageRoute(builder: (context) => PreviousQuiz()), + ); + }, + child:Container( + child: Row( + children: [Icon(Icons.arrow_back,color: Color(0xff7F1AF1),size: 15,),Text('Back',style: TextStyle( + color: Color(0xff7F1AF1), + fontFamily: 'Brandon-bld', + fontSize: (MediaQuery.of(context).size.height) * + (13 / 926), + ),)], + + ), + )), + ) + ], + ), + ), + ), + ); + + } +} diff --git a/lib/screens/Welcome/PreviousQuiz/tile.dart b/lib/screens/Welcome/PreviousQuiz/tile.dart index 5f59667..3b4e78f 100644 --- a/lib/screens/Welcome/PreviousQuiz/tile.dart +++ b/lib/screens/Welcome/PreviousQuiz/tile.dart @@ -1,137 +1,137 @@ -import 'package:flutter/material.dart'; -import 'package:testify/screens/Welcome/PreviousQuiz/test_details.dart'; - -class Tile extends StatelessWidget { - final String name; - final int quizId; - final String status; - final String score; - final String date; - final List questions; - final String totalQuestions; - final List subjects; - final List systems; - final List topics; - Tile({required this.name, required this.quizId, required this.status, required this.score, required this.totalQuestions, required this.questions, required this.date, required this.subjects, required this.systems, required this.topics}); - @override - Widget build(BuildContext context) { - return Container( - height: (MediaQuery.of(context).size.height) * (84 / 926), - width: (MediaQuery.of(context).size.width) * (385 / 428), - decoration: BoxDecoration( - borderRadius: BorderRadius.circular(2), - color: Colors.white, - boxShadow: [ - BoxShadow(color: Colors.grey, offset: Offset(0, 4), blurRadius: 6) - ], - ), - child: Row( - children: [ - Container( - height: (MediaQuery.of(context).size.height) * (84 / 926), - width: (MediaQuery.of(context).size.width) * (87 / 428), - color: Color(0xff6D5A8D), - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Text( - 'Quiz ID', - style: TextStyle( - color: Colors.white, - fontFamily: 'Brandon-bld', - fontSize: - (MediaQuery.of(context).size.height) * (18 / 926), - ), - ), - Text(quizId.toString(), - style: TextStyle( - color: Colors.white, - fontFamily: 'Brandon-med', - fontSize: - (MediaQuery.of(context).size.height) * (17 / 926), - )) - ], - )), - Container( - height: (MediaQuery.of(context).size.height) * (84 / 926), - width: (MediaQuery.of(context).size.width) * (248 / 428), - color: Colors.white, - padding: EdgeInsets.all( - (MediaQuery.of(context).size.height) * (16 / 926)), - child: Column( - children: [ - Row( - children: [ - Icon( - Icons.sticky_note_2_rounded, - color: Colors.grey, - ), - SizedBox( - width: (MediaQuery.of(context).size.width) * (12 / 428), - ), - Text( - name, - style: TextStyle( - color: Colors.black, - fontFamily: 'Brandon-med', - fontSize: - (MediaQuery.of(context).size.height) * (18 / 926), - ), - ) - ], - ), - Divider( - height: 1.5, - ), - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Text( - score + ' / 100', - style: TextStyle( - color: Color(0xff6C63FF), - fontFamily: 'Brandon-med', - fontSize: - (MediaQuery.of(context).size.height) * (14 / 926), - ), - ), - Text( - status, - style: TextStyle( - color: Color(0xff6C63FF), - fontFamily: 'Brandon-med', - fontSize: - (MediaQuery.of(context).size.height) * (14 / 926), - ), - ), - ], - ) - ], - ), - ), - Container( - height: (MediaQuery.of(context).size.height) * (84 / 926), - width: (MediaQuery.of(context).size.width) * (50 / 428), - color: Colors.white, - child: IconButton( - icon: Icon(Icons.arrow_right, - color: Color(0xff6D5A8D), - size: (MediaQuery.of(context).size.height) * (60 / 926)), - onPressed: () async { - Navigator.of(context).pop(); - final result = await Navigator.push( - context, - MaterialPageRoute( - builder: (context) => TestDetails( - quizId: quizId, - system: systems, - subject: subjects, - topic: topics, - score: score, - status: status))); - })), - ], - ), - ); - } -} +import 'package:flutter/material.dart'; +import 'package:testify/screens/Welcome/PreviousQuiz/test_details.dart'; + +class Tile extends StatelessWidget { + final String name; + final int quizId; + final String status; + final String score; + final String date; + final List questions; + final String totalQuestions; + final List subjects; + final List systems; + final List topics; + Tile({required this.name, required this.quizId, required this.status, required this.score, required this.totalQuestions, required this.questions, required this.date, required this.subjects, required this.systems, required this.topics}); + @override + Widget build(BuildContext context) { + return Container( + height: (MediaQuery.of(context).size.height) * (84 / 926), + width: (MediaQuery.of(context).size.width) * (385 / 428), + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(2), + color: Colors.white, + boxShadow: [ + BoxShadow(color: Colors.grey, offset: Offset(0, 4), blurRadius: 6) + ], + ), + child: Row( + children: [ + Container( + height: (MediaQuery.of(context).size.height) * (84 / 926), + width: (MediaQuery.of(context).size.width) * (87 / 428), + color: Color(0xff6D5A8D), + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Text( + 'Quiz ID', + style: TextStyle( + color: Colors.white, + fontFamily: 'Brandon-bld', + fontSize: + (MediaQuery.of(context).size.height) * (18 / 926), + ), + ), + Text(quizId.toString(), + style: TextStyle( + color: Colors.white, + fontFamily: 'Brandon-med', + fontSize: + (MediaQuery.of(context).size.height) * (17 / 926), + )) + ], + )), + Container( + height: (MediaQuery.of(context).size.height) * (84 / 926), + width: (MediaQuery.of(context).size.width) * (248 / 428), + color: Colors.white, + padding: EdgeInsets.all( + (MediaQuery.of(context).size.height) * (16 / 926)), + child: Column( + children: [ + Row( + children: [ + Icon( + Icons.sticky_note_2_rounded, + color: Colors.grey, + ), + SizedBox( + width: (MediaQuery.of(context).size.width) * (12 / 428), + ), + Text( + (name.length >= 22) ? name.substring(0, 22) : name, + style: TextStyle( + color: Colors.black, + fontFamily: 'Brandon-med', + fontSize: + (MediaQuery.of(context).size.height) * (18 / 926), + ), + ) + ], + ), + Divider( + height: 1.5, + ), + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + score + ' / ' + totalQuestions, + style: TextStyle( + color: Color(0xff6C63FF), + fontFamily: 'Brandon-med', + fontSize: + (MediaQuery.of(context).size.height) * (14 / 926), + ), + ), + Text( + status, + style: TextStyle( + color: Color(0xff6C63FF), + fontFamily: 'Brandon-med', + fontSize: + (MediaQuery.of(context).size.height) * (14 / 926), + ), + ), + ], + ) + ], + ), + ), + Container( + height: (MediaQuery.of(context).size.height) * (84 / 926), + width: (MediaQuery.of(context).size.width) * (50 / 428), + color: Colors.white, + child: IconButton( + icon: Icon(Icons.arrow_right, + color: Color(0xff6D5A8D), + size: (MediaQuery.of(context).size.height) * (60 / 926)), + onPressed: () async { + Navigator.of(context).pop(); + final result = await Navigator.push( + context, + MaterialPageRoute( + builder: (context) => TestDetails( + quizId: quizId, + system: systems, + subject: subjects, + topic: topics, + score: score, + status: status))); + })), + ], + ), + ); + } +} diff --git a/lib/screens/Welcome/QuizModule/buttons.dart b/lib/screens/Welcome/QuizModule/buttons.dart index c702dde..55e4e7c 100644 --- a/lib/screens/Welcome/QuizModule/buttons.dart +++ b/lib/screens/Welcome/QuizModule/buttons.dart @@ -1,55 +1,55 @@ -import 'package:flutter/material.dart'; - -// creating Stateless Widget for buttons -class MyButton extends StatelessWidget { - -// declaring variables - final color; - final textColor; - final String buttonText; - final buttontapped; - -//Constructor - MyButton({this.color, this.textColor, required this.buttonText, this.buttontapped}); - - @override - Widget build(BuildContext context) { - return Scaffold( - body: GestureDetector( - onTap: buttontapped, - child: Center( - child: Container( - height: 35, - width: 35, - decoration: BoxDecoration( - color: Colors.white, - boxShadow: [ - BoxShadow( - offset: Offset(0, 4), - blurRadius: 6, - color: Colors.black45//Color(0xFFF9F8F9), // background color - ), - ], - borderRadius: BorderRadius.circular(5), - ), - - child: Center( - child: Text( - buttonText, - style: TextStyle( - color: Colors.black, - fontFamily: 'Brandon-bld', - fontSize: (MediaQuery.of(context).size.height*(20/926)), - fontWeight: FontWeight.bold, - ), - ), - ), - ), - ), - ), - - - ); - } -} - +import 'package:flutter/material.dart'; + +// creating Stateless Widget for buttons +class MyButton extends StatelessWidget { + +// declaring variables + final color; + final textColor; + final String buttonText; + final buttontapped; + +//Constructor + MyButton({this.color, this.textColor, required this.buttonText, this.buttontapped}); + + @override + Widget build(BuildContext context) { + return Scaffold( + body: GestureDetector( + onTap: buttontapped, + child: Center( + child: Container( + height: 35, + width: 35, + decoration: BoxDecoration( + color: Colors.white, + boxShadow: [ + BoxShadow( + offset: Offset(0, 4), + blurRadius: 6, + color: Colors.black45//Color(0xFFF9F8F9), // background color + ), + ], + borderRadius: BorderRadius.circular(5), + ), + + child: Center( + child: Text( + buttonText, + style: TextStyle( + color: Colors.black, + fontFamily: 'Brandon-bld', + fontSize: (MediaQuery.of(context).size.height*(20/926)), + fontWeight: FontWeight.bold, + ), + ), + ), + ), + ), + ), + + + ); + } +} + diff --git a/lib/screens/Welcome/QuizModule/calculator.dart b/lib/screens/Welcome/QuizModule/calculator.dart index b46b9d0..d7529cb 100644 --- a/lib/screens/Welcome/QuizModule/calculator.dart +++ b/lib/screens/Welcome/QuizModule/calculator.dart @@ -1,179 +1,179 @@ -import 'package:flutter/material.dart'; -import 'buttons.dart'; -import 'package:math_expressions/math_expressions.dart'; -class Calculator extends StatefulWidget { - @override - _CalculatorState createState() => _CalculatorState(); -} - -class _CalculatorState extends State { - var userInput = ''; - var answer = ''; - final List buttons = [ - '7', - '8', - '9', - '%', - 'C', - '4', - '5', - '6', - 'x', - 'DEL', - '1', - '2', - '3', - '+', - '/', - '.', - '0', - '=', - '-', - - ]; - bool isOperator(String x) { - if (x == '/' || x == 'x' || x == '-' || x == '+' || x == '=') { - return true; - } - return false; - } -// function to calculate the input operation - void equalPressed() { - String finaluserinput = userInput; - finaluserinput = userInput.replaceAll('x', '*'); - - Parser p = Parser(); - Expression exp = p.parse(finaluserinput); - ContextModel cm = ContextModel(); - double eval = exp.evaluate(EvaluationType.REAL, cm); - answer = eval.toString(); - } - @override - Widget build(BuildContext context) { - return AlertDialog( - content: SizedBox( - height: (MediaQuery.of(context).size.height)*(310/926), - width: (MediaQuery.of(context).size.width)*(237/428), - child: Container( - padding: EdgeInsets.all(0), - decoration: BoxDecoration( - borderRadius: BorderRadius.circular(5), - color: Colors.white - ), - child: Column( - children: [ - - Container( - width: (MediaQuery.of(context).size.width)*(237/428), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Container( - alignment: Alignment.centerLeft, - child: Text( - userInput, - style: TextStyle( - color: Color(0xff7F1AF1), - fontFamily: 'Brandon-bld', - fontSize: (MediaQuery.of(context).size.height) * (20 / 926), - ), - ),), - Spacer(), - Container( - alignment: Alignment.centerRight, - child: Text( - answer, - style: TextStyle( - color: Color(0xff7F1AF1), - fontFamily: 'Brandon-bld', - fontSize: (MediaQuery.of(context).size.height) * (29 / 926), - ), - ), - ), - - ]), - ), - Divider(), - Container( - height: (MediaQuery.of(context).size.height)*(237/926), - width: (MediaQuery.of(context).size.width)*(310/428), - padding: EdgeInsets.all(8), - child: GridView.builder(itemCount: buttons.length,gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 5, crossAxisSpacing: 2.0, - mainAxisSpacing: 2.0,mainAxisExtent: 40), itemBuilder: (BuildContext context, int index) { - // Clear Button - if (index == 4) { - return MyButton( - buttontapped: () { - setState(() { - userInput = ''; - answer = '0'; - }); - }, - buttonText: buttons[index], - - ); - } - - // % Button - else if (index == 3) { - return MyButton( - buttontapped: () { - setState(() { - userInput += buttons[index]; - }); - }, - buttonText: buttons[index], - - ); - } - // Delete Button - else if (index == 9) { - return MyButton( - buttontapped: () { - setState(() { - userInput = - userInput.substring(0, userInput.length - 1); - }); - }, - buttonText: buttons[index], - - );} - // Equal_to Button - else if (index == 17) { - return MyButton( - buttontapped: () { - setState(() { - equalPressed(); - }); - }, - buttonText: buttons[index], - - ); - } - // other buttons - else { - return MyButton( - buttontapped: () { - setState(() { - userInput += buttons[index]; - }); - }, - buttonText: buttons[index], - - ); - } - }), - ) - - ], - ), - ), - ), - ); - } - - - } - - - +import 'package:flutter/material.dart'; +import 'buttons.dart'; +import 'package:math_expressions/math_expressions.dart'; +class Calculator extends StatefulWidget { + @override + _CalculatorState createState() => _CalculatorState(); +} + +class _CalculatorState extends State { + var userInput = ''; + var answer = ''; + final List buttons = [ + '7', + '8', + '9', + '%', + 'C', + '4', + '5', + '6', + 'x', + 'DEL', + '1', + '2', + '3', + '+', + '/', + '.', + '0', + '=', + '-', + + ]; + bool isOperator(String x) { + if (x == '/' || x == 'x' || x == '-' || x == '+' || x == '=') { + return true; + } + return false; + } +// function to calculate the input operation + void equalPressed() { + String finaluserinput = userInput; + finaluserinput = userInput.replaceAll('x', '*'); + + Parser p = Parser(); + Expression exp = p.parse(finaluserinput); + ContextModel cm = ContextModel(); + double eval = exp.evaluate(EvaluationType.REAL, cm); + answer = eval.toString(); + } + @override + Widget build(BuildContext context) { + return AlertDialog( + content: SizedBox( + height: (MediaQuery.of(context).size.height)*(310/926), + width: (MediaQuery.of(context).size.width)*(237/428), + child: Container( + padding: EdgeInsets.all(0), + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(5), + color: Colors.white + ), + child: Column( + children: [ + + Container( + width: (MediaQuery.of(context).size.width)*(237/428), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Container( + alignment: Alignment.centerLeft, + child: Text( + userInput, + style: TextStyle( + color: Color(0xff7F1AF1), + fontFamily: 'Brandon-bld', + fontSize: (MediaQuery.of(context).size.height) * (20 / 926), + ), + ),), + Spacer(), + Container( + alignment: Alignment.centerRight, + child: Text( + answer, + style: TextStyle( + color: Color(0xff7F1AF1), + fontFamily: 'Brandon-bld', + fontSize: (MediaQuery.of(context).size.height) * (29 / 926), + ), + ), + ), + + ]), + ), + Divider(), + Container( + height: (MediaQuery.of(context).size.height)*(237/926), + width: (MediaQuery.of(context).size.width)*(310/428), + padding: EdgeInsets.all(8), + child: GridView.builder(itemCount: buttons.length,gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 5, crossAxisSpacing: 2.0, + mainAxisSpacing: 2.0,mainAxisExtent: 40), itemBuilder: (BuildContext context, int index) { + // Clear Button + if (index == 4) { + return MyButton( + buttontapped: () { + setState(() { + userInput = ''; + answer = '0'; + }); + }, + buttonText: buttons[index], + + ); + } + + // % Button + else if (index == 3) { + return MyButton( + buttontapped: () { + setState(() { + userInput += buttons[index]; + }); + }, + buttonText: buttons[index], + + ); + } + // Delete Button + else if (index == 9) { + return MyButton( + buttontapped: () { + setState(() { + userInput = + userInput.substring(0, userInput.length - 1); + }); + }, + buttonText: buttons[index], + + );} + // Equal_to Button + else if (index == 17) { + return MyButton( + buttontapped: () { + setState(() { + equalPressed(); + }); + }, + buttonText: buttons[index], + + ); + } + // other buttons + else { + return MyButton( + buttontapped: () { + setState(() { + userInput += buttons[index]; + }); + }, + buttonText: buttons[index], + + ); + } + }), + ) + + ], + ), + ), + ), + ); + } + + + } + + + diff --git a/lib/screens/Welcome/QuizModule/question_explanation.dart b/lib/screens/Welcome/QuizModule/question_explanation.dart index f86203c..183609f 100644 --- a/lib/screens/Welcome/QuizModule/question_explanation.dart +++ b/lib/screens/Welcome/QuizModule/question_explanation.dart @@ -1,372 +1,372 @@ -import 'package:flutter/material.dart'; -import 'package:flutter_countdown_timer/flutter_countdown_timer.dart'; -import 'package:flutter_svg/svg.dart'; -import 'package:testify/screens/Welcome/side_menu_bar.dart'; - -class QuestionExplanation extends StatefulWidget { - const QuestionExplanation({Key? key, required this.questionId, required this.question, required this.correctAnswer, required this.explanation}) : super(key: key); - - final int questionId; - final String question; - final String correctAnswer; - final String explanation; - - @override - State createState() => _QuestionExplanationState(); -} - -class _QuestionExplanationState extends State { - int endTime = DateTime.now().millisecondsSinceEpoch + 1000 * 30; - - void onEnd() { - print('onEnd'); - } - - @override - Widget build(BuildContext context) { - // print(widget.questionId); - // print(widget.question); - // print(widget.correctAnswer); - // print(widget.explanation); - return Scaffold( - backgroundColor: Color(0xffF8F9FB), - drawer: SideMenuBar(), - // drawer: moreMenu(), - appBar: AppBar( - toolbarHeight: (MediaQuery.of(context).size.height) * (73.52 / 926), - backgroundColor: Color(0xff3F2668), - elevation: 2, - centerTitle: true, - title: Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Text( - 'Question ', - style: TextStyle( - color: Color(0xffffffff), - fontFamily: 'Brandon-bld', - fontSize: (MediaQuery.of(context).size.height) * (20 / 926), - ), - ), - ], - ), - flexibleSpace: Container( - decoration: const BoxDecoration( - gradient: LinearGradient( - begin: Alignment.topCenter, - end: Alignment.bottomCenter, - colors: [Color(0xff7F1AF1), Color(0xff482384)])), - ), - actions: [ - TextButton( - onPressed: () async { - }, - child: SvgPicture.asset( - "assets/Images/logout.svg", - height: (MediaQuery.of(context).size.height) *(32/926), - ), - ), - ], - ), - body: Column( - children: [ - Container( - height: ((MediaQuery.of(context).size.height) * ((926-73.52-50.88-(MediaQuery.of(context).padding.top)-8.1) / 926)), - child: ListView( - scrollDirection: Axis.vertical, - children: [ - Container( - padding: EdgeInsets.only( - top: (MediaQuery.of(context).size.height) * (15 / 926), - bottom: (MediaQuery.of(context).size.height) * (8 / 926), - left: (MediaQuery.of(context).size.width) * (18 / 428), - right: (MediaQuery.of(context).size.width) * (18 / 428)), - child: Column( - children: [ - Row( - children: [ - Container( - width: (MediaQuery.of(context).size.width) * (221 / 428), - //height: (MediaQuery.of(context).size.height) *(91/926), - child: Column( - children: [ - Align( - alignment: Alignment.topLeft, - child: Text( - "Attempt Your Quiz", - style: TextStyle( - color: Color(0xff232323), - fontFamily: 'Brandon-bld', - fontSize: (MediaQuery.of(context).size.height) * - (20 / 926), //38, - ), - ), - ), - SizedBox( - height: (MediaQuery.of(context).size.height) * - (2 / 926), - ), - Align( - alignment: Alignment.topLeft, - child: Text( - "Question ID: " + widget.questionId.toString(), // questionNumber - style: TextStyle( - color: Color(0xFF7F1AF1), - fontFamily: 'Brandon-med', - fontSize: (MediaQuery.of(context).size.height) * - (13 / 926), //38, - ), - ), - ) - ], - ), - ), - SizedBox( - width: (MediaQuery.of(context).size.width) * (39 / 428), - ), - // for timer - Container( - height: (MediaQuery.of(context).size.height) * (25 / 926), - width: (MediaQuery.of(context).size.width) * (107 / 428), - color: Color(0xFF3F2668), - child: Row( - children: [ - Text(' Time Left ', - style: TextStyle( - color: Color(0xFFFFFFFF), - fontFamily: 'Brandon-med', - fontSize: (MediaQuery.of(context).size.height) * - (7 / 926), - )), - CountdownTimer( - textStyle: TextStyle( - color: Color(0xFFFFFFFF), - fontFamily: 'Brandon-med', - fontSize: (MediaQuery.of(context).size.height) * - (13 / 926), - ), - endTime: endTime, - onEnd: onEnd, - endWidget: Text( - "00 : 00 : 00", - style: TextStyle( - color: Color(0xFFFFFFFF), - fontFamily: 'Brandon-med', - fontSize: (MediaQuery.of(context).size.height) * - (13 / 926), - ), - ), - ), - ], - ), - ) - ], - ), - SizedBox( - height: (MediaQuery.of(context).size.height) * (35.47 / 926), - ), - Text( - widget.question, - style: TextStyle( - color: Color(0xFF483A3A), - fontFamily: 'Brandon-med', - fontSize: - (MediaQuery.of(context).size.height) * (18 / 926), //38, - ), - ), - SizedBox( - height: (MediaQuery.of(context).size.height) * (25 / 926), - ), - Align( - alignment: Alignment.topLeft, - child: Text( - "Correct Answer: ", // questionNumber - style: TextStyle( - color: Color(0xFF7F1AF1), - fontFamily: 'Brandon-med', - fontSize: (MediaQuery.of(context).size.height) * - (13 / 926), //38, - ), - ), - ), - SizedBox( - height: (MediaQuery.of(context).size.height) * (10.75 / 926), - ), - Container( - // height: (MediaQuery.of(context).size.height) * (50 / 926), - // width: (MediaQuery.of(context).size.width) * (385 / 428), - padding: EdgeInsets.only( - top: (MediaQuery.of(context).size.height) * (8 / 928), - left: (MediaQuery.of(context).size.width) * (13 / 428), - bottom: (MediaQuery.of(context).size.height) * (8 / 928), - ), - decoration: BoxDecoration( - color: Color(0xFF3F2668), - border: Border.all( - color: Color(0xFF3F2668), - ), - borderRadius: BorderRadius.all(Radius.circular(0)) - ), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - Container( - width: (MediaQuery.of(context).size.width) * (300 / 428), - child: Text(widget.correctAnswer, - style: TextStyle( - color: Colors.white, - fontFamily: 'Brandon-med', - fontSize: (MediaQuery.of(context).size.height) * - (18 / 926), //38, - )), - ), - ], - )), - SizedBox( - height: (MediaQuery.of(context).size.height) * (20.2 / 926), - ), - Align( - alignment: Alignment.topLeft, - child: Text( - "Explanation: ", // questionNumber - style: TextStyle( - color: Color(0xFF7F1AF1), - fontFamily: 'Brandon-med', - fontSize: (MediaQuery.of(context).size.height) * - (13 / 926), //38, - ), - ), - ), - SizedBox( - height: (MediaQuery.of(context).size.height) * (10.75 / 926), - ), - Text( - widget.explanation, - style: TextStyle( - color: Color(0xFF483A3A), - fontFamily: 'Brandon-med', - fontSize: - (MediaQuery.of(context).size.height) * (18 / 926), //38, - ), - ), - SizedBox( - height: (MediaQuery.of(context).size.height) * (20.75 / 926), - ), - TextButton( - onPressed: () { - Navigator.of(context).pop(); - }, - style: TextButton.styleFrom( - padding: EdgeInsets.zero,), - child: Row( - children: [ - Container( - child: Icon(Icons.arrow_back, - color: Color(0xFF7F1AF1), - size: (MediaQuery.of(context).size.height) * - (15 / 926),), - ), - SizedBox(width: (MediaQuery.of(context).size.width) * - (3 / 428),), - Text( - "Back to Question", // questionNumber - style: TextStyle( - color: Color(0xFF7F1AF1), - fontFamily: 'Brandon-med', - fontSize: (MediaQuery.of(context).size.height) * - (13 / 926), //38, - ), - ), - ], - ), - ), - ], - )), - ], - ), - ) , - Align( - alignment: Alignment.bottomCenter, - child: Container( - height: ((MediaQuery.of(context).size.height) * (51 / 926)), - color: Colors.grey, - // decoration: const BoxDecoration( - // gradient: LinearGradient( - // begin: Alignment.topCenter, - // end: Alignment.bottomCenter, - // colors: [Color(0xff7F1AF1), Color(0xff482384)])), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - TextButton( - onPressed: null, - style: TextButton.styleFrom( - padding: EdgeInsets.zero,), - child: Row( - children: [ - SizedBox(width: (MediaQuery.of(context).size.width) * (16 / 428)), - Container( - child: Icon(Icons.arrow_back_ios_outlined, - color: Color(0xFFE4E4E4), - size: ((MediaQuery.of(context).size.width) * (23.1 / 428)),), - ), - ], - ), - ), - TextButton( - onPressed: null, - style: TextButton.styleFrom( - padding: EdgeInsets.zero,), - child: Row( - children: [ - Container( - width: ((MediaQuery.of(context).size.height) * (15 / 926)), - decoration: BoxDecoration( - color: Color(0xFFE4E4E4), - shape: BoxShape.circle - ), - ), - SizedBox(width: (MediaQuery.of(context).size.width) * (6 / 428)), - Container( - width: ((MediaQuery.of(context).size.height) * (15 / 926)), - decoration: BoxDecoration( - color: Color(0xFFE4E4E4), - shape: BoxShape.circle - ), - ), - SizedBox(width: (MediaQuery.of(context).size.width) * (6 / 428)), - Container( - width: ((MediaQuery.of(context).size.height) * (15 / 926)), - decoration: BoxDecoration( - color: Color(0xFFE4E4E4), - shape: BoxShape.circle - ), - ), - ], - ), - ), - TextButton( - onPressed: null, - style: TextButton.styleFrom( - padding: EdgeInsets.zero,), - child: Row( - children: [ - Container( - child: Icon(Icons.arrow_forward_ios_outlined, - color: Color(0xFFE4E4E4), - size: ((MediaQuery.of(context).size.width) * (23.1 / 428)),), - ), - SizedBox(width: (MediaQuery.of(context).size.width) * (16 / 428)), - ], - ), - ), - ], - ), - ), - ) - ], - ), - ); - } -} +import 'package:flutter/material.dart'; +import 'package:flutter_countdown_timer/flutter_countdown_timer.dart'; +import 'package:flutter_svg/svg.dart'; +import 'package:testify/screens/Welcome/side_menu_bar.dart'; + +class QuestionExplanation extends StatefulWidget { + const QuestionExplanation({Key? key, required this.questionId, required this.question, required this.correctAnswer, required this.explanation}) : super(key: key); + + final int questionId; + final String question; + final String correctAnswer; + final String explanation; + + @override + State createState() => _QuestionExplanationState(); +} + +class _QuestionExplanationState extends State { + int endTime = DateTime.now().millisecondsSinceEpoch + 1000 * 30; + + void onEnd() { + print('onEnd'); + } + + @override + Widget build(BuildContext context) { + // print(widget.questionId); + // print(widget.question); + // print(widget.correctAnswer); + // print(widget.explanation); + return Scaffold( + backgroundColor: Color(0xffF8F9FB), + drawer: SideMenuBar(), + // drawer: moreMenu(), + appBar: AppBar( + toolbarHeight: (MediaQuery.of(context).size.height) * (73.52 / 926), + backgroundColor: Color(0xff3F2668), + elevation: 2, + centerTitle: true, + title: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Text( + 'Question ', + style: TextStyle( + color: Color(0xffffffff), + fontFamily: 'Brandon-bld', + fontSize: (MediaQuery.of(context).size.height) * (20 / 926), + ), + ), + ], + ), + flexibleSpace: Container( + decoration: const BoxDecoration( + gradient: LinearGradient( + begin: Alignment.topCenter, + end: Alignment.bottomCenter, + colors: [Color(0xff7F1AF1), Color(0xff482384)])), + ), + actions: [ + TextButton( + onPressed: () async { + }, + child: SvgPicture.asset( + "assets/Images/logout.svg", + height: (MediaQuery.of(context).size.height) *(32/926), + ), + ), + ], + ), + body: Column( + children: [ + Container( + height: ((MediaQuery.of(context).size.height) * ((926-73.52-50.88-(MediaQuery.of(context).padding.top)-8.1) / 926)), + child: ListView( + scrollDirection: Axis.vertical, + children: [ + Container( + padding: EdgeInsets.only( + top: (MediaQuery.of(context).size.height) * (15 / 926), + bottom: (MediaQuery.of(context).size.height) * (8 / 926), + left: (MediaQuery.of(context).size.width) * (18 / 428), + right: (MediaQuery.of(context).size.width) * (18 / 428)), + child: Column( + children: [ + Row( + children: [ + Container( + width: (MediaQuery.of(context).size.width) * (221 / 428), + //height: (MediaQuery.of(context).size.height) *(91/926), + child: Column( + children: [ + Align( + alignment: Alignment.topLeft, + child: Text( + "Attempt Your Quiz", + style: TextStyle( + color: Color(0xff232323), + fontFamily: 'Brandon-bld', + fontSize: (MediaQuery.of(context).size.height) * + (20 / 926), //38, + ), + ), + ), + SizedBox( + height: (MediaQuery.of(context).size.height) * + (2 / 926), + ), + Align( + alignment: Alignment.topLeft, + child: Text( + "Question ID: " + widget.questionId.toString(), // questionNumber + style: TextStyle( + color: Color(0xFF7F1AF1), + fontFamily: 'Brandon-med', + fontSize: (MediaQuery.of(context).size.height) * + (13 / 926), //38, + ), + ), + ) + ], + ), + ), + SizedBox( + width: (MediaQuery.of(context).size.width) * (39 / 428), + ), + // for timer + Container( + height: (MediaQuery.of(context).size.height) * (25 / 926), + width: (MediaQuery.of(context).size.width) * (107 / 428), + color: Color(0xFF3F2668), + child: Row( + children: [ + Text(' Time Left ', + style: TextStyle( + color: Color(0xFFFFFFFF), + fontFamily: 'Brandon-med', + fontSize: (MediaQuery.of(context).size.height) * + (7 / 926), + )), + CountdownTimer( + textStyle: TextStyle( + color: Color(0xFFFFFFFF), + fontFamily: 'Brandon-med', + fontSize: (MediaQuery.of(context).size.height) * + (13 / 926), + ), + endTime: endTime, + onEnd: onEnd, + endWidget: Text( + "00 : 00 : 00", + style: TextStyle( + color: Color(0xFFFFFFFF), + fontFamily: 'Brandon-med', + fontSize: (MediaQuery.of(context).size.height) * + (13 / 926), + ), + ), + ), + ], + ), + ) + ], + ), + SizedBox( + height: (MediaQuery.of(context).size.height) * (35.47 / 926), + ), + Text( + widget.question, + style: TextStyle( + color: Color(0xFF483A3A), + fontFamily: 'Brandon-med', + fontSize: + (MediaQuery.of(context).size.height) * (18 / 926), //38, + ), + ), + SizedBox( + height: (MediaQuery.of(context).size.height) * (25 / 926), + ), + Align( + alignment: Alignment.topLeft, + child: Text( + "Correct Answer: ", // questionNumber + style: TextStyle( + color: Color(0xFF7F1AF1), + fontFamily: 'Brandon-med', + fontSize: (MediaQuery.of(context).size.height) * + (13 / 926), //38, + ), + ), + ), + SizedBox( + height: (MediaQuery.of(context).size.height) * (10.75 / 926), + ), + Container( + // height: (MediaQuery.of(context).size.height) * (50 / 926), + // width: (MediaQuery.of(context).size.width) * (385 / 428), + padding: EdgeInsets.only( + top: (MediaQuery.of(context).size.height) * (8 / 928), + left: (MediaQuery.of(context).size.width) * (13 / 428), + bottom: (MediaQuery.of(context).size.height) * (8 / 928), + ), + decoration: BoxDecoration( + color: Color(0xFF3F2668), + border: Border.all( + color: Color(0xFF3F2668), + ), + borderRadius: BorderRadius.all(Radius.circular(0)) + ), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Container( + width: (MediaQuery.of(context).size.width) * (300 / 428), + child: Text(widget.correctAnswer, + style: TextStyle( + color: Colors.white, + fontFamily: 'Brandon-med', + fontSize: (MediaQuery.of(context).size.height) * + (18 / 926), //38, + )), + ), + ], + )), + SizedBox( + height: (MediaQuery.of(context).size.height) * (20.2 / 926), + ), + Align( + alignment: Alignment.topLeft, + child: Text( + "Explanation: ", // questionNumber + style: TextStyle( + color: Color(0xFF7F1AF1), + fontFamily: 'Brandon-med', + fontSize: (MediaQuery.of(context).size.height) * + (13 / 926), //38, + ), + ), + ), + SizedBox( + height: (MediaQuery.of(context).size.height) * (10.75 / 926), + ), + Text( + widget.explanation, + style: TextStyle( + color: Color(0xFF483A3A), + fontFamily: 'Brandon-med', + fontSize: + (MediaQuery.of(context).size.height) * (18 / 926), //38, + ), + ), + SizedBox( + height: (MediaQuery.of(context).size.height) * (20.75 / 926), + ), + TextButton( + onPressed: () { + Navigator.of(context).pop(); + }, + style: TextButton.styleFrom( + padding: EdgeInsets.zero,), + child: Row( + children: [ + Container( + child: Icon(Icons.arrow_back, + color: Color(0xFF7F1AF1), + size: (MediaQuery.of(context).size.height) * + (15 / 926),), + ), + SizedBox(width: (MediaQuery.of(context).size.width) * + (3 / 428),), + Text( + "Back to Question", // questionNumber + style: TextStyle( + color: Color(0xFF7F1AF1), + fontFamily: 'Brandon-med', + fontSize: (MediaQuery.of(context).size.height) * + (13 / 926), //38, + ), + ), + ], + ), + ), + ], + )), + ], + ), + ) , + Align( + alignment: Alignment.bottomCenter, + child: Container( + height: ((MediaQuery.of(context).size.height) * (51 / 926)), + color: Colors.grey, + // decoration: const BoxDecoration( + // gradient: LinearGradient( + // begin: Alignment.topCenter, + // end: Alignment.bottomCenter, + // colors: [Color(0xff7F1AF1), Color(0xff482384)])), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + TextButton( + onPressed: null, + style: TextButton.styleFrom( + padding: EdgeInsets.zero,), + child: Row( + children: [ + SizedBox(width: (MediaQuery.of(context).size.width) * (16 / 428)), + Container( + child: Icon(Icons.arrow_back_ios_outlined, + color: Color(0xFFE4E4E4), + size: ((MediaQuery.of(context).size.width) * (23.1 / 428)),), + ), + ], + ), + ), + TextButton( + onPressed: null, + style: TextButton.styleFrom( + padding: EdgeInsets.zero,), + child: Row( + children: [ + Container( + width: ((MediaQuery.of(context).size.height) * (15 / 926)), + decoration: BoxDecoration( + color: Color(0xFFE4E4E4), + shape: BoxShape.circle + ), + ), + SizedBox(width: (MediaQuery.of(context).size.width) * (6 / 428)), + Container( + width: ((MediaQuery.of(context).size.height) * (15 / 926)), + decoration: BoxDecoration( + color: Color(0xFFE4E4E4), + shape: BoxShape.circle + ), + ), + SizedBox(width: (MediaQuery.of(context).size.width) * (6 / 428)), + Container( + width: ((MediaQuery.of(context).size.height) * (15 / 926)), + decoration: BoxDecoration( + color: Color(0xFFE4E4E4), + shape: BoxShape.circle + ), + ), + ], + ), + ), + TextButton( + onPressed: null, + style: TextButton.styleFrom( + padding: EdgeInsets.zero,), + child: Row( + children: [ + Container( + child: Icon(Icons.arrow_forward_ios_outlined, + color: Color(0xFFE4E4E4), + size: ((MediaQuery.of(context).size.width) * (23.1 / 428)),), + ), + SizedBox(width: (MediaQuery.of(context).size.width) * (16 / 428)), + ], + ), + ), + ], + ), + ), + ) + ], + ), + ); + } +} diff --git a/lib/screens/Welcome/QuizModule/quiz_final.dart b/lib/screens/Welcome/QuizModule/quiz_final.dart new file mode 100644 index 0000000..394e98e --- /dev/null +++ b/lib/screens/Welcome/QuizModule/quiz_final.dart @@ -0,0 +1,10 @@ +import 'package:flutter/material.dart'; + +class QuizFinal extends StatelessWidget { + const QuizFinal({Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + return Scaffold(backgroundColor: Colors.deepPurpleAccent,); + } +} diff --git a/lib/screens/Welcome/QuizModule/quiz_module.dart b/lib/screens/Welcome/QuizModule/quiz_module.dart index 6224bc3..cc82f57 100644 --- a/lib/screens/Welcome/QuizModule/quiz_module.dart +++ b/lib/screens/Welcome/QuizModule/quiz_module.dart @@ -1,1402 +1,1767 @@ -import 'dart:async'; -import 'dart:convert'; -import 'dart:math' as math; - -import 'package:flutter/material.dart'; -import 'package:flutter_countdown_timer/current_remaining_time.dart'; -import 'package:flutter_countdown_timer/flutter_countdown_timer.dart'; -import 'package:http/http.dart' as http; -import 'package:testify/models/GenerateQuizModels/QuizModuleModels/generate_quiz_model.dart'; -import 'package:testify/screens/Authentication/login.dart'; -import 'package:testify/screens/Welcome/QuizModule/question_explanation.dart'; -import 'package:testify/screens/Welcome/QuizModule/search_bar.dart'; -import 'package:testify/screens/Welcome/side_menu_bar.dart'; -import 'package:testify/screens/Welcome//QuizModule/calculator.dart'; -import 'package:flutter_svg/flutter_svg.dart'; -import 'package:shared_preferences/shared_preferences.dart'; -import 'package:flutter/cupertino.dart'; - -class QuizModule extends StatefulWidget { - const QuizModule({Key? key, required this.totalQuestions, required this.questions, required this.timedMode}) : super(key: key); - - final int totalQuestions; - final List questions; - final bool timedMode; - @override - _QuizModuleState createState() => _QuizModuleState(); -} - -class _QuizModuleState extends State { - int endTime = DateTime.now().millisecondsSinceEpoch + 1000 * 30; - List _questions = ['1', '2', '3', '4']; - String _currentQuestion = '1'; - int _currentSelected = 0; - String _labValues="Lorem ipsum dolor sit amet, consectetur adipiscing elit. Cras imperdiet finibus elit non luctus. Morbi auctor mattis ante. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Cras imperdiet finibus elit non luctus. Morbi auctor mattis ante."; - String _note="Lorem ipsum dolor sit amet, consectetur adipiscing elit. Cras imperdiet finibus elit non luctus. Morbi auctor mattis ante. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Cras imperdiet finibus elit non luctus. Morbi auctor mattis ante."; - late TextEditingController _textController; - double _fontSize = 18; // To change font size - bool _showTextZoom = false; // To show ths slider - - int timeElapsed = 0; - /// declare a timer - Timer? timer; - // Timer? saveQuiz; // Saves quiz every few seconds. - - //BottomNavBar - int _selectedIndex = 0; - - // This key is used to open the side drawer - final GlobalKey _scaffoldKey = new GlobalKey(); - - //Shared Pref - var _token; - var _userId; - - //Model Data - var _getGenerateQuizSuccessful; - var _quizId; - - //Changing quiz questions - // This changes the array index which in turn changes the rest. - int questionNumber = 0; - - //To change Icon and color - int whichOption = 0; - - // To void null safety error - bool hasDataLoaded = false; - bool ranSaveQuizAtTheStart = false; // To auto save the quiz at the start and avoid the quizzes from being suspended - // if(hasDataLoaded = true) { - // if(ranSaveQuizAtTheStart = false) { - // SaveQuizAPI(); - // setState(() { - // ranSaveQuizAtTheStart = true; - // }); - // } - // } - - //Storing the data required to display quiz questions and store their answers - var questionsData = { - "title": [], - "ID": [], - "question": [], - "correct_msg": [], // This is the explanation - "options": [], // A list would be added to this list - "statistics": [], // [1, 0, 0] - "answeredCorrectly": [], // Stores string and turns true if answered correctly. Can't be a bool since values are correct/incorrect/notAnswered - "optionSelectedInt": [], //To change Icon and color - // "isSelected": [] - }; - - @override - void initState() { - super.initState(); - _textController = TextEditingController(); - GenerateQuizAPI(); - timer = Timer.periodic( - const Duration(seconds: 1), - (timer) { - setState(() { - timeElapsed++; - }); - }, - ); - - // saveQuiz = Timer.periodic( - // const Duration(seconds: 10), - // (timer) { - // SaveQuizAPI(); - // }, - // ); - } - - Future submitAnswerAPI(int? indexOfOptionThatIsActuallyCorrect, int? correct, int? optionIndexSelected) async { - final String apiUrlGenerateQuiz = "https://demo.pookidevs.com/quiz/solver/submitAnswer"; - - // print("user id: "+ _userId.toString()); - // print("questionId: "+ questionsData["id"]![questionNumber].toString()); - // print("quizId: "+ _getGenerateQuizSuccessful.data.quizId.toString()); - // print("indexOfOptionThatIsActuallyCorrect: " + indexOfOptionThatIsActuallyCorrect.toString()); - // print("correct: " + correct.toString()); - // print("optionIndexSelected: " + optionIndexSelected.toString()); - - - - http.post(Uri.parse(apiUrlGenerateQuiz), headers: { - 'Content-type': 'application/json; charset=UTF-8', 'Authorization' : _token.toString(), - }, body: json.encode( - { - "data":{ - "userId": _userId.toString(), - "questionId": questionsData["id"]![questionNumber].toString(), - "quizId": _getGenerateQuizSuccessful.data.quizId.toString(), - "answerMeta":{ - "index": questionsData["id"]![questionNumber].toString(), - "Correctanswerindex": indexOfOptionThatIsActuallyCorrect.toString(), // indexOfOptionThatIsActuallyCorrect - "correct": correct.toString(), // Correct = 1 if answer is correct, -1 if answer is omitted and 0 if answer is incorrect - "optionIndexSelected": optionIndexSelected.toString() - } - } - }) - ).then((response) { - // print(jsonDecode(response.body).toString()); - if((response.statusCode == 200)) { - print(jsonDecode(response.body).toString()); - if(jsonDecode(response.body) == "{data: {status: true, message: Answer Submitted}}") { - - } else { - ScaffoldMessenger.of(context) - ..removeCurrentSnackBar() - ..showSnackBar(SnackBar(content: Text("Error! Answer not Saved!"))); - } - } - else { // Token Invalid - - } - } - ); - } - - - Future SaveQuizAPI() async { - SharedPreferences prefs = await SharedPreferences.getInstance(); - prefs.setInt("quizId", _getGenerateQuizSuccessful.data.quizId); - final String apiUrlGenerateQuiz = "https://demo.pookidevs.com/quiz/solver/saveQuiz"; - - var date = new DateTime.now().toString().split("."); - int quizScore = 0; - bool allQuestionsAreAnswered = true; - int totalQuizTime = timeElapsed; - for(int i = 0; i{ - 'Content-type': 'application/json; charset=UTF-8', 'Authorization' : _token.toString(), - }, body: json.encode( - { - "data": - { - "quiz" : { - "quizId": _getGenerateQuizSuccessful.data.quizId, - "quizTitle": "Custom Quiz" + date[0].toString(), // "Custom Quiz" + Date.now() - "quizDate": date[0].toString(), // "Custom Quiz" - "quizScore": quizScore.toString(), // total correct - "quizTotalQuestions": widget.totalQuestions, - "quizStatus": allQuestionsAreAnswered ? "completed" : "suspended", // "completed", "suspended" - "quizQuestions": widget.questions.toString(), // Question IDs - "quizMode":"tutor", // "tutor", "exam" - "quizTime": totalQuizTime.toString(), // total quiz time in seconds - "isTimed": widget.timedMode, // bool true or false - "omittedQuestions": [], // Don't send anything here - "SelectedOptionsArray": [] // Don't send anything here - }, - "userId": _userId - } - } - - ) - ).then((response) { - print(jsonDecode(response.body).toString()); - if((response.statusCode == 200) & (json.decode(response.body).toString().substring(0,14) != "{status: false")) { - - } - else { // Token Invalid - - } - } - ); - } - - Future GenerateQuizAPI() async { - SharedPreferences prefs = await SharedPreferences.getInstance(); - final String apiUrlGenerateQuiz = "https://demo.pookidevs.com/quiz/generator/generateQuiz"; - _token = prefs.getString('token')!; - _userId = prefs.getInt("userId")!; - http.post(Uri.parse(apiUrlGenerateQuiz), headers: { - 'Content-type': 'application/json; charset=UTF-8', 'Authorization' : _token.toString(), - }, body: json.encode( - { - "data": - { - "questionIds": widget.questions, - "count": widget.totalQuestions - } - }) - ).then((response) { - // print("This is: " + jsonDecode(response.body).toString()); - if((response.statusCode == 200) & (json.decode(response.body).toString().substring(0,14) != "{status: false")) { - final responseString = (response.body); - var generateQuizSuccessful = generateQuizSuccessfulFromJson(responseString); - final GenerateQuizSuccessful getGenerateQuizSuccessful = generateQuizSuccessful; - setState(() { - _getGenerateQuizSuccessful = getGenerateQuizSuccessful; - _quizId = _getGenerateQuizSuccessful.data.quizId; - print(_quizId); - }); - categoriesGenerateQuizData(); - } - else { // Token Invalid - - } - } - ); - } - - Future BookmarkQuestionAPI() async { - final String apiUrlGenerateQuiz = "https://demo.pookidevs.com/quiz/solver/markQuestion"; - http.post(Uri.parse(apiUrlGenerateQuiz), headers: { - 'Content-type': 'application/json; charset=UTF-8', 'Authorization' : _token.toString(), - }, body: json.encode( - { - "data": { - "userId": _userId, - "questionId": questionsData["id"]![questionNumber].toString(), - "tableName": "marked_questions", - "isMarked": true - } - }) - ).then((response) { - print(jsonDecode(response.body).toString()); - if((response.statusCode == 200) & (json.decode(response.body).toString().substring(0,14) != "{status: false")) { - - } - else { // Token Invalid - - } - } - ); - } - - Future addNotesAPI() async { - // print(_userId); - // print(questionsData["id"]![questionNumber].toString()); - // print(_quizId); - // print(_note); - final String apiUrlGenerateQuiz = "https://demo.pookidevs.com/quiz/notes/addNotes"; - http.post(Uri.parse(apiUrlGenerateQuiz), headers: { - 'Content-type': 'application/json; charset=UTF-8', 'Authorization' : _token.toString(), - }, body: json.encode( - { - "data": { - "userId": _userId, - "questionId": questionsData["id"]![questionNumber].toString(), - "quizId": _quizId, - "note": _note, - "tableName": "notes" - } - } - ) - ).then((response) { - // print(jsonDecode(response.body).toString()); - // print(json.decode(response.body).toString().substring(json.decode(response.body).toString().length-12,json.decode(response.body).toString().length)); - if((response.statusCode == 200) & (json.decode(response.body).toString().substring(json.decode(response.body).toString().length-12,json.decode(response.body).toString().length) == "Note Added}}")) { - ScaffoldMessenger.of(context) - ..removeCurrentSnackBar() - ..showSnackBar(SnackBar(content: Text("Note Added!"))); - } - else if((response.statusCode == 200) & (json.decode(response.body).toString().substring(0,14) == "{status: false")) { // Token Invalid - ScaffoldMessenger.of(context) - ..removeCurrentSnackBar() - ..showSnackBar(SnackBar(content: Text("Token Expired!"))); - final result = Navigator.push( - context, - MaterialPageRoute(builder: (context) => const Login(fromWhere:"Home")), - ); - } - else { - ScaffoldMessenger.of(context) - ..removeCurrentSnackBar() - ..showSnackBar(SnackBar(content: Text("Note not Added!"))); - } - } - ); - } - - void categoriesGenerateQuizData() async { - setState(() { - questionsData["id"] = []; - questionsData["question"] = []; - questionsData["options"] = []; - questionsData["statistics"] = []; - questionsData["correct_msg"] = []; - questionsData["answeredCorrectly"] = []; - questionsData["optionSelectedInt"] = []; - _questions = []; - }); - int c = 0; - if(_getGenerateQuizSuccessful != null) { - while ((c < _getGenerateQuizSuccessful.data.questions - .toList() - .length) & (_getGenerateQuizSuccessful.data.questions - .toList() - .length > 0)) { - // questionsData - setState(() { - questionsData["id"]!.add( - _getGenerateQuizSuccessful.data.questions[c].id); - questionsData["question"]!.add( - _getGenerateQuizSuccessful.data.questions[c].question); - questionsData["options"]!.add( - _getGenerateQuizSuccessful.data.questions[c].options); - questionsData["statistics"]!.add( - _getGenerateQuizSuccessful.data.questions[c].statistics); - questionsData["correct_msg"]!.add( - _getGenerateQuizSuccessful.data.questions[c] - .correctMsg); //answeredCorrectly - questionsData["answeredCorrectly"]!.add("notAnswered"); - questionsData["optionSelectedInt"]!.add(0); - _questions.add((c+1).toString()); - }); - c++; - } - setState(() { - hasDataLoaded = true; - }); - if(hasDataLoaded == true) { - if(ranSaveQuizAtTheStart == false) { - SaveQuizAPI(); - setState(() { - ranSaveQuizAtTheStart = true; - }); - } - } - } - // print(questionsData); - } - - // To change text size - text zoom - Widget _textZoom(BuildContext context) { - return GestureDetector( - onTap: () { - }, - child: Container( - height: ((MediaQuery.of(context).size.height) * (51 / 926)), - decoration: const BoxDecoration( - gradient: LinearGradient( - begin: Alignment.topCenter, - end: Alignment.bottomCenter, - colors: [Color(0xff7F1AF1), Color(0xff482384)])), - child: new Slider( - value: _fontSize, - activeColor: Colors.white, - inactiveColor: Colors.red, - onChanged: (double value) { - setState(() { - _fontSize = value; - print(_fontSize); - }); - }, - divisions: 4, - min: 14.0, - max: 22.0, - ), - ), - ); - } - - - void onEnd() { - print('onEnd'); - } - - Widget bookmarkQuestion(BuildContext context) { - return SizedBox( - child: AlertDialog( - contentPadding: EdgeInsets.all(MediaQuery.of(context).size.width*(15/428)), - content: Column( - mainAxisSize: MainAxisSize.min, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Text( - 'Bookmark', - style: TextStyle( - color: Color(0xffB0A6C2), - fontFamily: 'Brandon-bld', - fontSize: (MediaQuery.of(context).size.height) * (18 / 926), - ), - ), - IconButton(icon:Icon(Icons.cancel),iconSize:23,color: Color(0xFF3F2668),onPressed: () { - Navigator.of(context).pop(); - },), - ], - ), - Divider(), - Text("Are you sure you want to bookmark this question", - ), - ], - ), - actions: [ - Divider(), - Row( - mainAxisAlignment: MainAxisAlignment.end, - children: [ - TextButton( - onPressed: () { - Navigator.of(context).pop(); - }, - child: Text('No', - style: TextStyle( - color: Color(0xff3F2668), - fontFamily: 'Brandon-bld', - fontSize: - (MediaQuery.of(context).size.height) * (21 / 926), - )), - ), - Divider(), - TextButton( - onPressed: () { - Navigator.of(context).pop(); - print(questionsData["id"]![questionNumber].toString()); - BookmarkQuestionAPI(); - }, - child: Text('Yes', - style: TextStyle( - color: Color(0xff3F2668), - fontFamily: 'Brandon-bld', - fontSize: - (MediaQuery.of(context).size.height) * (21 / 926), - )), - ), - ], - ), - ], - ), - ); - } - - Widget labValues(BuildContext context) { - return SizedBox( - child: AlertDialog( - contentPadding: EdgeInsets.all(MediaQuery.of(context).size.width*(15/428)), - content: Column( - mainAxisSize: MainAxisSize.min, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Text( - 'Lab Values', - style: TextStyle( - color: Color(0xffB0A6C2), - fontFamily: 'Brandon-bld', - fontSize: (MediaQuery.of(context).size.height) * (18 / 926), - ), - ), - IconButton(icon:Icon(Icons.cancel),iconSize:23,color: Color(0xFF3F2668),onPressed: () { - Navigator.of(context).pop(); - },), - ], - ), - Divider(), - Text(_labValues), - ], - ), - ), - ); - } - Widget moreMenu() { - return Container( - width: (MediaQuery.of(context).size.width) * 0.3, - child: Drawer( - child: Container( - decoration: const BoxDecoration( - gradient: LinearGradient( - begin: Alignment.topRight, - end: Alignment.bottomLeft, - colors: [Color(0xff3F2668), Color(0xff482384)])), - child: ListView( - // Remove padding - padding: EdgeInsets.zero, - children: [ - Container( - padding: EdgeInsets.only( - top: MediaQuery.of(context).padding.top), - height: (MediaQuery.of(context).size.height), - color: Colors.transparent, - child: Column( - children: [ - ListTile( - leading: Icon( - Icons.close, - color: Colors.white, - ), - onTap: () => Navigator.pop(context), - ), - SizedBox( - height: - (MediaQuery.of(context).size.height) * (47 / 926), - ), - InkWell( - onTap: () { - Navigator.of(context).pop(); - // showDialog( - // context: context, - // builder: (BuildContext context) => - // labValues(context), - // ); - final result = Navigator.push( - context, - MaterialPageRoute(builder: (context) => SearchListExample()), - ); - }, - child: Container( - alignment: Alignment.center, - child: Column( - children: [ - SvgPicture.asset( - 'assets/Images/lab.svg', - height: (MediaQuery.of(context).size.height) * - (37 / 926), - color: Colors.white, - ), - SizedBox( - height: (MediaQuery.of(context).size.height) * - (10 / 926), - ), - Text( - 'Lab Values', - style: TextStyle( - color: Colors.white, - fontFamily: 'Brandon-bld', - fontSize: - (MediaQuery.of(context).size.height) * - (15 / 926), - ), - ) - ], - ), - ) - - //Divider(), - ), - SizedBox( - height: - (MediaQuery.of(context).size.height) * (47 / 926), - ), - InkWell( - onTap: () { - Navigator.of(context).pop(); - // bookmarkQuestion - showDialog( - context: context, - builder: (BuildContext context) => - bookmarkQuestion(context), - ); - }, - child: Container( - alignment: Alignment.center, - child: Column( - children: [ - Icon( - Icons.bookmark, - size: 37, - color: Colors.white, - ), - SizedBox( - height: (MediaQuery.of(context).size.height) * - (10 / 926), - ), - Text( - 'Bookmarks', - style: TextStyle( - color: Colors.white, - fontFamily: 'Brandon-bld', - fontSize: - (MediaQuery.of(context).size.height) * - (15 / 926), - ), - ) - ], - ), - ) - - //Divider(), - ), - SizedBox( - height: - (MediaQuery.of(context).size.height) * (47 / 926), - ), - InkWell( - onTap: () { - Navigator.of(context).pop(); - showDialog( - context: context, - builder: (BuildContext context) => - notes(context), - ); - }, - child: Container( - alignment: Alignment.center, - child: Column( - children: [ - Icon( - Icons.note_rounded, - size: 37, - color: Colors.white, - ), - SizedBox( - height: - (MediaQuery.of(context).size.height) * - (10 / 926), - ), - Text( - 'Notes', - style: TextStyle( - color: Colors.white, - fontFamily: 'Brandon-bld', - fontSize: - (MediaQuery.of(context).size.height) * - (15 / 926), - ), - ) - ], - ), - ) - - //Divider(), - ), - SizedBox( - height: - (MediaQuery.of(context).size.height) * (47 / 926), - ), - InkWell( - onTap:() {Navigator.of(context).pop(); - showDialog( - context: context, - builder: (BuildContext context) => - Calculator(), - );}, - child: Container( - alignment: Alignment.center, - child: Column( - children: [ - SvgPicture.asset('assets/Images/calculator.svg', - height: (MediaQuery.of(context).size.height) * - (37 / 926)), - SizedBox( - height: (MediaQuery.of(context).size.height) * - (10 / 926), - ), - Text( - 'Calculator', - style: TextStyle( - color: Colors.white, - fontFamily: 'Brandon-bld', - fontSize: - (MediaQuery.of(context).size.height) * - (15 / 926), - ), - ) - ], - ), - )), - SizedBox( - height: - (MediaQuery.of(context).size.height) * (47 / 926), - ), - InkWell( - onTap: () { - Navigator.of(context).pop(); - setState(() { - _showTextZoom = true; - }); - }, - child: Container( - alignment: Alignment.center, - child: Column( - children: [ - SvgPicture.asset('assets/Images/zoom.svg', - height: (MediaQuery.of(context).size.height) * - (37 / 926)), - SizedBox( - height: (MediaQuery.of(context).size.height) * - (10 / 926), - ), - Text( - 'Text Zoom', - style: TextStyle( - color: Colors.white, - fontFamily: 'Brandon-bld', - fontSize: - (MediaQuery.of(context).size.height) * - (15 / 926), - ), - ) - ], - ), - )) - ], - ), - ), - ]), - ))); - } - Widget notes(BuildContext context) { - return SizedBox( - child: AlertDialog( - contentPadding: EdgeInsets.all(MediaQuery.of(context).size.width*(15/428)), - content: Column( - mainAxisSize: MainAxisSize.min, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Text( - 'Take Notes', - style: TextStyle( - color: Color(0xffB0A6C2), - fontFamily: 'Brandon-bld', - fontSize: (MediaQuery.of(context).size.height) * (18 / 926), - ), - ), - IconButton(icon:Icon(Icons.cancel),iconSize:23,color: Color(0xFF3F2668),onPressed: () { - Navigator.of(context).pop(); - },), - ], - ), - Divider(), - TextField( - controller: _textController, - keyboardType: TextInputType.multiline, - minLines: 1,//Normal textInputField will be displayed - maxLines: 5,// when user presses enter it will adapt to it - decoration: InputDecoration( - hintText: "Add notes here...", - hintStyle: TextStyle(color: Color(0xffAEAEAE), - fontSize: (MediaQuery.of(context).size.height)*(15/926), - fontFamily: 'Brandon-med',), - contentPadding: EdgeInsets.fromLTRB(2.0, 1, 2.0, 1), - focusedBorder: OutlineInputBorder( - borderSide: BorderSide( - color: Colors.transparent, - width: 0.0, - ), - ), - ), - style: TextStyle( - color: Colors.black, - fontSize: (MediaQuery.of(context).size.height)*(15/926), - fontFamily: 'Brandon-med', - ), - onChanged: (String value) { - setState(() { - _note = value; - }); - }, - ), - Row( - mainAxisAlignment: MainAxisAlignment.end, - children: [ - IconButton(onPressed:(){ - setState((){ - _note=''; - _textController.clear(); - } - ); - } , iconSize: 21 ,icon: Icon(Icons.refresh,color: Color(0xFF3F2668))), - TextButton( - onPressed: () { - addNotesAPI(); - _textController.clear(); - Navigator.of(context).pop(); - }, - style: TextButton.styleFrom( - padding: EdgeInsets.zero,), - child: Container( - height: (MediaQuery.of(context).size.height) * (31 / 926), - width:(MediaQuery.of(context).size.width) * (97 / 428), - decoration: BoxDecoration(borderRadius:BorderRadius.circular(4),color: Color(0xFFDDDAE2),), - child:Row( - mainAxisAlignment: MainAxisAlignment.center, - children:[ - Icon(Icons.save,color: Color(0xFF3F2668),), - SizedBox( - height: (MediaQuery.of(context).size.width) * - (14 / 428), - ), - Text( - 'Save', - style: TextStyle( - color: Color(0xff3F2668), - fontFamily: 'Brandon-bld', - fontSize: (MediaQuery.of(context).size.height) * (19 / 926), - ), - ), - ]) - ),) - ], - ) - ], - ), - ),);} - Future _onQuit() async { - return (await showDialog( - context: context, - builder: (context) => AlertDialog( - content: Text( - 'Do you want to quit the quiz', - style: TextStyle( - color: Color(0xffA1A1A1), - fontFamily: 'Brandon-bld', - fontSize: (MediaQuery.of(context).size.height) * (21 / 926), - ), - ), - actions: [ - TextButton( - onPressed: () => Navigator.of(context).pop(false), - child: Text('No', - style: TextStyle( - color: Color(0xff3F2668), - fontFamily: 'Brandon-bld', - fontSize: - (MediaQuery.of(context).size.height) * (21 / 926), - )), - ), - TextButton( - onPressed: () { - SaveQuizAPI(); - ScaffoldMessenger.of(context) - ..removeCurrentSnackBar() - ..showSnackBar(SnackBar(content: Text("The Quiz has been saved!"))); - Navigator.of(context).pop(true); - Navigator.of(context).pop(); - }, - child: Text('Yes', - style: TextStyle( - color: Color(0xff3F2668), - fontFamily: 'Brandon-bld', - fontSize: - (MediaQuery.of(context).size.height) * (21 / 926), - )), - ), - ], - ), - )) ?? - false; - } - - @override - void dispose() { - _textController.dispose(); - timer?.cancel(); - // saveQuiz?.cancel(); - super.dispose(); - } - - @override - Widget build(BuildContext context) { - return WillPopScope( - onWillPop: () async { - ScaffoldMessenger.of(context) - ..removeCurrentSnackBar() - ..showSnackBar(SnackBar(content: Text("Click on Quit Quiz!"))); - return false; - }, - child: Scaffold( - resizeToAvoidBottomInset: false, - backgroundColor: Color(0xffF8F9FB), - drawer: SideMenuBar(), - // drawer: moreMenu(), - endDrawer: moreMenu(), - appBar: AppBar( - toolbarHeight: (MediaQuery.of(context).size.height) * (73.52 / 926), - backgroundColor: Color(0xff3F2668), - elevation: 2, - centerTitle: true, - title: Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Text( - 'Question ', - style: TextStyle( - color: Color(0xffffffff), - fontFamily: 'Brandon-bld', - fontSize: (MediaQuery.of(context).size.height) * (20 / 926), - ), - ), - DropdownButton( - value: (questionNumber + 1).toString(), - underline: Container(), - iconEnabledColor: Colors.white, - dropdownColor: Color(0xff3F2668), - onChanged: (newValue) { - setState(() { - print(newValue); - _currentQuestion = newValue as String; - questionNumber = int.parse(newValue) - 1; - }); - }, - items: _questions.map((question) { - return DropdownMenuItem( - child: new Text( - question + ' / ' + widget.totalQuestions.toString(), - style: TextStyle( - color: Colors.white, - fontFamily: 'Brandon-bld', - fontSize: - (MediaQuery.of(context).size.height) * (20 / 926), - ), - ), - value: question, - ); - }).toList(), - ), - ], - ), - flexibleSpace: Container( - decoration: const BoxDecoration( - gradient: LinearGradient( - begin: Alignment.topCenter, - end: Alignment.bottomCenter, - colors: [Color(0xff7F1AF1), Color(0xff482384)])), - ), - actions: [ - TextButton( - onPressed: () async { - SaveQuizAPI(); - }, - child: SvgPicture.asset( - "assets/Images/logout.svg", - height: (MediaQuery.of(context).size.height) *(32/926), - ), - ), - ], - ), - body: hasDataLoaded == false ? Center(child: CircularProgressIndicator()) : Column( - children: [ - GestureDetector( - onTap: () { - setState(() { - _showTextZoom = false; - }); - }, - child: Container( - height: ((MediaQuery.of(context).size.height) * ((926-73.52-50.88-(MediaQuery.of(context).padding.top)-8.1) / 926)), - child: ListView( - scrollDirection: Axis.vertical, - children: [ - Container( - padding: EdgeInsets.only( - top: (MediaQuery.of(context).size.height) * (15 / 926), - bottom: (MediaQuery.of(context).size.height) * (8 / 926), - left: (MediaQuery.of(context).size.width) * (18 / 428), - right: (MediaQuery.of(context).size.width) * (18 / 428)), - child: Column( - children: [ - Row( - children: [ - Container( - width: (MediaQuery.of(context).size.width) * (221 / 428), - //height: (MediaQuery.of(context).size.height) *(91/926), - child: Column( - children: [ - Align( - alignment: Alignment.topLeft, - child: Text( - "Attempt Your Quiz", - style: TextStyle( - color: Color(0xff232323), - fontFamily: 'Brandon-bld', - fontSize: (MediaQuery.of(context).size.height) * - (20 / 926), //38, - ), - ), - ), - SizedBox( - height: (MediaQuery.of(context).size.height) * - (2 / 926), - ), - Align( - alignment: Alignment.topLeft, - child: Text( - "Question ID: " + questionsData["id"]![questionNumber].toString(), // questionNumber - style: TextStyle( - color: Color(0xFF7F1AF1), - fontFamily: 'Brandon-med', - fontSize: (MediaQuery.of(context).size.height) * - (13 / 926), //38, - ), - ), - ) - ], - ), - ), - SizedBox( - width: (MediaQuery.of(context).size.width) * (39 / 428), - ), - // for timer - Container( - height: (MediaQuery.of(context).size.height) * (25 / 926), - width: (MediaQuery.of(context).size.width) * (87 / 428), - color: Color(0xFF3F2668), - child: Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Text('', - style: TextStyle( - color: Color(0xFFFFFFFF), - fontFamily: 'Brandon-med', - fontSize: (MediaQuery.of(context).size.height) * - (7 / 926), - )), - CountdownTimer( - textStyle: TextStyle( - color: Color(0xFFFFFFFF), - fontFamily: 'Brandon-med', - fontSize: (MediaQuery.of(context).size.height) * - (13 / 926), - ), - endTime: endTime, - onEnd: onEnd, - endWidget: Text( - "00 : 00 : 00", - style: TextStyle( - color: Color(0xFFFFFFFF), - fontFamily: 'Brandon-med', - fontSize: (MediaQuery.of(context).size.height) * - (13 / 926), - ), - ), - ), - ], - ), - ) - ], - ), - SizedBox( - height: (MediaQuery.of(context).size.height) * (25 / 926), - ), - Text( - questionsData["question"]![questionNumber].toString(), - style: TextStyle( - color: Color(0xFF483A3A), - fontFamily: 'Brandon-med', - fontSize: - (MediaQuery.of(context).size.height) * (_fontSize / 926), //38, - ), - ), - SizedBox( - height: (MediaQuery.of(context).size.height) * (25 / 926), - ), - if(questionsData["options"] != null) - for(int i = 0; i QuestionExplanation(question: questionsData["question"]![questionNumber].toString(), correctAnswer: correctAns.toString(), questionId: questionsData["id"]![questionNumber], explanation: questionsData["correct_msg"]![questionNumber].toString(),)), - ); - }, - child: Container( - alignment: Alignment.topRight, - child: Text( - "See Explanation", - style: TextStyle( - color: Color(0xFF7F1AF1), - fontFamily: 'Brandon-med', - fontSize: (MediaQuery.of(context).size.height) * - (13 / 926), //38, - ), - ), - ), - ) : Container(), - SizedBox( - height: (MediaQuery.of(context).size.height) * (20 / 926), - ), - ], - ), - SizedBox( - height: (MediaQuery.of(context).size.height) * (5 / 926), - ), - SizedBox( - height: (MediaQuery.of(context).size.height) * (96 / 926), - ), - Row( - mainAxisAlignment: MainAxisAlignment.end, - children: [ - Container( - alignment: Alignment.bottomRight, - child: InkWell( - child: Icon(Icons.power_settings_new, - color: Color(0xFF7F1AF1), - size: (MediaQuery.of(context).size.height) * - (23 / 926),), - ), - ), - SizedBox( - width: (MediaQuery.of(context).size.width) * (5 / 428), - ), - Container( - alignment: Alignment.bottomRight, - child: InkWell( - child: Text( - "Quit Quiz", - style: TextStyle( - color: Color(0xFF7F1AF1), - fontFamily: 'Brandon-bld', - fontSize: (MediaQuery.of(context).size.height) * - (13 / 926), //38, - ), - ), - onTap: () => _onQuit())), - ], - ), - SizedBox( - height: (MediaQuery.of(context).size.height) * (26 / 926), - ), - ], - )), - ], - ), - ), - ) , - Align( - alignment: Alignment.bottomCenter, - child: Container( - height: ((MediaQuery.of(context).size.height) * (51 / 926)), - decoration: const BoxDecoration( - gradient: LinearGradient( - begin: Alignment.topCenter, - end: Alignment.bottomCenter, - colors: [Color(0xff7F1AF1), Color(0xff482384)])), - child: _showTextZoom == true ? _textZoom(context) : Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - TextButton( - onPressed: () { - if(questionNumber > 0) { - setState(() { - questionNumber--; - }); - } - }, - style: TextButton.styleFrom( - padding: EdgeInsets.zero,), - child: Row( - children: [ - SizedBox(width: (MediaQuery.of(context).size.width) * (16 / 428)), - Container( - child: Icon(Icons.arrow_back_ios_outlined, - color: Colors.white, - size: ((MediaQuery.of(context).size.width) * (23.1 / 428)),), - ), - ], - ), - ), - Builder( - builder: (context) => TextButton( - onPressed: () { Scaffold.of(context).openEndDrawer(); }, - style: TextButton.styleFrom( - padding: EdgeInsets.zero,), - child: Row( - children: [ - Container( - width: ((MediaQuery.of(context).size.height) * (15 / 926)), - decoration: BoxDecoration( - color: Colors.white, - shape: BoxShape.circle - ), - ), - SizedBox(width: (MediaQuery.of(context).size.width) * (6 / 428)), - Container( - width: ((MediaQuery.of(context).size.height) * (15 / 926)), - decoration: BoxDecoration( - color: Colors.white, - shape: BoxShape.circle - ), - ), - SizedBox(width: (MediaQuery.of(context).size.width) * (6 / 428)), - Container( - width: ((MediaQuery.of(context).size.height) * (15 / 926)), - decoration: BoxDecoration( - color: Colors.white, - shape: BoxShape.circle - ), - ), - ], - ), - ), - ), - TextButton( - onPressed: () { - if(questionNumber < (widget.totalQuestions - 1)) { - setState(() { - questionNumber++; - }); - } - }, - style: TextButton.styleFrom( - padding: EdgeInsets.zero,), - child: Row( - children: [ - Container( - child: Icon(Icons.arrow_forward_ios_outlined, - color: Colors.white, - size: ((MediaQuery.of(context).size.width) * (23.1 / 428)),), - ), - SizedBox(width: (MediaQuery.of(context).size.width) * (16 / 428)), - ], - ), - ), - ], - ), - ), - ) - ], - ), - ), - ); - } -} +import 'dart:async'; +import 'dart:convert'; +import 'dart:math' as math; + +import 'package:flutter/material.dart'; +import 'package:flutter_countdown_timer/current_remaining_time.dart'; +import 'package:flutter_countdown_timer/flutter_countdown_timer.dart'; +import 'package:http/http.dart' as http; +import 'package:testify/models/GenerateQuizModels/QuizModuleModels/generate_quiz_model.dart'; +import 'package:testify/models/GetPreviousQuizzesModel/ResumeQuiz/resume_quiz_model.dart'; +import 'package:testify/screens/Authentication/login.dart'; +import 'package:testify/screens/Welcome/QuizModule/question_explanation.dart'; +import 'package:testify/screens/Welcome/QuizModule/quiz_final.dart'; +import 'package:testify/screens/Welcome/QuizModule/search_bar.dart'; +import 'package:testify/screens/Welcome/side_menu_bar.dart'; +import 'package:testify/screens/Welcome//QuizModule/calculator.dart'; +import 'package:flutter_svg/flutter_svg.dart'; +import 'package:shared_preferences/shared_preferences.dart'; +import 'package:flutter/cupertino.dart'; + +class QuizModule extends StatefulWidget { + const QuizModule({Key? key, required this.totalQuestions, required this.questions, required this.timedMode, required this.mode, required this.whatsDone}) : super(key: key); + + final int totalQuestions; + final List questions; + final bool timedMode; + final String mode; + final String whatsDone; // new(From Generate Quiz), resumed, reviewed + @override + _QuizModuleState createState() => _QuizModuleState(); +} + +class _QuizModuleState extends State with WidgetsBindingObserver{ + int endTime = DateTime.now().millisecondsSinceEpoch + 1000 * 30; + List _questions = ['1', '2', '3', '4']; + String _currentQuestion = '1'; + int _currentSelected = 0; + String _labValues="Lorem ipsum dolor sit amet, consectetur adipiscing elit. Cras imperdiet finibus elit non luctus. Morbi auctor mattis ante. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Cras imperdiet finibus elit non luctus. Morbi auctor mattis ante."; + String _note="Lorem ipsum dolor sit amet, consectetur adipiscing elit. Cras imperdiet finibus elit non luctus. Morbi auctor mattis ante. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Cras imperdiet finibus elit non luctus. Morbi auctor mattis ante."; + late TextEditingController _textController; + double _fontSize = 18; // To change font size + bool _showTextZoom = false; // To show ths slider + + int timeElapsed = 0; + /// declare a timer + Timer? timer; + // Timer? saveQuiz; // Saves quiz every few seconds. + + //BottomNavBar + int _selectedIndex = 0; + + // This key is used to open the side drawer + final GlobalKey _scaffoldKey = new GlobalKey(); + + //Shared Pref + var _token; + var _userId; + + //Model Data + var _getGenerateQuizSuccessful; + var _resumeQuizSuccessful; + var _quizId; + + //Changing quiz questions + // This changes the array index which in turn changes the rest. + int questionNumber = 0; + + //To change Icon and color + int whichOption = 0; + + // To void null safety error + bool hasDataLoaded = false; + bool ranSaveQuizAtTheStart = false; // To auto save the quiz at the start and avoid the quizzes from being suspended + // if(hasDataLoaded = true) { + // if(ranSaveQuizAtTheStart = false) { + // SaveQuizAPI(); + // setState(() { + // ranSaveQuizAtTheStart = true; + // }); + // } + // } + + //Storing the data required to display quiz questions and store their answers + var questionsData = { + "title": [], + "ID": [], + "question": [], + "correct_msg": [], // This is the explanation + "options": [], // A list would be added to this list + "statistics": [], // [1, 0, 0] + "answeredCorrectly": [], // Stores string and turns true if answered correctly. Can't be a bool since values are correct/incorrect/notAnswered + "optionSelectedInt": [], //To change Icon and color + "notes": [], + "submitData": [], + // "isSelected": [] + }; + + @override + void initState() { + super.initState(); + _textController = TextEditingController(); + WidgetsBinding.instance!.addObserver(this); + if(widget.whatsDone == "new") + GenerateQuizAPI(); + else if(widget.whatsDone == "resumed") + ResumeQuizAPI(); + + timer = Timer.periodic( + const Duration(seconds: 1), + (timer) { + setState(() { + timeElapsed++; + }); + }, + ); + + // saveQuiz = Timer.periodic( + // const Duration(seconds: 10), + // (timer) { + // SaveQuizAPI(); + // }, + // ); + } + + @override + void didChangeAppLifecycleState(AppLifecycleState state) async { + super.didChangeAppLifecycleState(state); + + final isBackground = state == AppLifecycleState.paused; + final isClosed = state == AppLifecycleState.detached; + if(isBackground) { // As soon as the user closes the app this runs. The application is still in the app switcher(ram) + print("xD in Background"); + SaveQuizAPI("suspended"); + // ScaffoldMessenger.of(context) + // ..removeCurrentSnackBar() + // ..showSnackBar(SnackBar(content: Text("The Quiz has been saved as Suspended!"))); + Navigator.of(context).pop(); + } + if(isClosed) { // When app is closed from the app switcher. Doesn't run for now for some odd reason. + print("xD Closed"); + } + } + + Future ResumeQuizAPI() async { + SharedPreferences prefs = await SharedPreferences.getInstance(); + final String apiUrlGenerateQuiz = "https://demo.pookidevs.com/quiz/solver/resumeQuiz"; + var quizID = prefs.getInt("quizId"); + _token = prefs.getString('token')!; + print(_token); + _userId = prefs.getInt("userId")!; + http.post(Uri.parse(apiUrlGenerateQuiz), headers: { + 'Content-type': 'application/json; charset=UTF-8', 'Authorization' : _token.toString(), + }, body: json.encode( + { + "quizId": quizID + }) + ).then((response) { + // print(jsonDecode(response.body).toString()); + if((response.statusCode == 200) & (json.decode(response.body).toString().substring(0,14) != "{status: false")) { + final responseString = (response.body); + var resumeQuizSuccessful1 = resumeQuizModelFromJson(responseString); + final ResumeQuizModel resumeQuizSuccessful = resumeQuizSuccessful1; + setState(() { + _resumeQuizSuccessful = resumeQuizSuccessful; + print(_resumeQuizSuccessful.data.previousQuizzes[0].quizMeta.quizMode); + print(_resumeQuizSuccessful.data.previousQuizzes[0].quizMeta.quizTotalQuestions); + print(_resumeQuizSuccessful.data.previousQuizzes[0].quizMeta.quizQuestions); + print(_resumeQuizSuccessful.data.previousQuizzes[0].quizMeta.quizStatus); + print(_resumeQuizSuccessful.data.previousQuizzes[0].quizMeta.isTimed); + // print(_resumeQuizSuccessful.data.previousQuizzes[0].quizMeta.quizId.runtimeType); + // print(_resumeQuizSuccessful.data.previousQuizzes[0].quizMeta.quizScore.runtimeType); + // _quizId = _getGenerateQuizSuccessful.data.quizId; + // print(_quizId); + }); + categoriesGenerateQuizData(); + // categoriesGenerateQuizData(); + } + else { // Token Invalid + + } + } + ); + } + + Future submitAnswerAPI(int? indexOfOptionThatIsActuallyCorrect, int? correct, int? optionIndexSelected) async { // doesn't work properly in exam mode + final String apiUrlGenerateQuiz = "https://demo.pookidevs.com/quiz/solver/submitAnswer"; + // print(_token); + SharedPreferences prefs = await SharedPreferences.getInstance(); + var _quizID = prefs.getInt("quizId"); + + print(widget.whatsDone); + print("user id: "+ _userId.toString()); + print("questionId: "+ questionsData["id"]![questionNumber].toString()); + print("quizId" + _quizID.toString()); + print("indexOfOptionThatIsActuallyCorrect: " + indexOfOptionThatIsActuallyCorrect.toString()); + print("correct: " + correct.toString()); + print("optionIndexSelected: " + optionIndexSelected.toString()); + + + + http.post(Uri.parse(apiUrlGenerateQuiz), headers: { + 'Content-type': 'application/json; charset=UTF-8', 'Authorization' : _token.toString(), + }, body: json.encode( + { + "data":{ + "userId": _userId.toString(), + "questionId": questionsData["id"]![questionNumber].toString(), + // "quizId": widget.whatsDone == "new" ? _getGenerateQuizSuccessful.data.quizId.toString() : _resumeQuizSuccessful.data.previousQuizzes[0].quizId.toString(), + "quizId": _quizID.toString(), + "answerMeta":{ + "index": questionsData["id"]![questionNumber].toString(), + "Correctanswerindex": indexOfOptionThatIsActuallyCorrect.toString(), // indexOfOptionThatIsActuallyCorrect + "correct": correct.toString(), // Correct = 1 if answer is correct, -1 if answer is omitted and 0 if answer is incorrect + "optionIndexSelected": optionIndexSelected.toString() + } + } + }) + ).then((response) { + if((response.statusCode == 200)) { + print(jsonDecode(response.body).toString()); + if((jsonDecode(response.body).toString()) == "{data: {status: true, message: Answer Submitted}}") { + + } else { + ScaffoldMessenger.of(context) + ..removeCurrentSnackBar() + ..showSnackBar(SnackBar(content: Text("Error! Answer not Saved!"))); + } + } + else { // Token Invalid + ScaffoldMessenger.of(context) + ..removeCurrentSnackBar() + ..showSnackBar(SnackBar(content: Text("Token Invalid!"))); + final result = Navigator.pushAndRemoveUntil( + context, + MaterialPageRoute(builder: (BuildContext context) => const Login(fromWhere:"Home")), + ModalRoute.withName('/'), + ); + } + } + ); + } + + + Future SaveQuizAPI(String saveAs, [bool? hasUserClicked]) async { + SharedPreferences prefs = await SharedPreferences.getInstance(); + widget.whatsDone == "new" ? prefs.setInt("quizId", _getGenerateQuizSuccessful.data.quizId) : null; + final String apiUrlGenerateQuiz = "https://demo.pookidevs.com/quiz/solver/saveQuiz"; + print(widget.totalQuestions); + var date = new DateTime.now().toString().split("."); + date = date[0].split(" "); + print(date); + int quizScore = 0; + var addToOmittedQuestionsArray = []; + var totalQuizTime = timeElapsed.toString(); + for(int i = 0; i{ + 'Content-type': 'application/json; charset=UTF-8', 'Authorization' : _token.toString(), + }, body: json.encode( + { + "data": + { + "quiz" : { + "quizId": widget.whatsDone == "new" ? _getGenerateQuizSuccessful.data.quizId.toString() : _resumeQuizSuccessful.data.previousQuizzes[0].quizId, + "quizTitle": "Custom Quiz" + date[0].toString(), // "Custom Quiz" + Date.now() + "quizDate": date[0].toString(), // "Custom Quiz" + "quizScore": quizScore.toString(), // total correct + "quizTotalQuestions": widget.totalQuestions.toString(), + "quizStatus": saveAs, // == "completed" ? "completed" : "suspended", // "completed", "suspended" + "quizQuestions": questionsData["id"].toString(), // Question IDs + "quizMode": widget.mode, // "tutor", "exam" + "quizTime": totalQuizTime.toString(), // total quiz time in seconds + "isTimed": widget.timedMode, // bool true or false + "omittedQuestions": addToOmittedQuestionsArray, // Don't send anything here + "SelectedOptionsArray": [] // Don't send anything here + }, + "userId": _userId.toString() + } + } + + ) + ).then((response) async { + print(jsonDecode(response.body).toString()); + if((response.statusCode == 200) & (json.decode(response.body).toString().substring(0,14) != "{status: false")) { + + } + else { // Token Invalid + ScaffoldMessenger.of(context) + ..removeCurrentSnackBar() + ..showSnackBar(SnackBar(content: Text("Token Invalid!"))); + final result = Navigator.pushAndRemoveUntil( + context, + MaterialPageRoute(builder: (BuildContext context) => const Login(fromWhere:"Home")), + ModalRoute.withName('/'), + ); + } + } + ).whenComplete(() { + if(hasUserClicked == true) { + ScaffoldMessenger.of(context) + ..removeCurrentSnackBar() + ..showSnackBar(SnackBar(content: Text("The Quiz has been saved as $saveAs!"))); + Navigator.of(context) + .popUntil(ModalRoute.withName("/home")); + final result = Navigator.push( + context, + MaterialPageRoute(builder: (context) => QuizFinal()), + ); + } + }); + + } + + Future GenerateQuizAPI() async { + print("Mode: " + widget.mode.toString()); + SharedPreferences prefs = await SharedPreferences.getInstance(); + final String apiUrlGenerateQuiz = "https://demo.pookidevs.com/quiz/generator/generateQuiz"; + _token = prefs.getString('token')!; + _userId = prefs.getInt("userId")!; + http.post(Uri.parse(apiUrlGenerateQuiz), headers: { + 'Content-type': 'application/json; charset=UTF-8', 'Authorization' : _token.toString(), + }, body: json.encode( + { + "data": + { + "questionIds": widget.questions, + "count": widget.totalQuestions + } + }) + ).then((response) { + // print("This is: " + jsonDecode(response.body).toString()); + if((response.statusCode == 200) & (json.decode(response.body).toString().substring(0,14) != "{status: false")) { + final responseString = (response.body); + var generateQuizSuccessful = generateQuizSuccessfulFromJson(responseString); + final GenerateQuizSuccessful getGenerateQuizSuccessful = generateQuizSuccessful; + setState(() { + _getGenerateQuizSuccessful = getGenerateQuizSuccessful; + _quizId = _getGenerateQuizSuccessful.data.quizId; + print(_quizId); + }); + categoriesGenerateQuizData(); + } + else { // Token Invalid + + } + } + ); + } + + Future BookmarkQuestionAPI() async { + final String apiUrlGenerateQuiz = "https://demo.pookidevs.com/quiz/solver/markQuestion"; + http.post(Uri.parse(apiUrlGenerateQuiz), headers: { + 'Content-type': 'application/json; charset=UTF-8', 'Authorization' : _token.toString(), + }, body: json.encode( + { + "data": { + "userId": _userId, + "questionId": questionsData["id"]![questionNumber].toString(), + "tableName": "marked_questions", + "isMarked": true + } + }) + ).then((response) { + if((response.statusCode == 200)) { // & (json.decode(response.body).toString().substring(0,14) != "{status: false")) { + print(jsonDecode(response.body).toString()); + } + else { // Token Invalid + ScaffoldMessenger.of(context) + ..removeCurrentSnackBar() + ..showSnackBar(SnackBar(content: Text("Token Invalid!"))); + final result = Navigator.pushAndRemoveUntil( + context, + MaterialPageRoute(builder: (BuildContext context) => const Login(fromWhere:"Home")), + ModalRoute.withName('/'), + ); + } + } + ); + } + + Future addNotesAPI() async { + // print(_userId); + // print(questionsData["id"]![questionNumber].toString()); + // print(_quizId); + // print(_note); + final String apiUrlGenerateQuiz = "https://demo.pookidevs.com/quiz/notes/addNotes"; + http.post(Uri.parse(apiUrlGenerateQuiz), headers: { + 'Content-type': 'application/json; charset=UTF-8', 'Authorization' : _token.toString(), + }, body: json.encode( + { + "data": { + "userId": _userId, + "questionId": questionsData["id"]![questionNumber].toString(), + "quizId": _quizId, + "note": _note, + "tableName": "notes" + } + } + ) + ).then((response) { + // print(jsonDecode(response.body).toString()); + // print(json.decode(response.body).toString().substring(json.decode(response.body).toString().length-12,json.decode(response.body).toString().length)); + if((response.statusCode == 200) & (json.decode(response.body).toString().substring(json.decode(response.body).toString().length-12,json.decode(response.body).toString().length) == "Note Added}}")) { + ScaffoldMessenger.of(context) + ..removeCurrentSnackBar() + ..showSnackBar(SnackBar(content: Text("Note Added!"))); + } + else if((response.statusCode == 200) & (json.decode(response.body).toString().substring(0,14) == "{status: false")) { // Token Invalid + ScaffoldMessenger.of(context) + ..removeCurrentSnackBar() + ..showSnackBar(SnackBar(content: Text("Token Expired!"))); + final result = Navigator.push( + context, + MaterialPageRoute(builder: (context) => const Login(fromWhere:"Home")), + ); + } + else { + ScaffoldMessenger.of(context) + ..removeCurrentSnackBar() + ..showSnackBar(SnackBar(content: Text("Note not Added!"))); + } + } + ); + } + + void categoriesGenerateQuizData() async { + setState(() { + questionsData["id"] = []; + questionsData["question"] = []; + questionsData["options"] = []; + questionsData["statistics"] = []; + questionsData["correct_msg"] = []; + questionsData["answeredCorrectly"] = []; + questionsData["optionSelectedInt"] = []; + questionsData["notes"] = []; + questionsData["submitData"] = []; + _questions = []; + }); + if(widget.whatsDone == "new") + { + int c = 0; + if (_getGenerateQuizSuccessful != null) { + while ((c < _getGenerateQuizSuccessful.data.questions.toList().length) & + (_getGenerateQuizSuccessful.data.questions.toList().length > 0)) { + // questionsData + setState(() { + questionsData["id"]! + .add(_getGenerateQuizSuccessful.data.questions[c].id); + questionsData["question"]! + .add(_getGenerateQuizSuccessful.data.questions[c].question); + questionsData["options"]! + .add(_getGenerateQuizSuccessful.data.questions[c].options); + questionsData["statistics"]! + .add(_getGenerateQuizSuccessful.data.questions[c].statistics); + questionsData["correct_msg"]!.add(_getGenerateQuizSuccessful + .data.questions[c].correctMsg); //answeredCorrectly + questionsData["answeredCorrectly"]!.add("notAnswered"); + questionsData["optionSelectedInt"]!.add(0); + _questions.add((c + 1).toString()); + }); + c++; + } + setState(() { + hasDataLoaded = true; + }); + if (hasDataLoaded == true) { + if (ranSaveQuizAtTheStart == false) { + SaveQuizAPI("suspended"); + setState(() { + ranSaveQuizAtTheStart = true; + }); + } + } + } + } + // print(questionsData); + else if(widget.whatsDone == "resumed") + { + int c = 0; + if (_resumeQuizSuccessful != null) { + while ((c < _resumeQuizSuccessful.data.questions.length) & + (_resumeQuizSuccessful.data.questions.length > 0)) { + // questionsData + setState(() { + questionsData["id"]! + .add(_resumeQuizSuccessful.data.questions[c].id); + questionsData["question"]! + .add(_resumeQuizSuccessful.data.questions[c].question); + questionsData["options"]! + .add(_resumeQuizSuccessful.data.questions[c].options); + questionsData["statistics"]! + .add(_resumeQuizSuccessful.data.questions[c].statistics); + questionsData["correct_msg"]!.add(_resumeQuizSuccessful + .data.questions[c].correctMsg); //answeredCorrectly + questionsData["answeredCorrectly"]!.add("notAnswered"); + questionsData["optionSelectedInt"]!.add(0); + _questions.add((c + 1).toString()); + if(_resumeQuizSuccessful.data.questions[c].notes != null) { // notes + questionsData["notes"]!.add(_resumeQuizSuccessful + .data.questions[c].notes); + } else { + questionsData["notes"]!.add(""); + } + if(_resumeQuizSuccessful.data.questions[c].submitData != null) { // submitData + String str = _resumeQuizSuccessful.data.questions[c].submitData; + str = str.replaceAll("\\", ""); + var strMap = json.decode(str); + print(strMap); + if(strMap['correct'] == '1') { + questionsData["answeredCorrectly"]![c] = "correct"; + } + else if (strMap['correct'] == '0') { + questionsData["answeredCorrectly"]![c] = "incorrect"; + } + questionsData["optionSelectedInt"]![c] = int.parse(strMap['optionIndexSelected']); + questionsData["submitData"]!.add(_resumeQuizSuccessful + .data.questions[c].submitData); + } else { + questionsData["submitData"]!.add(""); + } + }); + c++; + } + print(questionsData["answeredCorrectly"]); + setState(() { + hasDataLoaded = true; + }); + if (hasDataLoaded == true) { + if (ranSaveQuizAtTheStart == false) { + SaveQuizAPI("suspended"); + setState(() { + ranSaveQuizAtTheStart = true; + }); + } + } + } + } + // print(_resumeQuizSuccessful.data.previousQuizzes[0].quizMeta.quizMode); + } + + // To change text size - text zoom + Widget _textZoom(BuildContext context) { + return GestureDetector( + onTap: () { + }, + child: Container( + height: ((MediaQuery.of(context).size.height) * (51 / 926)), + decoration: const BoxDecoration( + gradient: LinearGradient( + begin: Alignment.topCenter, + end: Alignment.bottomCenter, + colors: [Color(0xff7F1AF1), Color(0xff482384)])), + child: new Slider( + value: _fontSize, + activeColor: Colors.white, + inactiveColor: Colors.red, + onChanged: (double value) { + setState(() { + _fontSize = value; + print(_fontSize); + }); + }, + divisions: 4, + min: 14.0, + max: 22.0, + ), + ), + ); + } + + + void onEnd() { + print('onEnd'); + } + + Widget bookmarkQuestion(BuildContext context) { + return SizedBox( + child: AlertDialog( + contentPadding: EdgeInsets.all(MediaQuery.of(context).size.width*(15/428)), + content: Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + 'Bookmark', + style: TextStyle( + color: Color(0xffB0A6C2), + fontFamily: 'Brandon-bld', + fontSize: (MediaQuery.of(context).size.height) * (18 / 926), + ), + ), + IconButton(icon:Icon(Icons.cancel),iconSize:23,color: Color(0xFF3F2668),onPressed: () { + Navigator.of(context).pop(); + },), + ], + ), + Divider(), + Text("Are you sure you want to bookmark this question", + ), + ], + ), + actions: [ + Divider(), + Row( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + TextButton( + onPressed: () { + Navigator.of(context).pop(); + }, + child: Text('No', + style: TextStyle( + color: Color(0xff3F2668), + fontFamily: 'Brandon-bld', + fontSize: + (MediaQuery.of(context).size.height) * (21 / 926), + )), + ), + Divider(), + TextButton( + onPressed: () { + Navigator.of(context).pop(); + print(questionsData["id"]![questionNumber].toString()); + BookmarkQuestionAPI(); + }, + child: Text('Yes', + style: TextStyle( + color: Color(0xff3F2668), + fontFamily: 'Brandon-bld', + fontSize: + (MediaQuery.of(context).size.height) * (21 / 926), + )), + ), + ], + ), + ], + ), + ); + } + + Widget labValues(BuildContext context) { + return SizedBox( + child: AlertDialog( + contentPadding: EdgeInsets.all(MediaQuery.of(context).size.width*(15/428)), + content: Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + 'Lab Values', + style: TextStyle( + color: Color(0xffB0A6C2), + fontFamily: 'Brandon-bld', + fontSize: (MediaQuery.of(context).size.height) * (18 / 926), + ), + ), + IconButton(icon:Icon(Icons.cancel),iconSize:23,color: Color(0xFF3F2668),onPressed: () { + Navigator.of(context).pop(); + },), + ], + ), + Divider(), + Text(_labValues), + ], + ), + ), + ); + } + Widget moreMenu() { + return Container( + width: (MediaQuery.of(context).size.width) * 0.3, + child: Drawer( + child: Container( + decoration: const BoxDecoration( + gradient: LinearGradient( + begin: Alignment.topRight, + end: Alignment.bottomLeft, + colors: [Color(0xff3F2668), Color(0xff482384)])), + child: ListView( + // Remove padding + padding: EdgeInsets.zero, + children: [ + Container( + padding: EdgeInsets.only( + top: MediaQuery.of(context).padding.top), + height: (MediaQuery.of(context).size.height), + color: Colors.transparent, + child: Column( + children: [ + ListTile( + leading: Icon( + Icons.close, + color: Colors.white, + ), + onTap: () => Navigator.pop(context), + ), + SizedBox( + height: + (MediaQuery.of(context).size.height) * (47 / 926), + ), + InkWell( + onTap: () { + Navigator.of(context).pop(); + // showDialog( + // context: context, + // builder: (BuildContext context) => + // labValues(context), + // ); + final result = Navigator.push( + context, + MaterialPageRoute(builder: (context) => SearchListExample()), + ); + }, + child: Container( + alignment: Alignment.center, + child: Column( + children: [ + SvgPicture.asset( + 'assets/Images/lab.svg', + height: (MediaQuery.of(context).size.height) * + (37 / 926), + color: Colors.white, + ), + SizedBox( + height: (MediaQuery.of(context).size.height) * + (10 / 926), + ), + Text( + 'Lab Values', + style: TextStyle( + color: Colors.white, + fontFamily: 'Brandon-bld', + fontSize: + (MediaQuery.of(context).size.height) * + (15 / 926), + ), + ) + ], + ), + ) + + //Divider(), + ), + SizedBox( + height: + (MediaQuery.of(context).size.height) * (47 / 926), + ), + InkWell( + onTap: () { + Navigator.of(context).pop(); + // bookmarkQuestion + showDialog( + context: context, + builder: (BuildContext context) => + bookmarkQuestion(context), + ); + }, + child: Container( + alignment: Alignment.center, + child: Column( + children: [ + Icon( + Icons.bookmark, + size: 37, + color: Colors.white, + ), + SizedBox( + height: (MediaQuery.of(context).size.height) * + (10 / 926), + ), + Text( + 'Bookmarks', + style: TextStyle( + color: Colors.white, + fontFamily: 'Brandon-bld', + fontSize: + (MediaQuery.of(context).size.height) * + (15 / 926), + ), + ) + ], + ), + ) + + //Divider(), + ), + SizedBox( + height: + (MediaQuery.of(context).size.height) * (47 / 926), + ), + InkWell( + onTap: () { + Navigator.of(context).pop(); + showDialog( + context: context, + builder: (BuildContext context) => + notes(context), + ); + }, + child: Container( + alignment: Alignment.center, + child: Column( + children: [ + Icon( + Icons.note_rounded, + size: 37, + color: Colors.white, + ), + SizedBox( + height: + (MediaQuery.of(context).size.height) * + (10 / 926), + ), + Text( + 'Notes', + style: TextStyle( + color: Colors.white, + fontFamily: 'Brandon-bld', + fontSize: + (MediaQuery.of(context).size.height) * + (15 / 926), + ), + ) + ], + ), + ) + + //Divider(), + ), + SizedBox( + height: + (MediaQuery.of(context).size.height) * (47 / 926), + ), + InkWell( + onTap:() {Navigator.of(context).pop(); + showDialog( + context: context, + builder: (BuildContext context) => + Calculator(), + );}, + child: Container( + alignment: Alignment.center, + child: Column( + children: [ + SvgPicture.asset('assets/Images/calculator.svg', + height: (MediaQuery.of(context).size.height) * + (37 / 926)), + SizedBox( + height: (MediaQuery.of(context).size.height) * + (10 / 926), + ), + Text( + 'Calculator', + style: TextStyle( + color: Colors.white, + fontFamily: 'Brandon-bld', + fontSize: + (MediaQuery.of(context).size.height) * + (15 / 926), + ), + ) + ], + ), + )), + SizedBox( + height: + (MediaQuery.of(context).size.height) * (47 / 926), + ), + InkWell( + onTap: () { + Navigator.of(context).pop(); + setState(() { + _showTextZoom = true; + }); + }, + child: Container( + alignment: Alignment.center, + child: Column( + children: [ + SvgPicture.asset('assets/Images/zoom.svg', + height: (MediaQuery.of(context).size.height) * + (37 / 926)), + SizedBox( + height: (MediaQuery.of(context).size.height) * + (10 / 926), + ), + Text( + 'Text Zoom', + style: TextStyle( + color: Colors.white, + fontFamily: 'Brandon-bld', + fontSize: + (MediaQuery.of(context).size.height) * + (15 / 926), + ), + ) + ], + ), + )) + ], + ), + ), + ]), + ))); + } + Widget notes(BuildContext context) { + return SizedBox( + child: AlertDialog( + contentPadding: EdgeInsets.all(MediaQuery.of(context).size.width*(15/428)), + content: Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + 'Take Notes', + style: TextStyle( + color: Color(0xffB0A6C2), + fontFamily: 'Brandon-bld', + fontSize: (MediaQuery.of(context).size.height) * (18 / 926), + ), + ), + IconButton(icon:Icon(Icons.cancel),iconSize:23,color: Color(0xFF3F2668),onPressed: () { + Navigator.of(context).pop(); + },), + ], + ), + Divider(), + TextField( + controller: _textController, + keyboardType: TextInputType.multiline, + minLines: 1,//Normal textInputField will be displayed + maxLines: 5,// when user presses enter it will adapt to it + decoration: InputDecoration( + hintText: "Add notes here...", + hintStyle: TextStyle(color: Color(0xffAEAEAE), + fontSize: (MediaQuery.of(context).size.height)*(15/926), + fontFamily: 'Brandon-med',), + contentPadding: EdgeInsets.fromLTRB(2.0, 1, 2.0, 1), + focusedBorder: OutlineInputBorder( + borderSide: BorderSide( + color: Colors.transparent, + width: 0.0, + ), + ), + ), + style: TextStyle( + color: Colors.black, + fontSize: (MediaQuery.of(context).size.height)*(15/926), + fontFamily: 'Brandon-med', + ), + onChanged: (String value) { + setState(() { + _note = value; + }); + }, + ), + Row( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + IconButton(onPressed:(){ + setState((){ + _note=''; + _textController.clear(); + } + ); + } , iconSize: 21 ,icon: Icon(Icons.refresh,color: Color(0xFF3F2668))), + TextButton( + onPressed: () { + addNotesAPI(); + _textController.clear(); + Navigator.of(context).pop(); + }, + style: TextButton.styleFrom( + padding: EdgeInsets.zero,), + child: Container( + height: (MediaQuery.of(context).size.height) * (31 / 926), + width:(MediaQuery.of(context).size.width) * (97 / 428), + decoration: BoxDecoration(borderRadius:BorderRadius.circular(4),color: Color(0xFFDDDAE2),), + child:Row( + mainAxisAlignment: MainAxisAlignment.center, + children:[ + Icon(Icons.save,color: Color(0xFF3F2668),), + SizedBox( + height: (MediaQuery.of(context).size.width) * + (14 / 428), + ), + Text( + 'Save', + style: TextStyle( + color: Color(0xff3F2668), + fontFamily: 'Brandon-bld', + fontSize: (MediaQuery.of(context).size.height) * (19 / 926), + ), + ), + ]) + ),) + ], + ) + ], + ), + ),);} + Future _onQuit() async { + return (await showDialog( + context: context, + builder: (context) => AlertDialog( + content: Text( + 'Mark Quiz as', + style: TextStyle( + color: Color(0xffA1A1A1), + fontFamily: 'Brandon-bld', + fontSize: (MediaQuery.of(context).size.height) * (21 / 926), + ), + ), + actions: [ + TextButton( + onPressed: () async { + await SaveQuizAPI("suspended", true); + // ScaffoldMessenger.of(context) + // ..removeCurrentSnackBar() + // ..showSnackBar(SnackBar(content: Text("The Quiz has been saved as Suspended!"))); + // Navigator.of(context).pop(); + // Navigator.of(context).pop(); + }, + child: Text('Suspended', + style: TextStyle( + color: Color(0xff3F2668), + fontFamily: 'Brandon-bld', + fontSize: + (MediaQuery.of(context).size.height) * (21 / 926), + )), + ), + TextButton( + onPressed: () async { + await SaveQuizAPI("completed", true); + // Navigator.of(context).pop(); + // Navigator.of(context).pop(); // Uncomment when "completed" and omittedQuestionsArray work again. + }, + child: Text('Completed', + style: TextStyle( + color: Color(0xff3F2668), + fontFamily: 'Brandon-bld', + fontSize: + (MediaQuery.of(context).size.height) * (21 / 926), + )), + ), + ], + ), + )) ?? + false; + } + + @override + void dispose() { + _textController.dispose(); + timer?.cancel(); + WidgetsBinding.instance!.removeObserver(this); + // saveQuiz?.cancel(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + return WillPopScope( + onWillPop: () async { + // ScaffoldMessenger.of(context) + // ..removeCurrentSnackBar() + // ..showSnackBar(SnackBar(content: Text("Click on Quit Quiz!"))); + return true; + }, + child: Scaffold( + resizeToAvoidBottomInset: false, + backgroundColor: Color(0xffF8F9FB), + drawer: SideMenuBar(), + // drawer: moreMenu(), + endDrawer: moreMenu(), + appBar: AppBar( + toolbarHeight: (MediaQuery.of(context).size.height) * (73.52 / 926), + backgroundColor: Color(0xff3F2668), + elevation: 2, + centerTitle: true, + title: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Text( + 'Question ', + style: TextStyle( + color: Color(0xffffffff), + fontFamily: 'Brandon-bld', + fontSize: (MediaQuery.of(context).size.height) * (20 / 926), + ), + ), + DropdownButton( + value: (questionNumber + 1).toString(), + underline: Container(), + iconEnabledColor: Colors.white, + dropdownColor: Color(0xff3F2668), + onChanged: (newValue) { + setState(() { + // print(newValue); + _currentQuestion = newValue as String; + questionNumber = int.parse(newValue) - 1; + }); + }, + items: _questions.map((question) { + return DropdownMenuItem( + child: new Text( + question + ' / ' + widget.totalQuestions.toString(), + style: TextStyle( + color: Colors.white, + fontFamily: 'Brandon-bld', + fontSize: + (MediaQuery.of(context).size.height) * (20 / 926), + ), + ), + value: question, + ); + }).toList(), + ), + ], + ), + flexibleSpace: Container( + decoration: const BoxDecoration( + gradient: LinearGradient( + begin: Alignment.topCenter, + end: Alignment.bottomCenter, + colors: [Color(0xff7F1AF1), Color(0xff482384)])), + ), + actions: [ + TextButton( + onPressed: () async { + SaveQuizAPI("suspended", false); + }, + child: SvgPicture.asset( + "assets/Images/logout.svg", + height: (MediaQuery.of(context).size.height) *(32/926), + ), + ), + ], + ), + body: hasDataLoaded == false ? Center(child: CircularProgressIndicator()) : Column( + children: [ + GestureDetector( + onTap: () { + setState(() { + _showTextZoom = false; + }); + }, + child: Container( + height: ((MediaQuery.of(context).size.height) * ((926-73.52-50.88-(MediaQuery.of(context).padding.top)-8.1) / 926)), + child: ListView( + scrollDirection: Axis.vertical, + children: [ + Container( + padding: EdgeInsets.only( + top: (MediaQuery.of(context).size.height) * (15 / 926), + bottom: (MediaQuery.of(context).size.height) * (8 / 926), + left: (MediaQuery.of(context).size.width) * (18 / 428), + right: (MediaQuery.of(context).size.width) * (18 / 428)), + child: Column( + children: [ + Row( + children: [ + Container( + width: (MediaQuery.of(context).size.width) * (221 / 428), + //height: (MediaQuery.of(context).size.height) *(91/926), + child: Column( + children: [ + Align( + alignment: Alignment.topLeft, + child: Text( + "Attempt Your Quiz", + style: TextStyle( + color: Color(0xff232323), + fontFamily: 'Brandon-bld', + fontSize: (MediaQuery.of(context).size.height) * + (20 / 926), //38, + ), + ), + ), + SizedBox( + height: (MediaQuery.of(context).size.height) * + (2 / 926), + ), + Align( + alignment: Alignment.topLeft, + child: Text( + "Question ID: " + questionsData["id"]![questionNumber].toString(), // questionNumber + style: TextStyle( + color: Color(0xFF7F1AF1), + fontFamily: 'Brandon-med', + fontSize: (MediaQuery.of(context).size.height) * + (13 / 926), //38, + ), + ), + ) + ], + ), + ), + SizedBox( + width: (MediaQuery.of(context).size.width) * (39 / 428), + ), + // for timer + Container( + height: (MediaQuery.of(context).size.height) * (25 / 926), + width: (MediaQuery.of(context).size.width) * (87 / 428), + color: Color(0xFF3F2668), + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Text('', + style: TextStyle( + color: Color(0xFFFFFFFF), + fontFamily: 'Brandon-med', + fontSize: (MediaQuery.of(context).size.height) * + (7 / 926), + )), + CountdownTimer( + textStyle: TextStyle( + color: Color(0xFFFFFFFF), + fontFamily: 'Brandon-med', + fontSize: (MediaQuery.of(context).size.height) * + (13 / 926), + ), + endTime: endTime, + onEnd: onEnd, + endWidget: Text( + "00 : 00 : 00", + style: TextStyle( + color: Color(0xFFFFFFFF), + fontFamily: 'Brandon-med', + fontSize: (MediaQuery.of(context).size.height) * + (13 / 926), + ), + ), + ), + ], + ), + ) + ], + ), + SizedBox( + height: (MediaQuery.of(context).size.height) * (25 / 926), + ), + Text( + questionsData["question"]![questionNumber].toString(), + style: TextStyle( + color: Color(0xFF483A3A), + fontFamily: 'Brandon-med', + fontSize: + (MediaQuery.of(context).size.height) * (_fontSize / 926), //38, + ), + ), + SizedBox( + height: (MediaQuery.of(context).size.height) * (25 / 926), + ), + if(questionsData["options"] != null) + for(int i = 0; i QuestionExplanation(question: questionsData["question"]![questionNumber].toString(), correctAnswer: correctAns.toString(), questionId: questionsData["id"]![questionNumber], explanation: questionsData["correct_msg"]![questionNumber].toString(),)), + ); + }, + child: Container( + alignment: Alignment.topRight, + child: Text( + "See Explanation", + style: TextStyle( + color: Color(0xFF7F1AF1), + fontFamily: 'Brandon-med', + fontSize: (MediaQuery.of(context).size.height) * + (13 / 926), //38, + ), + ), + ), + ) : Container(), + SizedBox( + height: (MediaQuery.of(context).size.height) * (20 / 926), + ), + ], + ) : + Column( // Exam Mode! + children: [ + TextButton( + onPressed: () { + // print("i: " + i.toString()); + // if(questionsData["answeredCorrectly"]![questionNumber] == "notAnswered") { + if((questionsData["answeredCorrectly"]![questionNumber] == "notAnswered") || (questionsData["answeredCorrectly"]![questionNumber] != "notAnswered")) { + int? indexOfOptionThatIsActuallyCorrect; + int? correct; + // whichOption = i; optionSelectedInt + setState(() { + questionsData["optionSelectedInt"]![questionNumber] = i; + }); + int j = 0; + for(j = 0; j<10; j++) { + if(questionsData["options"]![questionNumber][i].toString() == questionsData["options"]![questionNumber][j].toString()) { + break; + } + } + if(questionsData["statistics"]![questionNumber][j] == 1) { + setState(() { + questionsData["answeredCorrectly"]![questionNumber] = "correct"; + }); + correct = 1; + // print("correct: " + correct.toString()); + // print(questionsData["answeredCorrectly"]); + } + else if(questionsData["statistics"]![questionNumber][j] == 0) { + setState(() { + questionsData["answeredCorrectly"]![questionNumber] = "incorrect"; + }); + correct = 0; + // print(questionsData["answeredCorrectly"]); + } + for(int c = 0; c QuestionExplanation(question: questionsData["question"]![questionNumber].toString(), correctAnswer: correctAns.toString(), questionId: questionsData["id"]![questionNumber], explanation: questionsData["correct_msg"]![questionNumber].toString(),)), + // ); + // }, + // child: Container( + // alignment: Alignment.topRight, + // child: Text( + // "See Explanation", + // style: TextStyle( + // color: Color(0xFF7F1AF1), + // fontFamily: 'Brandon-med', + // fontSize: (MediaQuery.of(context).size.height) * + // (13 / 926), //38, + // ), + // ), + // ), + // ) : Container(), + SizedBox( + height: (MediaQuery.of(context).size.height) * (20 / 926), + ), + ], + ),// here + SizedBox( + height: (MediaQuery.of(context).size.height) * (5 / 926), + ), + SizedBox( + height: (MediaQuery.of(context).size.height) * (96 / 926), + ), + Row( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + Container( + alignment: Alignment.bottomRight, + child: InkWell( + child: Icon(Icons.power_settings_new, + color: Color(0xFF7F1AF1), + size: (MediaQuery.of(context).size.height) * + (23 / 926),), + ), + ), + SizedBox( + width: (MediaQuery.of(context).size.width) * (5 / 428), + ), + Container( + alignment: Alignment.bottomRight, + child: InkWell( + child: Text( + "Quit Quiz", + style: TextStyle( + color: Color(0xFF7F1AF1), + fontFamily: 'Brandon-bld', + fontSize: (MediaQuery.of(context).size.height) * + (13 / 926), //38, + ), + ), + onTap: () => _onQuit())), + ], + ), + SizedBox( + height: (MediaQuery.of(context).size.height) * (26 / 926), + ), + ], + )), + ], + ), + ), + ) , + Align( + alignment: Alignment.bottomCenter, + child: Container( + height: ((MediaQuery.of(context).size.height) * (51 / 926)), + decoration: const BoxDecoration( + gradient: LinearGradient( + begin: Alignment.topCenter, + end: Alignment.bottomCenter, + colors: [Color(0xff7F1AF1), Color(0xff482384)])), + child: _showTextZoom == true ? _textZoom(context) : Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + TextButton( + onPressed: () { + if(questionNumber > 0) { + setState(() { + questionNumber--; + }); + } + }, + style: TextButton.styleFrom( + padding: EdgeInsets.zero,), + child: Row( + children: [ + SizedBox(width: (MediaQuery.of(context).size.width) * (16 / 428)), + Container( + child: Icon(Icons.arrow_back_ios_outlined, + color: Colors.white, + size: ((MediaQuery.of(context).size.width) * (23.1 / 428)),), + ), + ], + ), + ), + Builder( + builder: (context) => TextButton( + onPressed: () { Scaffold.of(context).openEndDrawer(); }, + style: TextButton.styleFrom( + padding: EdgeInsets.zero,), + child: Row( + children: [ + Container( + width: ((MediaQuery.of(context).size.height) * (15 / 926)), + decoration: BoxDecoration( + color: Colors.white, + shape: BoxShape.circle + ), + ), + SizedBox(width: (MediaQuery.of(context).size.width) * (6 / 428)), + Container( + width: ((MediaQuery.of(context).size.height) * (15 / 926)), + decoration: BoxDecoration( + color: Colors.white, + shape: BoxShape.circle + ), + ), + SizedBox(width: (MediaQuery.of(context).size.width) * (6 / 428)), + Container( + width: ((MediaQuery.of(context).size.height) * (15 / 926)), + decoration: BoxDecoration( + color: Colors.white, + shape: BoxShape.circle + ), + ), + ], + ), + ), + ), + TextButton( + onPressed: () { + if(questionNumber < (widget.totalQuestions - 1)) { + setState(() { + questionNumber++; + }); + } + }, + style: TextButton.styleFrom( + padding: EdgeInsets.zero,), + child: Row( + children: [ + Container( + child: Icon(Icons.arrow_forward_ios_outlined, + color: Colors.white, + size: ((MediaQuery.of(context).size.width) * (23.1 / 428)),), + ), + SizedBox(width: (MediaQuery.of(context).size.width) * (16 / 428)), + ], + ), + ), + ], + ), + ), + ) + ], + ), + ), + ); + } +} diff --git a/lib/screens/Welcome/QuizModule/search_bar.dart b/lib/screens/Welcome/QuizModule/search_bar.dart index 29dcac1..6f925a0 100644 --- a/lib/screens/Welcome/QuizModule/search_bar.dart +++ b/lib/screens/Welcome/QuizModule/search_bar.dart @@ -1,861 +1,861 @@ -import 'package:flutter/material.dart'; - -class SearchListExample extends StatefulWidget { - @override - _SearchListExampleState createState() => new _SearchListExampleState(); -} - -class _SearchListExampleState extends State with SingleTickerProviderStateMixin { - - final bloodLabValues = [ - {"title": 'Alanine aminotransferase (ALT), serum', "value": '8-40 U/L', "siValue": '8-40 U/L', - "subtitle": [{"title": '', "value": ''}] - }, - {"title": 'Alkaline phosphatase, serum ', "value": '', "siValue": '', - "subtitle": [ - {"title": 'Male', "value": '30-100 U/L', "siValue": '30-100 U/L'}, - {"title": 'Female', "value": '45-115 U/L', "siValue": '45-115 U/L'}, - ] - }, - {"title": 'Amylase, serum', "value": '25-125 U/L', "subtitle": [], "siValue": '25-125 U/L' }, - {"title": 'Aspartate aminotransferase (AST), serum', "value": '8-40 U/L', "subtitle": [], "siValue": '8-40 U/L'}, - {"title": 'Bilirubin, serum (adult)' , "value": '', "siValue": '', - "subtitle": [ - {"title": 'Total', "value": '0.1-1.0 mg/dL', "siValue": '2-17 μmol/L'}, - {"title": 'Direct', "value": '0.0-0.3 mg/dL', "siValue": '0.0-0.05 μmol/L'}, - ] - }, - {"title": 'Calcium, serum (total)', "value": '8.4-10.2 mg/dL', "subtitle": [], "siValue": '2.1-2.8 mmol/L'}, - {"title": 'Cholesterol, serum' , "value": '', "siValue": '', - "subtitle": [ - {"title": 'Total', "value": '150-240 mg/dL', "siValue": '3.9-6.2 mmol/L'}, - {"title": 'HDL', "value": '0-70 mg/dL', "siValue": '0.8-1.8 mmol/L'}, - {"title": 'LDL', "value": '<160 mg/dL', "siValue": '<4.2 mmol/L'}, - ] - }, - {"title": 'Cortisol, serum', "value": '', "siValue": '', - "subtitle": [ - {"title": '0800 h', "value": '5-23 μg/dL', "siValue": '138-635 nmol/L'}, - {"title": '1600 h', "value": '3-15 μg/dL', "siValue": '82-413 nmol/L'}, - {"title": '2000 h', "value": '50% of 0800 h', "siValue": 'Fraction of 0800 h: ≤0.50'}, - ] - }, - {"title": 'Creatine kinase, serum', "value": '', "siValue": 'L', - "subtitle": [ - {"title": 'Male', "value": '25-90 U/L', "siValue": '25-90 U/L'}, - {"title": 'Female', "value": '10-70 U/L', "siValue": '10-70 U/L'}, - ] - }, - {"title": 'Creatinine, serum', "value": '0.6-1.2 mg/dL', "subtitle": [], "siValue": '53-106 μmol/L'}, - {"title": 'Electrolytes, serum', "value": '', "siValue": '', - "subtitle": [ - {"title": 'Sodium (Na+)', "value": '136-145 mEq/L', "siValue": '136-145 mEq/L'}, - {"title": 'Potassium (K+)', "value": '3.5-5.0 mEq/L', "siValue": '95-105 mmol/L'}, - {"title": 'Chloride (Cl-)', "value": '95-105 mEq/L', "siValue": '3.5-5.0 mmol/L'}, - {"title": 'Bicarbonate (HCO3-)', "value": '22-28 mEq/L', "siValue": '22-28 mEq/L'}, - {"title": 'Magnesium (Mg2+)', "value": '1.5-2.0 mEq/L', "siValue": '0.75-1.0 mmol/L'}, - ] - }, - {"title": 'Estriol, total, serum (in pregnancy)', "value": '', "siValue": '', - "subtitle": [ - {"title": '24-28 wks', "value": '30-170 ng/mL', "siValue": '104-590 nmol/L'}, - {"title": '28-32 wks', "value": '40-220 ng/mL', "siValue": '140-760 nmol/L'}, - {"title": '32-36 wks', "value": '60-280 ng/mL', "siValue": '208-970 nmol/L'}, - {"title": '36-40 wks', "value": '80-350 ng/mL', "siValue": '280-1210 nmol/L'}, - ] - }, - - {"title": 'Ferritin, serum', "value": '', "siValue": '', - "subtitle": [ - {"title": 'Male', "value": '15-200 ng/mL', "siValue": '15-200 ng/mL'}, - {"title": 'Female', "value": '12-150 ng/mL', "siValue": '12-150 ng/mL'}, - ] - }, - {"title": 'Follicle-stimulating hormone, serum/plasma', "value": '', "siValue": '', - "subtitle": [ - {"title": 'Male', "value": '4-25 mIU/mL', "siValue": '4-25 mIU/mL'}, - {"title": 'Female', "value": '', "siValue": ''}, - {"title": 'premenopause', "value": '4-30 mIU/mL', "siValue": '4-30 mIU/mL'}, - {"title": 'midcycle peak', "value": '10-90 mIU/mLL', "siValue": '10-90 mIU/mLL'}, - {"title": 'postmenopause', "value": '40-250 mIU/mL', "siValue": '40-250 mIU/mL'}, - ] - }, - {"title": 'Gases, arterial blood (room air)', "value": '', "siValue": '', - "subtitle": [ - {"title": 'pH', "value": '7.35-7.45', "siValue": '[H+] 36-44 nmol/L'}, - {"title": 'Pco2', "value": '33-45 mm Hg', "siValue": '4.4-5.9 kPa'}, - {"title": 'Po2', "value": '75-105 mm Hg', "siValue": '10.0-14.0 kPa'}, - ] - }, - {"title": 'Glucose, serum', "value": '', "siValue": '', - "subtitle": [ - {"title": 'Fasting', "value": '70-110 mg/dL', "siValue": '3.8-6.1 mmol/L'}, - {"title": '2-h postprandial', "value": '<120 mg/dL', "siValue": '<6.6 mmol/L'}, - ] - }, - {"title": 'Growth hormone- arginine stimulation', "value": '', "siValue": '', - "subtitle": [ - {"title": 'Fasting', "value": '<5 ng/mL', "siValue": '<5 ng/mL'}, - {"title": 'Provocative stimuli', "value": '>7 ng/mL', "siValue": '>7 μg/L'}, - ] - }, - {"title": 'Immunoglobulins, serum', "value": '', "siValue": '', - "subtitle": [ - {"title": 'IgA', "value": '76-390 mg/dL', "siValue": '0.76-3.90 g/L'}, - {"title": 'IgE', "value": '0-380 IU/mL', "siValue": '0-380 kIU/L'}, - {"title": 'IgG', "value": '650-1,500 mg/dL', "siValue": '6.5-15 g/L'}, - {"title": 'IgM', "value": '40-345 mg/dL', "siValue": '0.4-3.45 g/L'}, - ] - }, - {"title": 'Iron', "value": '50-170 μg/dL', "subtitle": [], "siValue": '9-30 μmol/LL'}, - {"title": 'Lactate dehydrogenase, serum', "value": '45-90 U/L (100-250 IU/L)', "siValue": '45-90 U/L (100-250 IU/L)', - "subtitle": [] - }, - {"title": 'Luteinizing hormone, serum/plasma', "value": '', "siValue": '', - "subtitle": [ - {"title": 'Male', "value": '6-23 mIU/mL', "siValue": '6-23 U/L'}, - {"title": 'Female', "value": '', "siValue": ''}, - {"title": 'follicular phase', "value": '5-30 mIU/mL', "siValue": '5-30 U/L'}, - {"title": 'midcycle', "value": '75-150 mIU/mL', "siValue": '75-150 U/L'}, - {"title": 'postmenopause', "value": '30-200 mIU/mL', "siValue": '30-200 U/L'}, - ] - }, - {"title": 'Osmolality, serum', "value": '275-295 mOsmol/kg H2O', "siValue": '275-295 mOsmol/kg H2O', - "subtitle": [] - }, - {"title": 'Parathyroid hormone, serum, N-terminal', "value": '10-65 pg/mL', "siValue": '10-65 pg/mL', - "subtitle": [] - }, - {"title": 'Phosphate (alkaline), serum (p-NPP at 30° C)', "value": '20-70 U/L', "siValue": '20-70 U/L', - "subtitle": [] - }, - {"title": 'Phosphorus (inorganic), serum', "value": '3.0-4.5 mg/dL', "siValue": '1.0-1.5 mmol/L', - "subtitle": [] - }, - - {"title": 'Prolactin, serum (hPRL) ', "value": '<20 ng/mL', "siValue": '<20 ng/mL', - "subtitle": [] - }, - {"title": 'Proteins, serum', "value": '', "siValue": '', - "subtitle": [ - {"title": 'Total (recumbent)', "value": '6.0-7.8 g/dL', "siValue": '60-78 g/L'}, - {"title": 'Albumin', "value": '3.5-5.5 g/dL', "siValue": '35-55 g/L'}, - {"title": 'Globulin', "value": '2.3-3.5 g/dL', "siValue": '23-35 g/L'}, - ] - }, - {"title": 'Thyroid-stimulating hormone (TSH), serum', "value": '0.5-5.0 μU/mL', "siValue": '0.5-5.0 μU/mL', - "subtitle": [] - }, - {"title": 'Thyroidal iodine (123I) uptake', "value": '8%-30% of administered dose/24 h', "siValue": '0.08-0.30 fraction of administered dose/24 h', - "subtitle": [] - }, - {"title": 'Thyroxine (T4), serum', "value": '5-12 μg/dL', "siValue": '64-155 nmol/L', - "subtitle": [] - }, - {"title": 'Triglycerides, serum', "value": '35-160 mg/dL', "siValue": '0.4-1.81 mmol/L', - "subtitle": [] - }, - {"title": 'Triiodothyronine (T3), serum (RIA)', "value": '115-190 ng/dL', "siValue": '1.8-2.9 nmol/L', - "subtitle": [] - }, - {"title": 'Triiodothyronine (T3) resin uptake', "value": '25%-35%', "siValue": '0.25-0.35', - "subtitle": [] - }, - {"title": 'Urea nitrogen, serum (BUN)', "value": '7-18 mg/dL', "siValue": '1.2-3.0 mmol/L', - "subtitle": [] - }, - {"title": 'Uric acid, serum', "value": '3.0-8.2 mg/dL', "siValue": '0.18-0.48 mmol/L', - "subtitle": [] - }, - - ]; - final HematologicLabValues = [ - {"title": 'Bleeding time (template)', "value": '2-7 minutes', "siValue": '2-7 minutes', - "subtitle": [] - }, - {"title": 'CD4+ T-lymphocyte count', "value": '>500 mm^3', "siValue": '>500 x 106/L', - "subtitle": [] - }, - {"title": 'Erythrocyte count', "value": '', "siValue": '', - "subtitle": [ - {"title": 'Male', "value": '4.3-5.9 million/mm^3', "siValue": '4.3-5.9 x 10^12/L'}, - {"title": 'Female', "value": '3.5-5.5 million/mm^3', "siValue": '3.5-5.5 x 10^12/L'}, - ] - }, - {"title": 'Erythrocyte sedimentation rate (Westergren)', "value": '', "siValue": '', - "subtitle": [ - {"title": 'Male', "value": '0-15 mm/h', "siValue": '0-15 mm/h'}, - {"title": 'Female', "value": '0-20 mm/h', "siValue": '0-20 mm/h'}, - ] - }, - {"title": 'Hematocrit', "value": '', "siValue": '', - "subtitle": [ - {"title": 'Male', "value": '41%-53%', "siValue": '0.41-0.53'}, - {"title": 'Female', "value": '36%-46%', "siValue": '0.36-0.46'}, - ] - }, - {"title": 'Hemoglobin A1c', "value": '≤6%', "siValue": '≤0.06', - "subtitle": [] - }, - {"title": 'Hemoglobin, blood', "value": '', "siValue": '', - "subtitle": [ - {"title": 'Male', "value": '13.5-17.5 g/dL', "siValue": '2.09-2.71 mmol/L'}, - {"title": 'Female', "value": '12.0-16.0 g/dL', "siValue": '1.86-2.48 mmol/L'}, - ] - }, - {"title": 'Leukocyte count and differential', "value": '', "siValue": '', - "subtitle": [ - {"title": 'Leukocyte count', "value": '4,500-11,000/mm^3', "siValue": '4.5-11.0 x 10^9/L'}, - {"title": 'Neutrophils, segmented', "value": '54%-62%', "siValue": '0.54-0.62'}, - {"title": 'Neutrophils, banded', "value": '3%-5%', "siValue": '0.03-0.05'}, - {"title": 'Eosinophils', "value": '1%-3%', "siValue": '0.01-0.03'}, - {"title": 'Basophils', "value": '0%-0.75%', "siValue": '0-0.0075'}, - {"title": 'Lymphocytes', "value": '25%-33%', "siValue": '0.25-0.33'}, - {"title": 'Monocytes', "value": '3%-7%', "siValue": '0.03-0.07'}, - ] - }, - {"title": 'Mean corpuscular hemoglobin (MCH)', "value": '25.4-34.6 pg/cell', "siValue": '0.39-0.54 fmol/cell', - "subtitle": [] - }, - {"title": 'Mean corpuscular hemoglobin concentration (MCHC)', "value": '31%-36% Hb/cell', "siValue": '4.81-5.58 mmol Hb/L', - "subtitle": [] - }, - {"title": 'Mean corpuscular volume (MCV)', "value": '80-100 μm3', "siValue": '80-100 fL', - "subtitle": [] - }, - {"title": 'Partial thromboplastin time (activated)', "value": '25-40 seconds', "siValue": '25-40 seconds', - "subtitle": [] - }, - {"title": 'Platelet count', "value": '150,000-400,000/mm^3', "siValue": '150-400 x 10^9/L', - "subtitle": [] - }, - {"title": 'Prothrombin time', "value": '11-15 seconds', "siValue": '11-15 seconds', - "subtitle": [] - }, - {"title": 'Reticulocyte count', "value": '0.5%-1.5% of red cells', "siValue": '0.005-0.015 fraction of red cells', - "subtitle": [] - }, - {"title": 'Thrombin time', "value": '<2 seconds deviation from control', "siValue": '<2 seconds deviation from control', - "subtitle": [] - }, - {"title": 'Volume', "value": '', "siValue": '', - "subtitle": [ - {"title": 'Plasma', "value": '', "siValue": ''}, - {"title": 'Male', "value": '25-43 mL/kg', "siValue": '0.005-0.015 fraction of red cells' }, - {"title": 'Female', "value": '28-45 mL/kg', "siValue": '0.028-0.045 L/kg'}, - {"title": 'Red cell', "value": '', "siValue": ''}, - {"title": 'Male', "value": '20-36 mL/kg', "siValue": '0.020-0.036 L/kg'}, - {"title": 'Female', "value": '19-31 mL/kg', "siValue": '0.019-0.031 L/kg'}, - ] - }, - - - ]; - final CerebrospinalLabValues = [ - {"title": 'Cell count', "value": '0-5/mm^3', "siValue": '0-5 x 10^6/L', - "subtitle": [] - }, - {"title": 'Chloride', "value": '118-132 mEq/L', "siValue": '118-132 mmol/L', - "subtitle": [] - }, - {"title": 'Gamma globulin', "value": '3%-12% of total proteins', "siValue": '0.03-0.12 of total proteins', - "subtitle": [] - }, - {"title": 'Glucose', "value": '40-70 mg/dL', "siValue": '2.2-3.9 mmol/L', - "subtitle": [] - }, - {"title": 'Pressure', "value": '70-180 mm H2O', "siValue": '70-180 mm H2O', - "subtitle": [] - }, - {"title": 'Proteins, total', "value": '<40 mg/dL', "siValue": '<0.40 g/L', - "subtitle": [] - }, - ]; - final sweatLabValues = [ - {"title": 'Calcium', "value": '100-300 mg/24 h', "siValue": '2.5-7.5 mmol/24 h', - "subtitle": [] - }, - {"title": 'Chloride', "value": '1Varies with intake', "siValue": '1Varies with intake', - "subtitle": [] - }, - {"title": 'Creatine clearance', "value": '', "siValue": '', - "subtitle": [ - {"title": 'Male', "value": '97-137 mL/min', "siValue": '1.62-2.29 mL/s'}, - {"title": 'Female', "value": '88-128 mL/min', "siValue": '1.47-2.14 mL/s'}, - ] - }, - {"title": 'Estriol, total (in pregnancy)', "value": '', "siValue": '', - "subtitle": [ - {"title": '30 wks', "value": '6-18 mg/24 h', "siValue": '21-62 μmol/24 h'}, - {"title": '35 wks', "value": '9-28 mg/24 h', "siValue": '31-97 μmol/24 h'}, - {"title": '40 wks', "value": '13-42 mg/24 h', "siValue": '45-146 μmol/24 h'}, - ] - }, - {"title": '17-hydroxycorticosteroids', "value": '', "siValue": '', - "subtitle": [ - {"title": 'Male', "value": '3.0-10.0 mg/24 h', "siValue": '8.2-27.6 μmol/24 h'}, - {"title": 'Female', "value": '2.0-8.0 mg/24 h', "siValue": '5.5-22.0 μmol/24 h'}, - ] - }, - {"title": '17-ketosteroids, total', "value": '', "siValue": '', - "subtitle": [ - {"title": 'Male', "value": '8-20 mg/24 h', "siValue": '28-70 μmol/24 h'}, - {"title": 'Female', "value": '6-15 mg/24 h', "siValue": '21-52 μmol/24 h'}, - ] - }, - {"title": 'Osmolality', "value": '50-1,400 mOsmol/kg H2O', "siValue": '50-1,400 mmol/kg', - "subtitle": [] - }, - {"title": 'Oxalate', "value": '8-40 μg/mL', "siValue": '90-445 μmol/L', - "subtitle": [] - }, - {"title": 'Proteins, total', "value": '<150 mg/24 h', "siValue": '<0.15 g/24 h', - "subtitle": [] - }, - {"title": 'Sodium, total', "value": 'varies with diet', "siValue": 'varies with diet', - "subtitle": [] - }, - {"title": 'Uric acid', "value": 'varies with diet', "siValue": 'varies with diet', - "subtitle": [] - }, - {"title": 'Body Mass Index (Adult)', "value": '19-25 kg/m^2', "siValue": '19-25 kg/m^2', - "subtitle": [] - }, - ]; - - - - Widget appBarTitle = new Text( - "Search Values", - style: new TextStyle(color: Colors.white), - ); - Icon icon = new Icon( - Icons.search, - color: Colors.white, - ); - final globalKey = new GlobalKey(); - final TextEditingController _controller = new TextEditingController(); - List _list = []; // = ["Indian rupee", "United States dollar", "Australian dollar", "Euro", "British pound", "Yemeni rial", "Japanese yen", "Hong Kong dollar"]; - bool _isSearching = false; - String _searchText = ""; - List searchresult = []; - bool _siValues = false; - late TabController _tabController; - - var bloodLabValuesData = { - "title" : [], - "value" : [], - "siValue" : [] - }; - var HematologicLabValuesData = { - "title" : [], - "value" : [], - "siValue" : [] - }; - var CerebrospinalLabValuesData = { - "title" : [], - "value" : [], - "siValue" : [] - }; - var sweatLabValuesData = { - "title" : [], - "value" : [], - "siValue" : [] - }; - - var LabValuesList = { - "title" : [], - "value" : [], - "siValue" : [] - }; - - categorizebloodLabValues() { - for(int i = 0; i; - }); - // print(CerebrospinalLabValuesData["title"]); - // print(_list); - } - - _SearchListExampleState() { - _controller.addListener(() { - if (_controller.text.isEmpty) { - setState(() { - _isSearching = false; - _searchText = ""; - }); - } else { - setState(() { - _isSearching = true; - _searchText = _controller.text; - }); - } - }); - } - - @override - void initState() { - super.initState(); - _tabController = TabController(vsync: this, length: 4) - ..addListener(() { - setState(() { - if(_tabController.index == 0){ - // print(_tabController.index); - setState(() { - _handleSearchEnd(); - if(bloodLabValuesData["title"] != null) - _list = bloodLabValuesData["title"] as List; - _isSearching = false; - _searchText = ""; - searchOperation(""); - }); - } - else if(_tabController.index == 1){ - // print(_tabController.index); - setState(() { - _handleSearchEnd(); - if(HematologicLabValuesData["title"] != null) - _list = HematologicLabValuesData["title"] as List; - _isSearching = false; - _searchText = ""; - searchOperation(""); - }); - } - else if(_tabController.index == 2){ - // print(_tabController.index); - setState(() { - _handleSearchEnd(); - if(CerebrospinalLabValuesData["title"] != null) - _list = CerebrospinalLabValuesData["title"] as List; - _isSearching = false; - _searchText = ""; - searchOperation(""); - }); - } - else if(_tabController.index == 3){ - // print(_tabController.index); - setState(() { - _handleSearchEnd(); - if(sweatLabValuesData["title"] != null) - _list = sweatLabValuesData["title"] as List; - _isSearching = false; - _searchText = ""; - searchOperation(""); - }); - } - }); - }); - categorizebloodLabValues(); - _isSearching = false; - } - - @override - void dispose() { - _tabController.dispose(); - super.dispose(); - } - - Widget listTiles() { - return Container( // _tabController.index == 0 - child: ListView( - scrollDirection: Axis.vertical, - children: [ - Container( - child: searchresult.length != 0 || _controller.text.isNotEmpty - ? Column( - children: [ - for(int j = 0; j<_list.length;j++) - for(int i = 0; i[ - Color(0xff7F1AF1), - Color(0xff482384) - ]) - ), - ), - title: appBarTitle, actions: [ - new IconButton( - icon: icon, - onPressed: () { - setState(() { - if (this.icon.icon == Icons.search) { - this.icon = new Icon( - Icons.close, - color: Colors.white, - ); - this.appBarTitle = new TextField( - controller: _controller, - style: new TextStyle( - color: Colors.white, - ), - decoration: new InputDecoration( - prefixIcon: new Icon(Icons.search, color: Colors.white), - hintText: "Search...", - hintStyle: new TextStyle(color: Colors.white)), - onChanged: searchOperation, - ); - _handleSearchStart(); - } else { - _handleSearchEnd(); - } - }); - }, - ), - ]), - body: SingleChildScrollView( - child: Column( - children: [ - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - Container( - padding: EdgeInsets.only(top: (MediaQuery.of(context).size.height) * (30 / 926), bottom: (MediaQuery.of(context).size.height) * (20 / 926), - left: (MediaQuery.of(context).size.width) * (20 / 428)), - alignment: Alignment.center, - child: Text( - "Lab Values", - style: TextStyle( - color: Color(0xff232323), - fontFamily: 'Brandon-bld', - fontSize: (MediaQuery.of(context).size.height) * - (20 / 926), //38, - ), - ), - ), - Row( - children: [ - Transform.scale( - scale: 1, - child: Container( - height: (MediaQuery.of(context).size.height) *(15/926), - child: Switch( - value: _siValues, - onChanged: (value) { - setState(() { - _siValues = value; - // print(_siValues); - }); - }, - activeColor: Color(0xff3F2668), - ), - ), - ), - Container( - child: Text("Si Reference Intervals", - style: TextStyle( - color: Color(0xff483A3A), - fontFamily: 'Brandon-med', - fontSize: (MediaQuery.of(context).size.height) *(15/926) - ), - ), - ), - SizedBox(width: (MediaQuery.of(context).size.width) *(10/428)), - - ], - ), - ], - ), - Container( - margin: EdgeInsets.only(left: (MediaQuery.of(context).size.width) * (15 / 428), right: (MediaQuery.of(context).size.width) * (15 / 428)), - // padding: EdgeInsets.only(left: (MediaQuery.of(context).size.width) * (10 / 428), right: (MediaQuery.of(context).size.width) * (10 / 428)), - decoration: BoxDecoration( - border: Border(bottom: BorderSide(color: Colors.grey, width: 2)) - ), - child: TabBar( - padding: EdgeInsets.zero, - indicatorPadding: EdgeInsets.zero, - labelPadding: EdgeInsets.zero, - controller: _tabController, - tabs: [ - Tab(icon: Text( - "Blood", - style: TextStyle( - color: Color(0xff232323), - fontFamily: 'Brandon-bld', - fontSize: (MediaQuery.of(context).size.height) * - (15 / 926), //38, - ), - ),), - Tab(icon: Text( - "Hematologic", - style: TextStyle( - color: Color(0xff232323), - fontFamily: 'Brandon-bld', - fontSize: (MediaQuery.of(context).size.height) * - (15 / 926), //38, - ), - ),), - Tab(icon: Text( - "Cerebrospinal", - style: TextStyle( - color: Color(0xff232323), - fontFamily: 'Brandon-bld', - fontSize: (MediaQuery.of(context).size.height) * - (15 / 926), //38, - ), - ),), - Tab(icon: Text( - "Sweat", - style: TextStyle( - color: Color(0xff232323), - fontFamily: 'Brandon-bld', - fontSize: (MediaQuery.of(context).size.height) * - (15 / 926), //38, - ), - ),), - ], - ), - ), - SizedBox(height: (MediaQuery.of(context).size.height) * - (8 / 926),), - Row( - mainAxisAlignment: MainAxisAlignment.start, - children: [ - Container( - width: ((MediaQuery.of(context).size.width)*(2/3)), - padding: EdgeInsets.only(left: (MediaQuery.of(context).size.width) * - (20 / 428)), - child: Text( - _tabController.index == 0 ? "Blood, Plasma, Serum" : - _tabController.index == 1 ? "Serum" : - _tabController.index == 2 ? "Cerebrospinal Fluid" : - _tabController.index == 3 ? "Urine" : "Urine", - style: TextStyle( - color: Color(0xff232323), - fontFamily: 'Brandon-bld', - fontSize: (MediaQuery.of(context).size.height) * - (15 / 926), //38, - ), - ), - ), - Container( - padding: EdgeInsets.only(right: (MediaQuery.of(context).size.width) * - (20 / 428)), - child: Text( - _siValues == true ? "Si Reference Interval" : "Reference Range", - style: TextStyle( - color: Color(0xff232323), - fontFamily: 'Brandon-bld', - fontSize: (MediaQuery.of(context).size.height) * - (15 / 926), //38, - ), - ), - ), - ], - ), - Container( - padding: EdgeInsets.only(left: (MediaQuery.of(context).size.width) * (15 / 428), right: (MediaQuery.of(context).size.width) * (15 / 428)), - child: Divider(thickness: 0.4, color: Colors.grey,)), - Container( - padding: EdgeInsets.only(left: (MediaQuery.of(context).size.width) * (15 / 428), right: (MediaQuery.of(context).size.width) * (15 / 428)), - height: MediaQuery.of(context).size.height * 0.6, - child: TabBarView( - controller: _tabController, - children: [ - //Tab 1 - listTiles(), - //Tab 2 - listTiles(), - //Tab 3 - listTiles(), - //Tab 4 - listTiles(), - ], - ), - ), - ], - ), - )), - ); - } - - - void _handleSearchStart() { - setState(() { - _isSearching = true; - }); - } - - void _handleSearchEnd() { - setState(() { - this.icon = new Icon( - Icons.search, - color: Colors.white, - ); - this.appBarTitle = new Text( - "Search Values", - style: new TextStyle(color: Colors.white), - ); - _isSearching = false; - _controller.clear(); - }); - } - - void searchOperation(String searchText) { - searchresult.clear(); - if (_isSearching != null) { - for (int i = 0; i < _list.length; i++) { - String data = _list[i]; - if (data.toLowerCase().contains(searchText.toLowerCase())) { - searchresult.add(data); - } - } - } - } -} +import 'package:flutter/material.dart'; + +class SearchListExample extends StatefulWidget { + @override + _SearchListExampleState createState() => new _SearchListExampleState(); +} + +class _SearchListExampleState extends State with SingleTickerProviderStateMixin { + + final bloodLabValues = [ + {"title": 'Alanine aminotransferase (ALT), serum', "value": '8-40 U/L', "siValue": '8-40 U/L', + "subtitle": [{"title": '', "value": ''}] + }, + {"title": 'Alkaline phosphatase, serum ', "value": '', "siValue": '', + "subtitle": [ + {"title": 'Male', "value": '30-100 U/L', "siValue": '30-100 U/L'}, + {"title": 'Female', "value": '45-115 U/L', "siValue": '45-115 U/L'}, + ] + }, + {"title": 'Amylase, serum', "value": '25-125 U/L', "subtitle": [], "siValue": '25-125 U/L' }, + {"title": 'Aspartate aminotransferase (AST), serum', "value": '8-40 U/L', "subtitle": [], "siValue": '8-40 U/L'}, + {"title": 'Bilirubin, serum (adult)' , "value": '', "siValue": '', + "subtitle": [ + {"title": 'Total', "value": '0.1-1.0 mg/dL', "siValue": '2-17 μmol/L'}, + {"title": 'Direct', "value": '0.0-0.3 mg/dL', "siValue": '0.0-0.05 μmol/L'}, + ] + }, + {"title": 'Calcium, serum (total)', "value": '8.4-10.2 mg/dL', "subtitle": [], "siValue": '2.1-2.8 mmol/L'}, + {"title": 'Cholesterol, serum' , "value": '', "siValue": '', + "subtitle": [ + {"title": 'Total', "value": '150-240 mg/dL', "siValue": '3.9-6.2 mmol/L'}, + {"title": 'HDL', "value": '0-70 mg/dL', "siValue": '0.8-1.8 mmol/L'}, + {"title": 'LDL', "value": '<160 mg/dL', "siValue": '<4.2 mmol/L'}, + ] + }, + {"title": 'Cortisol, serum', "value": '', "siValue": '', + "subtitle": [ + {"title": '0800 h', "value": '5-23 μg/dL', "siValue": '138-635 nmol/L'}, + {"title": '1600 h', "value": '3-15 μg/dL', "siValue": '82-413 nmol/L'}, + {"title": '2000 h', "value": '50% of 0800 h', "siValue": 'Fraction of 0800 h: ≤0.50'}, + ] + }, + {"title": 'Creatine kinase, serum', "value": '', "siValue": 'L', + "subtitle": [ + {"title": 'Male', "value": '25-90 U/L', "siValue": '25-90 U/L'}, + {"title": 'Female', "value": '10-70 U/L', "siValue": '10-70 U/L'}, + ] + }, + {"title": 'Creatinine, serum', "value": '0.6-1.2 mg/dL', "subtitle": [], "siValue": '53-106 μmol/L'}, + {"title": 'Electrolytes, serum', "value": '', "siValue": '', + "subtitle": [ + {"title": 'Sodium (Na+)', "value": '136-145 mEq/L', "siValue": '136-145 mEq/L'}, + {"title": 'Potassium (K+)', "value": '3.5-5.0 mEq/L', "siValue": '95-105 mmol/L'}, + {"title": 'Chloride (Cl-)', "value": '95-105 mEq/L', "siValue": '3.5-5.0 mmol/L'}, + {"title": 'Bicarbonate (HCO3-)', "value": '22-28 mEq/L', "siValue": '22-28 mEq/L'}, + {"title": 'Magnesium (Mg2+)', "value": '1.5-2.0 mEq/L', "siValue": '0.75-1.0 mmol/L'}, + ] + }, + {"title": 'Estriol, total, serum (in pregnancy)', "value": '', "siValue": '', + "subtitle": [ + {"title": '24-28 wks', "value": '30-170 ng/mL', "siValue": '104-590 nmol/L'}, + {"title": '28-32 wks', "value": '40-220 ng/mL', "siValue": '140-760 nmol/L'}, + {"title": '32-36 wks', "value": '60-280 ng/mL', "siValue": '208-970 nmol/L'}, + {"title": '36-40 wks', "value": '80-350 ng/mL', "siValue": '280-1210 nmol/L'}, + ] + }, + + {"title": 'Ferritin, serum', "value": '', "siValue": '', + "subtitle": [ + {"title": 'Male', "value": '15-200 ng/mL', "siValue": '15-200 ng/mL'}, + {"title": 'Female', "value": '12-150 ng/mL', "siValue": '12-150 ng/mL'}, + ] + }, + {"title": 'Follicle-stimulating hormone, serum/plasma', "value": '', "siValue": '', + "subtitle": [ + {"title": 'Male', "value": '4-25 mIU/mL', "siValue": '4-25 mIU/mL'}, + {"title": 'Female', "value": '', "siValue": ''}, + {"title": 'premenopause', "value": '4-30 mIU/mL', "siValue": '4-30 mIU/mL'}, + {"title": 'midcycle peak', "value": '10-90 mIU/mLL', "siValue": '10-90 mIU/mLL'}, + {"title": 'postmenopause', "value": '40-250 mIU/mL', "siValue": '40-250 mIU/mL'}, + ] + }, + {"title": 'Gases, arterial blood (room air)', "value": '', "siValue": '', + "subtitle": [ + {"title": 'pH', "value": '7.35-7.45', "siValue": '[H+] 36-44 nmol/L'}, + {"title": 'Pco2', "value": '33-45 mm Hg', "siValue": '4.4-5.9 kPa'}, + {"title": 'Po2', "value": '75-105 mm Hg', "siValue": '10.0-14.0 kPa'}, + ] + }, + {"title": 'Glucose, serum', "value": '', "siValue": '', + "subtitle": [ + {"title": 'Fasting', "value": '70-110 mg/dL', "siValue": '3.8-6.1 mmol/L'}, + {"title": '2-h postprandial', "value": '<120 mg/dL', "siValue": '<6.6 mmol/L'}, + ] + }, + {"title": 'Growth hormone- arginine stimulation', "value": '', "siValue": '', + "subtitle": [ + {"title": 'Fasting', "value": '<5 ng/mL', "siValue": '<5 ng/mL'}, + {"title": 'Provocative stimuli', "value": '>7 ng/mL', "siValue": '>7 μg/L'}, + ] + }, + {"title": 'Immunoglobulins, serum', "value": '', "siValue": '', + "subtitle": [ + {"title": 'IgA', "value": '76-390 mg/dL', "siValue": '0.76-3.90 g/L'}, + {"title": 'IgE', "value": '0-380 IU/mL', "siValue": '0-380 kIU/L'}, + {"title": 'IgG', "value": '650-1,500 mg/dL', "siValue": '6.5-15 g/L'}, + {"title": 'IgM', "value": '40-345 mg/dL', "siValue": '0.4-3.45 g/L'}, + ] + }, + {"title": 'Iron', "value": '50-170 μg/dL', "subtitle": [], "siValue": '9-30 μmol/LL'}, + {"title": 'Lactate dehydrogenase, serum', "value": '45-90 U/L (100-250 IU/L)', "siValue": '45-90 U/L (100-250 IU/L)', + "subtitle": [] + }, + {"title": 'Luteinizing hormone, serum/plasma', "value": '', "siValue": '', + "subtitle": [ + {"title": 'Male', "value": '6-23 mIU/mL', "siValue": '6-23 U/L'}, + {"title": 'Female', "value": '', "siValue": ''}, + {"title": 'follicular phase', "value": '5-30 mIU/mL', "siValue": '5-30 U/L'}, + {"title": 'midcycle', "value": '75-150 mIU/mL', "siValue": '75-150 U/L'}, + {"title": 'postmenopause', "value": '30-200 mIU/mL', "siValue": '30-200 U/L'}, + ] + }, + {"title": 'Osmolality, serum', "value": '275-295 mOsmol/kg H2O', "siValue": '275-295 mOsmol/kg H2O', + "subtitle": [] + }, + {"title": 'Parathyroid hormone, serum, N-terminal', "value": '10-65 pg/mL', "siValue": '10-65 pg/mL', + "subtitle": [] + }, + {"title": 'Phosphate (alkaline), serum (p-NPP at 30° C)', "value": '20-70 U/L', "siValue": '20-70 U/L', + "subtitle": [] + }, + {"title": 'Phosphorus (inorganic), serum', "value": '3.0-4.5 mg/dL', "siValue": '1.0-1.5 mmol/L', + "subtitle": [] + }, + + {"title": 'Prolactin, serum (hPRL) ', "value": '<20 ng/mL', "siValue": '<20 ng/mL', + "subtitle": [] + }, + {"title": 'Proteins, serum', "value": '', "siValue": '', + "subtitle": [ + {"title": 'Total (recumbent)', "value": '6.0-7.8 g/dL', "siValue": '60-78 g/L'}, + {"title": 'Albumin', "value": '3.5-5.5 g/dL', "siValue": '35-55 g/L'}, + {"title": 'Globulin', "value": '2.3-3.5 g/dL', "siValue": '23-35 g/L'}, + ] + }, + {"title": 'Thyroid-stimulating hormone (TSH), serum', "value": '0.5-5.0 μU/mL', "siValue": '0.5-5.0 μU/mL', + "subtitle": [] + }, + {"title": 'Thyroidal iodine (123I) uptake', "value": '8%-30% of administered dose/24 h', "siValue": '0.08-0.30 fraction of administered dose/24 h', + "subtitle": [] + }, + {"title": 'Thyroxine (T4), serum', "value": '5-12 μg/dL', "siValue": '64-155 nmol/L', + "subtitle": [] + }, + {"title": 'Triglycerides, serum', "value": '35-160 mg/dL', "siValue": '0.4-1.81 mmol/L', + "subtitle": [] + }, + {"title": 'Triiodothyronine (T3), serum (RIA)', "value": '115-190 ng/dL', "siValue": '1.8-2.9 nmol/L', + "subtitle": [] + }, + {"title": 'Triiodothyronine (T3) resin uptake', "value": '25%-35%', "siValue": '0.25-0.35', + "subtitle": [] + }, + {"title": 'Urea nitrogen, serum (BUN)', "value": '7-18 mg/dL', "siValue": '1.2-3.0 mmol/L', + "subtitle": [] + }, + {"title": 'Uric acid, serum', "value": '3.0-8.2 mg/dL', "siValue": '0.18-0.48 mmol/L', + "subtitle": [] + }, + + ]; + final HematologicLabValues = [ + {"title": 'Bleeding time (template)', "value": '2-7 minutes', "siValue": '2-7 minutes', + "subtitle": [] + }, + {"title": 'CD4+ T-lymphocyte count', "value": '>500 mm^3', "siValue": '>500 x 106/L', + "subtitle": [] + }, + {"title": 'Erythrocyte count', "value": '', "siValue": '', + "subtitle": [ + {"title": 'Male', "value": '4.3-5.9 million/mm^3', "siValue": '4.3-5.9 x 10^12/L'}, + {"title": 'Female', "value": '3.5-5.5 million/mm^3', "siValue": '3.5-5.5 x 10^12/L'}, + ] + }, + {"title": 'Erythrocyte sedimentation rate (Westergren)', "value": '', "siValue": '', + "subtitle": [ + {"title": 'Male', "value": '0-15 mm/h', "siValue": '0-15 mm/h'}, + {"title": 'Female', "value": '0-20 mm/h', "siValue": '0-20 mm/h'}, + ] + }, + {"title": 'Hematocrit', "value": '', "siValue": '', + "subtitle": [ + {"title": 'Male', "value": '41%-53%', "siValue": '0.41-0.53'}, + {"title": 'Female', "value": '36%-46%', "siValue": '0.36-0.46'}, + ] + }, + {"title": 'Hemoglobin A1c', "value": '≤6%', "siValue": '≤0.06', + "subtitle": [] + }, + {"title": 'Hemoglobin, blood', "value": '', "siValue": '', + "subtitle": [ + {"title": 'Male', "value": '13.5-17.5 g/dL', "siValue": '2.09-2.71 mmol/L'}, + {"title": 'Female', "value": '12.0-16.0 g/dL', "siValue": '1.86-2.48 mmol/L'}, + ] + }, + {"title": 'Leukocyte count and differential', "value": '', "siValue": '', + "subtitle": [ + {"title": 'Leukocyte count', "value": '4,500-11,000/mm^3', "siValue": '4.5-11.0 x 10^9/L'}, + {"title": 'Neutrophils, segmented', "value": '54%-62%', "siValue": '0.54-0.62'}, + {"title": 'Neutrophils, banded', "value": '3%-5%', "siValue": '0.03-0.05'}, + {"title": 'Eosinophils', "value": '1%-3%', "siValue": '0.01-0.03'}, + {"title": 'Basophils', "value": '0%-0.75%', "siValue": '0-0.0075'}, + {"title": 'Lymphocytes', "value": '25%-33%', "siValue": '0.25-0.33'}, + {"title": 'Monocytes', "value": '3%-7%', "siValue": '0.03-0.07'}, + ] + }, + {"title": 'Mean corpuscular hemoglobin (MCH)', "value": '25.4-34.6 pg/cell', "siValue": '0.39-0.54 fmol/cell', + "subtitle": [] + }, + {"title": 'Mean corpuscular hemoglobin concentration (MCHC)', "value": '31%-36% Hb/cell', "siValue": '4.81-5.58 mmol Hb/L', + "subtitle": [] + }, + {"title": 'Mean corpuscular volume (MCV)', "value": '80-100 μm3', "siValue": '80-100 fL', + "subtitle": [] + }, + {"title": 'Partial thromboplastin time (activated)', "value": '25-40 seconds', "siValue": '25-40 seconds', + "subtitle": [] + }, + {"title": 'Platelet count', "value": '150,000-400,000/mm^3', "siValue": '150-400 x 10^9/L', + "subtitle": [] + }, + {"title": 'Prothrombin time', "value": '11-15 seconds', "siValue": '11-15 seconds', + "subtitle": [] + }, + {"title": 'Reticulocyte count', "value": '0.5%-1.5% of red cells', "siValue": '0.005-0.015 fraction of red cells', + "subtitle": [] + }, + {"title": 'Thrombin time', "value": '<2 seconds deviation from control', "siValue": '<2 seconds deviation from control', + "subtitle": [] + }, + {"title": 'Volume', "value": '', "siValue": '', + "subtitle": [ + {"title": 'Plasma', "value": '', "siValue": ''}, + {"title": 'Male', "value": '25-43 mL/kg', "siValue": '0.005-0.015 fraction of red cells' }, + {"title": 'Female', "value": '28-45 mL/kg', "siValue": '0.028-0.045 L/kg'}, + {"title": 'Red cell', "value": '', "siValue": ''}, + {"title": 'Male', "value": '20-36 mL/kg', "siValue": '0.020-0.036 L/kg'}, + {"title": 'Female', "value": '19-31 mL/kg', "siValue": '0.019-0.031 L/kg'}, + ] + }, + + + ]; + final CerebrospinalLabValues = [ + {"title": 'Cell count', "value": '0-5/mm^3', "siValue": '0-5 x 10^6/L', + "subtitle": [] + }, + {"title": 'Chloride', "value": '118-132 mEq/L', "siValue": '118-132 mmol/L', + "subtitle": [] + }, + {"title": 'Gamma globulin', "value": '3%-12% of total proteins', "siValue": '0.03-0.12 of total proteins', + "subtitle": [] + }, + {"title": 'Glucose', "value": '40-70 mg/dL', "siValue": '2.2-3.9 mmol/L', + "subtitle": [] + }, + {"title": 'Pressure', "value": '70-180 mm H2O', "siValue": '70-180 mm H2O', + "subtitle": [] + }, + {"title": 'Proteins, total', "value": '<40 mg/dL', "siValue": '<0.40 g/L', + "subtitle": [] + }, + ]; + final sweatLabValues = [ + {"title": 'Calcium', "value": '100-300 mg/24 h', "siValue": '2.5-7.5 mmol/24 h', + "subtitle": [] + }, + {"title": 'Chloride', "value": '1Varies with intake', "siValue": '1Varies with intake', + "subtitle": [] + }, + {"title": 'Creatine clearance', "value": '', "siValue": '', + "subtitle": [ + {"title": 'Male', "value": '97-137 mL/min', "siValue": '1.62-2.29 mL/s'}, + {"title": 'Female', "value": '88-128 mL/min', "siValue": '1.47-2.14 mL/s'}, + ] + }, + {"title": 'Estriol, total (in pregnancy)', "value": '', "siValue": '', + "subtitle": [ + {"title": '30 wks', "value": '6-18 mg/24 h', "siValue": '21-62 μmol/24 h'}, + {"title": '35 wks', "value": '9-28 mg/24 h', "siValue": '31-97 μmol/24 h'}, + {"title": '40 wks', "value": '13-42 mg/24 h', "siValue": '45-146 μmol/24 h'}, + ] + }, + {"title": '17-hydroxycorticosteroids', "value": '', "siValue": '', + "subtitle": [ + {"title": 'Male', "value": '3.0-10.0 mg/24 h', "siValue": '8.2-27.6 μmol/24 h'}, + {"title": 'Female', "value": '2.0-8.0 mg/24 h', "siValue": '5.5-22.0 μmol/24 h'}, + ] + }, + {"title": '17-ketosteroids, total', "value": '', "siValue": '', + "subtitle": [ + {"title": 'Male', "value": '8-20 mg/24 h', "siValue": '28-70 μmol/24 h'}, + {"title": 'Female', "value": '6-15 mg/24 h', "siValue": '21-52 μmol/24 h'}, + ] + }, + {"title": 'Osmolality', "value": '50-1,400 mOsmol/kg H2O', "siValue": '50-1,400 mmol/kg', + "subtitle": [] + }, + {"title": 'Oxalate', "value": '8-40 μg/mL', "siValue": '90-445 μmol/L', + "subtitle": [] + }, + {"title": 'Proteins, total', "value": '<150 mg/24 h', "siValue": '<0.15 g/24 h', + "subtitle": [] + }, + {"title": 'Sodium, total', "value": 'varies with diet', "siValue": 'varies with diet', + "subtitle": [] + }, + {"title": 'Uric acid', "value": 'varies with diet', "siValue": 'varies with diet', + "subtitle": [] + }, + {"title": 'Body Mass Index (Adult)', "value": '19-25 kg/m^2', "siValue": '19-25 kg/m^2', + "subtitle": [] + }, + ]; + + + + Widget appBarTitle = new Text( + "Search Values", + style: new TextStyle(color: Colors.white), + ); + Icon icon = new Icon( + Icons.search, + color: Colors.white, + ); + final globalKey = new GlobalKey(); + final TextEditingController _controller = new TextEditingController(); + List _list = []; // = ["Indian rupee", "United States dollar", "Australian dollar", "Euro", "British pound", "Yemeni rial", "Japanese yen", "Hong Kong dollar"]; + bool _isSearching = false; + String _searchText = ""; + List searchresult = []; + bool _siValues = false; + late TabController _tabController; + + var bloodLabValuesData = { + "title" : [], + "value" : [], + "siValue" : [] + }; + var HematologicLabValuesData = { + "title" : [], + "value" : [], + "siValue" : [] + }; + var CerebrospinalLabValuesData = { + "title" : [], + "value" : [], + "siValue" : [] + }; + var sweatLabValuesData = { + "title" : [], + "value" : [], + "siValue" : [] + }; + + var LabValuesList = { + "title" : [], + "value" : [], + "siValue" : [] + }; + + categorizebloodLabValues() { + for(int i = 0; i; + }); + // print(CerebrospinalLabValuesData["title"]); + // print(_list); + } + + _SearchListExampleState() { + _controller.addListener(() { + if (_controller.text.isEmpty) { + setState(() { + _isSearching = false; + _searchText = ""; + }); + } else { + setState(() { + _isSearching = true; + _searchText = _controller.text; + }); + } + }); + } + + @override + void initState() { + super.initState(); + _tabController = TabController(vsync: this, length: 4) + ..addListener(() { + setState(() { + if(_tabController.index == 0){ + // print(_tabController.index); + setState(() { + _handleSearchEnd(); + if(bloodLabValuesData["title"] != null) + _list = bloodLabValuesData["title"] as List; + _isSearching = false; + _searchText = ""; + searchOperation(""); + }); + } + else if(_tabController.index == 1){ + // print(_tabController.index); + setState(() { + _handleSearchEnd(); + if(HematologicLabValuesData["title"] != null) + _list = HematologicLabValuesData["title"] as List; + _isSearching = false; + _searchText = ""; + searchOperation(""); + }); + } + else if(_tabController.index == 2){ + // print(_tabController.index); + setState(() { + _handleSearchEnd(); + if(CerebrospinalLabValuesData["title"] != null) + _list = CerebrospinalLabValuesData["title"] as List; + _isSearching = false; + _searchText = ""; + searchOperation(""); + }); + } + else if(_tabController.index == 3){ + // print(_tabController.index); + setState(() { + _handleSearchEnd(); + if(sweatLabValuesData["title"] != null) + _list = sweatLabValuesData["title"] as List; + _isSearching = false; + _searchText = ""; + searchOperation(""); + }); + } + }); + }); + categorizebloodLabValues(); + _isSearching = false; + } + + @override + void dispose() { + _tabController.dispose(); + super.dispose(); + } + + Widget listTiles() { + return Container( // _tabController.index == 0 + child: ListView( + scrollDirection: Axis.vertical, + children: [ + Container( + child: searchresult.length != 0 || _controller.text.isNotEmpty + ? Column( + children: [ + for(int j = 0; j<_list.length;j++) + for(int i = 0; i[ + Color(0xff7F1AF1), + Color(0xff482384) + ]) + ), + ), + title: appBarTitle, actions: [ + new IconButton( + icon: icon, + onPressed: () { + setState(() { + if (this.icon.icon == Icons.search) { + this.icon = new Icon( + Icons.close, + color: Colors.white, + ); + this.appBarTitle = new TextField( + controller: _controller, + style: new TextStyle( + color: Colors.white, + ), + decoration: new InputDecoration( + prefixIcon: new Icon(Icons.search, color: Colors.white), + hintText: "Search...", + hintStyle: new TextStyle(color: Colors.white)), + onChanged: searchOperation, + ); + _handleSearchStart(); + } else { + _handleSearchEnd(); + } + }); + }, + ), + ]), + body: SingleChildScrollView( + child: Column( + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Container( + padding: EdgeInsets.only(top: (MediaQuery.of(context).size.height) * (30 / 926), bottom: (MediaQuery.of(context).size.height) * (20 / 926), + left: (MediaQuery.of(context).size.width) * (20 / 428)), + alignment: Alignment.center, + child: Text( + "Lab Values", + style: TextStyle( + color: Color(0xff232323), + fontFamily: 'Brandon-bld', + fontSize: (MediaQuery.of(context).size.height) * + (20 / 926), //38, + ), + ), + ), + Row( + children: [ + Transform.scale( + scale: 1, + child: Container( + height: (MediaQuery.of(context).size.height) *(15/926), + child: Switch( + value: _siValues, + onChanged: (value) { + setState(() { + _siValues = value; + // print(_siValues); + }); + }, + activeColor: Color(0xff3F2668), + ), + ), + ), + Container( + child: Text("Si Reference Intervals", + style: TextStyle( + color: Color(0xff483A3A), + fontFamily: 'Brandon-med', + fontSize: (MediaQuery.of(context).size.height) *(15/926) + ), + ), + ), + SizedBox(width: (MediaQuery.of(context).size.width) *(10/428)), + + ], + ), + ], + ), + Container( + margin: EdgeInsets.only(left: (MediaQuery.of(context).size.width) * (15 / 428), right: (MediaQuery.of(context).size.width) * (15 / 428)), + // padding: EdgeInsets.only(left: (MediaQuery.of(context).size.width) * (10 / 428), right: (MediaQuery.of(context).size.width) * (10 / 428)), + decoration: BoxDecoration( + border: Border(bottom: BorderSide(color: Colors.grey, width: 2)) + ), + child: TabBar( + padding: EdgeInsets.zero, + indicatorPadding: EdgeInsets.zero, + labelPadding: EdgeInsets.zero, + controller: _tabController, + tabs: [ + Tab(icon: Text( + "Blood", + style: TextStyle( + color: Color(0xff232323), + fontFamily: 'Brandon-bld', + fontSize: (MediaQuery.of(context).size.height) * + (15 / 926), //38, + ), + ),), + Tab(icon: Text( + "Hematologic", + style: TextStyle( + color: Color(0xff232323), + fontFamily: 'Brandon-bld', + fontSize: (MediaQuery.of(context).size.height) * + (15 / 926), //38, + ), + ),), + Tab(icon: Text( + "Cerebrospinal", + style: TextStyle( + color: Color(0xff232323), + fontFamily: 'Brandon-bld', + fontSize: (MediaQuery.of(context).size.height) * + (15 / 926), //38, + ), + ),), + Tab(icon: Text( + "Sweat", + style: TextStyle( + color: Color(0xff232323), + fontFamily: 'Brandon-bld', + fontSize: (MediaQuery.of(context).size.height) * + (15 / 926), //38, + ), + ),), + ], + ), + ), + SizedBox(height: (MediaQuery.of(context).size.height) * + (8 / 926),), + Row( + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Container( + width: ((MediaQuery.of(context).size.width)*(2/3)), + padding: EdgeInsets.only(left: (MediaQuery.of(context).size.width) * + (20 / 428)), + child: Text( + _tabController.index == 0 ? "Blood, Plasma, Serum" : + _tabController.index == 1 ? "Serum" : + _tabController.index == 2 ? "Cerebrospinal Fluid" : + _tabController.index == 3 ? "Urine" : "Urine", + style: TextStyle( + color: Color(0xff232323), + fontFamily: 'Brandon-bld', + fontSize: (MediaQuery.of(context).size.height) * + (15 / 926), //38, + ), + ), + ), + Container( + padding: EdgeInsets.only(right: (MediaQuery.of(context).size.width) * + (20 / 428)), + child: Text( + _siValues == true ? "Si Reference Interval" : "Reference Range", + style: TextStyle( + color: Color(0xff232323), + fontFamily: 'Brandon-bld', + fontSize: (MediaQuery.of(context).size.height) * + (15 / 926), //38, + ), + ), + ), + ], + ), + Container( + padding: EdgeInsets.only(left: (MediaQuery.of(context).size.width) * (15 / 428), right: (MediaQuery.of(context).size.width) * (15 / 428)), + child: Divider(thickness: 0.4, color: Colors.grey,)), + Container( + padding: EdgeInsets.only(left: (MediaQuery.of(context).size.width) * (15 / 428), right: (MediaQuery.of(context).size.width) * (15 / 428)), + height: MediaQuery.of(context).size.height * 0.6, + child: TabBarView( + controller: _tabController, + children: [ + //Tab 1 + listTiles(), + //Tab 2 + listTiles(), + //Tab 3 + listTiles(), + //Tab 4 + listTiles(), + ], + ), + ), + ], + ), + )), + ); + } + + + void _handleSearchStart() { + setState(() { + _isSearching = true; + }); + } + + void _handleSearchEnd() { + setState(() { + this.icon = new Icon( + Icons.search, + color: Colors.white, + ); + this.appBarTitle = new Text( + "Search Values", + style: new TextStyle(color: Colors.white), + ); + _isSearching = false; + _controller.clear(); + }); + } + + void searchOperation(String searchText) { + searchresult.clear(); + if (_isSearching != null) { + for (int i = 0; i < _list.length; i++) { + String data = _list[i]; + if (data.toLowerCase().contains(searchText.toLowerCase())) { + searchresult.add(data); + } + } + } + } +} diff --git a/lib/screens/home.dart b/lib/screens/home.dart index 5f0caf9..503f884 100644 --- a/lib/screens/home.dart +++ b/lib/screens/home.dart @@ -17,7 +17,45 @@ class Home extends StatefulWidget { _HomeState createState() => _HomeState(); } -class _HomeState extends State { +class _HomeState extends State with WidgetsBindingObserver{ + + AppLifecycleState? _lastLifecycleState; + + @override + void initState() { + super.initState(); + WidgetsBinding.instance!.addObserver(this); + } + + @override + void dispose() { + WidgetsBinding.instance!.removeObserver(this); + super.dispose(); + } + + @override + void didChangeAppLifecycleState(AppLifecycleState state) async { + super.didChangeAppLifecycleState(state); + + // if(state == AppLifecycleState.detached){ + // + // } + + final isBackground = state == AppLifecycleState.paused; + final isClosed = state == AppLifecycleState.detached; + if(isBackground) { + print("xD in Background"); + + + + } + if(isClosed) { + print("xD Closed"); + + + } + } + @override Widget build(BuildContext context) { return WillPopScope( @@ -69,57 +107,61 @@ class _HomeState extends State { ), ], ), - body: TextButton( - onPressed: () async { - final result = Navigator.push( - context, - MaterialPageRoute(builder: (context) => SearchListExample()), - ); - - - // SharedPreferences prefs = await SharedPreferences.getInstance(); - // var quizID = prefs.getInt("quizId"); - // var _token = prefs.getString('token')!; - // // print(quizID); - // final String apiUrlGenerateQuiz = "https://demo.pookidevs.com/quiz/solver/saveQuiz"; - // http.post(Uri.parse(apiUrlGenerateQuiz), headers: { - // 'Content-type': 'application/json; charset=UTF-8', 'Authorization' : _token.toString(), - // }, body: json.encode( - // { - // "data": - // { - // "quiz" : { - // "quizId": 387145, - // "quizTitle": "First Quiz", // "Custom Quiz" + Date.now() - // "quizDate": " ", // "Custom Quiz" - // "quizScore": "20", // total correct - // "quizTotalQuestions": "20", - // "quizStatus": "completed", // "completed", "suspended" - // "quizQuestions": "[15,18]", // Question IDs - // "quizMode":"tutor", // "tutor", "exam" - // "quizTime": "900", // total quiz time in seconds - // "isTimed": false, // bool true or false - // "omittedQuestions": [], // Don't send anything here - // "SelectedOptionsArray": [] // Don't send anything here - // }, - // "userId": 7 - // } - // }) - // ).then((response) { - // print(jsonDecode(response.body).toString()); - // if((response.statusCode == 200) & (json.decode(response.body).toString().substring(0,14) != "{status: false")) { - // - // } - // else { // Token Invalid - // - // } - // } - // ); - - - }, - child: Text("Search Bar"), - ), + // body: TextButton( + // onPressed: () async { + // // final result = Navigator.push( + // // context, + // // MaterialPageRoute(builder: (context) => SearchListExample()), + // // ); + // + // + // SharedPreferences prefs = await SharedPreferences.getInstance(); + // var quizID = prefs.getInt("quizId"); + // var _token = prefs.getString('token')!; + // // print(quizID); + // final String apiUrlGenerateQuiz = "https://demo.pookidevs.com/quiz/solver/saveQuiz"; + // await http.post(Uri.parse(apiUrlGenerateQuiz), headers: { + // 'Content-type': 'application/json; charset=UTF-8', 'Authorization' : _token.toString(), + // }, body: json.encode( + // { + // "data": + // { + // "quiz" : { + // "quizId": 387155.toString(), + // "quizTitle": "First quiz", + // "quizDate": DateTime.now().toString(), + // "quizScore": "2", + // "quizTotalQuestions": "5", + // "quizStatus": "Completed", + // "quizQuestions": "[15, 18, 91, 20, 22]", + // "quizMode": "tutor", + // "quizTime": "900", + // "isTimed": false, + // "omittedQuestions": [], + // "SelectedOptionsArray": [] + // }, + // "userId": 7.toString() + // } + // }) + // ).then((response) { + // print(jsonDecode(response.body).toString()); + // if((response.statusCode == 200) & (json.decode(response.body).toString().substring(0,14) != "{status: false")) { + // + // } + // else { // Token Invalid + // final result = Navigator.pushAndRemoveUntil( + // context, + // MaterialPageRoute(builder: (BuildContext context) => const Login(fromWhere:"Home")), + // ModalRoute.withName('/'), + // ); + // } + // } + // ); + // + // + // }, + // child: Text("Search Bar"), + // ), ), ); } From 4b1e140493d8418ba8db05a15ce603c27a0f61ad Mon Sep 17 00:00:00 2001 From: TheYoungWolf <68595463+TheYoungWolf-Productions@users.noreply.github.com> Date: Sat, 30 Apr 2022 05:15:19 -0700 Subject: [PATCH 17/23] Delete pubspec.yaml --- pubspec.yaml | 118 --------------------------------------------------- 1 file changed, 118 deletions(-) delete mode 100644 pubspec.yaml diff --git a/pubspec.yaml b/pubspec.yaml deleted file mode 100644 index 6cebda2..0000000 --- a/pubspec.yaml +++ /dev/null @@ -1,118 +0,0 @@ -name: testify -description: A new Flutter project. - -# The following line prevents the package from being accidentally published to -# pub.dev using `flutter pub publish`. This is preferred for private packages. -publish_to: 'none' # Remove this line if you wish to publish to pub.dev - -# The following defines the version and build number for your application. -# A version number is three numbers separated by dots, like 1.2.43 -# followed by an optional build number separated by a +. -# Both the version and the builder number may be overridden in flutter -# build by specifying --build-name and --build-number, respectively. -# In Android, build-name is used as versionName while build-number used as versionCode. -# Read more about Android versioning at https://developer.android.com/studio/publish/versioning -# In iOS, build-name is used as CFBundleShortVersionString while build-number used as CFBundleVersion. -# Read more about iOS versioning at -# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html -version: 1.0.0+1 - -environment: - sdk: ">=2.12.0 <3.0.0" - -# Dependencies specify other packages that your package needs in order to work. -# To automatically upgrade your package dependencies to the latest versions -# consider running `flutter pub upgrade --major-versions`. Alternatively, -# dependencies can be manually updated by changing the version numbers below to -# the latest version available on pub.dev. To see which dependencies have newer -# versions available, run `flutter pub outdated`. -dependencies: - flutter: - sdk: flutter - - - # The following adds the Cupertino Icons font to your application. - # Use with the CupertinoIcons class for iOS style icons. - cupertino_icons: ^1.0.2 - flutter_svg: ^1.0.2 - http: ^0.13.4 - path_provider: ^2.0.8 - shared_preferences: ^2.0.12 - flutter_countdown_timer: ^4.1.0 - math_expressions: ^2.0.0 - - -dev_dependencies: - flutter_test: - sdk: flutter - - # The "flutter_lints" package below contains a set of recommended lints to - # encourage good coding practices. The lint set provided by the package is - # activated in the `analysis_options.yaml` file located at the root of your - # package. See that file for information about deactivating specific lint - # rules and activating additional ones. - flutter_lints: ^1.0.0 - -# For information on the generic Dart part of this file, see the -# following page: https://dart.dev/tools/pub/pubspec - -# The following section is specific to Flutter. -flutter: - - # The following line ensures that the Material Icons font is - # included with your application, so that you can use the icons in - # the material Icons class. - uses-material-design: true - - # To add assets to your application, add an assets section, like this: - # assets: - # - images/a_dot_burr.jpeg - # - images/a_dot_ham.jpeg - assets: - - assets/Images/login_topLeftBubble_1.png - - assets/Images/login.svg - - assets/Images/login_bottomRight.svg - - assets/Images/login_bottomRight_png.png - - assets/Images/create_quiz.svg - - assets/Images/logout.svg - - assets/Images/lab.svg - - assets/Images/zoom.svg - - assets/Images/calculator.svg - - assets/Images/notes.svg - - assets/Images/testResults.svg - - assets/Images/testAnalysis.svg - - assets/Images/prevQuiz.svg - - fonts: - - family: Brandon-bld - fonts: - - asset: assets/Fonts/Brandon_bld.otf - - family: Brandon-med - fonts: - - asset: assets/Fonts/Brandon_med.otf - - # An image asset can refer to one or more resolution-specific "variants", see - # https://flutter.dev/assets-and-images/#resolution-aware. - - # For details regarding adding assets from package dependencies, see - # https://flutter.dev/assets-and-images/#from-packages - - # To add custom fonts to your application, add a fonts section here, - # in this "flutter" section. Each entry in this list should have a - # "family" key with the font family name, and a "fonts" key with a - # list giving the asset and other descriptors for the font. For - # example: - # fonts: - # - family: Schyler - # fonts: - # - asset: fonts/Schyler-Regular.ttf - # - asset: fonts/Schyler-Italic.ttf - # style: italic - # - family: Trajan Pro - # fonts: - # - asset: fonts/TrajanPro.ttf - # - asset: fonts/TrajanPro_Bold.ttf - # weight: 700 - # - # For details regarding fonts from package dependencies, - # see https://flutter.dev/custom-fonts/#from-packages From e4761930e1cba46567bf06748e511e481bdeaa32 Mon Sep 17 00:00:00 2001 From: TheYoungWolf <68595463+TheYoungWolf-Productions@users.noreply.github.com> Date: Sat, 30 Apr 2022 17:15:47 +0500 Subject: [PATCH 18/23] Add files via upload --- pubspec.yaml | 120 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 120 insertions(+) create mode 100644 pubspec.yaml diff --git a/pubspec.yaml b/pubspec.yaml new file mode 100644 index 0000000..b7130cf --- /dev/null +++ b/pubspec.yaml @@ -0,0 +1,120 @@ +name: testify +description: A new Flutter project. + +# The following line prevents the package from being accidentally published to +# pub.dev using `flutter pub publish`. This is preferred for private packages. +publish_to: 'none' # Remove this line if you wish to publish to pub.dev + +# The following defines the version and build number for your application. +# A version number is three numbers separated by dots, like 1.2.43 +# followed by an optional build number separated by a +. +# Both the version and the builder number may be overridden in flutter +# build by specifying --build-name and --build-number, respectively. +# In Android, build-name is used as versionName while build-number used as versionCode. +# Read more about Android versioning at https://developer.android.com/studio/publish/versioning +# In iOS, build-name is used as CFBundleShortVersionString while build-number used as CFBundleVersion. +# Read more about iOS versioning at +# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html +version: 1.0.0+1 + +environment: + sdk: ">=2.12.0 <3.0.0" + +# Dependencies specify other packages that your package needs in order to work. +# To automatically upgrade your package dependencies to the latest versions +# consider running `flutter pub upgrade --major-versions`. Alternatively, +# dependencies can be manually updated by changing the version numbers below to +# the latest version available on pub.dev. To see which dependencies have newer +# versions available, run `flutter pub outdated`. +dependencies: + flutter: + sdk: flutter + + + # The following adds the Cupertino Icons font to your application. + # Use with the CupertinoIcons class for iOS style icons. + cupertino_icons: ^1.0.2 + flutter_svg: ^1.0.2 + http: ^0.13.4 + path_provider: ^2.0.8 + shared_preferences: ^2.0.12 + flutter_countdown_timer: ^4.1.0 + math_expressions: ^2.0.0 + provider: ^6.0.2 + + +dev_dependencies: + flutter_test: + sdk: flutter + + # The "flutter_lints" package below contains a set of recommended lints to + # encourage good coding practices. The lint set provided by the package is + # activated in the `analysis_options.yaml` file located at the root of your + # package. See that file for information about deactivating specific lint + # rules and activating additional ones. + flutter_lints: ^1.0.0 + +# For information on the generic Dart part of this file, see the +# following page: https://dart.dev/tools/pub/pubspec + +# The following section is specific to Flutter. +flutter: + + # The following line ensures that the Material Icons font is + # included with your application, so that you can use the icons in + # the material Icons class. + uses-material-design: true + + # To add assets to your application, add an assets section, like this: + # assets: + # - images/a_dot_burr.jpeg + # - images/a_dot_ham.jpeg + assets: + - assets/Images/login_topLeftBubble_1.png + - assets/Images/login.svg + - assets/Images/login_bottomRight.svg + - assets/Images/login_bottomRight_png.png + - assets/Images/create_quiz.svg + - assets/Images/logout.svg + - assets/Images/lab.svg + - assets/Images/zoom.svg + - assets/Images/calculator.svg + - assets/Images/notes.svg + - assets/Images/testResults.svg + - assets/Images/testAnalysis.svg + - assets/Images/prevQuiz.svg + - assets/Images/notes_screen.svg + + fonts: + - family: Brandon-bld + fonts: + - asset: assets/Fonts/Brandon_bld.otf + - family: Brandon-med + fonts: + - asset: assets/Fonts/Brandon_med.otf + + # An image asset can refer to one or more resolution-specific "variants", see + # https://flutter.dev/assets-and-images/#resolution-aware. + + # For details regarding adding assets from package dependencies, see + # https://flutter.dev/assets-and-images/#from-packages + + # To add custom fonts to your application, add a fonts section here, + # in this "flutter" section. Each entry in this list should have a + # "family" key with the font family name, and a "fonts" key with a + # list giving the asset and other descriptors for the font. For + # example: + # fonts: + # - family: Schyler + # fonts: + # - asset: fonts/Schyler-Regular.ttf + # - asset: fonts/Schyler-Italic.ttf + # style: italic + # - family: Trajan Pro + # fonts: + # - asset: fonts/TrajanPro.ttf + # - asset: fonts/TrajanPro_Bold.ttf + # weight: 700 + # + # For details regarding fonts from package dependencies, + # see https://flutter.dev/custom-fonts/#from-packages From da54c153b59def07a80e1ae47773facc59a9ae71 Mon Sep 17 00:00:00 2001 From: TheYoungWolf <68595463+TheYoungWolf-Productions@users.noreply.github.com> Date: Sat, 30 Apr 2022 05:16:04 -0700 Subject: [PATCH 19/23] Delete assets directory --- assets/Fonts/Brandon_bld.otf | Bin 89928 -> 0 bytes assets/Fonts/Brandon_med.otf | Bin 89536 -> 0 bytes assets/Images/calculator.svg | 3 -- assets/Images/create_quiz.svg | 57 ---------------------- assets/Images/lab.svg | 3 -- assets/Images/login.svg | 1 - assets/Images/login_bottomRight.svg | 62 ------------------------ assets/Images/login_bottomRight_png.png | Bin 12155 -> 0 bytes assets/Images/login_topLeftBubble_1.png | Bin 51572 -> 0 bytes assets/Images/logout.svg | 3 -- assets/Images/notes.svg | 6 --- assets/Images/prevQuiz.svg | 50 ------------------- assets/Images/testAnalysis.svg | 3 -- assets/Images/testResults.svg | 3 -- assets/Images/zoom.svg | 3 -- 15 files changed, 194 deletions(-) delete mode 100644 assets/Fonts/Brandon_bld.otf delete mode 100644 assets/Fonts/Brandon_med.otf delete mode 100644 assets/Images/calculator.svg delete mode 100644 assets/Images/create_quiz.svg delete mode 100644 assets/Images/lab.svg delete mode 100644 assets/Images/login.svg delete mode 100644 assets/Images/login_bottomRight.svg delete mode 100644 assets/Images/login_bottomRight_png.png delete mode 100644 assets/Images/login_topLeftBubble_1.png delete mode 100644 assets/Images/logout.svg delete mode 100644 assets/Images/notes.svg delete mode 100644 assets/Images/prevQuiz.svg delete mode 100644 assets/Images/testAnalysis.svg delete mode 100644 assets/Images/testResults.svg delete mode 100644 assets/Images/zoom.svg diff --git a/assets/Fonts/Brandon_bld.otf b/assets/Fonts/Brandon_bld.otf deleted file mode 100644 index d70c281048459fdba23cd8ff9f09386df64ed9e5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 89928 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

5@$ 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Ŧbwg0>%6#JaK2y4?7ke&naHGfj*Oi^wK4(Qm}Q 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 Fe*%f=JV^im diff --git a/assets/Fonts/Brandon_med.otf b/assets/Fonts/Brandon_med.otf deleted file mode 100644 index 113eb2459d731ceeaf8ec567f22e11a6e92b3745..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 89536 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 diff --git a/assets/Images/calculator.svg b/assets/Images/calculator.svg deleted file mode 100644 index e988fff..0000000 --- a/assets/Images/calculator.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/assets/Images/create_quiz.svg b/assets/Images/create_quiz.svg deleted file mode 100644 index 1682976..0000000 --- a/assets/Images/create_quiz.svg +++ /dev/null @@ -1,57 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/assets/Images/lab.svg b/assets/Images/lab.svg deleted file mode 100644 index 4e9920a..0000000 --- a/assets/Images/lab.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/assets/Images/login.svg b/assets/Images/login.svg deleted file mode 100644 index cc6272d..0000000 --- a/assets/Images/login.svg +++ /dev/null @@ -1 +0,0 @@ -Login \ No newline at end of file diff --git a/assets/Images/login_bottomRight.svg b/assets/Images/login_bottomRight.svg deleted file mode 100644 index 517f851..0000000 --- a/assets/Images/login_bottomRight.svg +++ /dev/null @@ -1,62 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/assets/Images/login_bottomRight_png.png b/assets/Images/login_bottomRight_png.png deleted file mode 100644 index 38bae3b00f1b705f1738112b01dd3f37c95ef652..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 12155 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 diff --git a/assets/Images/login_topLeftBubble_1.png b/assets/Images/login_topLeftBubble_1.png deleted file mode 100644 index df0f7c9e8c74e4f3fbedd58116c9706495ef7491..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 51572 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 - - diff --git a/assets/Images/notes.svg b/assets/Images/notes.svg deleted file mode 100644 index 00038ae..0000000 --- a/assets/Images/notes.svg +++ /dev/null @@ -1,6 +0,0 @@ - - - - Notes - - diff --git a/assets/Images/prevQuiz.svg b/assets/Images/prevQuiz.svg deleted file mode 100644 index e1ed78f..0000000 --- a/assets/Images/prevQuiz.svg +++ /dev/null @@ -1,50 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/assets/Images/testAnalysis.svg b/assets/Images/testAnalysis.svg deleted file mode 100644 index 4602d15..0000000 --- a/assets/Images/testAnalysis.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/assets/Images/testResults.svg b/assets/Images/testResults.svg deleted file mode 100644 index 8c4e652..0000000 --- a/assets/Images/testResults.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/assets/Images/zoom.svg b/assets/Images/zoom.svg deleted file mode 100644 index 6a928a9..0000000 --- a/assets/Images/zoom.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - From a0971e6ca421d340e79d53c28ff516db82554ce6 Mon Sep 17 00:00:00 2001 From: TheYoungWolf <68595463+TheYoungWolf-Productions@users.noreply.github.com> Date: Sat, 30 Apr 2022 17:16:36 +0500 Subject: [PATCH 20/23] Add files via upload --- assets/Fonts/Brandon_bld.otf | Bin 0 -> 89928 bytes assets/Fonts/Brandon_med.otf | Bin 0 -> 89536 bytes assets/Images/calculator.svg | 3 ++ assets/Images/create_quiz.svg | 57 ++++++++++++++++++++++ assets/Images/lab.svg | 3 ++ assets/Images/login.svg | 1 + assets/Images/login_bottomRight.svg | 62 ++++++++++++++++++++++++ assets/Images/login_bottomRight_png.png | Bin 0 -> 12155 bytes assets/Images/login_topLeftBubble_1.png | Bin 0 -> 51572 bytes assets/Images/logout.svg | 3 ++ assets/Images/notes.svg | 6 +++ assets/Images/notes_screen.svg | 50 +++++++++++++++++++ assets/Images/prevQuiz.svg | 50 +++++++++++++++++++ assets/Images/testAnalysis.svg | 3 ++ assets/Images/testResults.svg | 3 ++ assets/Images/zoom.svg | 3 ++ 16 files changed, 244 insertions(+) create mode 100644 assets/Fonts/Brandon_bld.otf create mode 100644 assets/Fonts/Brandon_med.otf create mode 100644 assets/Images/calculator.svg create mode 100644 assets/Images/create_quiz.svg create mode 100644 assets/Images/lab.svg create mode 100644 assets/Images/login.svg create mode 100644 assets/Images/login_bottomRight.svg create mode 100644 assets/Images/login_bottomRight_png.png create mode 100644 assets/Images/login_topLeftBubble_1.png create mode 100644 assets/Images/logout.svg create mode 100644 assets/Images/notes.svg create mode 100644 assets/Images/notes_screen.svg create mode 100644 assets/Images/prevQuiz.svg create mode 100644 assets/Images/testAnalysis.svg create mode 100644 assets/Images/testResults.svg create mode 100644 assets/Images/zoom.svg diff --git a/assets/Fonts/Brandon_bld.otf b/assets/Fonts/Brandon_bld.otf new file mode 100644 index 0000000000000000000000000000000000000000..d70c281048459fdba23cd8ff9f09386df64ed9e5 GIT binary patch literal 89928 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

5@$ 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Ŧbwg0>%6#JaK2y4?7ke&naHGfj*Oi^wK4(Qm}Q zefOUIvPcFZzKDoqAR;)4m;@q{ft?f=wdZ+XRf4Pkb#3Xc{{8mK`oA~z%}ZJI*KbTO zH=noMtB=OCC~2108K1{|`uJ6=_+iD8N=pKJ1y`-Qw)&E=@ezqN18TLb)2m+F2DKXQ zZ``rTlqR#9q&8XIWD7Ay+cxjqVr7djTKw1|qeWf|Ys;p@7@gR1M$4p@OIw*+m9&;x z>sp7luGe~boAYgo+IqDOYFn>u%eEcco#`<6ft68TbgbI3QK#t6Pjnt4EhI9ePO3-D zhen_|=)f#qC-~VJ);$92y3j*@6pMNiY4qf~r?@@?p5y!H`FAhw=|hik0Qn3AgTP?$ z3K#-j1w+AWU>JCv5x(JI1kV}?MuE{_42T9XAQnsqOTjX*9J~!yfOo)3unMdOYrwl; zKjl6EJ_85Am(<}a@HIFLj)0@!8*mJK3yy>D!1v$>>hdEv0ZxLSz|Yj}7w{`}Jq^-9 z2FL_wz*&$5vcY9!QVM~)dlrHeb9hdO++n{8-cq(Gh#S3 z2gKKuTY^^LE%N`K>kr^ZZ~~kJKY^dYFTh0JW>5f#b0%K`7ElPRzy?IjGdpryD%Bx6 zNPXTh8i2b%V{kW-SnlE41T+J!KqtInXWrZ&!83MYeBm+DJqeq7^4(Khp8?OZm*9Cc z{32Q!!0!XWATSub0)~KB!BFrT7zSSFeQ-D!%QMD-@n8a&2quBa;0-VZya}d)X&?^7 zgBc(JB!Zb>7MKm@fVp5Em`{C@xF&-XumGfjMPM;l0^S1efwka$@Fn&A3VaO?gCpQ5 z_y!yU--6@dJMcaD0Xh5#PJol(C-5_}`UU)oyiS93kO4Bm8E_V4fozb2EY5-RAQxOl zo~7V7;DQYjkcr6R1-wB8-~)VtAMghifez>a<2bO?21{+ki@PKT0V3qd#LJXJ0Pl`4 zwFssb!PFv{S_D&zU}_OeErO{kmpa5J1mw*Kn z0xPhAB49@r6_~NvBI#UPMa zPI%~qhsAh3qT}&*8}!*0uC=Fy?m)ZSi}tq<=|=GTNH7YF24lcj?jHxng9%_Fm;@$+ zH^3C|CYTDQfoSrH0kL2@h~v9>FasojL@*P~0<*y!Fc-`N^C@o<*JO|a7JyW+h_WvR zOTb%TDdk!QmV>v!3h)kC308sCU=4T|yhr-A;C=7`_1*+FgDqeiGT0721RsGNU?qElkC2N;$i*Y%;t_K32)THKTs%T99w8TxP=Gfmz#EwH24*cjU@+GZV8EiQ zf$AU>)Zo4_mj&-&!8=&+4i>zF1@BJxO)8yi5a`7~|c$!>1O)j1$7f+K*kHrUV>p&aYqW1LvJJ28hfWJ3^ z&0q`I!}oi^KJY2n&pijgXW$@spIl1Fh3L7+zCH7v9Y7~??Toi^_qQDIJ0E_VrN^ox)cTI5j(oJyJ1b0nv*93P>aMuKPO>ox)cTI3NAMWPE-F&$z`8MO)91y7u{^rBq zeE9|XWW53YOQz=|zf8+GKx-v0!Rvf@oe!_`;dMT|&WG3e@H!t}=gYrx-#Ks|n5e56 z6o89>__T1`0mmJ1+yTcOaNGgM9nuz9S%eqP#ruAU=M9FLr(tF~%uL7gro+rUn0X3j zT481(%q)bNR+wppnb|Ni9cE_3%xsvM1v7JDW)`0K0?aIcnHhNETs(0uo;VjzoQo&U z#S`b^iF5J9xp?ASJaI0b_!m6!FL>Dx@tnbU&R{%eFrG6Q_MV2lr(y4D*n1lGo`$`r zVee_!dm8qhhP|g@?`hb38uq5c-gMZT4tvvKZ#wKv$8)CRIn!ZpI_yn{z3H$w9rmWf z-gMZT4tvvK?Qww2gAxyQx)IykQg{fAUYK5s*m@3{3vSDgA zOwER=*)TO5rl!NxbeNhBQ`2E;I!sN6sp&8^9j2zk)O47d4pXyXYBo&GhN)RFH4CO@ z!PG36ngvsHVQMZ+&4sDCFf|*dX5nSC@UmHW*(|(l7G5?BFPnvz&BDuO;bpV%vKL_L z1(+(LxL$y%1u(S$rWU}|0+^ZsQ!`*{223r4sd+Fp52oh9)I6A)2Sbm+&|`96So9KY zdOxoHxxP#vZvc3U^3Zz0*gP1U2V?VKY#xlwgRyxqHV?)Y$#@Gni*$GkIfv^xzB><0 z$iNH=z(sHgSU@4L0vjj-cJ#Cf|7yj*T48c=IZs^(lN~VG29s?t*#?sfVX_k@+hMXD zCfi}M9VXjhvK=PdV6q)1+hMW;CR?<(kY0H4KCt;ky!+pK|3Z9jAwIVdpIZoP9kA8` zYaOuG0c#zw)&XlBu+{-<9kA8`YaOuG0c&lr)&^^Bu+|1^ZLrn`Yi+RB25W7w)&^^B zu+|1^ZLrn`Yi+RB25X(L)(LB!u+|A{?f6`AW`-S~Yscr>@wp<3zn!?%cH&ms@xOLh zZHLu%sR-DC11P`=ia`lb!DUbiegiJrQwhkl^IpIkQ~_V7b2(t@eb|F64iVwEJcoog|VE| zfxo+(`O;4Gq1}Er1GZ+sRvTxz_IB801gPLL^)Cg#0hj9>j64S;Ghk!}jLd+M889*f zMrOds3>cXKBQs!R28_&rk>_CKIT(2kM&`iC92l7cBXeM64ve(JNIQ(Q!$>=fJO?8$ z;A=17YcJqyFW_r0;A=17YcJqyFW_r0;A<~j)1z%n%YQex2N0PY2HIet4F=j^pbZAv z@U4gOt%vcg1^Cqhn0N^$UV@3|V4@8s+F+s$CfZ=44JO)Pq75e6VB#fwY61SV07hPd zk(Xd(28_&rkr^;D14d@R$P5^n0V6YDWCo1PfRP!TF6V=f(*e;}tpo1H_qD;Vw&(8- zNc%qev7Pv?Gye7w;2tYfU}}!1hX7OAo%MSU!2(mQFx3K6Eily%Q=Kr?3R6q)sYNhV zg{dk`Rbi?MQ&pI%!c-NesxVcBsVYoWV5$OBMK8RVUU)IR@M3!5#q@nu`o1cCUzNTu z?_K130DJ}xf0)*rzMa1#6keg?mQ z8yP3eK{n^Wd5{Z4PvQb7W4al+2)17Ymw*Kn0*(F1l2aeB0MXkJ7Vu}i4GR`v!2&E; zfCUS%U;$Pvz={P}u>dO;V8sHgSb!A^uwnsLEWnBdSg`;L7GS{wELeaY3$SAWb}Yb- z1=z6wCl=tu0-RWY6AQ3l0ah%)iUnA)04o+?#R9BYfE5d{VgXhxz={Qw;FC-6$tC#Y z5`1tG7Epu*6nQK_!2%R4K*0hOEI`2m^09#Ya{XTm%vWH(0`nD^ufTi-<|{B?f%yu| zFW>*Q!gwo;x59WUjJLvgD~z|ocuu$jML@`OCrrBl7ZD1>1A2}z7Xv|;U|yFa`Z zwy%Tj8({l-{BkC2PloLd{BjX~xd^s9@XHST@^09k2HSVT_T8{O4Yp^(_QS9}lU_s) zjL(Ge$6)+17=H}LAA|A7VEi!{e+PiMXbXb)?p3nu!ap-!v?Hj zJwAUuK7Tzvemy>ZJ*-cL^~tc_0qY&GzKC8(5$rC)w->=|2h1*l*$#ZW1K;kzw>$9d z4tzT+MZs^t<=PFicf;&7n4Jc*(_nHMOiqKzX)rkr2JeQoX|Og8)@H)mOjw%Thhgkt7<(AT9)_`pVeDZTdl<%M!q`k0n+anx=|$wwi^!oDkwY&c2L@-t z-b~nAg#XTjy_v8#6ZU4p-b~ng3ih7Df2Y$ow&KIn=^Kk4MIL@U4?n&eHfO@-OxTTk+-T^o_0f^E~`{9{xNHcBjGaG}xU6yVGEI8thJk z-D$8p4R)u&?lk5ygBTmAhtF(;H1B53Q**9u84KvZIBF;Qr=4M>dn7)`!|W26Z7J8| zu)u5!%r?X9Y?v*^+{`fB>S1<{huLRfwjHJ_jG-xvp(%`^DU6{hjG;MTsspAvV5)=B zO+T3GU<}Q{7@C7IGzVj74#vmLg@Q$xum}?tk&Q)UV-eX{L^c+YjYVW*5!qNoHWrbMMPy?U*{o8hMZzMi zScDZ{uVN8atf4B_kcBmz#Tv5l^JlRJD}G+|W)fh39_&90`}1Lc9_&8{`_Fs&+lBb` zLfC&1zg~i0FTt;u;MYs=>m~U068w4ze!T?0UV>jQ!Ah)Hi4`lcVkK6r#EO+zu@Wm* zV#P|V_;VF2v0^1wti+0ySg{f-R$|3UtXPQ^E3slFR;VqKs<6K*?5_&@vtWM~ z?9YPzS+G9~_GiKVEZCm~`?Fww7VOW0{aLX8EbKoE`_IDuv#|dx?9axpXXDq;!v3?c z|19i33;WN){pcGbJpTPW{{1|?lKdO)m;Z5IqA_oa^mJkC zMSQvypKiscTk+{ue7Y58=D|!WKHG}Vw&Js`_-rda+ltS&;lG{^o^tjfU$1rF0PHi-K;aYhieni z3^eDrR$SX4$+onZ?MdH(S(xWw%JZNXzP1nkasYV_1cSg}@Cq0LUIjzJYhW079hM9S zBgl6o7zIXyF<>mu83)FL31A|a1SW$wz!dN%msp30Te5Z=< zRPmiEzEj0_s`yS7->Kp|6?zy7Jq(2&hC&a+f$wzSJ018=2eV`)%#I;1Sn@qA`5uOF z$`3Zx05sz7ySO$6_kbpVkqp>jh8>*0K?~i6zF1rQQ+v(_>)=X|?qe+BQCi67Krfim z2aMqUkzf=U4aR`6q#p;yg9%_Fm;@$+H^3C|CYTDQfoRgifLJgc#PMA`m;n+%BA5wg zf!SaVm<#5CB#;bJzygp87EzDIUo{}-~(i`32X*iz&7Nw9efBr0z1G?unT+)c7spA9%Q%|>;s>I{mAnG_zWBb zhmh^(;0xZrIT;j2l){Ko7*UF*RWz-lX%$VYXj(6b)HeE^RS>0zf+3eDaG%U;&)2%JEi!YQv6OSey3EL084&=B|p%zIbn(orkG)h z8K&4^iW#PuVTu{1m|=<;rr2PL8K#(F%61P^zJe+9VTzen%tC4luKX!vHjpL zN5k9E@OCu39SvL1umuf^evvqvtuLCkp=ld-F4n-Lgf>lR(}XrnXw!uDOlZ%9_DpEcg!W8m&xH0& zXwQW9OlZ%9_Du9(PoY5*8Z@Cn6B;z3K@%D@p+OTGG@(Hgc4tB>CbVL@j@@OVl}xmf ziB>YviUqA$(251ESkQ_Etys{C1+7@niUqA$(8@Wqat^JWLo4Ud%2lgX(8?LKat5uO zq4#R1_iCs2YNz*VM>{6D52L4yq@x`Zk)FgpaUBpNqpY+;L-}YZA3H2UOZjLi9}VTB zp?pn4tWH2n`Dlr=6q%=LO9|R@?ZDjReR$8#eZBSd>0R9fCP{TW`bE@HkbqE zf_WebB!d*N0HlIHYHBHES_YPbx4{bV4p<3Rfz@CQco)1!`nBMFunrldf%RYm*a$ul zb9Z1f*aEg8pY7m7@X`Nk?_8s!s;)SGPI!m`fguSAkjP^ogoFe{sn%+(EZc%YUE&i( zskIM3w05o9x3PAmCbq_cR+kn&bS;;5wYK8BKB}#c`qrvID+DxT0D+khj0u-XW+uJ; z?S1c^nVSS9ZS9Aad)I&FKF>X8@Bi87arZeFJPIBIkAo+`AHkF0DX#q!_%nDKJcB%+ z1Bk~-YUsEQ0d=EQxY`MvfTswU5A@I+S}Bq9-W=E~8lzPmqg5TFRUM;M9ivqpqg5TFRUM;M9ivqpqg5TF zRULzYtuU|^2DZY$Rv6d{1KVI=8w@<0H)P>fb%M0P82XUXlq5}*Bu(@miBH!aTG@MO zW$&Sty@yuz9@smSw_tnhSndhlfaTtP^>1az?POZRQ$RVW0LOxcYXW`HOd*vjsp zmEA!ryMx@4re7#c?RVfi*tNvtqu#j=<*n8*n7$fmtwvg_`C9HWa|e5OF#d5F-%ITV z2Y~ENU~d9@6U?u$_dVGA9?f;N?q+Ow7xr7cw>q%j2mIbs@!(35vksE0;`E#*$ytGC zL6V-+Bsokx3&eXX@GMA?yOQ)5r4Bn+eS=(k6<9+&))SBW!2RF>FwpC(1AEwkJ?y|9 zc3=+=U=I&q4-fncJ)(nofF)sX680XB2Uwg^HBPA-r&Nv8BbuZ~G)a%>P`nY6FkHM5 zlJt-!=^;(hLz<+AGzsem^F|noM_9f$LW=&Sl#Kx9ucwbG<$E6_VS5s`Ct-UMwkKhG z61FE{dlI%MVSADu&lK!V!R{2ycBnn|66xYeA& zc%>y~B{N7~YnGD#mznFCZR%QcHaLg*I?e^>gA15r0~ z;{I2_tKc>8I`}Ji1H1{|0vo_au$M67fI0-<`fOtEjwZe~+{E`jo0y@jiBb1WrVG$= zBZk)-hiebApX48ZXwwVmDKhxnn+$R41OEW7DPk;ok!AKc%Sb;v7K}3!?RXFY6F?Ct zF)Qpuz>He93^4xFPBxQmIj8{4&1I*8X8K<5HG^1ZW5QKnK_lJ^)>y8yo-!31hy7Gh6ST%H0v}9?#to z?v8MGgu5f$9pUZ>cSpF}dqd2u4%{8#*>g1(R(&m*3~ zsR*391WwiS)JC4#2&d}dR6U$3g;S+)suWI@`JAeNQ;Xo#GB{NOry_7F0;eKyDgvh> za4G_)B5*1Kry_7F0;eKysvb_&ld48i)kvxuNmV1MYJ^jbq^yyYH4^JaV%-R*>XA(& zoT`UY^>C^lPSwMydN@@IpGx6VDSRr0Po?mw6h4*0r!x3d2A9gi^ErLsnY?WCCmzLRTPy^tFR*FXg-SOqi8;g=A&pnisqweK8og}Xnrx8UySA#qxr>XeK}fR zj@Fl>_4&3I)PecT*1Likiq;YjvDQn8`BGxObdbFpIOn|;89_TSNqZ|vdn-wMD@l7R zsdt>tHK%j`>AE+Gy-Dm%(*A)BuxJA{k{;Rs4y{jz)~AfNa%g=z^bz#Z25<=3p#>_f zPsi^gkoN@+wU-37ml(B|PHG;9*T?q_!n_K6oBO{5z6-twz7Ku?eh97s_263YBXAw~ zG4aaxPPm?9ji3qK0DcO725tn+;3n{Muo|r4c{lTa3-|@N72F1H2X}y90!md{m<}yW zhZd%Dh<=0q{r(OuOotYxLkrWPh3U}3bZB8Zv@ji7m<}yWhZ+t|5g4Q%Ep{1XD;bg#=SbFogtDNHB#2Q%Eq51mj3Bjs)XKa4QnriUhYJ z!L8I8()7Zl>4lM=V(x%e z<8~237a{bpE&Dy}GwQ{aabSiRcj;ayWiAW*9}qU4zx*cL6sbFSsK;>Ue(qpo2yaD> z;{B#PYq$K$QLvx*?_=HT#@T+4BNG2E;?+$mxXN3+CkK1Ef8;5W=;2z4yKH+$^r&}4 z&x`yWay&7Le;z<4?M3FvuEt|i(c;MdhT9G4iHqQCINKNL2(1okx*eB+J2qYz37;GUP!W-BlaZ{ZUGq&U? zDfaH;{QGjHJXsdDL=WU*Z~xH0-1P$2(>n+l`HD8hzA;*vqYspskx=h$xH zXfJTw$K1!=2RSCQ1sIp{I})pb3z`+ZzQ;fBL{&aA69$?l&LSH*>u`=S4YGP6=+(R3 zHoXTMp&U`$*Z&FJ^A_h{LY6Oc{dTm)yhDp0VA1g=3GnTLayPQ$UVV-s}G;LP@dJ#vPJ76NJ>xk?s64?nZt&syraQVxI&3 zjyRNkmZyo-gT>PlGffyq&KdVskf%4&y%%o28eA>^$j`SzNGQApY}Q=q-Q!t!4PSV% z2KYALKfjxJzwB-MM|uLuV5$18{uTanc%$Tp=HA8DW^hYzBnT14bffpsB3zaQ9)#CH ztgDyS>>Z-z&{c#WC28IQabjsH*?2oD{`q~|S!ALQzA z>=RnrMYwdKA2#-e1u2XX7&)_NVr@@mZXLiGJEN=diG?yAz^vFMeA`JIO1tMILtrnp%l(LAa%1&?@rEz*8$Syey=|NcZ&FTelbQ(s`$=_==#6c-$v$V< z&hj=WNBda^EvLe<=Pu>mf7m_@&Yz7uEyo{?tt&nX$^=wJ(NKufN{cENCZS%JMUztZ*mwwj2JobYQwp|V%XVV}3bwOS`sR;g^H-Y5JC@eCW#n=QYD*$#Ya^Fm-Ny!J0A zXm|NnN&$=Z_aE zR|Rc_eC;OCbSEA<1&qc#l`F3>FXAy*fTz<4dfE)$F{9a&?{^M2(^!k~d^wG|9M8aC zY5}7;F2k?x3Vc$|G8sHYcG_Cjadw_vXvf=&SWE52tYvnky~0kiUtyhYzr{Mk-p(4e zYwbEa({8jaw$g61@7Oxq$~xc1>~4FU-D~6aMB8p1`$=Lk44<2eiPK7aZY+1zam1R> z5W{2e8H-Tk;R~Z?4*fyLn-eH;K1KcKG``4nt~n1+z)Ohh*Ufc!!QN^f#4BgB*$( zBG)0ULSi(YRpdF7_*LR_I2>Q6dFCj-q`H8ZE;J_*+ml&~@KQe&iJn3IY$AR}%lXpS z`S=#i)O1#9I_DtW2k~)f(4IjccXGwSrhy67Sip1;n?CcvrIy=eadpJ(qPPwMCgjp^kMF zshNk@;Bl;lq-g;fSjaktZ@_+n6rRXBmQ)7m98Wq=K|iOm;+4-@#JAEuOUggTTEZ8= zKTrA>vzFq8wFK^+$vO#6orPqVvL1_X(K5cB`vul%Nb77f9eJIDyq2>@k=psh{Q}l1 z{If2E0~fJYs~l^P<4RI+DQhj`ey<{R-$V-5e4APC3m8Lq9Y=m_enNV$$J1^E9-OO5 z?;4$};bwC)>Ai)S!;dz%o3*5Oow))wNQHQJ8G$8QY2UbD$$RFK7EpaION*ttD>j>^f5j^ETpPw#jZX)9l~u-+9*C_HAOd*>2{@ z7Q2PBEw+Utu#<&WPX?L={%ktG8`<~s+Sy+oS3K+jFIc%)5cC50tNORZ> zNQ|^vY?oQG?Iz_oVUb!1p z?jEbG9jB}vsjL;>!6j%^SUWY3wS~%BtE@dnSvx{mTcE5Rj$Jwzeh7EPx7713yb!ht zcPA=$%apsLmAlih1Yd{o!r+<8;0em$*~;L#%HYY$;5o|Rx;zF~!Qk7Fh%mSo2Hy>v zg}c?t-FeF0G0NRZ%H1i--SNuZDBRtM4urMil(i$3wZ+QXsd=m|RMuKp>yRIq*#>Rl ztB&4;y9IEUZ}BQ?@lRF1L}BeHWo<-RJ5gC%rmP*UtevK;ty9((!rFzV#IC^SaG1S> zZzB#J1do)Mas?sWoNC}MM4nf6)E#(Df23od9##xmCC##DRs>7 Fe*%f=JV^im literal 0 HcmV?d00001 diff --git a/assets/Fonts/Brandon_med.otf b/assets/Fonts/Brandon_med.otf new file mode 100644 index 0000000000000000000000000000000000000000..113eb2459d731ceeaf8ec567f22e11a6e92b3745 GIT binary patch literal 89536 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 literal 0 HcmV?d00001 diff --git a/assets/Images/calculator.svg b/assets/Images/calculator.svg new file mode 100644 index 0000000..e988fff --- /dev/null +++ b/assets/Images/calculator.svg @@ -0,0 +1,3 @@ + + + diff --git a/assets/Images/create_quiz.svg b/assets/Images/create_quiz.svg new file mode 100644 index 0000000..1682976 --- /dev/null +++ b/assets/Images/create_quiz.svg @@ -0,0 +1,57 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/Images/lab.svg b/assets/Images/lab.svg new file mode 100644 index 0000000..4e9920a --- /dev/null +++ b/assets/Images/lab.svg @@ -0,0 +1,3 @@ + + + diff --git a/assets/Images/login.svg b/assets/Images/login.svg new file mode 100644 index 0000000..cc6272d --- /dev/null +++ b/assets/Images/login.svg @@ -0,0 +1 @@ +Login \ No newline at end of file diff --git a/assets/Images/login_bottomRight.svg b/assets/Images/login_bottomRight.svg new file mode 100644 index 0000000..517f851 --- /dev/null +++ b/assets/Images/login_bottomRight.svg @@ -0,0 +1,62 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/Images/login_bottomRight_png.png b/assets/Images/login_bottomRight_png.png new file mode 100644 index 0000000000000000000000000000000000000000..38bae3b00f1b705f1738112b01dd3f37c95ef652 GIT binary patch literal 12155 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 literal 0 HcmV?d00001 diff --git a/assets/Images/login_topLeftBubble_1.png b/assets/Images/login_topLeftBubble_1.png new file mode 100644 index 0000000000000000000000000000000000000000..df0f7c9e8c74e4f3fbedd58116c9706495ef7491 GIT binary patch literal 51572 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 + + diff --git a/assets/Images/notes.svg b/assets/Images/notes.svg new file mode 100644 index 0000000..00038ae --- /dev/null +++ b/assets/Images/notes.svg @@ -0,0 +1,6 @@ + + + + Notes + + diff --git a/assets/Images/notes_screen.svg b/assets/Images/notes_screen.svg new file mode 100644 index 0000000..e1ed78f --- /dev/null +++ b/assets/Images/notes_screen.svg @@ -0,0 +1,50 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/Images/prevQuiz.svg b/assets/Images/prevQuiz.svg new file mode 100644 index 0000000..e1ed78f --- /dev/null +++ b/assets/Images/prevQuiz.svg @@ -0,0 +1,50 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/Images/testAnalysis.svg b/assets/Images/testAnalysis.svg new file mode 100644 index 0000000..4602d15 --- /dev/null +++ b/assets/Images/testAnalysis.svg @@ -0,0 +1,3 @@ + + + diff --git a/assets/Images/testResults.svg b/assets/Images/testResults.svg new file mode 100644 index 0000000..8c4e652 --- /dev/null +++ b/assets/Images/testResults.svg @@ -0,0 +1,3 @@ + + + diff --git a/assets/Images/zoom.svg b/assets/Images/zoom.svg new file mode 100644 index 0000000..6a928a9 --- /dev/null +++ b/assets/Images/zoom.svg @@ -0,0 +1,3 @@ + + + From cb15eb5f15066e440a598f7ed30a5ba2b4e746ee Mon Sep 17 00:00:00 2001 From: TheYoungWolf <68595463+TheYoungWolf-Productions@users.noreply.github.com> Date: Sat, 30 Apr 2022 05:16:52 -0700 Subject: [PATCH 21/23] Delete lib directory --- lib/auth_storage.dart | 41 - lib/main.dart | 40 - .../QuizModuleModels/generate_quiz_model.dart | 97 - .../get_system_categories_successful.dart | 97 - .../get_system_categories_unsuccessful.dart | 29 - .../ResumeQuiz/resume_quiz_model.dart | 226 --- .../get_previous_quizzes_model.dart | 97 - lib/models/user_model_successful_login.dart | 57 - lib/models/user_model_unsuccessful_login.dart | 45 - lib/screens/Authentication/login.dart | 599 ------ .../Welcome/GenerateQuiz/difficulty.dart | 281 --- .../Welcome/GenerateQuiz/generate_quiz.dart | 1598 --------------- .../GenerateQuiz/generate_quiz_last.dart | 276 --- .../Welcome/GenerateQuiz/question_types.dart | 281 --- .../Welcome/PreviousQuiz/previous_quiz.dart | 609 ------ .../Welcome/PreviousQuiz/test_details.dart | 478 ----- lib/screens/Welcome/PreviousQuiz/tile.dart | 137 -- lib/screens/Welcome/QuizModule/buttons.dart | 55 - .../Welcome/QuizModule/calculator.dart | 179 -- .../QuizModule/question_explanation.dart | 372 ---- .../Welcome/QuizModule/quiz_final.dart | 10 - .../Welcome/QuizModule/quiz_module.dart | 1767 ----------------- .../Welcome/QuizModule/search_bar.dart | 861 -------- lib/screens/Welcome/side_menu_bar.dart | 80 - lib/screens/home.dart | 168 -- 25 files changed, 8480 deletions(-) delete mode 100644 lib/auth_storage.dart delete mode 100644 lib/main.dart delete mode 100644 lib/models/GenerateQuizModels/QuizModuleModels/generate_quiz_model.dart delete mode 100644 lib/models/GenerateQuizModels/get_system_categories_successful.dart delete mode 100644 lib/models/GenerateQuizModels/get_system_categories_unsuccessful.dart delete mode 100644 lib/models/GetPreviousQuizzesModel/ResumeQuiz/resume_quiz_model.dart delete mode 100644 lib/models/GetPreviousQuizzesModel/get_previous_quizzes_model.dart delete mode 100644 lib/models/user_model_successful_login.dart delete mode 100644 lib/models/user_model_unsuccessful_login.dart delete mode 100644 lib/screens/Authentication/login.dart delete mode 100644 lib/screens/Welcome/GenerateQuiz/difficulty.dart delete mode 100644 lib/screens/Welcome/GenerateQuiz/generate_quiz.dart delete mode 100644 lib/screens/Welcome/GenerateQuiz/generate_quiz_last.dart delete mode 100644 lib/screens/Welcome/GenerateQuiz/question_types.dart delete mode 100644 lib/screens/Welcome/PreviousQuiz/previous_quiz.dart delete mode 100644 lib/screens/Welcome/PreviousQuiz/test_details.dart delete mode 100644 lib/screens/Welcome/PreviousQuiz/tile.dart delete mode 100644 lib/screens/Welcome/QuizModule/buttons.dart delete mode 100644 lib/screens/Welcome/QuizModule/calculator.dart delete mode 100644 lib/screens/Welcome/QuizModule/question_explanation.dart delete mode 100644 lib/screens/Welcome/QuizModule/quiz_final.dart delete mode 100644 lib/screens/Welcome/QuizModule/quiz_module.dart delete mode 100644 lib/screens/Welcome/QuizModule/search_bar.dart delete mode 100644 lib/screens/Welcome/side_menu_bar.dart delete mode 100644 lib/screens/home.dart diff --git a/lib/auth_storage.dart b/lib/auth_storage.dart deleted file mode 100644 index 03a99db..0000000 --- a/lib/auth_storage.dart +++ /dev/null @@ -1,41 +0,0 @@ -import 'package:path_provider/path_provider.dart'; -import 'dart:io'; - - -class AuthStorage { - Future getLocalPath() async { - var dir = await getApplicationDocumentsDirectory(); - return dir.path; - } - - Future getLocalFile() async { - String path = await getLocalPath(); - return File('$path/auth.txt'); - } - - Future writeAuth(String email, String password) async { - File file = await getLocalFile(); - return file.writeAsString('$email' + ' ' + '$password'); - } - - Future readAuth() async { - try { - final file = await getLocalFile(); - String content = await file.readAsString(); - return content; - } catch(e) { - return ""; - } - } - - Future deleteFile() async { - try { - final file = await getLocalFile(); - - await file.delete(); - return ""; - } catch (e) { - return ""; - } - } -} \ No newline at end of file diff --git a/lib/main.dart b/lib/main.dart deleted file mode 100644 index 1e0f65d..0000000 --- a/lib/main.dart +++ /dev/null @@ -1,40 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:flutter/services.dart'; -import 'package:testify/auth_storage.dart'; -import 'package:testify/screens/Authentication/login.dart'; -import 'package:testify/screens/Welcome/GenerateQuiz/generate_quiz.dart'; -import 'package:testify/screens/Welcome/QuizModule/quiz_module.dart'; -import 'package:testify/screens/home.dart'; - -void main() async { - WidgetsFlutterBinding.ensureInitialized(); - SystemChrome.setPreferredOrientations([ - DeviceOrientation.portraitUp, - DeviceOrientation.portraitDown, - ]); - - runApp(MyApp()); -} - -class MyApp extends StatefulWidget { - // This widget is the root of your application. - @override - State createState() => _MyAppState(); -} - -class _MyAppState extends State { - - @override - Widget build(BuildContext context) { - return MaterialApp( - initialRoute: '/', - routes: { - // When navigating to the "/" route, build the FirstScreen widget. - '/': (context) => Login(fromWhere: "main",), - // When navigating to the "/second" route, build the SecondScreen widget. - '/home': (context) => Home(), - }, - // home: Login(fromWhere: "main",) - ); - } -} \ No newline at end of file diff --git a/lib/models/GenerateQuizModels/QuizModuleModels/generate_quiz_model.dart b/lib/models/GenerateQuizModels/QuizModuleModels/generate_quiz_model.dart deleted file mode 100644 index 562990a..0000000 --- a/lib/models/GenerateQuizModels/QuizModuleModels/generate_quiz_model.dart +++ /dev/null @@ -1,97 +0,0 @@ -// To parse this JSON data, do -// -// final generateQuizSuccessful = generateQuizSuccessfulFromJson(jsonString); - -import 'dart:convert'; - -GenerateQuizSuccessful generateQuizSuccessfulFromJson(String str) => GenerateQuizSuccessful.fromJson(json.decode(str)); - -String generateQuizSuccessfulToJson(GenerateQuizSuccessful data) => json.encode(data.toJson()); - -class GenerateQuizSuccessful { - GenerateQuizSuccessful({ - required this.data, - }); - - Data data; - - factory GenerateQuizSuccessful.fromJson(Map json) => GenerateQuizSuccessful( - data: Data.fromJson(json["data"]), - ); - - Map toJson() => { - "data": data.toJson(), - }; -} - -class Data { - Data({ - required this.status, - required this.questions, - required this.totalQuestions, - required this.quizId, - }); - - bool status; - List questions; - int totalQuestions; - int quizId; - - factory Data.fromJson(Map json) => Data( - status: json["status"], - questions: List.from(json["questions"].map((x) => Question.fromJson(x))), - totalQuestions: json["totalQuestions"], - quizId: json["quizId"], - ); - - Map toJson() => { - "status": status, - "questions": List.from(questions.map((x) => x.toJson())), - "totalQuestions": totalQuestions, - "quizId": quizId, - }; -} - -class Question { - Question({ - required this.id, - required this.title, - required this.question, - required this.correctMsg, - required this.answerType, - required this.postId, - required this.options, - required this.statistics, - }); - - int id; - String title; - String question; - String correctMsg; - String answerType; - int postId; - List options; - List statistics; - - factory Question.fromJson(Map json) => Question( - id: json["id"], - title: json["title"], - question: json["question"], - correctMsg: json["correct_msg"], - answerType: json["answer_type"], - postId: json["postId"], - options: List.from(json["options"].map((x) => x)), - statistics: List.from(json["statistics"].map((x) => x)), - ); - - Map toJson() => { - "id": id, - "title": title, - "question": question, - "correct_msg": correctMsg, - "answer_type": answerType, - "postId": postId, - "options": List.from(options.map((x) => x)), - "statistics": List.from(statistics.map((x) => x)), - }; -} diff --git a/lib/models/GenerateQuizModels/get_system_categories_successful.dart b/lib/models/GenerateQuizModels/get_system_categories_successful.dart deleted file mode 100644 index 6ec60af..0000000 --- a/lib/models/GenerateQuizModels/get_system_categories_successful.dart +++ /dev/null @@ -1,97 +0,0 @@ -// To parse this JSON data, do -// -// final getSystemCategoriesSuccessfulModel = getSystemCategoriesSuccessfulModelFromJson(jsonString); - -import 'dart:convert'; - -GetSystemCategoriesSuccessfulModel getSystemCategoriesSuccessfulModelFromJson(String str) => GetSystemCategoriesSuccessfulModel.fromJson(json.decode(str)); - -String getSystemCategoriesSuccessfulModelToJson(GetSystemCategoriesSuccessfulModel data) => json.encode(data.toJson()); - -class GetSystemCategoriesSuccessfulModel { - GetSystemCategoriesSuccessfulModel({ - required this.data, - }); - - Data data; - - factory GetSystemCategoriesSuccessfulModel.fromJson(Map json) => GetSystemCategoriesSuccessfulModel( - data: Data.fromJson(json["data"]), - ); - - Map toJson() => { - "data": data.toJson(), - }; -} - -class Data { - Data({ - required this.status, - required this.categories, - required this.totalQuestions, - required this.questions, - }); - - bool status; - List categories; - int totalQuestions; - List questions; - - factory Data.fromJson(Map json) => Data( - status: json["status"], - categories: List.from(json["categories"].map((x) => Category.fromJson(x))), - totalQuestions: json["totalQuestions"], - questions: List.from(json["questions"].map((x) => x)), - ); - - Map toJson() => { - "status": status, - "categories": List.from(categories.map((x) => x.toJson())), - "totalQuestions": totalQuestions, - "questions": List.from(questions.map((x) => x)), - }; -} - -class Category { - Category({ - required this.parentCategory, - required this.subCategories, - }); - - String parentCategory; - List subCategories; - - factory Category.fromJson(Map json) => Category( - parentCategory: json["parentCategory"], - subCategories: List.from(json["subCategories"].map((x) => SubCategory.fromJson(x))), - ); - - Map toJson() => { - "parentCategory": parentCategory, - "subCategories": List.from(subCategories.map((x) => x.toJson())), - }; -} - -class SubCategory { - SubCategory({ - required this.id, - required this.title, - required this.questions, - }); - - String id; - String title; - int questions; - - factory SubCategory.fromJson(Map json) => SubCategory( - id: json["ID"], - title: json["Title"], - questions: json["Questions"], - ); - - Map toJson() => { - "ID": id, - "Title": title, - "Questions": questions, - }; -} diff --git a/lib/models/GenerateQuizModels/get_system_categories_unsuccessful.dart b/lib/models/GenerateQuizModels/get_system_categories_unsuccessful.dart deleted file mode 100644 index fbea9f6..0000000 --- a/lib/models/GenerateQuizModels/get_system_categories_unsuccessful.dart +++ /dev/null @@ -1,29 +0,0 @@ -// To parse this JSON data, do -// -// final getSystemCategoriesUnsuccessfulModel = getSystemCategoriesUnsuccessfulModelFromJson(jsonString); - -import 'dart:convert'; - -GetSystemCategoriesUnsuccessfulModel getSystemCategoriesUnsuccessfulModelFromJson(String str) => GetSystemCategoriesUnsuccessfulModel.fromJson(json.decode(str)); - -String getSystemCategoriesUnsuccessfulModelToJson(GetSystemCategoriesUnsuccessfulModel data) => json.encode(data.toJson()); - -class GetSystemCategoriesUnsuccessfulModel { - GetSystemCategoriesUnsuccessfulModel({ - required this.status, - required this.msg, - }); - - bool status; - String msg; - - factory GetSystemCategoriesUnsuccessfulModel.fromJson(Map json) => GetSystemCategoriesUnsuccessfulModel( - status: json["status"], - msg: json["msg"], - ); - - Map toJson() => { - "status": status, - "msg": msg, - }; -} diff --git a/lib/models/GetPreviousQuizzesModel/ResumeQuiz/resume_quiz_model.dart b/lib/models/GetPreviousQuizzesModel/ResumeQuiz/resume_quiz_model.dart deleted file mode 100644 index 52e5145..0000000 --- a/lib/models/GetPreviousQuizzesModel/ResumeQuiz/resume_quiz_model.dart +++ /dev/null @@ -1,226 +0,0 @@ -// To parse this JSON data, do -// -// final resumeQuizModel = resumeQuizModelFromJson(jsonString); - -import 'dart:convert'; - -ResumeQuizModel resumeQuizModelFromJson(String str) => ResumeQuizModel.fromJson(json.decode(str)); - -String resumeQuizModelToJson(ResumeQuizModel data) => json.encode(data.toJson()); - -class ResumeQuizModel { - ResumeQuizModel({ - required this.data, - }); - - Data data; - - factory ResumeQuizModel.fromJson(Map json) => ResumeQuizModel( - data: Data.fromJson(json["data"]), - ); - - Map toJson() => { - "data": data.toJson(), - }; -} - -class Data { - Data({ - required this.status, - required this.questions, - required this.previousQuizzes, - }); - - bool status; - List questions; - List previousQuizzes; - - factory Data.fromJson(Map json) => Data( - status: json["status"], - questions: List.from(json["questions"].map((x) => Question.fromJson(x))), - previousQuizzes: List.from(json["previousQuizzes"].map((x) => PreviousQuizz.fromJson(x))), - ); - - Map toJson() => { - "status": status, - "questions": List.from(questions.map((x) => x.toJson())), - "previousQuizzes": List.from(previousQuizzes.map((x) => x.toJson())), - }; -} - -class PreviousQuizz { - PreviousQuizz({ - required this.quizId, - required this.userId, - required this.quizMeta, - required this.sortId, - this.examId, - }); - - int quizId; - int userId; - QuizMeta quizMeta; - DateTime sortId; - dynamic examId; - - factory PreviousQuizz.fromJson(Map json) => PreviousQuizz( - quizId: json["quiz_id"], - userId: json["user_id"], - quizMeta: QuizMeta.fromJson(json["quiz_meta"]), - sortId: DateTime.parse(json["sortId"]), - examId: json["exam_id"], - ); - - Map toJson() => { - "quiz_id": quizId, - "user_id": userId, - "quiz_meta": quizMeta.toJson(), - "sortId": sortId.toIso8601String(), - "exam_id": examId, - }; -} - -class QuizMeta { - QuizMeta({ - required this.quizId, - required this.quizTitle, - required this.quizDate, - required this.quizScore, - required this.quizTotalQuestions, - required this.quizStatus, - required this.quizQuestions, - required this.quizMode, - required this.quizTime, - required this.isTimed, - required this.omittedQuestions, - required this.selectedOptionsArray, - }); - - // int quizId; - // String quizTitle; - // DateTime quizDate; - // String quizScore; - // int quizTotalQuestions; - // String quizStatus; - // String quizQuestions; - // String quizMode; - // String quizTime; - // bool isTimed; - // List omittedQuestions; - // List selectedOptionsArray; - - dynamic quizId; // Problem - String quizTitle; - DateTime quizDate; - dynamic quizScore; // Problem - int quizTotalQuestions; - String quizStatus; - String quizQuestions; - String quizMode; - String quizTime; - bool isTimed; - List omittedQuestions; - List selectedOptionsArray; - - factory QuizMeta.fromJson(Map json) => QuizMeta( - quizId: json["quizId"], - quizTitle: json["quizTitle"], - quizDate: DateTime.parse(json["quizDate"]), - quizScore: json["quizScore"], - quizTotalQuestions: json["quizTotalQuestions"], - quizStatus: json["quizStatus"], - quizQuestions: json["quizQuestions"], - quizMode: json["quizMode"], - quizTime: json["quizTime"], - isTimed: json["isTimed"], - omittedQuestions: List.from(json["omittedQuestions"].map((x) => x)), - selectedOptionsArray: List.from(json["selectedOptionsArray"].map((x) => x)), - ); - - Map toJson() => { - "quizId": quizId, - "quizTitle": quizTitle, - "quizDate": quizDate.toIso8601String(), - "quizScore": quizScore, - "quizTotalQuestions": quizTotalQuestions, - "quizStatus": quizStatus, - "quizQuestions": quizQuestions, - "quizMode": quizMode, - "quizTime": quizTime, - "isTimed": isTimed, - "omittedQuestions": List.from(omittedQuestions.map((x) => x)), - "selectedOptionsArray": List.from(selectedOptionsArray.map((x) => x)), - }; -} - -class Question { - Question({ - required this.id, - required this.title, - required this.question, - required this.correctMsg, - required this.answerType, - required this.postId, - this.userId, - this.submitData, - this.notes, - this.questionId, - this.noteId, - this.noteMeta, - required this.marked, - required this.options, - required this.statistics, - }); - - int id; - String title; - String question; - String correctMsg; - String answerType; - int postId; - dynamic userId; - dynamic submitData; - dynamic notes; - dynamic questionId; - dynamic noteId; - dynamic noteMeta; - int marked; - List options; - List statistics; - - factory Question.fromJson(Map json) => Question( - id: json["id"], - title: json["title"], - question: json["question"], - correctMsg: json["correct_msg"], - answerType: json["answer_type"], - postId: json["postId"], - userId: json["user_id"] == null ? null : json["user_id"], - submitData: json["submitData"] == null ? null : json["submitData"], - notes: json["notes"] == null ? null : json["notes"], - questionId: json["questionId"] == null ? null : json["questionId"], - noteId: json["noteId"] == null ? null : json["noteId"], - noteMeta: json["note_meta"] == null ? null : json["note_meta"], - marked: json["marked"], - options: List.from(json["options"].map((x) => x)), - statistics: List.from(json["statistics"].map((x) => x)), - ); - - Map toJson() => { - "id": id, - "title": title, - "question": question, - "correct_msg": correctMsg, - "answer_type": answerType, - "postId": postId, - "user_id": userId == null ? null : userId, - "submitData": submitData == null ? null : submitData, - "notes": notes, - "questionId": questionId, - "noteId": noteId, - "note_meta": noteMeta, - "marked": marked, - "options": List.from(options.map((x) => x)), - "statistics": List.from(statistics.map((x) => x)), - }; -} diff --git a/lib/models/GetPreviousQuizzesModel/get_previous_quizzes_model.dart b/lib/models/GetPreviousQuizzesModel/get_previous_quizzes_model.dart deleted file mode 100644 index a3aa346..0000000 --- a/lib/models/GetPreviousQuizzesModel/get_previous_quizzes_model.dart +++ /dev/null @@ -1,97 +0,0 @@ -// To parse this JSON data, do -// -// final getPreviousQuizzesModel = getPreviousQuizzesModelFromJson(jsonString); - -import 'dart:convert'; - -GetPreviousQuizzesModel getPreviousQuizzesModelFromJson(String str) => GetPreviousQuizzesModel.fromJson(json.decode(str)); - -String getPreviousQuizzesModelToJson(GetPreviousQuizzesModel data) => json.encode(data.toJson()); - -class GetPreviousQuizzesModel { - GetPreviousQuizzesModel({ - required this.data, - }); - - Data data; - - factory GetPreviousQuizzesModel.fromJson(Map json) => GetPreviousQuizzesModel( - data: Data.fromJson(json["data"]), - ); - - Map toJson() => { - "data": data.toJson(), - }; -} - -class Data { - Data({ - required this.status, - required this.quizzes, - }); - - bool status; - List quizzes; - - factory Data.fromJson(Map json) => Data( - status: json["status"], - quizzes: List.from(json["quizzes"].map((x) => Quiz.fromJson(x))), - ); - - Map toJson() => { - "status": status, - "quizzes": List.from(quizzes.map((x) => x.toJson())), - }; -} - -class Quiz { - Quiz({ - required this.quizId, - required this.name, - required this.score, - required this.date, - required this.status, - required this.questions, - required this.totalQuestions, - required this.subjects, - required this.systems, - required this.topics, - }); - - int quizId; - String name; - String score; - String date; - String status; - List questions; - String totalQuestions; - List subjects; - List systems; - List topics; - - factory Quiz.fromJson(Map json) => Quiz( - quizId: json["quizId"], - name: json["name"], - score: json["score"], - date: json["date"], - status: json["status"], - questions: List.from(json["questions"].map((x) => x)), - totalQuestions: json["totalQuestions"], - subjects: List.from(json["subjects"].map((x) => x)), - systems: List.from(json["systems"].map((x) => x)), - topics: List.from(json["topics"].map((x) => x)), - ); - - Map toJson() => { - "quizId": quizId, - "name": name, - "score": score, - "date": date, - "status": status, - "questions": List.from(questions.map((x) => x)), - "totalQuestions": totalQuestions, - "subjects": List.from(subjects.map((x) => x)), - "systems": List.from(systems.map((x) => x)), - "topics": List.from(topics.map((x) => x)), - }; -} diff --git a/lib/models/user_model_successful_login.dart b/lib/models/user_model_successful_login.dart deleted file mode 100644 index f179778..0000000 --- a/lib/models/user_model_successful_login.dart +++ /dev/null @@ -1,57 +0,0 @@ -// To parse this JSON data, do -// -// final userModelSuccessfulLogin = userModelSuccessfulLoginFromJson(jsonString); - -import 'dart:convert'; - -UserModelSuccessfulLogin userModelSuccessfulLoginFromJson(String str) => UserModelSuccessfulLogin.fromJson(json.decode(str)); - -String userModelSuccessfulLoginToJson(UserModelSuccessfulLogin data) => json.encode(data.toJson()); - -class UserModelSuccessfulLogin { - UserModelSuccessfulLogin({ - required this.data, - }); - - Data data; - - factory UserModelSuccessfulLogin.fromJson(Map json) => UserModelSuccessfulLogin( - data: Data.fromJson(json["data"]), - ); - - Map toJson() => { - "data": data.toJson(), - }; -} - -class Data { - Data({ - required this.status, - required this.id, - required this.username, - required this.ifAdmin, - required this.token, - }); - - bool status; - int id; - String username; - bool ifAdmin; - String token; - - factory Data.fromJson(Map json) => Data( - status: json["status"], - id: json["ID"], - username: json["username"], - ifAdmin: json["ifAdmin"], - token: json["token"], - ); - - Map toJson() => { - "status": status, - "ID": id, - "username": username, - "ifAdmin": ifAdmin, - "token": token, - }; -} diff --git a/lib/models/user_model_unsuccessful_login.dart b/lib/models/user_model_unsuccessful_login.dart deleted file mode 100644 index 6eb9603..0000000 --- a/lib/models/user_model_unsuccessful_login.dart +++ /dev/null @@ -1,45 +0,0 @@ -// To parse this JSON data, do -// -// final userModelUnsuccessfulLogin = userModelUnsuccessfulLoginFromJson(jsonString); - -import 'dart:convert'; - -UserModelUnsuccessfulLogin userModelUnsuccessfulLoginFromJson(String str) => UserModelUnsuccessfulLogin.fromJson(json.decode(str)); - -String userModelUnsuccessfulLoginToJson(UserModelUnsuccessfulLogin data) => json.encode(data.toJson()); - -class UserModelUnsuccessfulLogin { - UserModelUnsuccessfulLogin({ - required this.data, - }); - - Data data; - - factory UserModelUnsuccessfulLogin.fromJson(Map json) => UserModelUnsuccessfulLogin( - data: Data.fromJson(json["data"]), - ); - - Map toJson() => { - "data": data.toJson(), - }; -} - -class Data { - Data({ - required this.status, - required this.message, - }); - - bool status; - String message; - - factory Data.fromJson(Map json) => Data( - status: json["status"], - message: json["message"], - ); - - Map toJson() => { - "status": status, - "message": message, - }; -} diff --git a/lib/screens/Authentication/login.dart b/lib/screens/Authentication/login.dart deleted file mode 100644 index 3687098..0000000 --- a/lib/screens/Authentication/login.dart +++ /dev/null @@ -1,599 +0,0 @@ -import 'dart:convert'; -import 'dart:io'; - -import 'package:flutter/material.dart'; -import 'package:flutter_svg/flutter_svg.dart'; -import 'package:http/http.dart' as http; -import 'package:path_provider/path_provider.dart'; -import 'package:shared_preferences/shared_preferences.dart'; -import 'package:testify/auth_storage.dart'; -import 'package:testify/models/user_model_successful_login.dart'; -import 'package:testify/models/user_model_unsuccessful_login.dart'; -import 'package:testify/screens/home.dart'; - -class Login extends StatefulWidget { - const Login({Key? key, required this.fromWhere}) : super(key: key); - - final String fromWhere; - @override - State createState() => _LoginState(); -} - -class _LoginState extends State { - //Data Fields: - final _formKey = GlobalKey(); - String _email = ""; - String _password = ""; - bool _isChecked = false; - //To start animation - bool _loaded = false; - var _duration = const Duration(milliseconds: 450); - var _dataPreviouslyStored = false; - late UserModelSuccessfulLogin _successfulUser; - late UserModelUnsuccessfulLogin _unsuccessfulUser; - var _invalidUsername = false; - var _invalidPassword = false; - bool _isLoggingIn = false; // To start and finish CircularProgress Indicator - - //The data gets stored to local storage. Continue from there. - AuthStorage storage = new AuthStorage(); - - @override - void initState() { - super.initState(); - //To delete the auth file when the user logs out. - if(widget.fromWhere == "Home") { - storage.deleteFile(); - print("Deleted + :" + storage.readAuth().toString()); - setState(() { - _email = ""; - _password = ""; - _isChecked = false; - _dataPreviouslyStored = false; - }); - } - else { - storage.readAuth().then((value) { - if(value.length != 0) { - var temp = value.split(" "); - print(temp); - setState(() { - _email = temp[0]; - _password = temp[1]; - _dataPreviouslyStored = true; - }); - print("Email + Password: " + _email + _password); - } - else { - - } - }); - } - // Future.delayed(Duration(milliseconds: 1), () { - // setState(() { - // _loaded = true; - // }); - // }); - Future.delayed(Duration(microseconds: 0), () { - setState(() { - _loaded = true; - }); - }); - } - - //https://demo.pookidevs.com/auth/login - Future getUserData(BuildContext context, String email, String password) async { - setState(() { - _isLoggingIn = true; - }); - SharedPreferences prefs = await SharedPreferences.getInstance(); - final String apiUrl = "https://demo.pookidevs.com/auth/login"; - http.post(Uri.parse(apiUrl), headers: { - 'Content-type': 'application/json; charset=UTF-8', - }, body: json.encode( - { - "user": - { - "user_email": email, - "user_pass": password - } - }) - ).then((response) { - if(response.statusCode == 200) { - //The entered credentials are correct. - if(json.decode(response.body).toString().substring(0,20) == "{data: {status: true") { - final responseString = (response.body); - var loginData = userModelSuccessfulLoginFromJson(responseString); - final UserModelSuccessfulLogin successfulUser = loginData; - setState(() { - _successfulUser = successfulUser; - _isLoggingIn = false; - }); - //Saves Token to use later. - prefs.setString('token', _successfulUser.data.token); - prefs.setInt("userId", _successfulUser.data.id); - _navigateAndDisplaySelection(context); - print(_successfulUser.data.status); - } - //Credentials are incorrect - else if(json.decode(response.body).toString().substring(0,21) == "{data: {status: false") { - final responseString = (response.body); - var loginData = userModelUnsuccessfulLoginFromJson(responseString); - final UserModelUnsuccessfulLogin unsuccessfulUser = loginData; - setState(() { - _unsuccessfulUser = unsuccessfulUser; - }); - print(_unsuccessfulUser.data.status); - ScaffoldMessenger.of(context) - ..removeCurrentSnackBar() - ..showSnackBar(SnackBar(content: Text(_unsuccessfulUser.data.message))); - _navigateAndDisplaySelection(context); - var splitMessage = (_unsuccessfulUser.data.message).split(" "); - print(splitMessage); - if(splitMessage.length == 4) { - setState(() { - _invalidPassword = true; - _invalidUsername = true; - }); - } - else if(splitMessage.length == 2) { - setState(() { - _invalidPassword = true; - }); - } - } - //loginData = userModelLoginFromJson(responseString); - } else { - - } - }); - - } - - //After form validation navigation to next screen. - void _navigateAndDisplaySelection(BuildContext context) async { - if(_successfulUser.data.status == true) { - if(_isChecked == true) { - storage.writeAuth(_email, _password); - print("Email + Password: " + _email + _password); - // final result = await Navigator.push( - // context, - // MaterialPageRoute(builder: (context) => const Home()), - // ); - Navigator.pushNamed(context, '/home'); - } - else { - storage.writeAuth(_email, _password); - storage.deleteFile(); - print("Email + Password: " + _email + _password); - // final result = await Navigator.push( - // context, - // MaterialPageRoute(builder: (context) => const Home()), - // ); - Navigator.pushNamed(context, '/home'); - } - } - /*ScaffoldMessenger.of(context) - ..removeCurrentSnackBar() - ..showSnackBar(SnackBar(content: Text(_unsuccessfulUser.data.message)));*/ - } - - @override - Widget build(BuildContext context) { - return WillPopScope( - onWillPop: () async { - // ScaffoldMessenger.of(context) - // ..removeCurrentSnackBar() - // ..showSnackBar(SnackBar(content: Text(""))); - return false; - }, - child: GestureDetector( - onTap: () { - FocusScopeNode currentFocus = FocusScope.of(context); - - if (!currentFocus.hasPrimaryFocus) { - currentFocus.unfocus(); - } - }, - child: Scaffold( - backgroundColor: Color(0xff3F2668),//Color copied from xD=#3F2668 - body: SingleChildScrollView( - child: Container( - height: (MediaQuery.of(context).size.height), - child: Column( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - AnimatedCrossFade( - crossFadeState: _loaded ? CrossFadeState.showFirst : CrossFadeState.showSecond, - duration: _duration, - firstChild: Container( - height: (MediaQuery.of(context).size.height) *0.3, - color: Colors.transparent, - child: Align( - alignment: Alignment.topLeft, - child: Image( - image: AssetImage("assets/Images/login_topLeftBubble_1.png"), - ), - ), - ), - secondChild: Container( - height: (MediaQuery.of(context).size.height) *0.3, - color: Colors.transparent, - child: Text(""), - ), - ), - SizedBox(height: (MediaQuery.of(context).size.height) *0.02159,), - AnimatedCrossFade( - crossFadeState: _loaded ? CrossFadeState.showFirst : CrossFadeState.showSecond, - duration: _duration, - secondChild: Text(""), - firstChild: Container( - child: Form( - key: _formKey, - child: Stack( - alignment: Alignment.bottomCenter, - children: [ - Column(//Add extra space at the end of the container(the one that has TextFormField) so that the login button can be aligned. - children: [ - Container(//For Borders of lighter area //Main Container to add Welcome, TextFormFields and Login. - //tbd: Get the color right! - margin: EdgeInsets.only(top: 0, bottom: 0, left: (MediaQuery.of(context).size.width) *(31/428), right: (MediaQuery.of(context).size.width) *(31/428),), - padding: EdgeInsets.only(top: 0, bottom: (MediaQuery.of(context).size.height) *0.0179, left: 0, right: 0,), - decoration: BoxDecoration( - color: Color.fromRGBO(176, 166, 194, 210),//0xffB0A6C2, rgba(176, 166, 194, 1) - borderRadius: BorderRadius.all(Radius.circular(10)), - border: Border.all( - color: Color(0xff757575), - width: 0, - ), - boxShadow: [ - BoxShadow( - color: Color(0xff0000004D), - ), - ], - ), - child: Column( - children: [ - Container( - padding: EdgeInsets.only(top: (MediaQuery.of(context).size.height) *0.020518, bottom: 0, left: 0, right: 0,), - child: Text("Welcome!", - style: TextStyle( - color: Color(0xffFFFEFE), - fontFamily: 'Brandon-bld', - fontSize: (MediaQuery.of(context).size.height) *0.0410,//38, - ),), - ), - Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Container( - padding: EdgeInsets.only(top: 0, bottom: 0, left: 0, right: 0,), - child: Text("Don't have an account?", - style: TextStyle( - color: Color.fromRGBO(255, 255, 255, 100), - fontFamily: 'Brandon-med', - fontSize: (MediaQuery.of(context).size.height)*0.0194, - ),), - ), - Container( - padding: EdgeInsets.only(top: 0, bottom: 0, left: 0, right: 0,), - child: Text(" Sign Up", - style: TextStyle( - color: Color(0xffFFFEFE), - fontFamily: 'Brandon-med', - fontSize: (MediaQuery.of(context).size.height)*0.0194, - ),), - ), - ], - ), - SizedBox(height: (MediaQuery.of(context).size.height)*0.04535,), - Container( - //color: Colors.white, - height: (MediaQuery.of(context).size.height)*0.055, - //padding: EdgeInsets.fromLTRB(20.0, (MediaQuery.of(context).size.height - MediaQuery.of(context).padding.top)*0.0037797, 20.0, (MediaQuery.of(context).size.height - MediaQuery.of(context).padding.top)*0.0037797), - margin: EdgeInsets.only(top: 0, bottom: 0, left: (MediaQuery.of(context).size.width) *(45/428), right: (MediaQuery.of(context).size.width) *(45/428),), - decoration: BoxDecoration( - color: Colors.white, - borderRadius: BorderRadius.all(Radius.circular(10)), - border: Border.all( - color: _invalidUsername == true ? Colors.red : Color(0xff757575), - width: _invalidUsername == true ? 3 : 1, - ), - boxShadow: [ - BoxShadow( - color: Color(0xff0000004D), - ), - ], - ), - child: TextFormField( - keyboardType: TextInputType.emailAddress, - decoration: InputDecoration( - suffixIcon: _invalidUsername == true ? Text("! ", - style: TextStyle( - color: Colors.red, - fontSize: (MediaQuery.of(context).size.height)*(20/926), - fontFamily: 'Brandon-med', - ),) : Text(""), - suffixIconConstraints: BoxConstraints(minWidth: 0, minHeight: 0), - hintText: _dataPreviouslyStored == null ? "Loading..." : (_dataPreviouslyStored ? _email : "Username"), - hintStyle: TextStyle(color: _dataPreviouslyStored ? Color(0xff171616) : Color(0xffAEAEAE), - fontSize: (MediaQuery.of(context).size.height)*(20/926), - fontFamily: 'Brandon-med',), - contentPadding: EdgeInsets.fromLTRB(20.0, (MediaQuery.of(context).size.height)*0.0037797, 20.0, (MediaQuery.of(context).size.height)*0.0037797), - enabledBorder: OutlineInputBorder( - borderSide: BorderSide( - color: Colors.transparent, - width: 0.0, - ), - borderRadius: BorderRadius.circular(10.0), - ), - focusedBorder: OutlineInputBorder( - borderSide: BorderSide( - color: Colors.transparent, - width: 0.0, - ), - ), - ), - //validator: (val) => val!.isEmpty ? "Please enter a Username." : null, - onChanged: (val) { - _dataPreviouslyStored == null ? val = "" : - (_dataPreviouslyStored ? val = _email : _email = val); - //_email = val; - }, - style: TextStyle( - color: Colors.black, - fontSize: (MediaQuery.of(context).size.height)*(20/926), - fontFamily: 'Brandon-med', - ), - ), - ), - SizedBox(height: (MediaQuery.of(context).size.height)*0.0226781,), - Container( - //color: Colors.white, - height: (MediaQuery.of(context).size.height)*0.055, - margin: EdgeInsets.only(top: 0, bottom: 0, left: (MediaQuery.of(context).size.width) *(45/428), right: (MediaQuery.of(context).size.width) *(45/428),), - decoration: BoxDecoration( - color: Colors.white, - borderRadius: BorderRadius.all(Radius.circular(10)), - border: Border.all( - color: _invalidPassword == true ? Colors.red : Color(0xff757575), - width: _invalidPassword == true ? 3 : 1, - ), - boxShadow: [ - BoxShadow( - color: Color(0xff0000004D), - ), - ], - ), - child: TextFormField( - //keyboardType: TextInputType.visiblePassword, - obscureText: true, - decoration: InputDecoration( - suffixIcon: _invalidPassword == true ? Text("! ", - style: TextStyle( - color: Colors.red, - fontSize: (MediaQuery.of(context).size.height)*(20/926), - fontFamily: 'Brandon-med', - ),) : Text(""), - suffixIconConstraints: BoxConstraints(minWidth: 0, minHeight: 0), - hintText: _dataPreviouslyStored == null ? "Loading..." : (_dataPreviouslyStored ? _password : "Password"), - hintStyle: TextStyle(color: _dataPreviouslyStored ? Colors.black : Color(0xffAEAEAE), - fontSize: (MediaQuery.of(context).size.height)*(20/926), - fontFamily: 'Brandon-med',), - contentPadding: EdgeInsets.fromLTRB(20.0, (MediaQuery.of(context).size.height)*0.0037797, 20.0, (MediaQuery.of(context).size.height)*0.0037797), - enabledBorder: OutlineInputBorder( - borderSide: BorderSide( - color: Colors.transparent, - width: 0.0, - ), - borderRadius: BorderRadius.circular(10.0), - ), - focusedBorder: OutlineInputBorder( - borderSide: BorderSide( - color: Colors.transparent, - width: 0.0, - ), - ), - ), - //validator: (val) => val!.isEmpty ? "Please enter a Password." : null, - onChanged: (val) { - setState(() { - _dataPreviouslyStored == null ? val = "" : - (_dataPreviouslyStored ? val = _password : _password = val); - }); - }, - style: TextStyle( - color: Colors.black, - fontSize: (MediaQuery.of(context).size.height)*(20/926), - fontFamily: 'Brandon-med', - ), - ), - ), - SizedBox(height: (MediaQuery.of(context).size.height)*0.024838,), - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - GestureDetector( - onTap: () { - if(_isChecked == false) - setState(() { - _isChecked = true; - }); - else if(_isChecked == true) - setState(() { - _isChecked = false; - }); - }, - child: Row( - mainAxisAlignment: MainAxisAlignment.start, - children: [ - Container( - margin: EdgeInsets.only(top: 0, bottom: 0, left: (MediaQuery.of(context).size.width) *(45/428), right: 0,), - height: (MediaQuery.of(context).size.height)*0.0167, - width: (MediaQuery.of(context).size.height)*0.0167, - color: Colors.white, - child: Transform.scale( - scale: (MediaQuery.of(context).size.height)*0.001, - child: Checkbox( - side: BorderSide( - color: Color(0xffB0A6C2), - width: 0, - ), - checkColor: Colors.white, - value: _isChecked, - onChanged: (bool? value) { - setState(() { - _isChecked = value!; - }); - }, - ), - ), - ), - Container( - padding: EdgeInsets.only(top: 0, bottom: 0, left: (MediaQuery.of(context).size.width) *(5/428), right: 0,), - child: Text("Remember me!", - style: TextStyle( - color: Color.fromRGBO(255, 255, 255, 100), - fontFamily: 'Brandon-med', - fontSize: (MediaQuery.of(context).size.height)*0.0161987, - ),), - ), - ], - ), - ), - Container( - padding: EdgeInsets.only(top: 0, bottom: 0, left: 0, right: (MediaQuery.of(context).size.width) *(45/428),), - child: Text("Forgot Password?", - style: TextStyle( - color: Color(0xffFFFEFE), - fontFamily: 'Brandon-med', - fontSize: (MediaQuery.of(context).size.height)*0.0161987, - ),), - ), - ], - ), - _isLoggingIn ? Container() : SizedBox(height: (MediaQuery.of(context).size.height) *0.0864,), - _isLoggingIn ? Container( - height: (MediaQuery.of(context).size.height) *0.0864, - child: Container( - alignment: Alignment.center, - height: (MediaQuery.of(context).size.height) *0.0664, - child: CircularProgressIndicator(color: Colors.white,)), - ) : Container(), - ], - ), - ), - SizedBox(height: (MediaQuery.of(context).size.height) *(25/926),), - ], - ), - // GestureDetector( - // child: Container(//Login button - // child: Align( - // alignment: Alignment.center, - // child: SvgPicture.asset( - // "assets/Images/login.svg", - // height: (MediaQuery.of(context).size.height) *0.0486, - // ), - // ), - // ), - // onTap: () { - // if(_formKey.currentState!.validate()) { - // //_navigateAndDisplaySelection(context); - // //print(_isChecked); - // getUserData(context, _email, _password); - // } - // }, - // ), - Container( - height: (MediaQuery.of(context).size.height) *(45/926), - width: (MediaQuery.of(context).size.width) *(150/428), - decoration: BoxDecoration( - gradient: LinearGradient( - begin: Alignment.centerLeft, - end: Alignment.centerRight, - colors: [ - Color(0xff7F1AF1), - Color(0xff482384) - ]), - borderRadius: new BorderRadius.only( - bottomLeft: const Radius.circular(20.0), - topRight: const Radius.circular(20.0), - ) - ), - child: TextButton( - style: TextButton.styleFrom( - padding: EdgeInsets.zero, - ), - onPressed: () { - // setState(() { - // _isLoggingIn = !_isLoggingIn; - // }); - if(_formKey.currentState!.validate()) { - //_navigateAndDisplaySelection(context); - // print(_isChecked); - getUserData(context, _email, _password); - } - }, - child: Text("Login", - style: TextStyle( - color: Color(0xffFFFEFE), - fontFamily: 'Brandon-bld', - fontSize: (MediaQuery.of(context).size.height)*(25/926), - ),), - ), - ), - ], - ), - ), - ), - ), - AnimatedCrossFade( - crossFadeState: _loaded ? CrossFadeState.showFirst : CrossFadeState.showSecond, - duration: _duration, - secondChild: Container( - height: (MediaQuery.of(context).size.height) *0.183, - child: Text("")), - firstChild: Row( - mainAxisAlignment: MainAxisAlignment.end, - //crossAxisAlignment: CrossAxisAlignment.end, - children: [ - Stack( - //alignment: Alignment.centerRight, - children: [ - Positioned( - left: (MediaQuery.of(context).size.height) *(80/926), - top: (MediaQuery.of(context).size.height) *(50/926), - child: Align( - alignment: Alignment.bottomRight, - child: SvgPicture.asset( - "assets/Images/login_bottomRight.svg", - height: (MediaQuery.of(context).size.height) *0.183, - width: (MediaQuery.of(context).size.height) *0.183, - ), - ), - ), - Positioned(//Remove and add again - child: Align( - alignment: Alignment.bottomRight, - child: SvgPicture.asset( - "assets/Images/login_bottomRight.svg", - height: (MediaQuery.of(context).size.height) *0.183, - width: (MediaQuery.of(context).size.height) *0.183, - color: Colors.transparent, - ), - ), - ), - ], - ), - ], - ), - ), - ], - ), - ), - ), - ), - ), - ); - } -} diff --git a/lib/screens/Welcome/GenerateQuiz/difficulty.dart b/lib/screens/Welcome/GenerateQuiz/difficulty.dart deleted file mode 100644 index cc6ca55..0000000 --- a/lib/screens/Welcome/GenerateQuiz/difficulty.dart +++ /dev/null @@ -1,281 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:flutter_svg/flutter_svg.dart'; -import 'package:testify/screens/Authentication/login.dart'; -import 'package:testify/screens/Welcome/GenerateQuiz/generate_quiz_last.dart'; -import 'package:testify/screens/Welcome/GenerateQuiz/question_types.dart'; -import 'package:testify/screens/Welcome/side_menu_bar.dart'; - -class Difficulty extends StatefulWidget { - @override - State createState() => _DifficultyState(); -} - -class _DifficultyState extends State { - //Fields - - @override - Widget build(BuildContext context) { - return Scaffold( - backgroundColor: Color(0xffF8F9FB), - drawer: SideMenuBar(), - appBar: AppBar( - backgroundColor: Color(0xff3F2668), - elevation: 2, - centerTitle: true, - flexibleSpace: Container( - decoration: BoxDecoration( - gradient: LinearGradient( - begin: Alignment.topCenter, - end: Alignment.bottomCenter, - colors: [ - Color(0xff7F1AF1), - Color(0xff482384) - ]) - ), - ), - title: const Text("Generate Quiz", - style: TextStyle( - color: Color(0xffFFFEFE), - fontFamily: 'Brandon-bld', - ), - ), - actions: [ - TextButton( - onPressed: () async { - final result = await Navigator.push( - context, - MaterialPageRoute(builder: (context) => const Login(fromWhere:"Home")), - ); - }, - child: const Icon( - Icons.logout, - color: Colors.white, - ), - ), - ], - ), - body: Container( - padding: EdgeInsets.only(top:(MediaQuery.of(context).size.height) *(15/926), - bottom: (MediaQuery.of(context).size.height) *(8/926), - left: (MediaQuery.of(context).size.width) *(18/428), - right: (MediaQuery.of(context).size.width) *(18/428)), - child: Column( - children: [ - Row( - children: [ - Container( - width: (MediaQuery.of(context).size.width) *(221/428), - //height: (MediaQuery.of(context).size.height) *(91/926), - child: Column( - children: [ - Align( - alignment: Alignment.topLeft, - child: Text("Create Quiz", - style: TextStyle( - color: Color(0xff232323), - fontFamily: 'Brandon-bld', - fontSize: (MediaQuery.of(context).size.height) *(20/926),//38, - ),), - ), - SizedBox(height: (MediaQuery.of(context).size.height) *(2/926),), - Text("Lorem ipsum dolor sit amet, consectetur adipiscing elit. Cras imperdiet finibus elit non luctus. Morbi auctor mattis ante.", - style: TextStyle( - color: Color(0xFF483A3A), - fontFamily: 'Brandon-med', - fontSize: (MediaQuery.of(context).size.height) *(10/926),//38, - ),), - ], - ), - ), - SizedBox(width: (MediaQuery.of(context).size.width) *(39/428),), - Container( - //color: Colors.transparent, - child: SvgPicture.asset( - "assets/Images/create_quiz.svg", - height: (MediaQuery.of(context).size.height) *(100/926), - //width: (MediaQuery.of(context).size.width) *(132/428), - ), - ), - ], - ), - SizedBox(height: (MediaQuery.of(context).size.height) *(25/926),), - //a - Container( - height: (MediaQuery.of(context).size.height) *(35.32/926), - decoration: BoxDecoration( - color: Color(0xff3F2668),//0xffB0A6C2, rgba(176, 166, 194, 1) - borderRadius: BorderRadius.only(topLeft: Radius.circular(50), topRight: Radius.circular(50)), - boxShadow: [ - BoxShadow( - color: Colors.black12,//Color(0xff00000029), - spreadRadius: 5, - blurRadius: 5, - offset: Offset(0, 0), - ), - ], - ), - child: Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - SizedBox(width: (MediaQuery.of(context).size.width) *(28/428),), - Container( - padding: EdgeInsets.only(top: (MediaQuery.of(context).size.height) *(9/926), bottom: (MediaQuery.of(context).size.height) *(4/926)), - height: (MediaQuery.of(context).size.height) *(35.32/926), - width: (MediaQuery.of(context).size.width) *(113/428), - color: Color(0xFF3F2668), - child: Column( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Text(" Systems/Subjects/Topics ", - style: TextStyle( - color: Color(0xffFEFEFE), - fontFamily: 'Brandon-bld', - fontSize: (MediaQuery.of(context).size.height) *(12/926), - ),), - ], - ), - ), - Container( - padding: EdgeInsets.only(top: (MediaQuery.of(context).size.height) *(5/926), bottom: (MediaQuery.of(context).size.height) *(5/926)), - height: (MediaQuery.of(context).size.height) *(35.32/926), - width: (MediaQuery.of(context).size.width) *(80/428), - color: Color(0xFF3F2668), - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Text("Question Types", - style: TextStyle( - color: Color(0xffFEFEFE), - fontFamily: 'Brandon-bld', - fontSize: (MediaQuery.of(context).size.height) *(12/926), - ),), - ], - ), - ), - Container( - padding: EdgeInsets.only(top: (MediaQuery.of(context).size.height) *(5/926), bottom: (MediaQuery.of(context).size.height) *(5/926)), - height: (MediaQuery.of(context).size.height) *(35.32/926), - width: (MediaQuery.of(context).size.width) *(65/428), - color: Colors.white, - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Text("Difficulty", - style: TextStyle( - color: Color(0xFF3F2668),//0xFF3F2668 - fontFamily: 'Brandon-bld', - fontSize: (MediaQuery.of(context).size.height) *(12/926), - ),), - Container( - padding: EdgeInsets.only(left: (MediaQuery.of(context).size.width) *(13/428), right: (MediaQuery.of(context).size.width) *(13/428)), - //margin: EdgeInsets.only(top: (MediaQuery.of(context).size.height) *(1/926)), - child: Divider(height: 3, - thickness: 2, - color: Color(0xFF3F2668),), - ), - ], - ), - ), - Container( - padding: EdgeInsets.only(top: (MediaQuery.of(context).size.height) *(5/926), bottom: (MediaQuery.of(context).size.height) *(5/926)), - height: (MediaQuery.of(context).size.height) *(35.32/926), - width: (MediaQuery.of(context).size.width) *(75/428), - color: Color(0xFF3F2668), - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Text("Generate Quiz", - style: TextStyle( - color: Color(0xffFEFEFE), - fontFamily: 'Brandon-bld', - fontSize: (MediaQuery.of(context).size.height) *(12/926), - ),), - ], - ), - ), - SizedBox(width: (MediaQuery.of(context).size.width) *(28/428),), - ], - ), - ), - SizedBox(height: (MediaQuery.of(context).size.height) *(15.28/926),), - Container( - height: (MediaQuery.of(context).size.height) *(167.52/926), - color: Colors.red, - ), - SizedBox(height: (MediaQuery.of(context).size.height) *(10.74/926),), - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - InkWell( - child: Container( - height: (MediaQuery.of(context).size.height) *(42/926), - width: (MediaQuery.of(context).size.width) *(68/428), - decoration: BoxDecoration( - color: Color(0xff3F2668),//0xffB0A6C2, rgba(176, 166, 194, 1) - borderRadius: BorderRadius.all(Radius.circular(3)), - boxShadow: [ - BoxShadow( - color: Colors.black12,//Color(0xff00000029), - spreadRadius: 2, - blurRadius: 2, - offset: Offset(0, 0), - ), - ], - ), - child: TextButton( - onPressed: () { - Navigator.pop(context); - }, - child: Center( - child: Text("Back", - style: TextStyle( - color: Colors.white, - fontFamily: 'Brandon-med', - ), - ), - ), - ), - ), - ), - InkWell( - child: Container( - height: (MediaQuery.of(context).size.height) *(42/926), - width: (MediaQuery.of(context).size.width) *(68/428), - decoration: BoxDecoration( - color: Color(0xff3F2668),//0xffB0A6C2, rgba(176, 166, 194, 1) - borderRadius: BorderRadius.all(Radius.circular(3)), - boxShadow: [ - BoxShadow( - color: Colors.black12,//Color(0xff00000029), - spreadRadius: 2, - blurRadius: 2, - offset: Offset(0, 0), - ), - ], - ), - child: TextButton( - onPressed: () async { - final result = await Navigator.push( - context, - MaterialPageRoute(builder: (context) => GenerateQuizLast()), - ); - }, - child: Center( - child: Text("Next", - style: TextStyle( - color: Colors.white, - fontFamily: 'Brandon-med', - ), - ), - ), - ), - ), - ), - ], - ), - ], - ), - ), - ); - } -} \ No newline at end of file diff --git a/lib/screens/Welcome/GenerateQuiz/generate_quiz.dart b/lib/screens/Welcome/GenerateQuiz/generate_quiz.dart deleted file mode 100644 index 0326fc7..0000000 --- a/lib/screens/Welcome/GenerateQuiz/generate_quiz.dart +++ /dev/null @@ -1,1598 +0,0 @@ -import 'dart:convert'; -import 'package:flutter/services.dart'; - -import 'package:flutter/cupertino.dart'; -import 'package:http/http.dart' as http; - -import 'package:flutter/material.dart'; -import 'package:flutter_svg/flutter_svg.dart'; -import 'package:shared_preferences/shared_preferences.dart'; -import 'package:testify/models/GenerateQuizModels/get_system_categories_successful.dart'; -import 'package:testify/models/GenerateQuizModels/get_system_categories_unsuccessful.dart'; -import 'package:testify/screens/Authentication/login.dart'; -import 'package:testify/screens/Welcome/QuizModule/quiz_module.dart'; -import 'package:testify/screens/Welcome/side_menu_bar.dart'; -import 'dart:math' as math; - -class GenerateQuiz extends StatefulWidget { - @override - State createState() => _GenerateQuizState(); -} - -class _GenerateQuizState extends State with SingleTickerProviderStateMixin { - late TabController _tabController; - - // Once the data is loaded only then it shows the containers. - bool _hasDataLoaded = false; - - //Total Questions returned by the API. - // First gets its value when getUserData is run and then gets updated as getQuestionCounts is run. - int _totalQuestions = 0; - List _questions = []; - - //Tab 1 Data: - //Not allowing Subjects or topics to be selected if Systems is empty - bool _systemsDisabled = true; - bool _topicsDisabled = true; - //Title, ID, questions(total questions available), isSelected(which checkbox is clicked), finalTitles(titles that work on getQuestionsCount). - var systemsEverything = { - "title": [], // Saves titles - "finalTitles": [], // Save the final titles that are to be sent to getQuestionsCount - "ID": [], // Saves IDs - "questions": [], // Saves questions - "isSelected": [] // Whichever checkbox is true that bool turns true. - }; - - // Tab 2 Data: - var subjectsEverything = { - "title": [], - "finalTitles": [], // Save the final titles that are to be sent to getQuestionsCount - "ID": [], - "questions": [], - "isSelected": [] - }; - - // Tab 3 Data: - var topicsEverything = { - "title": [], - "finalTitles": [], // Save the final titles that are to be sent to getQuestionsCount - "ID": [], - "questions": [], - "isSelected": [] - }; - - //Tab 4 Data: - //If no option is selected everything stays false and zero is sent. - /*None is not populated*/ - List _questionTypesTitle = ["None", "Unused Questions", "Incorrect Questions", "Correct Questions", "Omitted Questions", "Marked Questions", "All"]; - List _questionTypeSelectedBool = [true, false, false, false, false, false, false]; - int _questionTypeInt = 0; - - //Tab 5 Data: - List _difficultyLevelTitle = ["Very Easy", "Easy", "Medium", "Hard", "Very Hard"]; - List _difficultyLevelBool = [false, false, false, false, false]; - List _difficultyLevel = []; - //Generate Quiz - bool _tutorMode = true; - bool _timedMode = false; - // Just a form key for the questionCount - final _numberOfQuestionsKey = GlobalKey(); - var _questionsCount; - - //Shared Pref - var _token; - var _userId; - - // Token Valid - var _getSystemCategoriesSuccessful; - // Token Incorrect - var _getSystemCategoriesUnsuccessful; - - //When getQuestionCount is run(Just used to get the totalQuestions - var _getQuestionsCountCategoriesSuccessful; - var _getQuestionsCountCategoriesUnsuccessful; - - @override - void initState() { - super.initState(); - _tabController = TabController(vsync: this, length: 5); - getUserDataSST(); - } - - //This is run only once. - Future getUserDataSST() async { - SharedPreferences prefs = await SharedPreferences.getInstance(); - final String apiUrlSystemCategories = "https://demo.pookidevs.com/quiz/generator/getAllCategories"; - _token = prefs.getString('token')!; - _userId = prefs.getInt("userId")!; - http.get(Uri.parse(apiUrlSystemCategories), headers: { - 'Content-type': 'application/json; charset=UTF-8', 'Authorization' : _token.toString(), - },).then((response) { - // print(jsonDecode(response.body).toString()); - if(response.statusCode == 200) { - if(json.decode(response.body).toString().substring(0,20) == "{data: {status: true") { - final responseString = (response.body); - var systemCategoriesDataSuccessful = getSystemCategoriesSuccessfulModelFromJson(responseString); - final GetSystemCategoriesSuccessfulModel getSystemCategoriesSuccessful = systemCategoriesDataSuccessful; - setState(() { - _getSystemCategoriesSuccessful = getSystemCategoriesSuccessful; - _hasDataLoaded = true; - _totalQuestions = _getSystemCategoriesSuccessful.data.totalQuestions; - _questions = _getSystemCategoriesSuccessful.data.questions; - }); - // print(_questions); - } else { - - } - //Adds data to lists - categorizeUserData(); - } - else { // Status Code is 401 here that is why if written in the above if statement it would not work. - //Token is Invalid - if(json.decode(response.body).toString().substring(0,14) == "{status: false") { - final responseString = (response.body); - var systemCategoriesDataUnsuccessful = getSystemCategoriesUnsuccessfulModelFromJson(responseString); - final GetSystemCategoriesUnsuccessfulModel getSystemCategoriesUnsuccessful = systemCategoriesDataUnsuccessful; - setState(() { - _getSystemCategoriesUnsuccessful = getSystemCategoriesUnsuccessful; - }); - print(_getSystemCategoriesUnsuccessful.msg); - ScaffoldMessenger.of(context) - ..removeCurrentSnackBar() - ..showSnackBar(SnackBar(content: Text("Token Expired!"))); - final result = Navigator.push( - context, - MaterialPageRoute(builder: (context) => const Login(fromWhere:"Home")), - ); - } - else { - - } - } - } - ); - } - - Future getQuestionsCount() async { - // print(subjectsEverything["finalTitles"]); - // print(systemsEverything["finalTitles"]); - // print(topicsEverything["finalTitles"]); - // print(_userId); - // print(_questionTypeInt); - // print(_difficultyLevel); - - final String apiUrl = "https://demo.pookidevs.com/quiz/generator/getQuestionCounts"; - http.post(Uri.parse(apiUrl), headers: { - 'Content-type': 'application/json; charset=UTF-8', 'Authorization' : _token.toString(), - }, body: json.encode( - { - "data": - { - "subjects": subjectsEverything["finalTitles"], - "systems": systemsEverything["finalTitles"], - "topics": topicsEverything["finalTitles"], - "userId": _userId, // Add _userId here. - "statusLevels": _questionTypeInt, // Add _questionType here - "difficultyLevels": _difficultyLevel, // Add _difficultyLevels here - } - }) - ).then((response) { - if(response.statusCode == 200) { - // print("getQuestionsCount() : " + response.body.toString()); - if(json.decode(response.body).toString().substring(0,20) == "{data: {status: true") { - final responseString = (response.body); - var QuestionsCountCategoriesSuccessful = getSystemCategoriesSuccessfulModelFromJson(responseString); - final GetSystemCategoriesSuccessfulModel getQuestionsCountCategoriesSuccessful = QuestionsCountCategoriesSuccessful; - setState(() { - _getQuestionsCountCategoriesSuccessful = getQuestionsCountCategoriesSuccessful; - _totalQuestions = _getQuestionsCountCategoriesSuccessful.data.totalQuestions; - _questions = _getQuestionsCountCategoriesSuccessful.data.questions; - }); - // print(_getSystemCategoriesSuccessful); - print(_totalQuestions); - print(_questions); - } else { - - } - } else { - //Token is Invalid - if(json.decode(response.body).toString().substring(0,14) == "{status: false") { - final responseString = (response.body); - var QuestionsCountCategoriesDataUnsuccessful = getSystemCategoriesUnsuccessfulModelFromJson(responseString); - final GetSystemCategoriesUnsuccessfulModel getQuestionsCountCategoriesUnsuccessful = QuestionsCountCategoriesDataUnsuccessful; - setState(() { - _getQuestionsCountCategoriesUnsuccessful = getQuestionsCountCategoriesUnsuccessful; - }); - print(_getQuestionsCountCategoriesUnsuccessful.msg); - ScaffoldMessenger.of(context) - ..removeCurrentSnackBar() - ..showSnackBar(SnackBar(content: Text("Token Expired!"))); - final result = Navigator.push( - context, - MaterialPageRoute(builder: (context) => const Login(fromWhere:"Home")), - ); - } - else { - - } - } - }); - - } - - //Add data to lists. Only done the first time. - categorizeUserData() { - //To clear any past data - int c = 0; - while((c<_getSystemCategoriesSuccessful.data.categories.toList().length) & (_getSystemCategoriesSuccessful.data.categories.toList().length > 0)) { - var tempLength = _getSystemCategoriesSuccessful.data.categories.toList().length; - if(_getSystemCategoriesSuccessful.data.categories[c].subCategories != null) { - if(_getSystemCategoriesSuccessful.data.categories[c].parentCategory.toString() == "systems") { - //Gets the length of subjects(Number of Subjects) - var lenSystems = _getSystemCategoriesSuccessful.data.categories[c].subCategories.toList().length; - int i = 0; - setState(() { - while((lenSystems>0) & (i0) & (i0) & (i[ - Color(0xff7F1AF1), - Color(0xff482384) - ]) - ), - ), - title: const Text("Generate Quiz", - style: TextStyle( - color: Color(0xffFFFEFE), - fontFamily: 'Brandon-bld', - ), - ), - actions: [ - TextButton( - onPressed: () async { - final result = await Navigator.push( - context, - MaterialPageRoute(builder: (context) => const Login(fromWhere:"Home")), - ); - }, - child: SvgPicture.asset( - "assets/Images/logout.svg", - height: (MediaQuery.of(context).size.height) *(32/926), - ), - ), - ], - ), - body: SingleChildScrollView( - child: Container( - padding: EdgeInsets.only(top:(MediaQuery.of(context).size.height) *(15/926), - bottom: (MediaQuery.of(context).size.height) *(8/926), - left: (MediaQuery.of(context).size.width) *(18/428), - right: (MediaQuery.of(context).size.width) *(18/428)), - child: Column( - children: [ - Row( - children: [ - Container( - width: (MediaQuery.of(context).size.width) *(221/428), - //height: (MediaQuery.of(context).size.height) *(91/926), - child: Column( - children: [ - Align( - alignment: Alignment.topLeft, - child: Text("Create Quiz", - style: TextStyle( - color: Color(0xff232323), - fontFamily: 'Brandon-bld', - fontSize: (MediaQuery.of(context).size.height) *(25/926),//38, - ),), - ), - SizedBox(height: (MediaQuery.of(context).size.height) *(2/926),), - Text("Lorem ipsum dolor sit amet, consectetur adipiscing elit. Cras imperdiet finibus elit non luctus. Morbi auctor mattis ante.", - style: TextStyle( - color: Color(0xFF483A3A), - fontFamily: 'Brandon-med', - fontSize: (MediaQuery.of(context).size.height) *(13/926),//38, - ),), - ], - ), - ), - SizedBox(width: (MediaQuery.of(context).size.width) *(39/428),), - Container( - //color: Colors.transparent, - child: SvgPicture.asset( - "assets/Images/create_quiz.svg", - height: (MediaQuery.of(context).size.height) *(100/926), - //width: (MediaQuery.of(context).size.width) *(132/428), - ), - ), - ], - ), - SizedBox(height: (MediaQuery.of(context).size.height) *(25/926),), - SizedBox(height: (MediaQuery.of(context).size.height) *(13.28/926),), - Container( - height: (MediaQuery.of(context).size.height) *(596/926), - width: double.infinity, - child: TabBarView( - // physics: NeverScrollableScrollPhysics(), - controller: _tabController, - children: [ - //Tab1: Subjects - Column( - children: [ - Container( - height: (MediaQuery.of(context).size.height) *(40.32/926), - width: (MediaQuery.of(context).size.width) *(386/428), - decoration: BoxDecoration( - color: Color(0xFF3F2668), - borderRadius: BorderRadius.only(bottomLeft: Radius.circular(15.0), topRight: Radius.circular(15.0),), - boxShadow: [ - BoxShadow( - color: Colors.black12, - spreadRadius: 2, - blurRadius: 2, - offset: Offset(0, 0), - ), - ], - ), - child: Center( - child: Text("Select Subjects", - style: TextStyle( - color: Colors.white, - fontFamily: 'Brandon-bld', - fontSize: (MediaQuery.of(context).size.height) *(26.31/926),//38, - ),), - ), - ), - SizedBox(height: (MediaQuery.of(context).size.height) *(33/926)), - Container( - padding: EdgeInsets.only(left: (MediaQuery.of(context).size.width) *(10/428), right: (MediaQuery.of(context).size.width) *(10/428)), - width: (MediaQuery.of(context).size.width) *(366/428), - child: _hasDataLoaded == false ? - Container(height: (MediaQuery.of(context).size.height) *(460/926),child: Center(child: CircularProgressIndicator(color: Color(0xFF3F2668),))) - : - Container( - height: (MediaQuery.of(context).size.height) *(460/926), - child: ListView( - scrollDirection: Axis.vertical, - children: [ - Container( - height: (MediaQuery.of(context).size.height) *(120.9/926), - child: GridView( - gridDelegate: SliverGridDelegateWithFixedCrossAxisCount( - crossAxisCount: 2, - crossAxisSpacing: (MediaQuery.of(context).size.width) *(30/428), - mainAxisExtent: (MediaQuery.of(context).size.height) *(40.224/926),), - children: [ - for(int i = 0; i 0) { - setState(() { - _systemsDisabled = false; - }); - } - - //Unchecking the previously checked boxes. - if(subjectsEverything["isSelected"]![i] == false) { - if(systemsEverything["isSelected"]!.length > 0) { - for(int i = 0; i 0) { - for(int i = 0; i[ - for(int i = 0; i 0) { - setState(() { - _topicsDisabled = false; - }); - } - - //Unchecking the previously checked boxes. - if(systemsEverything["isSelected"]![i] == false) { - // topicsEverything - if(topicsEverything["isSelected"]!.length > 0) { - for(int i = 0; i AlertDialog( - content: Text( - 'Select Subjects First!', - style: TextStyle( - color: Color(0xffA1A1A1), - fontFamily: 'Brandon-bld', - fontSize: (MediaQuery.of(context).size.height) * (21 / 926), - ), - ), - actions: [ - Divider(), - TextButton( - onPressed: () { - Navigator.of(context).pop(); - }, - child: Text('Okay', - style: TextStyle( - color: Color(0xff3F2668), - fontFamily: 'Brandon-bld', - fontSize: - (MediaQuery.of(context).size.height) * (21 / 926), - )), - ), - ], - ), - ); - } - }, - ), - ), - ], - ) - ), - ], - ), - ), - ), - SizedBox(height: (MediaQuery.of(context).size.height) *(10.74/926),), - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - InkWell( - child: Container( - height: (MediaQuery.of(context).size.height) *(42/926), - width: (MediaQuery.of(context).size.width) *(68/428), - decoration: BoxDecoration( - color: Color(0xff3F2668),//0xffB0A6C2, rgba(176, 166, 194, 1) - borderRadius: BorderRadius.all(Radius.circular(3)), - boxShadow: [ - BoxShadow( - color: Colors.black12,//Color(0xff00000029), - spreadRadius: 2, - blurRadius: 2, - offset: Offset(0, 0), - ), - ], - ), - child: TextButton( - onPressed: () { - //Animates to next tab - _backTab(); - }, - child: Center( - child: Text("Back", - style: TextStyle( - color: Colors.white, - fontFamily: 'Brandon-med', - ), - ), - ), - ), - ), - ), - InkWell( - child: Container( - height: (MediaQuery.of(context).size.height) *(42/926), - width: (MediaQuery.of(context).size.width) *(68/428), - decoration: BoxDecoration( - color: Color(0xff3F2668),//0xffB0A6C2, rgba(176, 166, 194, 1) - borderRadius: BorderRadius.all(Radius.circular(3)), - boxShadow: [ - BoxShadow( - color: Colors.black12,//Color(0xff00000029), - spreadRadius: 2, - blurRadius: 2, - offset: Offset(0, 0), - ), - ], - ), - child: TextButton( - onPressed: () { - //Animates to next tab - _nextTab(); - }, - child: Center( - child: Text("Next", - style: TextStyle( - color: Colors.white, - fontFamily: 'Brandon-med', - ), - ), - ), - ), - ), - ), - ], - ), - ], - ), - - //Tab3: Topics - Column( - children: [ - Container( - height: (MediaQuery.of(context).size.height) *(40.32/926), - width: (MediaQuery.of(context).size.width) *(366/428), - //color: Colors.red, - decoration: BoxDecoration( - color: Color(0xFF3F2668),//0xffB0A6C2, rgba(176, 166, 194, 1) - borderRadius: BorderRadius.only(bottomLeft: Radius.circular(15.0), topRight: Radius.circular(15.0),), - boxShadow: [ - BoxShadow( - color: Colors.black12,//Color(0xff00000029), - spreadRadius: 2, - blurRadius: 2, - offset: Offset(0, 0), - ), - ], - ), - child: Center( - child: Text("Select Topics", - style: TextStyle( - color: Colors.white, - fontFamily: 'Brandon-bld', - fontSize: (MediaQuery.of(context).size.height) *(26.31/926),//38, - ),), - ), - ), - SizedBox(height: (MediaQuery.of(context).size.height) *(33/926)), - Container( - padding: EdgeInsets.only(left: (MediaQuery.of(context).size.width) *(10/428), right: (MediaQuery.of(context).size.width) *(10/428)), - width: (MediaQuery.of(context).size.width) *(366/428), - child: Container( - height: (MediaQuery.of(context).size.height) *(460/926), - child: _hasDataLoaded == false ? Text("") : ListView( - scrollDirection: Axis.vertical, - children: [ - Container( - height: (MediaQuery.of(context).size.height) *(120.9/926), - child: GridView( - gridDelegate: SliverGridDelegateWithFixedCrossAxisCount( - crossAxisCount: 2, - crossAxisSpacing: (MediaQuery.of(context).size.width) *(30/428), - mainAxisExtent: (MediaQuery.of(context).size.height) *(40.224/926),), - children: [ - for(int i = 0; i AlertDialog( - content: Text( - 'Select Systems First!', - style: TextStyle( - color: Color(0xffA1A1A1), - fontFamily: 'Brandon-bld', - fontSize: (MediaQuery.of(context).size.height) * (21 / 926), - ), - ), - actions: [ - Divider(), - TextButton( - onPressed: () { - Navigator.of(context).pop(); - }, - child: Text('Okay', - style: TextStyle( - color: Color(0xff3F2668), - fontFamily: 'Brandon-bld', - fontSize: - (MediaQuery.of(context).size.height) * (21 / 926), - )), - ), - ], - ), - ); - } - // print(subjectsEverything["finalTitles"]); - // print(systemsEverything["finalTitles"]); - // print(topicsEverything["finalTitles"]); - getQuestionsCount(); - }, - ), - ), - ], - ) - ), - ], - ), - ), - ), - SizedBox(height: (MediaQuery.of(context).size.height) *(10.74/926),), - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - InkWell( - child: Container( - height: (MediaQuery.of(context).size.height) *(42/926), - width: (MediaQuery.of(context).size.width) *(68/428), - decoration: BoxDecoration( - color: Color(0xff3F2668),//0xffB0A6C2, rgba(176, 166, 194, 1) - borderRadius: BorderRadius.all(Radius.circular(3)), - boxShadow: [ - BoxShadow( - color: Colors.black12,//Color(0xff00000029), - spreadRadius: 2, - blurRadius: 2, - offset: Offset(0, 0), - ), - ], - ), - child: TextButton( - onPressed: () { - //Animates to next tab - _backTab(); - }, - child: Center( - child: Text("Back", - style: TextStyle( - color: Colors.white, - fontFamily: 'Brandon-med', - ), - ), - ), - ), - ), - ), - InkWell( - child: Container( - height: (MediaQuery.of(context).size.height) *(42/926), - width: (MediaQuery.of(context).size.width) *(68/428), - decoration: BoxDecoration( - color: Color(0xff3F2668),//0xffB0A6C2, rgba(176, 166, 194, 1) - borderRadius: BorderRadius.all(Radius.circular(3)), - boxShadow: [ - BoxShadow( - color: Colors.black12,//Color(0xff00000029), - spreadRadius: 2, - blurRadius: 2, - offset: Offset(0, 0), - ), - ], - ), - child: TextButton( - onPressed: () { - //Animates to next tab - _nextTab(); - }, - child: Center( - child: Text("Next", - style: TextStyle( - color: Colors.white, - fontFamily: 'Brandon-med', - ), - ), - ), - ), - ), - ), - ], - ), - ], - ), - - //Tab4: Question Types - Column( - children: [ - Container( - height: (MediaQuery.of(context).size.height) *(40.32/926), - width: (MediaQuery.of(context).size.width) *(386/428), - //color: Colors.red, - decoration: BoxDecoration( - color: Color(0xFF3F2668),//0xffB0A6C2, rgba(176, 166, 194, 1) - borderRadius: BorderRadius.only(bottomLeft: Radius.circular(15.0), topRight: Radius.circular(15.0),), - boxShadow: [ - BoxShadow( - color: Colors.black12,//Color(0xff00000029), - spreadRadius: 2, - blurRadius: 2, - offset: Offset(0, 0), - ), - ], - ), - child: Center( - child: Text("Select Question Types", - style: TextStyle( - color: Colors.white, - fontFamily: 'Brandon-bld', - fontSize: (MediaQuery.of(context).size.height) *(26.31/926),//38, - ),), - ), - ), - SizedBox(height: (MediaQuery.of(context).size.height) *(33/926)), - Container( - padding: EdgeInsets.only(left: (MediaQuery.of(context).size.width) *(10/428), right: (MediaQuery.of(context).size.width) *(10/428)), - width: (MediaQuery.of(context).size.width) *(366/428), - height: (MediaQuery.of(context).size.height) *(460/926), - child: Column( - children: [ - for(int i = 1; i<7; i++) - Column( - children: [ - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Container( - height: (MediaQuery.of(context).size.height) *(40.224/926), - width: (MediaQuery.of(context).size.width) *(302/428), - color: _questionTypeSelectedBool[i] == false ? Colors.white : Color(0xFF3F2668), - child: TextButton( - style: TextButton.styleFrom( - padding: EdgeInsets.zero,), - child: Text(_questionTypesTitle[i], - style: TextStyle( - color: _questionTypeSelectedBool[i] == false ? Color(0xFF3F3D56) : Colors.white, - fontFamily: 'Brandon-med', - fontSize: (MediaQuery.of(context).size.height)*(15/926), - ),), - onPressed: () { - _questionTypesLogic(i); - getQuestionsCount(); - }, - ), - ), - _questionTypeSelectedBool[i] == false ? - GestureDetector( - onTap: () { - _questionTypesLogic(i); - getQuestionsCount(); - }, - child: Container( - height: (MediaQuery.of(context).size.height) *(34.224/926), - width: (MediaQuery.of(context).size.height) *(34.224/926), - // width: (MediaQuery.of(context).size.width) *(29.224/428), - decoration: BoxDecoration( - border: Border.all(width: 9, color: Color(0xFFA1A1A1)), - borderRadius: BorderRadius.all(Radius.circular(50)), - ), - ), - ) - : - GestureDetector( - onTap: () { - _questionTypesLogic(i); - getQuestionsCount(); - }, - child: Container( - child: Icon(Icons.check, - size: (MediaQuery.of(context).size.height) *(34.224/926), - color: Color(0xFF3F2668),) - ), - ), - ], - ), - SizedBox(height: (MediaQuery.of(context).size.height) *(25.224/926)), - ], - ), - ], - ), - ), - SizedBox(height: (MediaQuery.of(context).size.height) *(10.74/926),), - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - InkWell( - child: Container( - height: (MediaQuery.of(context).size.height) *(42/926), - width: (MediaQuery.of(context).size.width) *(68/428), - decoration: BoxDecoration( - color: Color(0xff3F2668),//0xffB0A6C2, rgba(176, 166, 194, 1) - borderRadius: BorderRadius.all(Radius.circular(3)), - boxShadow: [ - BoxShadow( - color: Colors.black12,//Color(0xff00000029), - spreadRadius: 2, - blurRadius: 2, - offset: Offset(0, 0), - ), - ], - ), - child: TextButton( - onPressed: () { - //Animates to next tab - _backTab(); - }, - child: Center( - child: Text("Back", - style: TextStyle( - color: Colors.white, - fontFamily: 'Brandon-med', - ), - ), - ), - ), - ), - ), - InkWell( - child: Container( - height: (MediaQuery.of(context).size.height) *(42/926), - width: (MediaQuery.of(context).size.width) *(68/428), - decoration: BoxDecoration( - color: Color(0xff3F2668),//0xffB0A6C2, rgba(176, 166, 194, 1) - borderRadius: BorderRadius.all(Radius.circular(3)), - boxShadow: [ - BoxShadow( - color: Colors.black12,//Color(0xff00000029), - spreadRadius: 2, - blurRadius: 2, - offset: Offset(0, 0), - ), - ], - ), - child: TextButton( - onPressed: () { - //Animates to next tab - _nextTab(); - }, - child: Center( - child: Text("Next", - style: TextStyle( - color: Colors.white, - fontFamily: 'Brandon-med', - ), - ), - ), - ), - ), - ), - ], - ), - ], - ), - - //Tab5: Generate Quiz - Column( - children: [ - Container( - height: (MediaQuery.of(context).size.height) *(40.32/926), - width: (MediaQuery.of(context).size.width) *(386/428), - //color: Colors.red, - decoration: BoxDecoration( - color: Color(0xFF3F2668),//0xffB0A6C2, rgba(176, 166, 194, 1) - borderRadius: BorderRadius.only(bottomLeft: Radius.circular(15.0), topRight: Radius.circular(15.0),), - boxShadow: [ - BoxShadow( - color: Colors.black12,//Color(0xff00000029), - spreadRadius: 2, - blurRadius: 2, - offset: Offset(0, 0), - ), - ], - ), - child: Center( - child: Text("Generate Quiz", - style: TextStyle( - color: Colors.white, - fontFamily: 'Brandon-bld', - fontSize: (MediaQuery.of(context).size.height) *(26.31/926),//38, - ),), - ), - ), - SizedBox(height: (MediaQuery.of(context).size.height) *(22.8/926)), - Container( - width: (MediaQuery.of(context).size.width) *(386/428), // 460/926 - height: (MediaQuery.of(context).size.height) *(460/926), - child: Column( - children: [ - Center( - child: Text("Set Difficulty Level", - style: TextStyle( - color: Color(0xFF232323), - fontFamily: 'Brandon-med', - fontSize: (MediaQuery.of(context).size.height) *(16/926), - ), - ), - ), - SizedBox(height: (MediaQuery.of(context).size.height) *(26.59/926),), - Row( - children: [ - for(int i = 1; i<6; i++) - Row( - children: [ - Container( - height: (MediaQuery.of(context).size.height) *(40.224/926), - width: (MediaQuery.of(context).size.width) *((60)/428), - color: _difficultyLevelBool[i-1] == false ? Color(0xFFE4E4E4) : Color(0xFF7F1AF1), - child: TextButton( - style: TextButton.styleFrom( - padding: EdgeInsets.zero,), - child: Text(_difficultyLevelTitle[i-1], - style: TextStyle( - color: _difficultyLevelBool[i-1] == false ? Color(0xFF3F2668) : Colors.white, - fontFamily: 'Brandon-med', - fontSize: (MediaQuery.of(context).size.height)*(13/926), - ),), - onPressed: () { - setState(() { - if(_difficultyLevelBool[i-1] == false) { - _difficultyLevelBool[i-1] = true; - _difficultyLevel.add(i); - } - else if(_difficultyLevelBool[i-1] == true) { - _difficultyLevelBool[i-1] = false; - _difficultyLevel.remove(i); - } - }); - getQuestionsCount(); - }, - ), - ), - if(i != 5) - // SizedBox(width: (MediaQuery.of(context).size.width) *(46/926)), - for(int j = 0; j<6; j++) - Row( - children: [ - Container( - child: Container( - height: (MediaQuery.of(context).size.height) *(2/926), - width: (MediaQuery.of(context).size.width) *(3.55/428), - decoration: BoxDecoration( - color: Color(0xFFE4E4E4), - shape: BoxShape.circle, - ), - ), - ), - ], - ) - ], - ), - ], - ), - SizedBox(height: (MediaQuery.of(context).size.height) *(48/926),), - Center( - child: Text("Generate Quiz", - style: TextStyle( - color: Color(0xFF232323), - fontFamily: 'Brandon-med', - fontSize: (MediaQuery.of(context).size.height) *(16/926), - ), - ), - ), - SizedBox(height: (MediaQuery.of(context).size.height) *(28/926),), - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Row( - children: [ - Container( - height: (MediaQuery.of(context).size.height) *(30/926), - width: (MediaQuery.of(context).size.width) *(98/428), - padding: EdgeInsets.zero, - margin: EdgeInsets.zero, - decoration: BoxDecoration( - color: _tutorMode? Color(0xff3F2668) : Colors.white, - border: Border.all(color: Color(0xff3F2668)), - borderRadius: BorderRadius.only(topLeft: Radius.circular(3), bottomLeft: Radius.circular(3)), - ), - //color: Colors.red, - child: InkWell( - onTap: () { - if(_tutorMode == false) { - setState(() { - _tutorMode = true; - print(_tutorMode); - }); - } - }, - child: Center( - child: Text("Tutor Mode", - style: TextStyle( - color: _tutorMode? Colors.white : Color(0xff3F2668), - fontFamily: 'Brandon-med', - fontSize: (MediaQuery.of(context).size.height) *(15/926) - ), - ), - ), - ) - ), - Container( - height: (MediaQuery.of(context).size.height) *(30/926), - width: (MediaQuery.of(context).size.width) *(98/428), - padding: EdgeInsets.zero, - margin: EdgeInsets.zero, - decoration: BoxDecoration( - color: _tutorMode? Colors.white : Color(0xff3F2668), - border: Border.all(color: Color(0xff3F2668)), - borderRadius: BorderRadius.only(topRight: Radius.circular(3), bottomRight: Radius.circular(3)), - ), - //color: Colors.red, - child: InkWell( - onTap: () { - if(_tutorMode == true) { - setState(() { - _tutorMode = false; - // print(_tutorMode); - }); - } - }, - child: Center( - child: Text("Exam Mode", - style: TextStyle( - color: _tutorMode? Color(0xff3F2668) : Colors.white, - fontFamily: 'Brandon-med', - fontSize: (MediaQuery.of(context).size.height) *(15/926) - ), - ), - ), - ) - ), - ], - ), - Row( - children: [ - Transform.scale( - scale: 1, - child: Container( - height: (MediaQuery.of(context).size.height) *(20/926), - child: Switch( - value: _timedMode, - onChanged: (value) { - setState(() { - _timedMode = value; - // print(_timedMode); - }); - }, - activeColor: Color(0xff3F2668), - ), - ), - ), - Container( - child: Text("Timed Mode", - style: TextStyle( - color: Color(0xff483A3A), - fontFamily: 'Brandon-med', - fontSize: (MediaQuery.of(context).size.height) *(15/926) - ), - ), - ), - SizedBox(width: (MediaQuery.of(context).size.width) *(10/428)), - - ], - ), - ], - ), - SizedBox(height: (MediaQuery.of(context).size.height) *(40/926)), - Container( - padding: EdgeInsets.only(bottom: (MediaQuery.of(context).size.height) *(15/926)), - child: Row( - children: [ - Text("Enter The Number Of Questions: ", - style: TextStyle( - color: Color(0xff3F3D56), - fontFamily: 'Brandon-med', - fontSize: (MediaQuery.of(context).size.height) *(15/926) - ), - ), - Container( - height: (MediaQuery.of(context).size.height) *(24/926), - width: (MediaQuery.of(context).size.width) *(40.01/428), - color: Colors.white, - child: Form( - key: _numberOfQuestionsKey, - child: TextField( - keyboardType: TextInputType.number, - inputFormatters: [ - FilteringTextInputFormatter.digitsOnly - ], // Only numbers can be entered - textAlign: TextAlign.center, - decoration: InputDecoration( - hintText: "4", - hintStyle: TextStyle(color: Color(0xffAEAEAE), - fontSize: (MediaQuery.of(context).size.height)*(15/926), - fontFamily: 'Brandon-med',), - contentPadding: EdgeInsets.fromLTRB(2.0, 1, 2.0, 1), - enabledBorder: OutlineInputBorder( - borderSide: BorderSide( - color: Color(0xFF7070709E), - width: 1.0, - ), - borderRadius: BorderRadius.circular(3.0), - ), - focusedBorder: OutlineInputBorder( - borderSide: BorderSide( - color: Colors.transparent, - width: 0.0, - ), - ), - ), - style: TextStyle( - color: Colors.black, - fontSize: (MediaQuery.of(context).size.height)*(15/926), - fontFamily: 'Brandon-med', - ), - onChanged: (val) { - final number = num.tryParse(val); - if(number != null) { - var totalQuestions; - try { - totalQuestions = _totalQuestions; - } catch (error) { - ScaffoldMessenger.of(context) - ..removeCurrentSnackBar() - ..showSnackBar(SnackBar(content: Text("Error"))); - } - if((int.parse(val)>totalQuestions) || (int.parse(val)>=40)) { - ScaffoldMessenger.of(context) - ..removeCurrentSnackBar() - ..showSnackBar(SnackBar(content: Text("Enter a smaller number"))); - setState(() { - _questionsCount = 0; - }); - } - else{ - setState(() { - _questionsCount = int.parse(val); - }); - } - } - }, - ), - ), - ), - Text(" /" + _totalQuestions.toString(), - style: TextStyle( - color: Color(0xFF98A4A4), - fontSize: (MediaQuery.of(context).size.height)*(15/926), - fontFamily: 'Brandon-med', - ),), - ], - ), - ), - ], - ), - ), - SizedBox(height: (MediaQuery.of(context).size.height) *(21/926),), - - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - InkWell( - child: Container( - height: (MediaQuery.of(context).size.height) *(42/926), - width: (MediaQuery.of(context).size.width) *(68/428), - decoration: BoxDecoration( - color: Color(0xff3F2668),//0xffB0A6C2, rgba(176, 166, 194, 1) - borderRadius: BorderRadius.all(Radius.circular(3)), - boxShadow: [ - BoxShadow( - color: Colors.black12,//Color(0xff00000029), - spreadRadius: 2, - blurRadius: 2, - offset: Offset(0, 0), - ), - ], - ), - child: TextButton( - onPressed: () { - //Animates to next tab - _backTab(); - }, - child: Center( - child: Text("Back", - style: TextStyle( - color: Colors.white, - fontFamily: 'Brandon-med', - ), - ), - ), - ), - ), - ), - InkWell( - child: Container( - height: (MediaQuery.of(context).size.height) *(42/926), - width: (MediaQuery.of(context).size.width) *(100/428), - decoration: BoxDecoration( - color: Color(0xff3F2668),//0xffB0A6C2, rgba(176, 166, 194, 1) - borderRadius: BorderRadius.all(Radius.circular(3)), - boxShadow: [ - BoxShadow( - color: Colors.black12,//Color(0xff00000029), - spreadRadius: 2, - blurRadius: 2, - offset: Offset(0, 0), - ), - ], - ), - child: TextButton( - onPressed: () { - print("adsdsa"); - // print(num.tryParse(_questionsCount)); - if(_questionsCount > 0) { - final result = Navigator.push( - context, - MaterialPageRoute(builder: (context) => QuizModule(totalQuestions: _questionsCount, questions: _questions, timedMode: _timedMode, mode: _tutorMode ? "tutor" : "exam", whatsDone: "new",)), - ); - } - }, - child: Center( - child: Text("Create Quiz", - style: TextStyle( - color: Colors.white, - fontFamily: 'Brandon-med', - ), - ), - ), - ), - ), - ), - ], - ), - ], - ), - ], - ), - ), - ], - ), - ), - ), - ); - } -} \ No newline at end of file diff --git a/lib/screens/Welcome/GenerateQuiz/generate_quiz_last.dart b/lib/screens/Welcome/GenerateQuiz/generate_quiz_last.dart deleted file mode 100644 index 61d6d5f..0000000 --- a/lib/screens/Welcome/GenerateQuiz/generate_quiz_last.dart +++ /dev/null @@ -1,276 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:flutter_svg/flutter_svg.dart'; -import 'package:testify/screens/Authentication/login.dart'; -import 'package:testify/screens/Welcome/GenerateQuiz/difficulty.dart'; -import 'package:testify/screens/Welcome/GenerateQuiz/question_types.dart'; -import 'package:testify/screens/Welcome/side_menu_bar.dart'; - -class GenerateQuizLast extends StatefulWidget { - @override - State createState() => _GenerateQuizLastState(); -} - -class _GenerateQuizLastState extends State { - //Fields - - @override - Widget build(BuildContext context) { - return Scaffold( - backgroundColor: Color(0xffF8F9FB), - drawer: SideMenuBar(), - appBar: AppBar( - backgroundColor: Color(0xff3F2668), - elevation: 2, - centerTitle: true, - flexibleSpace: Container( - decoration: BoxDecoration( - gradient: LinearGradient( - begin: Alignment.topCenter, - end: Alignment.bottomCenter, - colors: [ - Color(0xff7F1AF1), - Color(0xff482384) - ]) - ), - ), - title: const Text("Generate Quiz", - style: TextStyle( - color: Color(0xffFFFEFE), - fontFamily: 'Brandon-bld', - ), - ), - actions: [ - TextButton( - onPressed: () async { - final result = await Navigator.push( - context, - MaterialPageRoute(builder: (context) => const Login(fromWhere:"Home")), - ); - }, - child: const Icon( - Icons.logout, - color: Colors.white, - ), - ), - ], - ), - body: Container( - padding: EdgeInsets.only(top:(MediaQuery.of(context).size.height) *(15/926), - bottom: (MediaQuery.of(context).size.height) *(8/926), - left: (MediaQuery.of(context).size.width) *(18/428), - right: (MediaQuery.of(context).size.width) *(18/428)), - child: Column( - children: [ - Row( - children: [ - Container( - width: (MediaQuery.of(context).size.width) *(221/428), - //height: (MediaQuery.of(context).size.height) *(91/926), - child: Column( - children: [ - Align( - alignment: Alignment.topLeft, - child: Text("Create Quiz", - style: TextStyle( - color: Color(0xff232323), - fontFamily: 'Brandon-bld', - fontSize: (MediaQuery.of(context).size.height) *(20/926),//38, - ),), - ), - SizedBox(height: (MediaQuery.of(context).size.height) *(2/926),), - Text("Lorem ipsum dolor sit amet, consectetur adipiscing elit. Cras imperdiet finibus elit non luctus. Morbi auctor mattis ante.", - style: TextStyle( - color: Color(0xFF483A3A), - fontFamily: 'Brandon-med', - fontSize: (MediaQuery.of(context).size.height) *(10/926),//38, - ),), - ], - ), - ), - SizedBox(width: (MediaQuery.of(context).size.width) *(39/428),), - Container( - //color: Colors.transparent, - child: SvgPicture.asset( - "assets/Images/create_quiz.svg", - height: (MediaQuery.of(context).size.height) *(100/926), - //width: (MediaQuery.of(context).size.width) *(132/428), - ), - ), - ], - ), - SizedBox(height: (MediaQuery.of(context).size.height) *(25/926),), - //a - Container( - height: (MediaQuery.of(context).size.height) *(35.32/926), - decoration: BoxDecoration( - color: Color(0xff3F2668),//0xffB0A6C2, rgba(176, 166, 194, 1) - borderRadius: BorderRadius.only(topLeft: Radius.circular(50), topRight: Radius.circular(50)), - boxShadow: [ - BoxShadow( - color: Colors.black12,//Color(0xff00000029), - spreadRadius: 5, - blurRadius: 5, - offset: Offset(0, 0), - ), - ], - ), - child: Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - SizedBox(width: (MediaQuery.of(context).size.width) *(28/428),), - Container( - padding: EdgeInsets.only(top: (MediaQuery.of(context).size.height) *(9/926), bottom: (MediaQuery.of(context).size.height) *(4/926)), - height: (MediaQuery.of(context).size.height) *(35.32/926), - width: (MediaQuery.of(context).size.width) *(113/428), - color: Color(0xFF3F2668), - child: Column( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Text(" Systems/Subjects/Topics ", - style: TextStyle( - color: Color(0xffFEFEFE), - fontFamily: 'Brandon-bld', - fontSize: (MediaQuery.of(context).size.height) *(12/926), - ),), - ], - ), - ), - Container( - padding: EdgeInsets.only(top: (MediaQuery.of(context).size.height) *(5/926), bottom: (MediaQuery.of(context).size.height) *(5/926)), - height: (MediaQuery.of(context).size.height) *(35.32/926), - width: (MediaQuery.of(context).size.width) *(80/428), - color: Color(0xFF3F2668), - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Text("Question Types", - style: TextStyle( - color: Color(0xffFEFEFE), - fontFamily: 'Brandon-bld', - fontSize: (MediaQuery.of(context).size.height) *(12/926), - ),), - ], - ), - ), - Container( - padding: EdgeInsets.only(top: (MediaQuery.of(context).size.height) *(5/926), bottom: (MediaQuery.of(context).size.height) *(5/926)), - height: (MediaQuery.of(context).size.height) *(35.32/926), - width: (MediaQuery.of(context).size.width) *(65/428), - color: Color(0xFF3F2668), - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Text("Difficulty", - style: TextStyle( - color: Color(0xffFEFEFE), - fontFamily: 'Brandon-bld', - fontSize: (MediaQuery.of(context).size.height) *(12/926), - ),), - ], - ), - ), - Container( - padding: EdgeInsets.only(top: (MediaQuery.of(context).size.height) *(5/926), bottom: (MediaQuery.of(context).size.height) *(5/926)), - height: (MediaQuery.of(context).size.height) *(35.32/926), - width: (MediaQuery.of(context).size.width) *(75/428), - color: Colors.white, - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Text("Generate Quiz", - style: TextStyle( - color: Color(0xFF3F2668),//0xFF3F2668 - fontFamily: 'Brandon-bld', - fontSize: (MediaQuery.of(context).size.height) *(12/926), - ),), - Container( - padding: EdgeInsets.only(left: (MediaQuery.of(context).size.width) *(13/428), right: (MediaQuery.of(context).size.width) *(13/428)), - //margin: EdgeInsets.only(top: (MediaQuery.of(context).size.height) *(1/926)), - child: Divider(height: 3, - thickness: 2, - color: Color(0xFF3F2668),), - ), - ], - ), - ), - SizedBox(width: (MediaQuery.of(context).size.width) *(28/428),), - ], - ), - ), - SizedBox(height: (MediaQuery.of(context).size.height) *(15.28/926),), - Container( - height: (MediaQuery.of(context).size.height) *(167.52/926), - color: Colors.red, - ), - SizedBox(height: (MediaQuery.of(context).size.height) *(10.74/926),), - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - InkWell( - child: Container( - height: (MediaQuery.of(context).size.height) *(42/926), - width: (MediaQuery.of(context).size.width) *(68/428), - decoration: BoxDecoration( - color: Color(0xff3F2668),//0xffB0A6C2, rgba(176, 166, 194, 1) - borderRadius: BorderRadius.all(Radius.circular(3)), - boxShadow: [ - BoxShadow( - color: Colors.black12,//Color(0xff00000029), - spreadRadius: 2, - blurRadius: 2, - offset: Offset(0, 0), - ), - ], - ), - child: TextButton( - onPressed: () { - Navigator.pop(context); - }, - child: Center( - child: Text("Back", - style: TextStyle( - color: Colors.white, - fontFamily: 'Brandon-med', - ), - ), - ), - ), - ), - ), - InkWell( - child: Container( - height: (MediaQuery.of(context).size.height) *(42/926), - width: (MediaQuery.of(context).size.width) *(100/428), - decoration: BoxDecoration( - color: Color(0xff3F2668),//0xffB0A6C2, rgba(176, 166, 194, 1) - borderRadius: BorderRadius.all(Radius.circular(3)), - boxShadow: [ - BoxShadow( - color: Colors.black12,//Color(0xff00000029), - spreadRadius: 2, - blurRadius: 2, - offset: Offset(0, 0), - ), - ], - ), - child: TextButton( - onPressed: () { }, - child: Center( - child: Text("Create Quiz", - style: TextStyle( - color: Colors.white, - fontFamily: 'Brandon-med', - ), - ), - ), - ), - ), - ), - ], - ), - ], - ), - ), - ); - } -} \ No newline at end of file diff --git a/lib/screens/Welcome/GenerateQuiz/question_types.dart b/lib/screens/Welcome/GenerateQuiz/question_types.dart deleted file mode 100644 index b0dc5f3..0000000 --- a/lib/screens/Welcome/GenerateQuiz/question_types.dart +++ /dev/null @@ -1,281 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:flutter_svg/flutter_svg.dart'; -import 'package:testify/screens/Authentication/login.dart'; -import 'package:testify/screens/Welcome/GenerateQuiz/difficulty.dart'; -import 'package:testify/screens/Welcome/GenerateQuiz/question_types.dart'; -import 'package:testify/screens/Welcome/side_menu_bar.dart'; - -class QuestionTypes extends StatefulWidget { - @override - State createState() => _QuestionTypesState(); -} - -class _QuestionTypesState extends State { - //Fields - - @override - Widget build(BuildContext context) { - return Scaffold( - backgroundColor: Color(0xffF8F9FB), - drawer: SideMenuBar(), - appBar: AppBar( - backgroundColor: Color(0xff3F2668), - elevation: 2, - centerTitle: true, - flexibleSpace: Container( - decoration: BoxDecoration( - gradient: LinearGradient( - begin: Alignment.topCenter, - end: Alignment.bottomCenter, - colors: [ - Color(0xff7F1AF1), - Color(0xff482384) - ]) - ), - ), - title: const Text("Generate Quiz", - style: TextStyle( - color: Color(0xffFFFEFE), - fontFamily: 'Brandon-bld', - ), - ), - actions: [ - TextButton( - onPressed: () async { - final result = await Navigator.push( - context, - MaterialPageRoute(builder: (context) => const Login(fromWhere:"Home")), - ); - }, - child: const Icon( - Icons.logout, - color: Colors.white, - ), - ), - ], - ), - body: Container( - padding: EdgeInsets.only(top:(MediaQuery.of(context).size.height) *(15/926), - bottom: (MediaQuery.of(context).size.height) *(8/926), - left: (MediaQuery.of(context).size.width) *(18/428), - right: (MediaQuery.of(context).size.width) *(18/428)), - child: Column( - children: [ - Row( - children: [ - Container( - width: (MediaQuery.of(context).size.width) *(221/428), - //height: (MediaQuery.of(context).size.height) *(91/926), - child: Column( - children: [ - Align( - alignment: Alignment.topLeft, - child: Text("Create Quiz", - style: TextStyle( - color: Color(0xff232323), - fontFamily: 'Brandon-bld', - fontSize: (MediaQuery.of(context).size.height) *(20/926),//38, - ),), - ), - SizedBox(height: (MediaQuery.of(context).size.height) *(2/926),), - Text("Lorem ipsum dolor sit amet, consectetur adipiscing elit. Cras imperdiet finibus elit non luctus. Morbi auctor mattis ante.", - style: TextStyle( - color: Color(0xFF483A3A), - fontFamily: 'Brandon-med', - fontSize: (MediaQuery.of(context).size.height) *(10/926),//38, - ),), - ], - ), - ), - SizedBox(width: (MediaQuery.of(context).size.width) *(39/428),), - Container( - //color: Colors.transparent, - child: SvgPicture.asset( - "assets/Images/create_quiz.svg", - height: (MediaQuery.of(context).size.height) *(100/926), - //width: (MediaQuery.of(context).size.width) *(132/428), - ), - ), - ], - ), - SizedBox(height: (MediaQuery.of(context).size.height) *(25/926),), - //a - Container( - height: (MediaQuery.of(context).size.height) *(35.32/926), - decoration: BoxDecoration( - color: Color(0xff3F2668),//0xffB0A6C2, rgba(176, 166, 194, 1) - borderRadius: BorderRadius.only(topLeft: Radius.circular(50), topRight: Radius.circular(50)), - boxShadow: [ - BoxShadow( - color: Colors.black12,//Color(0xff00000029), - spreadRadius: 5, - blurRadius: 5, - offset: Offset(0, 0), - ), - ], - ), - child: Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - SizedBox(width: (MediaQuery.of(context).size.width) *(28/428),), - Container( - padding: EdgeInsets.only(top: (MediaQuery.of(context).size.height) *(9/926), bottom: (MediaQuery.of(context).size.height) *(4/926)), - height: (MediaQuery.of(context).size.height) *(35.32/926), - width: (MediaQuery.of(context).size.width) *(113/428), - color: Color(0xFF3F2668), - child: Column( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Text(" Systems/Subjects/Topics ", - style: TextStyle( - color: Color(0xffFEFEFE), - fontFamily: 'Brandon-bld', - fontSize: (MediaQuery.of(context).size.height) *(12/926), - ),), - ], - ), - ), - Container( - padding: EdgeInsets.only(top: (MediaQuery.of(context).size.height) *(5/926), bottom: (MediaQuery.of(context).size.height) *(5/926)), - height: (MediaQuery.of(context).size.height) *(35.32/926), - width: (MediaQuery.of(context).size.width) *(80/428), - color: Colors.white, - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Text("Question Types", - style: TextStyle( - color: Color(0xFF3F2668), - fontFamily: 'Brandon-bld', - fontSize: (MediaQuery.of(context).size.height) *(12/926), - ),), - Container( - padding: EdgeInsets.only(left: (MediaQuery.of(context).size.width) *(13/428), right: (MediaQuery.of(context).size.width) *(13/428)), - //margin: EdgeInsets.only(top: (MediaQuery.of(context).size.height) *(1/926)), - child: Divider(height: 3, - thickness: 2, - color: Color(0xFF3F2668),), - ), - ], - ), - ), - Container( - padding: EdgeInsets.only(top: (MediaQuery.of(context).size.height) *(5/926), bottom: (MediaQuery.of(context).size.height) *(5/926)), - height: (MediaQuery.of(context).size.height) *(35.32/926), - width: (MediaQuery.of(context).size.width) *(65/428), - color: Color(0xFF3F2668), - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Text("Difficulty", - style: TextStyle( - color: Color(0xffFEFEFE), - fontFamily: 'Brandon-bld', - fontSize: (MediaQuery.of(context).size.height) *(12/926), - ),), - ], - ), - ), - Container( - padding: EdgeInsets.only(top: (MediaQuery.of(context).size.height) *(5/926), bottom: (MediaQuery.of(context).size.height) *(5/926)), - height: (MediaQuery.of(context).size.height) *(35.32/926), - width: (MediaQuery.of(context).size.width) *(75/428), - color: Color(0xFF3F2668), - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Text("Generate Quiz", - style: TextStyle( - color: Color(0xffFEFEFE), - fontFamily: 'Brandon-bld', - fontSize: (MediaQuery.of(context).size.height) *(12/926), - ),), - ], - ), - ), - SizedBox(width: (MediaQuery.of(context).size.width) *(28/428),), - ], - ), - ), - SizedBox(height: (MediaQuery.of(context).size.height) *(15.28/926),), - Container( - height: (MediaQuery.of(context).size.height) *(167.52/926), - color: Colors.red, - ), - SizedBox(height: (MediaQuery.of(context).size.height) *(10.74/926),), - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - InkWell( - child: Container( - height: (MediaQuery.of(context).size.height) *(42/926), - width: (MediaQuery.of(context).size.width) *(68/428), - decoration: BoxDecoration( - color: Color(0xff3F2668),//0xffB0A6C2, rgba(176, 166, 194, 1) - borderRadius: BorderRadius.all(Radius.circular(3)), - boxShadow: [ - BoxShadow( - color: Colors.black12,//Color(0xff00000029), - spreadRadius: 2, - blurRadius: 2, - offset: Offset(0, 0), - ), - ], - ), - child: TextButton( - onPressed: () { - Navigator.pop(context); - }, - child: Center( - child: Text("Back", - style: TextStyle( - color: Colors.white, - fontFamily: 'Brandon-med', - ), - ), - ), - ), - ), - ), - InkWell( - child: Container( - height: (MediaQuery.of(context).size.height) *(42/926), - width: (MediaQuery.of(context).size.width) *(68/428), - decoration: BoxDecoration( - color: Color(0xff3F2668),//0xffB0A6C2, rgba(176, 166, 194, 1) - borderRadius: BorderRadius.all(Radius.circular(3)), - boxShadow: [ - BoxShadow( - color: Colors.black12,//Color(0xff00000029), - spreadRadius: 2, - blurRadius: 2, - offset: Offset(0, 0), - ), - ], - ), - child: TextButton( - onPressed: () async { - final result = await Navigator.push( - context, - MaterialPageRoute(builder: (context) => Difficulty()), - ); - }, - child: Center( - child: Text("Next", - style: TextStyle( - color: Colors.white, - fontFamily: 'Brandon-med', - ), - ), - ), - ), - ), - ), - ], - ), - ], - ), - ), - ); - } -} \ No newline at end of file diff --git a/lib/screens/Welcome/PreviousQuiz/previous_quiz.dart b/lib/screens/Welcome/PreviousQuiz/previous_quiz.dart deleted file mode 100644 index 6523ef5..0000000 --- a/lib/screens/Welcome/PreviousQuiz/previous_quiz.dart +++ /dev/null @@ -1,609 +0,0 @@ - -import 'package:flutter/material.dart'; -import 'package:flutter_svg/flutter_svg.dart'; -import 'package:shared_preferences/shared_preferences.dart'; -import 'package:testify/models/GenerateQuizModels/get_system_categories_successful.dart'; -import 'package:testify/models/GenerateQuizModels/get_system_categories_unsuccessful.dart'; -import 'package:testify/models/GetPreviousQuizzesModel/get_previous_quizzes_model.dart'; -import 'package:testify/screens/Authentication/login.dart'; -import 'package:testify/screens/Welcome/PreviousQuiz/test_details.dart'; -import 'package:testify/screens/Welcome/PreviousQuiz/tile.dart'; -import '../side_menu_bar.dart'; -import 'package:http/http.dart' as http; -import 'dart:convert'; - -class PreviousQuiz extends StatefulWidget { - @override - _PreviousQuizState createState() => _PreviousQuizState(); -} - -class _PreviousQuizState extends State { - final filterList=['Filter By','Subjects','Systems','Topics']; - int filterIndex = 0; - String _currentfilter='Filter By'; - String _currentsubfilter='Filter By'; - int subFilterIndex = 0; - List subFilterList=['option1','option2']; - List subjectsSubFilterList = ["Select"]; - List systemsSubFilterList = ["Select"]; - List topicsSubFilterList = ["Select"]; - List filterSubFilterSelected = ["",""]; // 0: Filter, 1: SubFilter. - double? _swipeStartX; - String? _swipeDirection; - - bool hasPreviousQuizzesDataLoaded = false; - var previousQuizzesData = { - "quizId": [], - "name": [], - "score": [], - "date": [], - "status": [], - "questions": [], - "totalQuestions": [], - "subjects": [], - "systems": [], - "topics": [], - }; - - var previousQuizzesDataFiltered = { - "quizId": [], - "name": [], - "score": [], - "date": [], - "status": [], - "questions": [], - "totalQuestions": [], - "subjects": [], - "systems": [], - "topics": [], - }; - - //Shared Pref - var _token; - var _userId; - - // Token Valid - var _getSystemCategoriesSuccessful; - // Token Incorrect - var _getSystemCategoriesUnsuccessful; - - //Get Previous Quizzes - var _getPreviousQuizzesSuccessful; - - @override - void initState() { - super.initState(); - getPreviousQuizzes(); - getUserDataSST(); - } - - Future getPreviousQuizzes() async { - SharedPreferences prefs = await SharedPreferences.getInstance(); - final String apiUrlSystemCategories = "https://demo.pookidevs.com/quiz/generator/getPreviousQuizzes"; - _token = prefs.getString('token')!; - _userId = prefs.getInt("userId")!; - http.get(Uri.parse(apiUrlSystemCategories), headers: { - 'Content-type': 'application/json; charset=UTF-8', 'Authorization' : _token.toString(), - },).then((response) { - // print(jsonDecode(response.body)); - if(response.statusCode == 200) { - if(json.decode(response.body).toString().substring(0,20) == "{data: {status: true"){ - final responseString = (response.body); - var getPrevQuiz = getPreviousQuizzesModelFromJson(responseString); - final GetPreviousQuizzesModel getPreviousQuizzesSuccessful = getPrevQuiz; - setState(() { - _getPreviousQuizzesSuccessful = getPreviousQuizzesSuccessful; - }); - // print(_getPreviousQuizzesSuccessful.data.quizzes[0].quizId); - categorizePreviousQuizzesData(); - } - } - else { - //Token is Invalid - ScaffoldMessenger.of(context) - ..removeCurrentSnackBar() - ..showSnackBar(SnackBar(content: Text("Token Expired!"))); - final result = Navigator.push( - context, - MaterialPageRoute(builder: (context) => const Login(fromWhere:"Home")), - ); - } - } - ); - } - - categorizePreviousQuizzesData() { - int c = 0; - while((c<_getPreviousQuizzesSuccessful.data.quizzes.toList().length) & (_getPreviousQuizzesSuccessful.data.quizzes.toList().length > 0)) { - setState(() { - previousQuizzesData["quizId"]!.add(_getPreviousQuizzesSuccessful.data.quizzes[c].quizId); - previousQuizzesData["name"]!.add(_getPreviousQuizzesSuccessful.data.quizzes[c].name); - previousQuizzesData["score"]!.add(_getPreviousQuizzesSuccessful.data.quizzes[c].score); - previousQuizzesData["date"]!.add(_getPreviousQuizzesSuccessful.data.quizzes[c].date); - previousQuizzesData["status"]!.add(_getPreviousQuizzesSuccessful.data.quizzes[c].status); - previousQuizzesData["questions"]!.add(_getPreviousQuizzesSuccessful.data.quizzes[c].questions); - previousQuizzesData["totalQuestions"]!.add(_getPreviousQuizzesSuccessful.data.quizzes[c].totalQuestions); - previousQuizzesData["subjects"]!.add(_getPreviousQuizzesSuccessful.data.quizzes[c].subjects); - previousQuizzesData["systems"]!.add(_getPreviousQuizzesSuccessful.data.quizzes[c].systems); - previousQuizzesData["topics"]!.add(_getPreviousQuizzesSuccessful.data.quizzes[c].topics); - }); - c++; - } - setState(() { - hasPreviousQuizzesDataLoaded = true; - }); - // print(previousQuizzesData); - } - - applyingPreviousQuizzesFilters() { - setState(() { - previousQuizzesDataFiltered["quizId"] = []; - previousQuizzesDataFiltered["name"] = []; - previousQuizzesDataFiltered["score"] = []; - previousQuizzesDataFiltered["date"] = []; - previousQuizzesDataFiltered["status"] = []; - previousQuizzesDataFiltered["questions"] = []; - previousQuizzesDataFiltered["totalQuestions"] = []; - previousQuizzesDataFiltered["subjects"] = []; - previousQuizzesDataFiltered["systems"] = []; - previousQuizzesDataFiltered["topics"] = []; - }); - if(filterSubFilterSelected[0] == "Subjects") { - for(int j = 0; j getUserDataSST() async { - SharedPreferences prefs = await SharedPreferences.getInstance(); - final String apiUrlSystemCategories = "https://demo.pookidevs.com/quiz/generator/getAllCategories"; - _token = prefs.getString('token')!; - _userId = prefs.getInt("userId")!; - // print(_userId); - // print(_token); - http.get(Uri.parse(apiUrlSystemCategories), headers: { - 'Content-type': 'application/json; charset=UTF-8', 'Authorization' : _token.toString(), - },).then((response) { - // print(jsonDecode(response.body).toString()); - if(response.statusCode == 200) { - if(json.decode(response.body).toString().substring(0,20) == "{data: {status: true") { - final responseString = (response.body); - var systemCategoriesDataSuccessful = getSystemCategoriesSuccessfulModelFromJson(responseString); - final GetSystemCategoriesSuccessfulModel getSystemCategoriesSuccessful = systemCategoriesDataSuccessful; - setState(() { - _getSystemCategoriesSuccessful = getSystemCategoriesSuccessful; - }); - // print(_questions); - } else { - - } - //Adds data to lists - categorizeUserData(); - } - else { // Status Code is 401 here that is why if written in the above if statement it would not work. - //Token is Invalid - if(json.decode(response.body).toString().substring(0,14) == "{status: false") { - final responseString = (response.body); - var systemCategoriesDataUnsuccessful = getSystemCategoriesUnsuccessfulModelFromJson(responseString); - final GetSystemCategoriesUnsuccessfulModel getSystemCategoriesUnsuccessful = systemCategoriesDataUnsuccessful; - setState(() { - _getSystemCategoriesUnsuccessful = getSystemCategoriesUnsuccessful; - }); - print(_getSystemCategoriesUnsuccessful.msg); - ScaffoldMessenger.of(context) - ..removeCurrentSnackBar() - ..showSnackBar(SnackBar(content: Text("Token Expired!"))); - final result = Navigator.push( - context, - MaterialPageRoute(builder: (context) => const Login(fromWhere:"Home")), - ); - } - else { - - } - } - } - ); - } - - //Add data to lists. Only done the first time. - categorizeUserData() { - //To clear any past data - int c = 0; - while((c<_getSystemCategoriesSuccessful.data.categories.toList().length) & (_getSystemCategoriesSuccessful.data.categories.toList().length > 0)) { - var tempLength = _getSystemCategoriesSuccessful.data.categories.toList().length; - if(_getSystemCategoriesSuccessful.data.categories[c].subCategories != null) { - if(_getSystemCategoriesSuccessful.data.categories[c].parentCategory.toString() == "systems") { - //Gets the length of subjects(Number of Subjects) - var lenSystems = _getSystemCategoriesSuccessful.data.categories[c].subCategories.toList().length; - int i = 0; - setState(() { - while((lenSystems>0) & (i0) & (i0) & (i[ - Color(0xff7F1AF1), - Color(0xff482384) - ]) - ), - ), - title: const Text("Previous Quiz", - style: TextStyle( - color: Color(0xffFFFEFE), - fontFamily: 'Brandon-bld', - ), - ), - actions: [ - TextButton( - onPressed: () async { - final result = await Navigator.push( - context, - MaterialPageRoute(builder: (context) => const Login(fromWhere:"Home")), - ); - }, - child: SvgPicture.asset( - "assets/Images/logout.svg", - height: (MediaQuery.of(context).size.height) *(32/926), - ), - ), - ], - ), - body: SingleChildScrollView( - child: Container( - padding: EdgeInsets.only(top:(MediaQuery.of(context).size.height) *(15/926), - bottom: (MediaQuery.of(context).size.height) *(8/926), - left: (MediaQuery.of(context).size.width) *(18/428), - right: (MediaQuery.of(context).size.width) *(18/428)), - child: Column( - children: [ - Row( - children: [ - Container( - width: (MediaQuery.of(context).size.width) *(221/428), - //height: (MediaQuery.of(context).size.height) *(91/926), - child: Column( - children: [ - Align( - alignment: Alignment.topLeft, - child: Text("Previous Quiz", - style: TextStyle( - color: Color(0xff232323), - fontFamily: 'Brandon-bld', - fontSize: (MediaQuery.of(context).size.height) *(25/926),//38, - ),), - ), - SizedBox(height: (MediaQuery.of(context).size.height) *(2/926),), - Text("Lorem ipsum dolor sit amet, consectetur adipiscing elit. Cras imperdiet finibus elit non luctus. Morbi auctor mattis ante.", - style: TextStyle( - color: Color(0xFF483A3A), - fontFamily: 'Brandon-med', - fontSize: (MediaQuery.of(context).size.height) *(13/926),//38, - ),), - ], - ), - ), - SizedBox(width: (MediaQuery.of(context).size.width) *(39/428),), - Container( - //color: Colors.transparent, - child: SvgPicture.asset( - "assets/Images/prevQuiz.svg", - height: (MediaQuery.of(context).size.height) *(100/926), - //width: (MediaQuery.of(context).size.width) *(132/428), - ), - ), - ], - ), - SizedBox(height: (MediaQuery.of(context).size.height)*(30/926),), - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Row( - children: [ - Text("Filter By: ", - style: TextStyle( - color: Color(0xFF483A3A), - fontFamily: 'Brandon-med', - fontSize: (MediaQuery.of(context).size.height) *(16/926),//38, - ),), - DropdownButton( - value: filterList[filterIndex], - underline: Container(), - iconEnabledColor: Color(0xff3F2668), - dropdownColor:Colors.white , - onChanged: (newValue) { - setState(() { - // print(newValue); - _currentfilter = newValue as String; - if(_currentfilter == filterList[1]){ - filterIndex = 1; - subFilterIndex = 0; - subFilterList = subjectsSubFilterList;} - else if(_currentfilter == filterList[2]){ - filterIndex = 2; - subFilterIndex = 0; - subFilterList = systemsSubFilterList;} - else if(_currentfilter == filterList[3]){ - filterIndex = 3; - subFilterIndex = 0; - subFilterList = topicsSubFilterList;} - else if(_currentfilter == filterList[0]){ - filterIndex = 0; - subFilterIndex = 0;} - filterSubFilterSelected[0] = _currentfilter; - applyingPreviousQuizzesFilters(); - // print(filterSubFilterSelected); - }); - }, - items: filterList.map((filter){ - return DropdownMenuItem( - child: Text(filter,style: TextStyle( - color: Color(0xff3F2668), - fontFamily: 'Brandon-bld', - fontSize: - (MediaQuery.of(context).size.height) * (16 / 926), - ),), - value: filter, - ); - }).toList(), - - - ), - ], - ), - // This below row is just for the if statement - if(_currentfilter != "Filter By") - Row( - children: [ - //SizedBox(width: (MediaQuery.of(context).size.width)*(40/428),), - Text(_currentfilter + ": ", - style: TextStyle( - color: Color(0xFF483A3A), - fontFamily: 'Brandon-med', - fontSize: (MediaQuery.of(context).size.height) *(16/926),//38, - ),), - DropdownButton( - value: (subFilterList.length<(subFilterIndex+1)) ? subFilterList[0] : subFilterList[subFilterIndex], - underline: Container(), - iconEnabledColor: Color(0xff3F2668), - dropdownColor:Colors.white , - onChanged: (newValue) { - setState(() { - // print(newValue); - subFilterIndex = 0; - _currentsubfilter = newValue as String; - for(int i = 0; i _swipeStartX!) ? "Right" : "Left"; - }, - onHorizontalDragEnd: (e) async { - if (_swipeDirection == "Right") - print("left"); - else if (_swipeDirection == "Left") { - print(previousQuizzesDataFiltered["system"]![i].toString()); - // final result = await Navigator.push( - // context, - // MaterialPageRoute( - // builder: (context) => TestDetails( - // quizId: previousQuizzesData["quizId"]![i], - // system: previousQuizzesData["system"]![i], - // subject: previousQuizzesData["subject"]![i], - // topic: previousQuizzesData["topic"]![i], - // score: previousQuizzesData["score"]![i], - // status: previousQuizzesData["status"]![i]))); - } - },), - ], - ) : - Column( - children: [ - SizedBox(height: (MediaQuery.of(context).size.height)*(30/926),), - GestureDetector(child: Tile( - name: previousQuizzesData["name"]![i], - quizId: previousQuizzesData["quizId"]![i], - status: previousQuizzesData["status"]![i], - score: previousQuizzesData["score"]![i], - systems: previousQuizzesData["systems"]![i], - questions: previousQuizzesData["questions"]![i], - date: previousQuizzesData["date"]![i], - topics: previousQuizzesData["topics"]![i], - subjects: previousQuizzesData["subjects"]![i], - totalQuestions: previousQuizzesData["totalQuestions"]![i],), - onHorizontalDragStart: (e) { - _swipeStartX = e.globalPosition.dx; - }, - onHorizontalDragUpdate: (e) { - _swipeDirection = - (e.globalPosition.dx > _swipeStartX!) ? "Right" : "Left"; - }, - onHorizontalDragEnd: (e) async { - if (_swipeDirection == "Right") - print("left"); - else if (_swipeDirection == "Left") { - print(previousQuizzesData["system"]![i].toString()); - // final result = await Navigator.push( - // context, - // MaterialPageRoute( - // builder: (context) => TestDetails( - // quizId: previousQuizzesData["quizId"]![i], - // system: previousQuizzesData["system"]![i], - // subject: previousQuizzesData["subject"]![i], - // topic: previousQuizzesData["topic"]![i], - // score: previousQuizzesData["score"]![i], - // status: previousQuizzesData["status"]![i]))); - } - },), - ], - ), - SizedBox(height: (MediaQuery.of(context).size.height)*(30/926),), - - ], - ), - ), - ), - ); - } -} diff --git a/lib/screens/Welcome/PreviousQuiz/test_details.dart b/lib/screens/Welcome/PreviousQuiz/test_details.dart deleted file mode 100644 index 697e1aa..0000000 --- a/lib/screens/Welcome/PreviousQuiz/test_details.dart +++ /dev/null @@ -1,478 +0,0 @@ -import 'dart:convert'; - -import 'package:flutter/cupertino.dart'; -import 'package:flutter/material.dart'; -import 'package:flutter_svg/svg.dart'; -import 'package:shared_preferences/shared_preferences.dart'; -import 'package:testify/models/GetPreviousQuizzesModel/ResumeQuiz/resume_quiz_model.dart'; -import 'package:testify/screens/Welcome/PreviousQuiz/previous_quiz.dart'; -import 'package:http/http.dart' as http; -import 'package:testify/screens/Welcome/QuizModule/quiz_module.dart'; -import '../../Authentication/login.dart'; -import '../side_menu_bar.dart'; - -class TestDetails extends StatefulWidget { - final int quizId; - final List system; - final List subject; - final List topic; - final String status; - final String score; - TestDetails( - {required this.quizId, - required this.system, - required this.subject, - required this.topic, - required this.status, - required this.score}); - - @override - State createState() => _TestDetailsState(); -} - -class _TestDetailsState extends State { - var _token; - var _userId; - var _resumeQuizSuccessful; - - @override - void initState() { - super.initState(); - ResumeQuizAPI(); - } - - Future ResumeQuizAPI() async { - SharedPreferences prefs = await SharedPreferences.getInstance(); - final String apiUrlGenerateQuiz = "https://demo.pookidevs.com/quiz/solver/resumeQuiz"; - _token = prefs.getString('token')!; - print(_token); - _userId = prefs.getInt("userId")!; - http.post(Uri.parse(apiUrlGenerateQuiz), headers: { - 'Content-type': 'application/json; charset=UTF-8', 'Authorization' : _token.toString(), - }, body: json.encode( - { - "quizId": widget.quizId - }) - ).then((response) { - // print(jsonDecode(response.body).toString()); - if((response.statusCode == 200) & (json.decode(response.body).toString().substring(0,14) != "{status: false")) { - final responseString = (response.body); - var resumeQuizSuccessful1 = resumeQuizModelFromJson(responseString); - final ResumeQuizModel resumeQuizSuccessful = resumeQuizSuccessful1; - setState(() { - _resumeQuizSuccessful = resumeQuizSuccessful; - // print(_resumeQuizSuccessful.data.previousQuizzes[0].quizMeta.quizMode); - // print(_resumeQuizSuccessful.data.previousQuizzes[0].quizMeta.quizTotalQuestions); - // print(_resumeQuizSuccessful.data.previousQuizzes[0].quizMeta.quizQuestions); - // print(_resumeQuizSuccessful.data.previousQuizzes[0].quizMeta.quizStatus); - // print(_resumeQuizSuccessful.data.previousQuizzes[0].quizMeta.isTimed); - // print(_resumeQuizSuccessful.data.previousQuizzes[0].quizMeta.quizId.runtimeType); - // print(_resumeQuizSuccessful.data.previousQuizzes[0].quizMeta.quizScore.runtimeType); - // _quizId = _getGenerateQuizSuccessful.data.quizId; - // print(_quizId); - }); - // categoriesGenerateQuizData(); - } - else { // Token Invalid - - } - } - ); - } - - @override - Widget build(BuildContext context) { - return Scaffold( - backgroundColor: Color(0xffF8F9FB), - drawer: SideMenuBar(), - appBar: AppBar( - toolbarHeight: (MediaQuery.of(context).size.height) * (73.52 / 926), - backgroundColor: Color(0xff3F2668), - elevation: 2, - centerTitle: true, - flexibleSpace: Container( - decoration: const BoxDecoration( - gradient: LinearGradient( - begin: Alignment.topCenter, - end: Alignment.bottomCenter, - colors: [Color(0xff7F1AF1), Color(0xff482384)])), - ), - title: const Text( - "Test Details", - style: TextStyle( - color: Color(0xffFFFEFE), - fontFamily: 'Brandon-bld', - ), - ), - actions: [ - TextButton( - onPressed: () async { - final result = await Navigator.push( - context, - MaterialPageRoute( - builder: (context) => const Login(fromWhere: "Home")), - ); - }, - child: SvgPicture.asset( - "assets/Images/logout.svg", - height: (MediaQuery.of(context).size.height) * (32 / 926), - ), - ), - ], - ), - body: SingleChildScrollView( - child: Padding( - padding: const EdgeInsets.symmetric(vertical: 100), - child: Column( - children: [ - Center( - child: Container( - // height: (MediaQuery.of(context).size.height) * (488 / 926), - width: (MediaQuery.of(context).size.width) * (385 / 428), - decoration: BoxDecoration( - borderRadius: BorderRadius.circular(2), - color: Colors.white, - boxShadow: [ - BoxShadow(color: Colors.grey, offset: Offset(0, 4), blurRadius: 6) - ], - ), - child: Column( - children: [ - - Container( - height: (MediaQuery.of(context).size.height) * (59 / 926), - width: (MediaQuery.of(context).size.width) * (385 / 428), - color: Color(0xff6D5A8D), - child: Center( - child: Text( - 'Test Details', - style: TextStyle( - color: Colors.white, - fontFamily: 'Brandon-bld', - fontSize: (MediaQuery.of(context).size.height) * (20 / 926), - ), - ), - ), - ), - Container( - // height: (MediaQuery.of(context).size.height) * (310 / 926), - width: (MediaQuery.of(context).size.width) * (385 / 428), - padding: EdgeInsets.all(25), - child: Table( - columnWidths: {0:FixedColumnWidth((MediaQuery.of(context).size.width) * (25 / 428)), - 1:FixedColumnWidth((MediaQuery.of(context).size.width) * (200 / 428))}, - border: TableBorder.all(color: Colors.transparent), - children: [ - TableRow(children: [ - Padding( - padding: const EdgeInsets.only(top:8.0), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - 'Quiz ID:', - style: TextStyle( - color: Color(0xff3F2668), - fontFamily: 'Brandon-bld', - fontSize: (MediaQuery.of(context).size.height) * - (16 / 926), - ), - ), - ], - ), - ), - Padding( - padding: const EdgeInsets.only(top:8.0), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text(widget.quizId.toString(), - textAlign: TextAlign.start, - style: TextStyle( - color: Colors.black, - fontFamily: 'Brandon-med', - fontSize: (MediaQuery.of(context).size.height) * - (16 / 926), - )) - ], - ), - ) - ]), - TableRow(children: [ - Padding( - padding: const EdgeInsets.only(top:8.0), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - 'System:', - style: TextStyle( - color: Color(0xff3F2668), - fontFamily: 'Brandon-bld', - fontSize: (MediaQuery.of(context).size.height) * - (16 / 926), - ), - ), - ], - ), - ), - Padding( - padding: const EdgeInsets.only(top:8.0), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text(widget.system.toString().substring(1, widget.system.toString().length-1) == "" ? "-" : widget.system.toString().substring(1, widget.system.toString().length-1), - style: TextStyle( - color: Colors.black, - fontFamily: 'Brandon-med', - fontSize: (MediaQuery.of(context).size.height) * - (16 / 926), - )) - ], - ), - ) - ]), - TableRow(children: [ - Padding( - padding: const EdgeInsets.only(top:8.0), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - 'Subject:', - style: TextStyle( - color: Color(0xff3F2668), - fontFamily: 'Brandon-bld', - fontSize: (MediaQuery.of(context).size.height) * - (16 / 926), - ), - ), - ], - ), - ), - Padding( - padding: const EdgeInsets.only(top:8.0), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text(widget.subject.toString().substring(1, widget.subject.toString().length-1) == "" ? "-" : widget.subject.toString().substring(1, widget.subject.toString().length-1), - style: TextStyle( - color: Colors.black, - fontFamily: 'Brandon-med', - fontSize: (MediaQuery.of(context).size.height) * - (16 / 926), - )) - ], - ), - ) - ]), - TableRow(children: [ - Padding( - padding: const EdgeInsets.only(top:8.0), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - 'Topic:', - style: TextStyle( - color: Color(0xff3F2668), - fontFamily: 'Brandon-bld', - fontSize: (MediaQuery.of(context).size.height) * - (16 / 926), - ), - ), - ], - ), - ), - Padding( - padding: const EdgeInsets.only(top:8.0), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text(widget.topic.toString().substring(1, widget.topic.toString().length-1) == "" ? "-" : widget.topic.toString().substring(1, widget.topic.toString().length-1), - style: TextStyle( - color: Colors.black, - fontFamily: 'Brandon-med', - fontSize: (MediaQuery.of(context).size.height) * - (16 / 926), - )) - ], - ), - ) - ]), - TableRow(children: [ - Padding( - padding: const EdgeInsets.only(top:8.0), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - 'Score:', - style: TextStyle( - color: Color(0xff3F2668), - fontFamily: 'Brandon-bld', - fontSize: (MediaQuery.of(context).size.height) * - (16 / 926), - ), - ), - ], - ), - ), - Padding( - padding: const EdgeInsets.only(top:8.0), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text(widget.score, - style: TextStyle( - color: Colors.black, - fontFamily: 'Brandon-med', - fontSize: (MediaQuery.of(context).size.height) * - (16 / 926), - )) - ], - ), - ) - ]), - TableRow(children: [ - Padding( - padding: const EdgeInsets.only(top:8.0), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - 'Status:', - style: TextStyle( - color: Color(0xff3F2668), - fontFamily: 'Brandon-bld', - fontSize: (MediaQuery.of(context).size.height) * - (16 / 926), - ), - ), - ], - ), - ), - Padding( - padding: const EdgeInsets.only(top:8.0), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text(widget.status, - style: TextStyle( - color: Colors.black, - fontFamily: 'Brandon-med', - fontSize: (MediaQuery.of(context).size.height) * - (16 / 926), - )) - ], - ), - ) - ]) - ], - ), - ), - - Container( - height: (MediaQuery.of(context).size.height) * (70 / 926), - width: (MediaQuery.of(context).size.width) * (385 / 428), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceEvenly, - children: [ - Column( - children: [ - Container(height:40,width:40,decoration: BoxDecoration(color: Color(0xff7F1AF1),borderRadius: BorderRadius.circular(20)), - child: Icon(Icons.show_chart_outlined,size: 20,color:Colors.white)) - ,Text('Test Analysis',style: TextStyle( - color: Color(0xff7F1AF1), - fontFamily: 'Brandon-med', - fontSize: (MediaQuery.of(context).size.height) * (15 / 926), - ),) - ], - ), - Column( - children: [ - Container(height:40,width:40,decoration: BoxDecoration(color: Color(0xff7F1AF1),borderRadius: BorderRadius.circular(20)), - child: Icon(Icons.event_note_outlined,size: 20,color:Colors.white)) - ,Text('Test Results',style: TextStyle( - color: Color(0xff7F1AF1), - fontFamily: 'Brandon-med', - fontSize: (MediaQuery.of(context).size.height) * (15 / 926), - ),) - ], - ), - GestureDetector( - onTap: () async { - // print(_resumeQuizSuccessful.data.previousQuizzes[0].quizMeta.quizMode); - // print(_resumeQuizSuccessful.data.previousQuizzes[0].quizMeta.quizTotalQuestions); - // print(_resumeQuizSuccessful.data.previousQuizzes[0].quizMeta.quizQuestions); - // print(_resumeQuizSuccessful.data.previousQuizzes[0].quizMeta.isTimed); - SharedPreferences prefs = await SharedPreferences.getInstance(); - prefs.setInt("quizId", widget.quizId); - List _quizQuestions = []; - for(int i = 0; i<_resumeQuizSuccessful.data.questions.length; i++) { - _quizQuestions.add(_resumeQuizSuccessful.data.questions[i].id); - } - - // Navigator.of(context) - // .popUntil(ModalRoute.withName("/home")); - final result = Navigator.push( - context, - MaterialPageRoute(builder: (context) => QuizModule(totalQuestions: _resumeQuizSuccessful.data.previousQuizzes[0].quizMeta.quizTotalQuestions, - questions: _quizQuestions, - timedMode: _resumeQuizSuccessful.data.previousQuizzes[0].quizMeta.isTimed, - mode: _resumeQuizSuccessful.data.previousQuizzes[0].quizMeta.quizMode.toString(), - whatsDone: "resumed",)), - ); - }, - child: Column( - children: [ - Container(height:40,width:40,decoration: BoxDecoration(color: Color(0xff7F1AF1),borderRadius: BorderRadius.circular(20)), - child: Icon(Icons.arrow_right,size: 40,color:Colors.white)) - ,Text('Resume',style: TextStyle( - color: Color(0xff7F1AF1), - fontFamily: 'Brandon-med', - fontSize: (MediaQuery.of(context).size.height) * (15 / 926), - ),) - ], - ), - ), - ], - ), - ) - - ], - ), - ), - ), - Padding( - padding: const EdgeInsets.all(20.0), - child: InkWell( - onTap:() async { - // Navigator.of(context).pop(); - Navigator.of(context) - .popUntil(ModalRoute.withName("/home")); - final result = await Navigator.push( - context, - MaterialPageRoute(builder: (context) => PreviousQuiz()), - ); - }, - child:Container( - child: Row( - children: [Icon(Icons.arrow_back,color: Color(0xff7F1AF1),size: 15,),Text('Back',style: TextStyle( - color: Color(0xff7F1AF1), - fontFamily: 'Brandon-bld', - fontSize: (MediaQuery.of(context).size.height) * - (13 / 926), - ),)], - - ), - )), - ) - ], - ), - ), - ), - ); - - } -} diff --git a/lib/screens/Welcome/PreviousQuiz/tile.dart b/lib/screens/Welcome/PreviousQuiz/tile.dart deleted file mode 100644 index 3b4e78f..0000000 --- a/lib/screens/Welcome/PreviousQuiz/tile.dart +++ /dev/null @@ -1,137 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:testify/screens/Welcome/PreviousQuiz/test_details.dart'; - -class Tile extends StatelessWidget { - final String name; - final int quizId; - final String status; - final String score; - final String date; - final List questions; - final String totalQuestions; - final List subjects; - final List systems; - final List topics; - Tile({required this.name, required this.quizId, required this.status, required this.score, required this.totalQuestions, required this.questions, required this.date, required this.subjects, required this.systems, required this.topics}); - @override - Widget build(BuildContext context) { - return Container( - height: (MediaQuery.of(context).size.height) * (84 / 926), - width: (MediaQuery.of(context).size.width) * (385 / 428), - decoration: BoxDecoration( - borderRadius: BorderRadius.circular(2), - color: Colors.white, - boxShadow: [ - BoxShadow(color: Colors.grey, offset: Offset(0, 4), blurRadius: 6) - ], - ), - child: Row( - children: [ - Container( - height: (MediaQuery.of(context).size.height) * (84 / 926), - width: (MediaQuery.of(context).size.width) * (87 / 428), - color: Color(0xff6D5A8D), - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Text( - 'Quiz ID', - style: TextStyle( - color: Colors.white, - fontFamily: 'Brandon-bld', - fontSize: - (MediaQuery.of(context).size.height) * (18 / 926), - ), - ), - Text(quizId.toString(), - style: TextStyle( - color: Colors.white, - fontFamily: 'Brandon-med', - fontSize: - (MediaQuery.of(context).size.height) * (17 / 926), - )) - ], - )), - Container( - height: (MediaQuery.of(context).size.height) * (84 / 926), - width: (MediaQuery.of(context).size.width) * (248 / 428), - color: Colors.white, - padding: EdgeInsets.all( - (MediaQuery.of(context).size.height) * (16 / 926)), - child: Column( - children: [ - Row( - children: [ - Icon( - Icons.sticky_note_2_rounded, - color: Colors.grey, - ), - SizedBox( - width: (MediaQuery.of(context).size.width) * (12 / 428), - ), - Text( - (name.length >= 22) ? name.substring(0, 22) : name, - style: TextStyle( - color: Colors.black, - fontFamily: 'Brandon-med', - fontSize: - (MediaQuery.of(context).size.height) * (18 / 926), - ), - ) - ], - ), - Divider( - height: 1.5, - ), - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Text( - score + ' / ' + totalQuestions, - style: TextStyle( - color: Color(0xff6C63FF), - fontFamily: 'Brandon-med', - fontSize: - (MediaQuery.of(context).size.height) * (14 / 926), - ), - ), - Text( - status, - style: TextStyle( - color: Color(0xff6C63FF), - fontFamily: 'Brandon-med', - fontSize: - (MediaQuery.of(context).size.height) * (14 / 926), - ), - ), - ], - ) - ], - ), - ), - Container( - height: (MediaQuery.of(context).size.height) * (84 / 926), - width: (MediaQuery.of(context).size.width) * (50 / 428), - color: Colors.white, - child: IconButton( - icon: Icon(Icons.arrow_right, - color: Color(0xff6D5A8D), - size: (MediaQuery.of(context).size.height) * (60 / 926)), - onPressed: () async { - Navigator.of(context).pop(); - final result = await Navigator.push( - context, - MaterialPageRoute( - builder: (context) => TestDetails( - quizId: quizId, - system: systems, - subject: subjects, - topic: topics, - score: score, - status: status))); - })), - ], - ), - ); - } -} diff --git a/lib/screens/Welcome/QuizModule/buttons.dart b/lib/screens/Welcome/QuizModule/buttons.dart deleted file mode 100644 index 55e4e7c..0000000 --- a/lib/screens/Welcome/QuizModule/buttons.dart +++ /dev/null @@ -1,55 +0,0 @@ -import 'package:flutter/material.dart'; - -// creating Stateless Widget for buttons -class MyButton extends StatelessWidget { - -// declaring variables - final color; - final textColor; - final String buttonText; - final buttontapped; - -//Constructor - MyButton({this.color, this.textColor, required this.buttonText, this.buttontapped}); - - @override - Widget build(BuildContext context) { - return Scaffold( - body: GestureDetector( - onTap: buttontapped, - child: Center( - child: Container( - height: 35, - width: 35, - decoration: BoxDecoration( - color: Colors.white, - boxShadow: [ - BoxShadow( - offset: Offset(0, 4), - blurRadius: 6, - color: Colors.black45//Color(0xFFF9F8F9), // background color - ), - ], - borderRadius: BorderRadius.circular(5), - ), - - child: Center( - child: Text( - buttonText, - style: TextStyle( - color: Colors.black, - fontFamily: 'Brandon-bld', - fontSize: (MediaQuery.of(context).size.height*(20/926)), - fontWeight: FontWeight.bold, - ), - ), - ), - ), - ), - ), - - - ); - } -} - diff --git a/lib/screens/Welcome/QuizModule/calculator.dart b/lib/screens/Welcome/QuizModule/calculator.dart deleted file mode 100644 index d7529cb..0000000 --- a/lib/screens/Welcome/QuizModule/calculator.dart +++ /dev/null @@ -1,179 +0,0 @@ -import 'package:flutter/material.dart'; -import 'buttons.dart'; -import 'package:math_expressions/math_expressions.dart'; -class Calculator extends StatefulWidget { - @override - _CalculatorState createState() => _CalculatorState(); -} - -class _CalculatorState extends State { - var userInput = ''; - var answer = ''; - final List buttons = [ - '7', - '8', - '9', - '%', - 'C', - '4', - '5', - '6', - 'x', - 'DEL', - '1', - '2', - '3', - '+', - '/', - '.', - '0', - '=', - '-', - - ]; - bool isOperator(String x) { - if (x == '/' || x == 'x' || x == '-' || x == '+' || x == '=') { - return true; - } - return false; - } -// function to calculate the input operation - void equalPressed() { - String finaluserinput = userInput; - finaluserinput = userInput.replaceAll('x', '*'); - - Parser p = Parser(); - Expression exp = p.parse(finaluserinput); - ContextModel cm = ContextModel(); - double eval = exp.evaluate(EvaluationType.REAL, cm); - answer = eval.toString(); - } - @override - Widget build(BuildContext context) { - return AlertDialog( - content: SizedBox( - height: (MediaQuery.of(context).size.height)*(310/926), - width: (MediaQuery.of(context).size.width)*(237/428), - child: Container( - padding: EdgeInsets.all(0), - decoration: BoxDecoration( - borderRadius: BorderRadius.circular(5), - color: Colors.white - ), - child: Column( - children: [ - - Container( - width: (MediaQuery.of(context).size.width)*(237/428), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Container( - alignment: Alignment.centerLeft, - child: Text( - userInput, - style: TextStyle( - color: Color(0xff7F1AF1), - fontFamily: 'Brandon-bld', - fontSize: (MediaQuery.of(context).size.height) * (20 / 926), - ), - ),), - Spacer(), - Container( - alignment: Alignment.centerRight, - child: Text( - answer, - style: TextStyle( - color: Color(0xff7F1AF1), - fontFamily: 'Brandon-bld', - fontSize: (MediaQuery.of(context).size.height) * (29 / 926), - ), - ), - ), - - ]), - ), - Divider(), - Container( - height: (MediaQuery.of(context).size.height)*(237/926), - width: (MediaQuery.of(context).size.width)*(310/428), - padding: EdgeInsets.all(8), - child: GridView.builder(itemCount: buttons.length,gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 5, crossAxisSpacing: 2.0, - mainAxisSpacing: 2.0,mainAxisExtent: 40), itemBuilder: (BuildContext context, int index) { - // Clear Button - if (index == 4) { - return MyButton( - buttontapped: () { - setState(() { - userInput = ''; - answer = '0'; - }); - }, - buttonText: buttons[index], - - ); - } - - // % Button - else if (index == 3) { - return MyButton( - buttontapped: () { - setState(() { - userInput += buttons[index]; - }); - }, - buttonText: buttons[index], - - ); - } - // Delete Button - else if (index == 9) { - return MyButton( - buttontapped: () { - setState(() { - userInput = - userInput.substring(0, userInput.length - 1); - }); - }, - buttonText: buttons[index], - - );} - // Equal_to Button - else if (index == 17) { - return MyButton( - buttontapped: () { - setState(() { - equalPressed(); - }); - }, - buttonText: buttons[index], - - ); - } - // other buttons - else { - return MyButton( - buttontapped: () { - setState(() { - userInput += buttons[index]; - }); - }, - buttonText: buttons[index], - - ); - } - }), - ) - - ], - ), - ), - ), - ); - } - - - } - - - diff --git a/lib/screens/Welcome/QuizModule/question_explanation.dart b/lib/screens/Welcome/QuizModule/question_explanation.dart deleted file mode 100644 index 183609f..0000000 --- a/lib/screens/Welcome/QuizModule/question_explanation.dart +++ /dev/null @@ -1,372 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:flutter_countdown_timer/flutter_countdown_timer.dart'; -import 'package:flutter_svg/svg.dart'; -import 'package:testify/screens/Welcome/side_menu_bar.dart'; - -class QuestionExplanation extends StatefulWidget { - const QuestionExplanation({Key? key, required this.questionId, required this.question, required this.correctAnswer, required this.explanation}) : super(key: key); - - final int questionId; - final String question; - final String correctAnswer; - final String explanation; - - @override - State createState() => _QuestionExplanationState(); -} - -class _QuestionExplanationState extends State { - int endTime = DateTime.now().millisecondsSinceEpoch + 1000 * 30; - - void onEnd() { - print('onEnd'); - } - - @override - Widget build(BuildContext context) { - // print(widget.questionId); - // print(widget.question); - // print(widget.correctAnswer); - // print(widget.explanation); - return Scaffold( - backgroundColor: Color(0xffF8F9FB), - drawer: SideMenuBar(), - // drawer: moreMenu(), - appBar: AppBar( - toolbarHeight: (MediaQuery.of(context).size.height) * (73.52 / 926), - backgroundColor: Color(0xff3F2668), - elevation: 2, - centerTitle: true, - title: Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Text( - 'Question ', - style: TextStyle( - color: Color(0xffffffff), - fontFamily: 'Brandon-bld', - fontSize: (MediaQuery.of(context).size.height) * (20 / 926), - ), - ), - ], - ), - flexibleSpace: Container( - decoration: const BoxDecoration( - gradient: LinearGradient( - begin: Alignment.topCenter, - end: Alignment.bottomCenter, - colors: [Color(0xff7F1AF1), Color(0xff482384)])), - ), - actions: [ - TextButton( - onPressed: () async { - }, - child: SvgPicture.asset( - "assets/Images/logout.svg", - height: (MediaQuery.of(context).size.height) *(32/926), - ), - ), - ], - ), - body: Column( - children: [ - Container( - height: ((MediaQuery.of(context).size.height) * ((926-73.52-50.88-(MediaQuery.of(context).padding.top)-8.1) / 926)), - child: ListView( - scrollDirection: Axis.vertical, - children: [ - Container( - padding: EdgeInsets.only( - top: (MediaQuery.of(context).size.height) * (15 / 926), - bottom: (MediaQuery.of(context).size.height) * (8 / 926), - left: (MediaQuery.of(context).size.width) * (18 / 428), - right: (MediaQuery.of(context).size.width) * (18 / 428)), - child: Column( - children: [ - Row( - children: [ - Container( - width: (MediaQuery.of(context).size.width) * (221 / 428), - //height: (MediaQuery.of(context).size.height) *(91/926), - child: Column( - children: [ - Align( - alignment: Alignment.topLeft, - child: Text( - "Attempt Your Quiz", - style: TextStyle( - color: Color(0xff232323), - fontFamily: 'Brandon-bld', - fontSize: (MediaQuery.of(context).size.height) * - (20 / 926), //38, - ), - ), - ), - SizedBox( - height: (MediaQuery.of(context).size.height) * - (2 / 926), - ), - Align( - alignment: Alignment.topLeft, - child: Text( - "Question ID: " + widget.questionId.toString(), // questionNumber - style: TextStyle( - color: Color(0xFF7F1AF1), - fontFamily: 'Brandon-med', - fontSize: (MediaQuery.of(context).size.height) * - (13 / 926), //38, - ), - ), - ) - ], - ), - ), - SizedBox( - width: (MediaQuery.of(context).size.width) * (39 / 428), - ), - // for timer - Container( - height: (MediaQuery.of(context).size.height) * (25 / 926), - width: (MediaQuery.of(context).size.width) * (107 / 428), - color: Color(0xFF3F2668), - child: Row( - children: [ - Text(' Time Left ', - style: TextStyle( - color: Color(0xFFFFFFFF), - fontFamily: 'Brandon-med', - fontSize: (MediaQuery.of(context).size.height) * - (7 / 926), - )), - CountdownTimer( - textStyle: TextStyle( - color: Color(0xFFFFFFFF), - fontFamily: 'Brandon-med', - fontSize: (MediaQuery.of(context).size.height) * - (13 / 926), - ), - endTime: endTime, - onEnd: onEnd, - endWidget: Text( - "00 : 00 : 00", - style: TextStyle( - color: Color(0xFFFFFFFF), - fontFamily: 'Brandon-med', - fontSize: (MediaQuery.of(context).size.height) * - (13 / 926), - ), - ), - ), - ], - ), - ) - ], - ), - SizedBox( - height: (MediaQuery.of(context).size.height) * (35.47 / 926), - ), - Text( - widget.question, - style: TextStyle( - color: Color(0xFF483A3A), - fontFamily: 'Brandon-med', - fontSize: - (MediaQuery.of(context).size.height) * (18 / 926), //38, - ), - ), - SizedBox( - height: (MediaQuery.of(context).size.height) * (25 / 926), - ), - Align( - alignment: Alignment.topLeft, - child: Text( - "Correct Answer: ", // questionNumber - style: TextStyle( - color: Color(0xFF7F1AF1), - fontFamily: 'Brandon-med', - fontSize: (MediaQuery.of(context).size.height) * - (13 / 926), //38, - ), - ), - ), - SizedBox( - height: (MediaQuery.of(context).size.height) * (10.75 / 926), - ), - Container( - // height: (MediaQuery.of(context).size.height) * (50 / 926), - // width: (MediaQuery.of(context).size.width) * (385 / 428), - padding: EdgeInsets.only( - top: (MediaQuery.of(context).size.height) * (8 / 928), - left: (MediaQuery.of(context).size.width) * (13 / 428), - bottom: (MediaQuery.of(context).size.height) * (8 / 928), - ), - decoration: BoxDecoration( - color: Color(0xFF3F2668), - border: Border.all( - color: Color(0xFF3F2668), - ), - borderRadius: BorderRadius.all(Radius.circular(0)) - ), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - Container( - width: (MediaQuery.of(context).size.width) * (300 / 428), - child: Text(widget.correctAnswer, - style: TextStyle( - color: Colors.white, - fontFamily: 'Brandon-med', - fontSize: (MediaQuery.of(context).size.height) * - (18 / 926), //38, - )), - ), - ], - )), - SizedBox( - height: (MediaQuery.of(context).size.height) * (20.2 / 926), - ), - Align( - alignment: Alignment.topLeft, - child: Text( - "Explanation: ", // questionNumber - style: TextStyle( - color: Color(0xFF7F1AF1), - fontFamily: 'Brandon-med', - fontSize: (MediaQuery.of(context).size.height) * - (13 / 926), //38, - ), - ), - ), - SizedBox( - height: (MediaQuery.of(context).size.height) * (10.75 / 926), - ), - Text( - widget.explanation, - style: TextStyle( - color: Color(0xFF483A3A), - fontFamily: 'Brandon-med', - fontSize: - (MediaQuery.of(context).size.height) * (18 / 926), //38, - ), - ), - SizedBox( - height: (MediaQuery.of(context).size.height) * (20.75 / 926), - ), - TextButton( - onPressed: () { - Navigator.of(context).pop(); - }, - style: TextButton.styleFrom( - padding: EdgeInsets.zero,), - child: Row( - children: [ - Container( - child: Icon(Icons.arrow_back, - color: Color(0xFF7F1AF1), - size: (MediaQuery.of(context).size.height) * - (15 / 926),), - ), - SizedBox(width: (MediaQuery.of(context).size.width) * - (3 / 428),), - Text( - "Back to Question", // questionNumber - style: TextStyle( - color: Color(0xFF7F1AF1), - fontFamily: 'Brandon-med', - fontSize: (MediaQuery.of(context).size.height) * - (13 / 926), //38, - ), - ), - ], - ), - ), - ], - )), - ], - ), - ) , - Align( - alignment: Alignment.bottomCenter, - child: Container( - height: ((MediaQuery.of(context).size.height) * (51 / 926)), - color: Colors.grey, - // decoration: const BoxDecoration( - // gradient: LinearGradient( - // begin: Alignment.topCenter, - // end: Alignment.bottomCenter, - // colors: [Color(0xff7F1AF1), Color(0xff482384)])), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - TextButton( - onPressed: null, - style: TextButton.styleFrom( - padding: EdgeInsets.zero,), - child: Row( - children: [ - SizedBox(width: (MediaQuery.of(context).size.width) * (16 / 428)), - Container( - child: Icon(Icons.arrow_back_ios_outlined, - color: Color(0xFFE4E4E4), - size: ((MediaQuery.of(context).size.width) * (23.1 / 428)),), - ), - ], - ), - ), - TextButton( - onPressed: null, - style: TextButton.styleFrom( - padding: EdgeInsets.zero,), - child: Row( - children: [ - Container( - width: ((MediaQuery.of(context).size.height) * (15 / 926)), - decoration: BoxDecoration( - color: Color(0xFFE4E4E4), - shape: BoxShape.circle - ), - ), - SizedBox(width: (MediaQuery.of(context).size.width) * (6 / 428)), - Container( - width: ((MediaQuery.of(context).size.height) * (15 / 926)), - decoration: BoxDecoration( - color: Color(0xFFE4E4E4), - shape: BoxShape.circle - ), - ), - SizedBox(width: (MediaQuery.of(context).size.width) * (6 / 428)), - Container( - width: ((MediaQuery.of(context).size.height) * (15 / 926)), - decoration: BoxDecoration( - color: Color(0xFFE4E4E4), - shape: BoxShape.circle - ), - ), - ], - ), - ), - TextButton( - onPressed: null, - style: TextButton.styleFrom( - padding: EdgeInsets.zero,), - child: Row( - children: [ - Container( - child: Icon(Icons.arrow_forward_ios_outlined, - color: Color(0xFFE4E4E4), - size: ((MediaQuery.of(context).size.width) * (23.1 / 428)),), - ), - SizedBox(width: (MediaQuery.of(context).size.width) * (16 / 428)), - ], - ), - ), - ], - ), - ), - ) - ], - ), - ); - } -} diff --git a/lib/screens/Welcome/QuizModule/quiz_final.dart b/lib/screens/Welcome/QuizModule/quiz_final.dart deleted file mode 100644 index 394e98e..0000000 --- a/lib/screens/Welcome/QuizModule/quiz_final.dart +++ /dev/null @@ -1,10 +0,0 @@ -import 'package:flutter/material.dart'; - -class QuizFinal extends StatelessWidget { - const QuizFinal({Key? key}) : super(key: key); - - @override - Widget build(BuildContext context) { - return Scaffold(backgroundColor: Colors.deepPurpleAccent,); - } -} diff --git a/lib/screens/Welcome/QuizModule/quiz_module.dart b/lib/screens/Welcome/QuizModule/quiz_module.dart deleted file mode 100644 index cc82f57..0000000 --- a/lib/screens/Welcome/QuizModule/quiz_module.dart +++ /dev/null @@ -1,1767 +0,0 @@ -import 'dart:async'; -import 'dart:convert'; -import 'dart:math' as math; - -import 'package:flutter/material.dart'; -import 'package:flutter_countdown_timer/current_remaining_time.dart'; -import 'package:flutter_countdown_timer/flutter_countdown_timer.dart'; -import 'package:http/http.dart' as http; -import 'package:testify/models/GenerateQuizModels/QuizModuleModels/generate_quiz_model.dart'; -import 'package:testify/models/GetPreviousQuizzesModel/ResumeQuiz/resume_quiz_model.dart'; -import 'package:testify/screens/Authentication/login.dart'; -import 'package:testify/screens/Welcome/QuizModule/question_explanation.dart'; -import 'package:testify/screens/Welcome/QuizModule/quiz_final.dart'; -import 'package:testify/screens/Welcome/QuizModule/search_bar.dart'; -import 'package:testify/screens/Welcome/side_menu_bar.dart'; -import 'package:testify/screens/Welcome//QuizModule/calculator.dart'; -import 'package:flutter_svg/flutter_svg.dart'; -import 'package:shared_preferences/shared_preferences.dart'; -import 'package:flutter/cupertino.dart'; - -class QuizModule extends StatefulWidget { - const QuizModule({Key? key, required this.totalQuestions, required this.questions, required this.timedMode, required this.mode, required this.whatsDone}) : super(key: key); - - final int totalQuestions; - final List questions; - final bool timedMode; - final String mode; - final String whatsDone; // new(From Generate Quiz), resumed, reviewed - @override - _QuizModuleState createState() => _QuizModuleState(); -} - -class _QuizModuleState extends State with WidgetsBindingObserver{ - int endTime = DateTime.now().millisecondsSinceEpoch + 1000 * 30; - List _questions = ['1', '2', '3', '4']; - String _currentQuestion = '1'; - int _currentSelected = 0; - String _labValues="Lorem ipsum dolor sit amet, consectetur adipiscing elit. Cras imperdiet finibus elit non luctus. Morbi auctor mattis ante. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Cras imperdiet finibus elit non luctus. Morbi auctor mattis ante."; - String _note="Lorem ipsum dolor sit amet, consectetur adipiscing elit. Cras imperdiet finibus elit non luctus. Morbi auctor mattis ante. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Cras imperdiet finibus elit non luctus. Morbi auctor mattis ante."; - late TextEditingController _textController; - double _fontSize = 18; // To change font size - bool _showTextZoom = false; // To show ths slider - - int timeElapsed = 0; - /// declare a timer - Timer? timer; - // Timer? saveQuiz; // Saves quiz every few seconds. - - //BottomNavBar - int _selectedIndex = 0; - - // This key is used to open the side drawer - final GlobalKey _scaffoldKey = new GlobalKey(); - - //Shared Pref - var _token; - var _userId; - - //Model Data - var _getGenerateQuizSuccessful; - var _resumeQuizSuccessful; - var _quizId; - - //Changing quiz questions - // This changes the array index which in turn changes the rest. - int questionNumber = 0; - - //To change Icon and color - int whichOption = 0; - - // To void null safety error - bool hasDataLoaded = false; - bool ranSaveQuizAtTheStart = false; // To auto save the quiz at the start and avoid the quizzes from being suspended - // if(hasDataLoaded = true) { - // if(ranSaveQuizAtTheStart = false) { - // SaveQuizAPI(); - // setState(() { - // ranSaveQuizAtTheStart = true; - // }); - // } - // } - - //Storing the data required to display quiz questions and store their answers - var questionsData = { - "title": [], - "ID": [], - "question": [], - "correct_msg": [], // This is the explanation - "options": [], // A list would be added to this list - "statistics": [], // [1, 0, 0] - "answeredCorrectly": [], // Stores string and turns true if answered correctly. Can't be a bool since values are correct/incorrect/notAnswered - "optionSelectedInt": [], //To change Icon and color - "notes": [], - "submitData": [], - // "isSelected": [] - }; - - @override - void initState() { - super.initState(); - _textController = TextEditingController(); - WidgetsBinding.instance!.addObserver(this); - if(widget.whatsDone == "new") - GenerateQuizAPI(); - else if(widget.whatsDone == "resumed") - ResumeQuizAPI(); - - timer = Timer.periodic( - const Duration(seconds: 1), - (timer) { - setState(() { - timeElapsed++; - }); - }, - ); - - // saveQuiz = Timer.periodic( - // const Duration(seconds: 10), - // (timer) { - // SaveQuizAPI(); - // }, - // ); - } - - @override - void didChangeAppLifecycleState(AppLifecycleState state) async { - super.didChangeAppLifecycleState(state); - - final isBackground = state == AppLifecycleState.paused; - final isClosed = state == AppLifecycleState.detached; - if(isBackground) { // As soon as the user closes the app this runs. The application is still in the app switcher(ram) - print("xD in Background"); - SaveQuizAPI("suspended"); - // ScaffoldMessenger.of(context) - // ..removeCurrentSnackBar() - // ..showSnackBar(SnackBar(content: Text("The Quiz has been saved as Suspended!"))); - Navigator.of(context).pop(); - } - if(isClosed) { // When app is closed from the app switcher. Doesn't run for now for some odd reason. - print("xD Closed"); - } - } - - Future ResumeQuizAPI() async { - SharedPreferences prefs = await SharedPreferences.getInstance(); - final String apiUrlGenerateQuiz = "https://demo.pookidevs.com/quiz/solver/resumeQuiz"; - var quizID = prefs.getInt("quizId"); - _token = prefs.getString('token')!; - print(_token); - _userId = prefs.getInt("userId")!; - http.post(Uri.parse(apiUrlGenerateQuiz), headers: { - 'Content-type': 'application/json; charset=UTF-8', 'Authorization' : _token.toString(), - }, body: json.encode( - { - "quizId": quizID - }) - ).then((response) { - // print(jsonDecode(response.body).toString()); - if((response.statusCode == 200) & (json.decode(response.body).toString().substring(0,14) != "{status: false")) { - final responseString = (response.body); - var resumeQuizSuccessful1 = resumeQuizModelFromJson(responseString); - final ResumeQuizModel resumeQuizSuccessful = resumeQuizSuccessful1; - setState(() { - _resumeQuizSuccessful = resumeQuizSuccessful; - print(_resumeQuizSuccessful.data.previousQuizzes[0].quizMeta.quizMode); - print(_resumeQuizSuccessful.data.previousQuizzes[0].quizMeta.quizTotalQuestions); - print(_resumeQuizSuccessful.data.previousQuizzes[0].quizMeta.quizQuestions); - print(_resumeQuizSuccessful.data.previousQuizzes[0].quizMeta.quizStatus); - print(_resumeQuizSuccessful.data.previousQuizzes[0].quizMeta.isTimed); - // print(_resumeQuizSuccessful.data.previousQuizzes[0].quizMeta.quizId.runtimeType); - // print(_resumeQuizSuccessful.data.previousQuizzes[0].quizMeta.quizScore.runtimeType); - // _quizId = _getGenerateQuizSuccessful.data.quizId; - // print(_quizId); - }); - categoriesGenerateQuizData(); - // categoriesGenerateQuizData(); - } - else { // Token Invalid - - } - } - ); - } - - Future submitAnswerAPI(int? indexOfOptionThatIsActuallyCorrect, int? correct, int? optionIndexSelected) async { // doesn't work properly in exam mode - final String apiUrlGenerateQuiz = "https://demo.pookidevs.com/quiz/solver/submitAnswer"; - // print(_token); - SharedPreferences prefs = await SharedPreferences.getInstance(); - var _quizID = prefs.getInt("quizId"); - - print(widget.whatsDone); - print("user id: "+ _userId.toString()); - print("questionId: "+ questionsData["id"]![questionNumber].toString()); - print("quizId" + _quizID.toString()); - print("indexOfOptionThatIsActuallyCorrect: " + indexOfOptionThatIsActuallyCorrect.toString()); - print("correct: " + correct.toString()); - print("optionIndexSelected: " + optionIndexSelected.toString()); - - - - http.post(Uri.parse(apiUrlGenerateQuiz), headers: { - 'Content-type': 'application/json; charset=UTF-8', 'Authorization' : _token.toString(), - }, body: json.encode( - { - "data":{ - "userId": _userId.toString(), - "questionId": questionsData["id"]![questionNumber].toString(), - // "quizId": widget.whatsDone == "new" ? _getGenerateQuizSuccessful.data.quizId.toString() : _resumeQuizSuccessful.data.previousQuizzes[0].quizId.toString(), - "quizId": _quizID.toString(), - "answerMeta":{ - "index": questionsData["id"]![questionNumber].toString(), - "Correctanswerindex": indexOfOptionThatIsActuallyCorrect.toString(), // indexOfOptionThatIsActuallyCorrect - "correct": correct.toString(), // Correct = 1 if answer is correct, -1 if answer is omitted and 0 if answer is incorrect - "optionIndexSelected": optionIndexSelected.toString() - } - } - }) - ).then((response) { - if((response.statusCode == 200)) { - print(jsonDecode(response.body).toString()); - if((jsonDecode(response.body).toString()) == "{data: {status: true, message: Answer Submitted}}") { - - } else { - ScaffoldMessenger.of(context) - ..removeCurrentSnackBar() - ..showSnackBar(SnackBar(content: Text("Error! Answer not Saved!"))); - } - } - else { // Token Invalid - ScaffoldMessenger.of(context) - ..removeCurrentSnackBar() - ..showSnackBar(SnackBar(content: Text("Token Invalid!"))); - final result = Navigator.pushAndRemoveUntil( - context, - MaterialPageRoute(builder: (BuildContext context) => const Login(fromWhere:"Home")), - ModalRoute.withName('/'), - ); - } - } - ); - } - - - Future SaveQuizAPI(String saveAs, [bool? hasUserClicked]) async { - SharedPreferences prefs = await SharedPreferences.getInstance(); - widget.whatsDone == "new" ? prefs.setInt("quizId", _getGenerateQuizSuccessful.data.quizId) : null; - final String apiUrlGenerateQuiz = "https://demo.pookidevs.com/quiz/solver/saveQuiz"; - print(widget.totalQuestions); - var date = new DateTime.now().toString().split("."); - date = date[0].split(" "); - print(date); - int quizScore = 0; - var addToOmittedQuestionsArray = []; - var totalQuizTime = timeElapsed.toString(); - for(int i = 0; i{ - 'Content-type': 'application/json; charset=UTF-8', 'Authorization' : _token.toString(), - }, body: json.encode( - { - "data": - { - "quiz" : { - "quizId": widget.whatsDone == "new" ? _getGenerateQuizSuccessful.data.quizId.toString() : _resumeQuizSuccessful.data.previousQuizzes[0].quizId, - "quizTitle": "Custom Quiz" + date[0].toString(), // "Custom Quiz" + Date.now() - "quizDate": date[0].toString(), // "Custom Quiz" - "quizScore": quizScore.toString(), // total correct - "quizTotalQuestions": widget.totalQuestions.toString(), - "quizStatus": saveAs, // == "completed" ? "completed" : "suspended", // "completed", "suspended" - "quizQuestions": questionsData["id"].toString(), // Question IDs - "quizMode": widget.mode, // "tutor", "exam" - "quizTime": totalQuizTime.toString(), // total quiz time in seconds - "isTimed": widget.timedMode, // bool true or false - "omittedQuestions": addToOmittedQuestionsArray, // Don't send anything here - "SelectedOptionsArray": [] // Don't send anything here - }, - "userId": _userId.toString() - } - } - - ) - ).then((response) async { - print(jsonDecode(response.body).toString()); - if((response.statusCode == 200) & (json.decode(response.body).toString().substring(0,14) != "{status: false")) { - - } - else { // Token Invalid - ScaffoldMessenger.of(context) - ..removeCurrentSnackBar() - ..showSnackBar(SnackBar(content: Text("Token Invalid!"))); - final result = Navigator.pushAndRemoveUntil( - context, - MaterialPageRoute(builder: (BuildContext context) => const Login(fromWhere:"Home")), - ModalRoute.withName('/'), - ); - } - } - ).whenComplete(() { - if(hasUserClicked == true) { - ScaffoldMessenger.of(context) - ..removeCurrentSnackBar() - ..showSnackBar(SnackBar(content: Text("The Quiz has been saved as $saveAs!"))); - Navigator.of(context) - .popUntil(ModalRoute.withName("/home")); - final result = Navigator.push( - context, - MaterialPageRoute(builder: (context) => QuizFinal()), - ); - } - }); - - } - - Future GenerateQuizAPI() async { - print("Mode: " + widget.mode.toString()); - SharedPreferences prefs = await SharedPreferences.getInstance(); - final String apiUrlGenerateQuiz = "https://demo.pookidevs.com/quiz/generator/generateQuiz"; - _token = prefs.getString('token')!; - _userId = prefs.getInt("userId")!; - http.post(Uri.parse(apiUrlGenerateQuiz), headers: { - 'Content-type': 'application/json; charset=UTF-8', 'Authorization' : _token.toString(), - }, body: json.encode( - { - "data": - { - "questionIds": widget.questions, - "count": widget.totalQuestions - } - }) - ).then((response) { - // print("This is: " + jsonDecode(response.body).toString()); - if((response.statusCode == 200) & (json.decode(response.body).toString().substring(0,14) != "{status: false")) { - final responseString = (response.body); - var generateQuizSuccessful = generateQuizSuccessfulFromJson(responseString); - final GenerateQuizSuccessful getGenerateQuizSuccessful = generateQuizSuccessful; - setState(() { - _getGenerateQuizSuccessful = getGenerateQuizSuccessful; - _quizId = _getGenerateQuizSuccessful.data.quizId; - print(_quizId); - }); - categoriesGenerateQuizData(); - } - else { // Token Invalid - - } - } - ); - } - - Future BookmarkQuestionAPI() async { - final String apiUrlGenerateQuiz = "https://demo.pookidevs.com/quiz/solver/markQuestion"; - http.post(Uri.parse(apiUrlGenerateQuiz), headers: { - 'Content-type': 'application/json; charset=UTF-8', 'Authorization' : _token.toString(), - }, body: json.encode( - { - "data": { - "userId": _userId, - "questionId": questionsData["id"]![questionNumber].toString(), - "tableName": "marked_questions", - "isMarked": true - } - }) - ).then((response) { - if((response.statusCode == 200)) { // & (json.decode(response.body).toString().substring(0,14) != "{status: false")) { - print(jsonDecode(response.body).toString()); - } - else { // Token Invalid - ScaffoldMessenger.of(context) - ..removeCurrentSnackBar() - ..showSnackBar(SnackBar(content: Text("Token Invalid!"))); - final result = Navigator.pushAndRemoveUntil( - context, - MaterialPageRoute(builder: (BuildContext context) => const Login(fromWhere:"Home")), - ModalRoute.withName('/'), - ); - } - } - ); - } - - Future addNotesAPI() async { - // print(_userId); - // print(questionsData["id"]![questionNumber].toString()); - // print(_quizId); - // print(_note); - final String apiUrlGenerateQuiz = "https://demo.pookidevs.com/quiz/notes/addNotes"; - http.post(Uri.parse(apiUrlGenerateQuiz), headers: { - 'Content-type': 'application/json; charset=UTF-8', 'Authorization' : _token.toString(), - }, body: json.encode( - { - "data": { - "userId": _userId, - "questionId": questionsData["id"]![questionNumber].toString(), - "quizId": _quizId, - "note": _note, - "tableName": "notes" - } - } - ) - ).then((response) { - // print(jsonDecode(response.body).toString()); - // print(json.decode(response.body).toString().substring(json.decode(response.body).toString().length-12,json.decode(response.body).toString().length)); - if((response.statusCode == 200) & (json.decode(response.body).toString().substring(json.decode(response.body).toString().length-12,json.decode(response.body).toString().length) == "Note Added}}")) { - ScaffoldMessenger.of(context) - ..removeCurrentSnackBar() - ..showSnackBar(SnackBar(content: Text("Note Added!"))); - } - else if((response.statusCode == 200) & (json.decode(response.body).toString().substring(0,14) == "{status: false")) { // Token Invalid - ScaffoldMessenger.of(context) - ..removeCurrentSnackBar() - ..showSnackBar(SnackBar(content: Text("Token Expired!"))); - final result = Navigator.push( - context, - MaterialPageRoute(builder: (context) => const Login(fromWhere:"Home")), - ); - } - else { - ScaffoldMessenger.of(context) - ..removeCurrentSnackBar() - ..showSnackBar(SnackBar(content: Text("Note not Added!"))); - } - } - ); - } - - void categoriesGenerateQuizData() async { - setState(() { - questionsData["id"] = []; - questionsData["question"] = []; - questionsData["options"] = []; - questionsData["statistics"] = []; - questionsData["correct_msg"] = []; - questionsData["answeredCorrectly"] = []; - questionsData["optionSelectedInt"] = []; - questionsData["notes"] = []; - questionsData["submitData"] = []; - _questions = []; - }); - if(widget.whatsDone == "new") - { - int c = 0; - if (_getGenerateQuizSuccessful != null) { - while ((c < _getGenerateQuizSuccessful.data.questions.toList().length) & - (_getGenerateQuizSuccessful.data.questions.toList().length > 0)) { - // questionsData - setState(() { - questionsData["id"]! - .add(_getGenerateQuizSuccessful.data.questions[c].id); - questionsData["question"]! - .add(_getGenerateQuizSuccessful.data.questions[c].question); - questionsData["options"]! - .add(_getGenerateQuizSuccessful.data.questions[c].options); - questionsData["statistics"]! - .add(_getGenerateQuizSuccessful.data.questions[c].statistics); - questionsData["correct_msg"]!.add(_getGenerateQuizSuccessful - .data.questions[c].correctMsg); //answeredCorrectly - questionsData["answeredCorrectly"]!.add("notAnswered"); - questionsData["optionSelectedInt"]!.add(0); - _questions.add((c + 1).toString()); - }); - c++; - } - setState(() { - hasDataLoaded = true; - }); - if (hasDataLoaded == true) { - if (ranSaveQuizAtTheStart == false) { - SaveQuizAPI("suspended"); - setState(() { - ranSaveQuizAtTheStart = true; - }); - } - } - } - } - // print(questionsData); - else if(widget.whatsDone == "resumed") - { - int c = 0; - if (_resumeQuizSuccessful != null) { - while ((c < _resumeQuizSuccessful.data.questions.length) & - (_resumeQuizSuccessful.data.questions.length > 0)) { - // questionsData - setState(() { - questionsData["id"]! - .add(_resumeQuizSuccessful.data.questions[c].id); - questionsData["question"]! - .add(_resumeQuizSuccessful.data.questions[c].question); - questionsData["options"]! - .add(_resumeQuizSuccessful.data.questions[c].options); - questionsData["statistics"]! - .add(_resumeQuizSuccessful.data.questions[c].statistics); - questionsData["correct_msg"]!.add(_resumeQuizSuccessful - .data.questions[c].correctMsg); //answeredCorrectly - questionsData["answeredCorrectly"]!.add("notAnswered"); - questionsData["optionSelectedInt"]!.add(0); - _questions.add((c + 1).toString()); - if(_resumeQuizSuccessful.data.questions[c].notes != null) { // notes - questionsData["notes"]!.add(_resumeQuizSuccessful - .data.questions[c].notes); - } else { - questionsData["notes"]!.add(""); - } - if(_resumeQuizSuccessful.data.questions[c].submitData != null) { // submitData - String str = _resumeQuizSuccessful.data.questions[c].submitData; - str = str.replaceAll("\\", ""); - var strMap = json.decode(str); - print(strMap); - if(strMap['correct'] == '1') { - questionsData["answeredCorrectly"]![c] = "correct"; - } - else if (strMap['correct'] == '0') { - questionsData["answeredCorrectly"]![c] = "incorrect"; - } - questionsData["optionSelectedInt"]![c] = int.parse(strMap['optionIndexSelected']); - questionsData["submitData"]!.add(_resumeQuizSuccessful - .data.questions[c].submitData); - } else { - questionsData["submitData"]!.add(""); - } - }); - c++; - } - print(questionsData["answeredCorrectly"]); - setState(() { - hasDataLoaded = true; - }); - if (hasDataLoaded == true) { - if (ranSaveQuizAtTheStart == false) { - SaveQuizAPI("suspended"); - setState(() { - ranSaveQuizAtTheStart = true; - }); - } - } - } - } - // print(_resumeQuizSuccessful.data.previousQuizzes[0].quizMeta.quizMode); - } - - // To change text size - text zoom - Widget _textZoom(BuildContext context) { - return GestureDetector( - onTap: () { - }, - child: Container( - height: ((MediaQuery.of(context).size.height) * (51 / 926)), - decoration: const BoxDecoration( - gradient: LinearGradient( - begin: Alignment.topCenter, - end: Alignment.bottomCenter, - colors: [Color(0xff7F1AF1), Color(0xff482384)])), - child: new Slider( - value: _fontSize, - activeColor: Colors.white, - inactiveColor: Colors.red, - onChanged: (double value) { - setState(() { - _fontSize = value; - print(_fontSize); - }); - }, - divisions: 4, - min: 14.0, - max: 22.0, - ), - ), - ); - } - - - void onEnd() { - print('onEnd'); - } - - Widget bookmarkQuestion(BuildContext context) { - return SizedBox( - child: AlertDialog( - contentPadding: EdgeInsets.all(MediaQuery.of(context).size.width*(15/428)), - content: Column( - mainAxisSize: MainAxisSize.min, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Text( - 'Bookmark', - style: TextStyle( - color: Color(0xffB0A6C2), - fontFamily: 'Brandon-bld', - fontSize: (MediaQuery.of(context).size.height) * (18 / 926), - ), - ), - IconButton(icon:Icon(Icons.cancel),iconSize:23,color: Color(0xFF3F2668),onPressed: () { - Navigator.of(context).pop(); - },), - ], - ), - Divider(), - Text("Are you sure you want to bookmark this question", - ), - ], - ), - actions: [ - Divider(), - Row( - mainAxisAlignment: MainAxisAlignment.end, - children: [ - TextButton( - onPressed: () { - Navigator.of(context).pop(); - }, - child: Text('No', - style: TextStyle( - color: Color(0xff3F2668), - fontFamily: 'Brandon-bld', - fontSize: - (MediaQuery.of(context).size.height) * (21 / 926), - )), - ), - Divider(), - TextButton( - onPressed: () { - Navigator.of(context).pop(); - print(questionsData["id"]![questionNumber].toString()); - BookmarkQuestionAPI(); - }, - child: Text('Yes', - style: TextStyle( - color: Color(0xff3F2668), - fontFamily: 'Brandon-bld', - fontSize: - (MediaQuery.of(context).size.height) * (21 / 926), - )), - ), - ], - ), - ], - ), - ); - } - - Widget labValues(BuildContext context) { - return SizedBox( - child: AlertDialog( - contentPadding: EdgeInsets.all(MediaQuery.of(context).size.width*(15/428)), - content: Column( - mainAxisSize: MainAxisSize.min, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Text( - 'Lab Values', - style: TextStyle( - color: Color(0xffB0A6C2), - fontFamily: 'Brandon-bld', - fontSize: (MediaQuery.of(context).size.height) * (18 / 926), - ), - ), - IconButton(icon:Icon(Icons.cancel),iconSize:23,color: Color(0xFF3F2668),onPressed: () { - Navigator.of(context).pop(); - },), - ], - ), - Divider(), - Text(_labValues), - ], - ), - ), - ); - } - Widget moreMenu() { - return Container( - width: (MediaQuery.of(context).size.width) * 0.3, - child: Drawer( - child: Container( - decoration: const BoxDecoration( - gradient: LinearGradient( - begin: Alignment.topRight, - end: Alignment.bottomLeft, - colors: [Color(0xff3F2668), Color(0xff482384)])), - child: ListView( - // Remove padding - padding: EdgeInsets.zero, - children: [ - Container( - padding: EdgeInsets.only( - top: MediaQuery.of(context).padding.top), - height: (MediaQuery.of(context).size.height), - color: Colors.transparent, - child: Column( - children: [ - ListTile( - leading: Icon( - Icons.close, - color: Colors.white, - ), - onTap: () => Navigator.pop(context), - ), - SizedBox( - height: - (MediaQuery.of(context).size.height) * (47 / 926), - ), - InkWell( - onTap: () { - Navigator.of(context).pop(); - // showDialog( - // context: context, - // builder: (BuildContext context) => - // labValues(context), - // ); - final result = Navigator.push( - context, - MaterialPageRoute(builder: (context) => SearchListExample()), - ); - }, - child: Container( - alignment: Alignment.center, - child: Column( - children: [ - SvgPicture.asset( - 'assets/Images/lab.svg', - height: (MediaQuery.of(context).size.height) * - (37 / 926), - color: Colors.white, - ), - SizedBox( - height: (MediaQuery.of(context).size.height) * - (10 / 926), - ), - Text( - 'Lab Values', - style: TextStyle( - color: Colors.white, - fontFamily: 'Brandon-bld', - fontSize: - (MediaQuery.of(context).size.height) * - (15 / 926), - ), - ) - ], - ), - ) - - //Divider(), - ), - SizedBox( - height: - (MediaQuery.of(context).size.height) * (47 / 926), - ), - InkWell( - onTap: () { - Navigator.of(context).pop(); - // bookmarkQuestion - showDialog( - context: context, - builder: (BuildContext context) => - bookmarkQuestion(context), - ); - }, - child: Container( - alignment: Alignment.center, - child: Column( - children: [ - Icon( - Icons.bookmark, - size: 37, - color: Colors.white, - ), - SizedBox( - height: (MediaQuery.of(context).size.height) * - (10 / 926), - ), - Text( - 'Bookmarks', - style: TextStyle( - color: Colors.white, - fontFamily: 'Brandon-bld', - fontSize: - (MediaQuery.of(context).size.height) * - (15 / 926), - ), - ) - ], - ), - ) - - //Divider(), - ), - SizedBox( - height: - (MediaQuery.of(context).size.height) * (47 / 926), - ), - InkWell( - onTap: () { - Navigator.of(context).pop(); - showDialog( - context: context, - builder: (BuildContext context) => - notes(context), - ); - }, - child: Container( - alignment: Alignment.center, - child: Column( - children: [ - Icon( - Icons.note_rounded, - size: 37, - color: Colors.white, - ), - SizedBox( - height: - (MediaQuery.of(context).size.height) * - (10 / 926), - ), - Text( - 'Notes', - style: TextStyle( - color: Colors.white, - fontFamily: 'Brandon-bld', - fontSize: - (MediaQuery.of(context).size.height) * - (15 / 926), - ), - ) - ], - ), - ) - - //Divider(), - ), - SizedBox( - height: - (MediaQuery.of(context).size.height) * (47 / 926), - ), - InkWell( - onTap:() {Navigator.of(context).pop(); - showDialog( - context: context, - builder: (BuildContext context) => - Calculator(), - );}, - child: Container( - alignment: Alignment.center, - child: Column( - children: [ - SvgPicture.asset('assets/Images/calculator.svg', - height: (MediaQuery.of(context).size.height) * - (37 / 926)), - SizedBox( - height: (MediaQuery.of(context).size.height) * - (10 / 926), - ), - Text( - 'Calculator', - style: TextStyle( - color: Colors.white, - fontFamily: 'Brandon-bld', - fontSize: - (MediaQuery.of(context).size.height) * - (15 / 926), - ), - ) - ], - ), - )), - SizedBox( - height: - (MediaQuery.of(context).size.height) * (47 / 926), - ), - InkWell( - onTap: () { - Navigator.of(context).pop(); - setState(() { - _showTextZoom = true; - }); - }, - child: Container( - alignment: Alignment.center, - child: Column( - children: [ - SvgPicture.asset('assets/Images/zoom.svg', - height: (MediaQuery.of(context).size.height) * - (37 / 926)), - SizedBox( - height: (MediaQuery.of(context).size.height) * - (10 / 926), - ), - Text( - 'Text Zoom', - style: TextStyle( - color: Colors.white, - fontFamily: 'Brandon-bld', - fontSize: - (MediaQuery.of(context).size.height) * - (15 / 926), - ), - ) - ], - ), - )) - ], - ), - ), - ]), - ))); - } - Widget notes(BuildContext context) { - return SizedBox( - child: AlertDialog( - contentPadding: EdgeInsets.all(MediaQuery.of(context).size.width*(15/428)), - content: Column( - mainAxisSize: MainAxisSize.min, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Text( - 'Take Notes', - style: TextStyle( - color: Color(0xffB0A6C2), - fontFamily: 'Brandon-bld', - fontSize: (MediaQuery.of(context).size.height) * (18 / 926), - ), - ), - IconButton(icon:Icon(Icons.cancel),iconSize:23,color: Color(0xFF3F2668),onPressed: () { - Navigator.of(context).pop(); - },), - ], - ), - Divider(), - TextField( - controller: _textController, - keyboardType: TextInputType.multiline, - minLines: 1,//Normal textInputField will be displayed - maxLines: 5,// when user presses enter it will adapt to it - decoration: InputDecoration( - hintText: "Add notes here...", - hintStyle: TextStyle(color: Color(0xffAEAEAE), - fontSize: (MediaQuery.of(context).size.height)*(15/926), - fontFamily: 'Brandon-med',), - contentPadding: EdgeInsets.fromLTRB(2.0, 1, 2.0, 1), - focusedBorder: OutlineInputBorder( - borderSide: BorderSide( - color: Colors.transparent, - width: 0.0, - ), - ), - ), - style: TextStyle( - color: Colors.black, - fontSize: (MediaQuery.of(context).size.height)*(15/926), - fontFamily: 'Brandon-med', - ), - onChanged: (String value) { - setState(() { - _note = value; - }); - }, - ), - Row( - mainAxisAlignment: MainAxisAlignment.end, - children: [ - IconButton(onPressed:(){ - setState((){ - _note=''; - _textController.clear(); - } - ); - } , iconSize: 21 ,icon: Icon(Icons.refresh,color: Color(0xFF3F2668))), - TextButton( - onPressed: () { - addNotesAPI(); - _textController.clear(); - Navigator.of(context).pop(); - }, - style: TextButton.styleFrom( - padding: EdgeInsets.zero,), - child: Container( - height: (MediaQuery.of(context).size.height) * (31 / 926), - width:(MediaQuery.of(context).size.width) * (97 / 428), - decoration: BoxDecoration(borderRadius:BorderRadius.circular(4),color: Color(0xFFDDDAE2),), - child:Row( - mainAxisAlignment: MainAxisAlignment.center, - children:[ - Icon(Icons.save,color: Color(0xFF3F2668),), - SizedBox( - height: (MediaQuery.of(context).size.width) * - (14 / 428), - ), - Text( - 'Save', - style: TextStyle( - color: Color(0xff3F2668), - fontFamily: 'Brandon-bld', - fontSize: (MediaQuery.of(context).size.height) * (19 / 926), - ), - ), - ]) - ),) - ], - ) - ], - ), - ),);} - Future _onQuit() async { - return (await showDialog( - context: context, - builder: (context) => AlertDialog( - content: Text( - 'Mark Quiz as', - style: TextStyle( - color: Color(0xffA1A1A1), - fontFamily: 'Brandon-bld', - fontSize: (MediaQuery.of(context).size.height) * (21 / 926), - ), - ), - actions: [ - TextButton( - onPressed: () async { - await SaveQuizAPI("suspended", true); - // ScaffoldMessenger.of(context) - // ..removeCurrentSnackBar() - // ..showSnackBar(SnackBar(content: Text("The Quiz has been saved as Suspended!"))); - // Navigator.of(context).pop(); - // Navigator.of(context).pop(); - }, - child: Text('Suspended', - style: TextStyle( - color: Color(0xff3F2668), - fontFamily: 'Brandon-bld', - fontSize: - (MediaQuery.of(context).size.height) * (21 / 926), - )), - ), - TextButton( - onPressed: () async { - await SaveQuizAPI("completed", true); - // Navigator.of(context).pop(); - // Navigator.of(context).pop(); // Uncomment when "completed" and omittedQuestionsArray work again. - }, - child: Text('Completed', - style: TextStyle( - color: Color(0xff3F2668), - fontFamily: 'Brandon-bld', - fontSize: - (MediaQuery.of(context).size.height) * (21 / 926), - )), - ), - ], - ), - )) ?? - false; - } - - @override - void dispose() { - _textController.dispose(); - timer?.cancel(); - WidgetsBinding.instance!.removeObserver(this); - // saveQuiz?.cancel(); - super.dispose(); - } - - @override - Widget build(BuildContext context) { - return WillPopScope( - onWillPop: () async { - // ScaffoldMessenger.of(context) - // ..removeCurrentSnackBar() - // ..showSnackBar(SnackBar(content: Text("Click on Quit Quiz!"))); - return true; - }, - child: Scaffold( - resizeToAvoidBottomInset: false, - backgroundColor: Color(0xffF8F9FB), - drawer: SideMenuBar(), - // drawer: moreMenu(), - endDrawer: moreMenu(), - appBar: AppBar( - toolbarHeight: (MediaQuery.of(context).size.height) * (73.52 / 926), - backgroundColor: Color(0xff3F2668), - elevation: 2, - centerTitle: true, - title: Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Text( - 'Question ', - style: TextStyle( - color: Color(0xffffffff), - fontFamily: 'Brandon-bld', - fontSize: (MediaQuery.of(context).size.height) * (20 / 926), - ), - ), - DropdownButton( - value: (questionNumber + 1).toString(), - underline: Container(), - iconEnabledColor: Colors.white, - dropdownColor: Color(0xff3F2668), - onChanged: (newValue) { - setState(() { - // print(newValue); - _currentQuestion = newValue as String; - questionNumber = int.parse(newValue) - 1; - }); - }, - items: _questions.map((question) { - return DropdownMenuItem( - child: new Text( - question + ' / ' + widget.totalQuestions.toString(), - style: TextStyle( - color: Colors.white, - fontFamily: 'Brandon-bld', - fontSize: - (MediaQuery.of(context).size.height) * (20 / 926), - ), - ), - value: question, - ); - }).toList(), - ), - ], - ), - flexibleSpace: Container( - decoration: const BoxDecoration( - gradient: LinearGradient( - begin: Alignment.topCenter, - end: Alignment.bottomCenter, - colors: [Color(0xff7F1AF1), Color(0xff482384)])), - ), - actions: [ - TextButton( - onPressed: () async { - SaveQuizAPI("suspended", false); - }, - child: SvgPicture.asset( - "assets/Images/logout.svg", - height: (MediaQuery.of(context).size.height) *(32/926), - ), - ), - ], - ), - body: hasDataLoaded == false ? Center(child: CircularProgressIndicator()) : Column( - children: [ - GestureDetector( - onTap: () { - setState(() { - _showTextZoom = false; - }); - }, - child: Container( - height: ((MediaQuery.of(context).size.height) * ((926-73.52-50.88-(MediaQuery.of(context).padding.top)-8.1) / 926)), - child: ListView( - scrollDirection: Axis.vertical, - children: [ - Container( - padding: EdgeInsets.only( - top: (MediaQuery.of(context).size.height) * (15 / 926), - bottom: (MediaQuery.of(context).size.height) * (8 / 926), - left: (MediaQuery.of(context).size.width) * (18 / 428), - right: (MediaQuery.of(context).size.width) * (18 / 428)), - child: Column( - children: [ - Row( - children: [ - Container( - width: (MediaQuery.of(context).size.width) * (221 / 428), - //height: (MediaQuery.of(context).size.height) *(91/926), - child: Column( - children: [ - Align( - alignment: Alignment.topLeft, - child: Text( - "Attempt Your Quiz", - style: TextStyle( - color: Color(0xff232323), - fontFamily: 'Brandon-bld', - fontSize: (MediaQuery.of(context).size.height) * - (20 / 926), //38, - ), - ), - ), - SizedBox( - height: (MediaQuery.of(context).size.height) * - (2 / 926), - ), - Align( - alignment: Alignment.topLeft, - child: Text( - "Question ID: " + questionsData["id"]![questionNumber].toString(), // questionNumber - style: TextStyle( - color: Color(0xFF7F1AF1), - fontFamily: 'Brandon-med', - fontSize: (MediaQuery.of(context).size.height) * - (13 / 926), //38, - ), - ), - ) - ], - ), - ), - SizedBox( - width: (MediaQuery.of(context).size.width) * (39 / 428), - ), - // for timer - Container( - height: (MediaQuery.of(context).size.height) * (25 / 926), - width: (MediaQuery.of(context).size.width) * (87 / 428), - color: Color(0xFF3F2668), - child: Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Text('', - style: TextStyle( - color: Color(0xFFFFFFFF), - fontFamily: 'Brandon-med', - fontSize: (MediaQuery.of(context).size.height) * - (7 / 926), - )), - CountdownTimer( - textStyle: TextStyle( - color: Color(0xFFFFFFFF), - fontFamily: 'Brandon-med', - fontSize: (MediaQuery.of(context).size.height) * - (13 / 926), - ), - endTime: endTime, - onEnd: onEnd, - endWidget: Text( - "00 : 00 : 00", - style: TextStyle( - color: Color(0xFFFFFFFF), - fontFamily: 'Brandon-med', - fontSize: (MediaQuery.of(context).size.height) * - (13 / 926), - ), - ), - ), - ], - ), - ) - ], - ), - SizedBox( - height: (MediaQuery.of(context).size.height) * (25 / 926), - ), - Text( - questionsData["question"]![questionNumber].toString(), - style: TextStyle( - color: Color(0xFF483A3A), - fontFamily: 'Brandon-med', - fontSize: - (MediaQuery.of(context).size.height) * (_fontSize / 926), //38, - ), - ), - SizedBox( - height: (MediaQuery.of(context).size.height) * (25 / 926), - ), - if(questionsData["options"] != null) - for(int i = 0; i QuestionExplanation(question: questionsData["question"]![questionNumber].toString(), correctAnswer: correctAns.toString(), questionId: questionsData["id"]![questionNumber], explanation: questionsData["correct_msg"]![questionNumber].toString(),)), - ); - }, - child: Container( - alignment: Alignment.topRight, - child: Text( - "See Explanation", - style: TextStyle( - color: Color(0xFF7F1AF1), - fontFamily: 'Brandon-med', - fontSize: (MediaQuery.of(context).size.height) * - (13 / 926), //38, - ), - ), - ), - ) : Container(), - SizedBox( - height: (MediaQuery.of(context).size.height) * (20 / 926), - ), - ], - ) : - Column( // Exam Mode! - children: [ - TextButton( - onPressed: () { - // print("i: " + i.toString()); - // if(questionsData["answeredCorrectly"]![questionNumber] == "notAnswered") { - if((questionsData["answeredCorrectly"]![questionNumber] == "notAnswered") || (questionsData["answeredCorrectly"]![questionNumber] != "notAnswered")) { - int? indexOfOptionThatIsActuallyCorrect; - int? correct; - // whichOption = i; optionSelectedInt - setState(() { - questionsData["optionSelectedInt"]![questionNumber] = i; - }); - int j = 0; - for(j = 0; j<10; j++) { - if(questionsData["options"]![questionNumber][i].toString() == questionsData["options"]![questionNumber][j].toString()) { - break; - } - } - if(questionsData["statistics"]![questionNumber][j] == 1) { - setState(() { - questionsData["answeredCorrectly"]![questionNumber] = "correct"; - }); - correct = 1; - // print("correct: " + correct.toString()); - // print(questionsData["answeredCorrectly"]); - } - else if(questionsData["statistics"]![questionNumber][j] == 0) { - setState(() { - questionsData["answeredCorrectly"]![questionNumber] = "incorrect"; - }); - correct = 0; - // print(questionsData["answeredCorrectly"]); - } - for(int c = 0; c QuestionExplanation(question: questionsData["question"]![questionNumber].toString(), correctAnswer: correctAns.toString(), questionId: questionsData["id"]![questionNumber], explanation: questionsData["correct_msg"]![questionNumber].toString(),)), - // ); - // }, - // child: Container( - // alignment: Alignment.topRight, - // child: Text( - // "See Explanation", - // style: TextStyle( - // color: Color(0xFF7F1AF1), - // fontFamily: 'Brandon-med', - // fontSize: (MediaQuery.of(context).size.height) * - // (13 / 926), //38, - // ), - // ), - // ), - // ) : Container(), - SizedBox( - height: (MediaQuery.of(context).size.height) * (20 / 926), - ), - ], - ),// here - SizedBox( - height: (MediaQuery.of(context).size.height) * (5 / 926), - ), - SizedBox( - height: (MediaQuery.of(context).size.height) * (96 / 926), - ), - Row( - mainAxisAlignment: MainAxisAlignment.end, - children: [ - Container( - alignment: Alignment.bottomRight, - child: InkWell( - child: Icon(Icons.power_settings_new, - color: Color(0xFF7F1AF1), - size: (MediaQuery.of(context).size.height) * - (23 / 926),), - ), - ), - SizedBox( - width: (MediaQuery.of(context).size.width) * (5 / 428), - ), - Container( - alignment: Alignment.bottomRight, - child: InkWell( - child: Text( - "Quit Quiz", - style: TextStyle( - color: Color(0xFF7F1AF1), - fontFamily: 'Brandon-bld', - fontSize: (MediaQuery.of(context).size.height) * - (13 / 926), //38, - ), - ), - onTap: () => _onQuit())), - ], - ), - SizedBox( - height: (MediaQuery.of(context).size.height) * (26 / 926), - ), - ], - )), - ], - ), - ), - ) , - Align( - alignment: Alignment.bottomCenter, - child: Container( - height: ((MediaQuery.of(context).size.height) * (51 / 926)), - decoration: const BoxDecoration( - gradient: LinearGradient( - begin: Alignment.topCenter, - end: Alignment.bottomCenter, - colors: [Color(0xff7F1AF1), Color(0xff482384)])), - child: _showTextZoom == true ? _textZoom(context) : Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - TextButton( - onPressed: () { - if(questionNumber > 0) { - setState(() { - questionNumber--; - }); - } - }, - style: TextButton.styleFrom( - padding: EdgeInsets.zero,), - child: Row( - children: [ - SizedBox(width: (MediaQuery.of(context).size.width) * (16 / 428)), - Container( - child: Icon(Icons.arrow_back_ios_outlined, - color: Colors.white, - size: ((MediaQuery.of(context).size.width) * (23.1 / 428)),), - ), - ], - ), - ), - Builder( - builder: (context) => TextButton( - onPressed: () { Scaffold.of(context).openEndDrawer(); }, - style: TextButton.styleFrom( - padding: EdgeInsets.zero,), - child: Row( - children: [ - Container( - width: ((MediaQuery.of(context).size.height) * (15 / 926)), - decoration: BoxDecoration( - color: Colors.white, - shape: BoxShape.circle - ), - ), - SizedBox(width: (MediaQuery.of(context).size.width) * (6 / 428)), - Container( - width: ((MediaQuery.of(context).size.height) * (15 / 926)), - decoration: BoxDecoration( - color: Colors.white, - shape: BoxShape.circle - ), - ), - SizedBox(width: (MediaQuery.of(context).size.width) * (6 / 428)), - Container( - width: ((MediaQuery.of(context).size.height) * (15 / 926)), - decoration: BoxDecoration( - color: Colors.white, - shape: BoxShape.circle - ), - ), - ], - ), - ), - ), - TextButton( - onPressed: () { - if(questionNumber < (widget.totalQuestions - 1)) { - setState(() { - questionNumber++; - }); - } - }, - style: TextButton.styleFrom( - padding: EdgeInsets.zero,), - child: Row( - children: [ - Container( - child: Icon(Icons.arrow_forward_ios_outlined, - color: Colors.white, - size: ((MediaQuery.of(context).size.width) * (23.1 / 428)),), - ), - SizedBox(width: (MediaQuery.of(context).size.width) * (16 / 428)), - ], - ), - ), - ], - ), - ), - ) - ], - ), - ), - ); - } -} diff --git a/lib/screens/Welcome/QuizModule/search_bar.dart b/lib/screens/Welcome/QuizModule/search_bar.dart deleted file mode 100644 index 6f925a0..0000000 --- a/lib/screens/Welcome/QuizModule/search_bar.dart +++ /dev/null @@ -1,861 +0,0 @@ -import 'package:flutter/material.dart'; - -class SearchListExample extends StatefulWidget { - @override - _SearchListExampleState createState() => new _SearchListExampleState(); -} - -class _SearchListExampleState extends State with SingleTickerProviderStateMixin { - - final bloodLabValues = [ - {"title": 'Alanine aminotransferase (ALT), serum', "value": '8-40 U/L', "siValue": '8-40 U/L', - "subtitle": [{"title": '', "value": ''}] - }, - {"title": 'Alkaline phosphatase, serum ', "value": '', "siValue": '', - "subtitle": [ - {"title": 'Male', "value": '30-100 U/L', "siValue": '30-100 U/L'}, - {"title": 'Female', "value": '45-115 U/L', "siValue": '45-115 U/L'}, - ] - }, - {"title": 'Amylase, serum', "value": '25-125 U/L', "subtitle": [], "siValue": '25-125 U/L' }, - {"title": 'Aspartate aminotransferase (AST), serum', "value": '8-40 U/L', "subtitle": [], "siValue": '8-40 U/L'}, - {"title": 'Bilirubin, serum (adult)' , "value": '', "siValue": '', - "subtitle": [ - {"title": 'Total', "value": '0.1-1.0 mg/dL', "siValue": '2-17 μmol/L'}, - {"title": 'Direct', "value": '0.0-0.3 mg/dL', "siValue": '0.0-0.05 μmol/L'}, - ] - }, - {"title": 'Calcium, serum (total)', "value": '8.4-10.2 mg/dL', "subtitle": [], "siValue": '2.1-2.8 mmol/L'}, - {"title": 'Cholesterol, serum' , "value": '', "siValue": '', - "subtitle": [ - {"title": 'Total', "value": '150-240 mg/dL', "siValue": '3.9-6.2 mmol/L'}, - {"title": 'HDL', "value": '0-70 mg/dL', "siValue": '0.8-1.8 mmol/L'}, - {"title": 'LDL', "value": '<160 mg/dL', "siValue": '<4.2 mmol/L'}, - ] - }, - {"title": 'Cortisol, serum', "value": '', "siValue": '', - "subtitle": [ - {"title": '0800 h', "value": '5-23 μg/dL', "siValue": '138-635 nmol/L'}, - {"title": '1600 h', "value": '3-15 μg/dL', "siValue": '82-413 nmol/L'}, - {"title": '2000 h', "value": '50% of 0800 h', "siValue": 'Fraction of 0800 h: ≤0.50'}, - ] - }, - {"title": 'Creatine kinase, serum', "value": '', "siValue": 'L', - "subtitle": [ - {"title": 'Male', "value": '25-90 U/L', "siValue": '25-90 U/L'}, - {"title": 'Female', "value": '10-70 U/L', "siValue": '10-70 U/L'}, - ] - }, - {"title": 'Creatinine, serum', "value": '0.6-1.2 mg/dL', "subtitle": [], "siValue": '53-106 μmol/L'}, - {"title": 'Electrolytes, serum', "value": '', "siValue": '', - "subtitle": [ - {"title": 'Sodium (Na+)', "value": '136-145 mEq/L', "siValue": '136-145 mEq/L'}, - {"title": 'Potassium (K+)', "value": '3.5-5.0 mEq/L', "siValue": '95-105 mmol/L'}, - {"title": 'Chloride (Cl-)', "value": '95-105 mEq/L', "siValue": '3.5-5.0 mmol/L'}, - {"title": 'Bicarbonate (HCO3-)', "value": '22-28 mEq/L', "siValue": '22-28 mEq/L'}, - {"title": 'Magnesium (Mg2+)', "value": '1.5-2.0 mEq/L', "siValue": '0.75-1.0 mmol/L'}, - ] - }, - {"title": 'Estriol, total, serum (in pregnancy)', "value": '', "siValue": '', - "subtitle": [ - {"title": '24-28 wks', "value": '30-170 ng/mL', "siValue": '104-590 nmol/L'}, - {"title": '28-32 wks', "value": '40-220 ng/mL', "siValue": '140-760 nmol/L'}, - {"title": '32-36 wks', "value": '60-280 ng/mL', "siValue": '208-970 nmol/L'}, - {"title": '36-40 wks', "value": '80-350 ng/mL', "siValue": '280-1210 nmol/L'}, - ] - }, - - {"title": 'Ferritin, serum', "value": '', "siValue": '', - "subtitle": [ - {"title": 'Male', "value": '15-200 ng/mL', "siValue": '15-200 ng/mL'}, - {"title": 'Female', "value": '12-150 ng/mL', "siValue": '12-150 ng/mL'}, - ] - }, - {"title": 'Follicle-stimulating hormone, serum/plasma', "value": '', "siValue": '', - "subtitle": [ - {"title": 'Male', "value": '4-25 mIU/mL', "siValue": '4-25 mIU/mL'}, - {"title": 'Female', "value": '', "siValue": ''}, - {"title": 'premenopause', "value": '4-30 mIU/mL', "siValue": '4-30 mIU/mL'}, - {"title": 'midcycle peak', "value": '10-90 mIU/mLL', "siValue": '10-90 mIU/mLL'}, - {"title": 'postmenopause', "value": '40-250 mIU/mL', "siValue": '40-250 mIU/mL'}, - ] - }, - {"title": 'Gases, arterial blood (room air)', "value": '', "siValue": '', - "subtitle": [ - {"title": 'pH', "value": '7.35-7.45', "siValue": '[H+] 36-44 nmol/L'}, - {"title": 'Pco2', "value": '33-45 mm Hg', "siValue": '4.4-5.9 kPa'}, - {"title": 'Po2', "value": '75-105 mm Hg', "siValue": '10.0-14.0 kPa'}, - ] - }, - {"title": 'Glucose, serum', "value": '', "siValue": '', - "subtitle": [ - {"title": 'Fasting', "value": '70-110 mg/dL', "siValue": '3.8-6.1 mmol/L'}, - {"title": '2-h postprandial', "value": '<120 mg/dL', "siValue": '<6.6 mmol/L'}, - ] - }, - {"title": 'Growth hormone- arginine stimulation', "value": '', "siValue": '', - "subtitle": [ - {"title": 'Fasting', "value": '<5 ng/mL', "siValue": '<5 ng/mL'}, - {"title": 'Provocative stimuli', "value": '>7 ng/mL', "siValue": '>7 μg/L'}, - ] - }, - {"title": 'Immunoglobulins, serum', "value": '', "siValue": '', - "subtitle": [ - {"title": 'IgA', "value": '76-390 mg/dL', "siValue": '0.76-3.90 g/L'}, - {"title": 'IgE', "value": '0-380 IU/mL', "siValue": '0-380 kIU/L'}, - {"title": 'IgG', "value": '650-1,500 mg/dL', "siValue": '6.5-15 g/L'}, - {"title": 'IgM', "value": '40-345 mg/dL', "siValue": '0.4-3.45 g/L'}, - ] - }, - {"title": 'Iron', "value": '50-170 μg/dL', "subtitle": [], "siValue": '9-30 μmol/LL'}, - {"title": 'Lactate dehydrogenase, serum', "value": '45-90 U/L (100-250 IU/L)', "siValue": '45-90 U/L (100-250 IU/L)', - "subtitle": [] - }, - {"title": 'Luteinizing hormone, serum/plasma', "value": '', "siValue": '', - "subtitle": [ - {"title": 'Male', "value": '6-23 mIU/mL', "siValue": '6-23 U/L'}, - {"title": 'Female', "value": '', "siValue": ''}, - {"title": 'follicular phase', "value": '5-30 mIU/mL', "siValue": '5-30 U/L'}, - {"title": 'midcycle', "value": '75-150 mIU/mL', "siValue": '75-150 U/L'}, - {"title": 'postmenopause', "value": '30-200 mIU/mL', "siValue": '30-200 U/L'}, - ] - }, - {"title": 'Osmolality, serum', "value": '275-295 mOsmol/kg H2O', "siValue": '275-295 mOsmol/kg H2O', - "subtitle": [] - }, - {"title": 'Parathyroid hormone, serum, N-terminal', "value": '10-65 pg/mL', "siValue": '10-65 pg/mL', - "subtitle": [] - }, - {"title": 'Phosphate (alkaline), serum (p-NPP at 30° C)', "value": '20-70 U/L', "siValue": '20-70 U/L', - "subtitle": [] - }, - {"title": 'Phosphorus (inorganic), serum', "value": '3.0-4.5 mg/dL', "siValue": '1.0-1.5 mmol/L', - "subtitle": [] - }, - - {"title": 'Prolactin, serum (hPRL) ', "value": '<20 ng/mL', "siValue": '<20 ng/mL', - "subtitle": [] - }, - {"title": 'Proteins, serum', "value": '', "siValue": '', - "subtitle": [ - {"title": 'Total (recumbent)', "value": '6.0-7.8 g/dL', "siValue": '60-78 g/L'}, - {"title": 'Albumin', "value": '3.5-5.5 g/dL', "siValue": '35-55 g/L'}, - {"title": 'Globulin', "value": '2.3-3.5 g/dL', "siValue": '23-35 g/L'}, - ] - }, - {"title": 'Thyroid-stimulating hormone (TSH), serum', "value": '0.5-5.0 μU/mL', "siValue": '0.5-5.0 μU/mL', - "subtitle": [] - }, - {"title": 'Thyroidal iodine (123I) uptake', "value": '8%-30% of administered dose/24 h', "siValue": '0.08-0.30 fraction of administered dose/24 h', - "subtitle": [] - }, - {"title": 'Thyroxine (T4), serum', "value": '5-12 μg/dL', "siValue": '64-155 nmol/L', - "subtitle": [] - }, - {"title": 'Triglycerides, serum', "value": '35-160 mg/dL', "siValue": '0.4-1.81 mmol/L', - "subtitle": [] - }, - {"title": 'Triiodothyronine (T3), serum (RIA)', "value": '115-190 ng/dL', "siValue": '1.8-2.9 nmol/L', - "subtitle": [] - }, - {"title": 'Triiodothyronine (T3) resin uptake', "value": '25%-35%', "siValue": '0.25-0.35', - "subtitle": [] - }, - {"title": 'Urea nitrogen, serum (BUN)', "value": '7-18 mg/dL', "siValue": '1.2-3.0 mmol/L', - "subtitle": [] - }, - {"title": 'Uric acid, serum', "value": '3.0-8.2 mg/dL', "siValue": '0.18-0.48 mmol/L', - "subtitle": [] - }, - - ]; - final HematologicLabValues = [ - {"title": 'Bleeding time (template)', "value": '2-7 minutes', "siValue": '2-7 minutes', - "subtitle": [] - }, - {"title": 'CD4+ T-lymphocyte count', "value": '>500 mm^3', "siValue": '>500 x 106/L', - "subtitle": [] - }, - {"title": 'Erythrocyte count', "value": '', "siValue": '', - "subtitle": [ - {"title": 'Male', "value": '4.3-5.9 million/mm^3', "siValue": '4.3-5.9 x 10^12/L'}, - {"title": 'Female', "value": '3.5-5.5 million/mm^3', "siValue": '3.5-5.5 x 10^12/L'}, - ] - }, - {"title": 'Erythrocyte sedimentation rate (Westergren)', "value": '', "siValue": '', - "subtitle": [ - {"title": 'Male', "value": '0-15 mm/h', "siValue": '0-15 mm/h'}, - {"title": 'Female', "value": '0-20 mm/h', "siValue": '0-20 mm/h'}, - ] - }, - {"title": 'Hematocrit', "value": '', "siValue": '', - "subtitle": [ - {"title": 'Male', "value": '41%-53%', "siValue": '0.41-0.53'}, - {"title": 'Female', "value": '36%-46%', "siValue": '0.36-0.46'}, - ] - }, - {"title": 'Hemoglobin A1c', "value": '≤6%', "siValue": '≤0.06', - "subtitle": [] - }, - {"title": 'Hemoglobin, blood', "value": '', "siValue": '', - "subtitle": [ - {"title": 'Male', "value": '13.5-17.5 g/dL', "siValue": '2.09-2.71 mmol/L'}, - {"title": 'Female', "value": '12.0-16.0 g/dL', "siValue": '1.86-2.48 mmol/L'}, - ] - }, - {"title": 'Leukocyte count and differential', "value": '', "siValue": '', - "subtitle": [ - {"title": 'Leukocyte count', "value": '4,500-11,000/mm^3', "siValue": '4.5-11.0 x 10^9/L'}, - {"title": 'Neutrophils, segmented', "value": '54%-62%', "siValue": '0.54-0.62'}, - {"title": 'Neutrophils, banded', "value": '3%-5%', "siValue": '0.03-0.05'}, - {"title": 'Eosinophils', "value": '1%-3%', "siValue": '0.01-0.03'}, - {"title": 'Basophils', "value": '0%-0.75%', "siValue": '0-0.0075'}, - {"title": 'Lymphocytes', "value": '25%-33%', "siValue": '0.25-0.33'}, - {"title": 'Monocytes', "value": '3%-7%', "siValue": '0.03-0.07'}, - ] - }, - {"title": 'Mean corpuscular hemoglobin (MCH)', "value": '25.4-34.6 pg/cell', "siValue": '0.39-0.54 fmol/cell', - "subtitle": [] - }, - {"title": 'Mean corpuscular hemoglobin concentration (MCHC)', "value": '31%-36% Hb/cell', "siValue": '4.81-5.58 mmol Hb/L', - "subtitle": [] - }, - {"title": 'Mean corpuscular volume (MCV)', "value": '80-100 μm3', "siValue": '80-100 fL', - "subtitle": [] - }, - {"title": 'Partial thromboplastin time (activated)', "value": '25-40 seconds', "siValue": '25-40 seconds', - "subtitle": [] - }, - {"title": 'Platelet count', "value": '150,000-400,000/mm^3', "siValue": '150-400 x 10^9/L', - "subtitle": [] - }, - {"title": 'Prothrombin time', "value": '11-15 seconds', "siValue": '11-15 seconds', - "subtitle": [] - }, - {"title": 'Reticulocyte count', "value": '0.5%-1.5% of red cells', "siValue": '0.005-0.015 fraction of red cells', - "subtitle": [] - }, - {"title": 'Thrombin time', "value": '<2 seconds deviation from control', "siValue": '<2 seconds deviation from control', - "subtitle": [] - }, - {"title": 'Volume', "value": '', "siValue": '', - "subtitle": [ - {"title": 'Plasma', "value": '', "siValue": ''}, - {"title": 'Male', "value": '25-43 mL/kg', "siValue": '0.005-0.015 fraction of red cells' }, - {"title": 'Female', "value": '28-45 mL/kg', "siValue": '0.028-0.045 L/kg'}, - {"title": 'Red cell', "value": '', "siValue": ''}, - {"title": 'Male', "value": '20-36 mL/kg', "siValue": '0.020-0.036 L/kg'}, - {"title": 'Female', "value": '19-31 mL/kg', "siValue": '0.019-0.031 L/kg'}, - ] - }, - - - ]; - final CerebrospinalLabValues = [ - {"title": 'Cell count', "value": '0-5/mm^3', "siValue": '0-5 x 10^6/L', - "subtitle": [] - }, - {"title": 'Chloride', "value": '118-132 mEq/L', "siValue": '118-132 mmol/L', - "subtitle": [] - }, - {"title": 'Gamma globulin', "value": '3%-12% of total proteins', "siValue": '0.03-0.12 of total proteins', - "subtitle": [] - }, - {"title": 'Glucose', "value": '40-70 mg/dL', "siValue": '2.2-3.9 mmol/L', - "subtitle": [] - }, - {"title": 'Pressure', "value": '70-180 mm H2O', "siValue": '70-180 mm H2O', - "subtitle": [] - }, - {"title": 'Proteins, total', "value": '<40 mg/dL', "siValue": '<0.40 g/L', - "subtitle": [] - }, - ]; - final sweatLabValues = [ - {"title": 'Calcium', "value": '100-300 mg/24 h', "siValue": '2.5-7.5 mmol/24 h', - "subtitle": [] - }, - {"title": 'Chloride', "value": '1Varies with intake', "siValue": '1Varies with intake', - "subtitle": [] - }, - {"title": 'Creatine clearance', "value": '', "siValue": '', - "subtitle": [ - {"title": 'Male', "value": '97-137 mL/min', "siValue": '1.62-2.29 mL/s'}, - {"title": 'Female', "value": '88-128 mL/min', "siValue": '1.47-2.14 mL/s'}, - ] - }, - {"title": 'Estriol, total (in pregnancy)', "value": '', "siValue": '', - "subtitle": [ - {"title": '30 wks', "value": '6-18 mg/24 h', "siValue": '21-62 μmol/24 h'}, - {"title": '35 wks', "value": '9-28 mg/24 h', "siValue": '31-97 μmol/24 h'}, - {"title": '40 wks', "value": '13-42 mg/24 h', "siValue": '45-146 μmol/24 h'}, - ] - }, - {"title": '17-hydroxycorticosteroids', "value": '', "siValue": '', - "subtitle": [ - {"title": 'Male', "value": '3.0-10.0 mg/24 h', "siValue": '8.2-27.6 μmol/24 h'}, - {"title": 'Female', "value": '2.0-8.0 mg/24 h', "siValue": '5.5-22.0 μmol/24 h'}, - ] - }, - {"title": '17-ketosteroids, total', "value": '', "siValue": '', - "subtitle": [ - {"title": 'Male', "value": '8-20 mg/24 h', "siValue": '28-70 μmol/24 h'}, - {"title": 'Female', "value": '6-15 mg/24 h', "siValue": '21-52 μmol/24 h'}, - ] - }, - {"title": 'Osmolality', "value": '50-1,400 mOsmol/kg H2O', "siValue": '50-1,400 mmol/kg', - "subtitle": [] - }, - {"title": 'Oxalate', "value": '8-40 μg/mL', "siValue": '90-445 μmol/L', - "subtitle": [] - }, - {"title": 'Proteins, total', "value": '<150 mg/24 h', "siValue": '<0.15 g/24 h', - "subtitle": [] - }, - {"title": 'Sodium, total', "value": 'varies with diet', "siValue": 'varies with diet', - "subtitle": [] - }, - {"title": 'Uric acid', "value": 'varies with diet', "siValue": 'varies with diet', - "subtitle": [] - }, - {"title": 'Body Mass Index (Adult)', "value": '19-25 kg/m^2', "siValue": '19-25 kg/m^2', - "subtitle": [] - }, - ]; - - - - Widget appBarTitle = new Text( - "Search Values", - style: new TextStyle(color: Colors.white), - ); - Icon icon = new Icon( - Icons.search, - color: Colors.white, - ); - final globalKey = new GlobalKey(); - final TextEditingController _controller = new TextEditingController(); - List _list = []; // = ["Indian rupee", "United States dollar", "Australian dollar", "Euro", "British pound", "Yemeni rial", "Japanese yen", "Hong Kong dollar"]; - bool _isSearching = false; - String _searchText = ""; - List searchresult = []; - bool _siValues = false; - late TabController _tabController; - - var bloodLabValuesData = { - "title" : [], - "value" : [], - "siValue" : [] - }; - var HematologicLabValuesData = { - "title" : [], - "value" : [], - "siValue" : [] - }; - var CerebrospinalLabValuesData = { - "title" : [], - "value" : [], - "siValue" : [] - }; - var sweatLabValuesData = { - "title" : [], - "value" : [], - "siValue" : [] - }; - - var LabValuesList = { - "title" : [], - "value" : [], - "siValue" : [] - }; - - categorizebloodLabValues() { - for(int i = 0; i; - }); - // print(CerebrospinalLabValuesData["title"]); - // print(_list); - } - - _SearchListExampleState() { - _controller.addListener(() { - if (_controller.text.isEmpty) { - setState(() { - _isSearching = false; - _searchText = ""; - }); - } else { - setState(() { - _isSearching = true; - _searchText = _controller.text; - }); - } - }); - } - - @override - void initState() { - super.initState(); - _tabController = TabController(vsync: this, length: 4) - ..addListener(() { - setState(() { - if(_tabController.index == 0){ - // print(_tabController.index); - setState(() { - _handleSearchEnd(); - if(bloodLabValuesData["title"] != null) - _list = bloodLabValuesData["title"] as List; - _isSearching = false; - _searchText = ""; - searchOperation(""); - }); - } - else if(_tabController.index == 1){ - // print(_tabController.index); - setState(() { - _handleSearchEnd(); - if(HematologicLabValuesData["title"] != null) - _list = HematologicLabValuesData["title"] as List; - _isSearching = false; - _searchText = ""; - searchOperation(""); - }); - } - else if(_tabController.index == 2){ - // print(_tabController.index); - setState(() { - _handleSearchEnd(); - if(CerebrospinalLabValuesData["title"] != null) - _list = CerebrospinalLabValuesData["title"] as List; - _isSearching = false; - _searchText = ""; - searchOperation(""); - }); - } - else if(_tabController.index == 3){ - // print(_tabController.index); - setState(() { - _handleSearchEnd(); - if(sweatLabValuesData["title"] != null) - _list = sweatLabValuesData["title"] as List; - _isSearching = false; - _searchText = ""; - searchOperation(""); - }); - } - }); - }); - categorizebloodLabValues(); - _isSearching = false; - } - - @override - void dispose() { - _tabController.dispose(); - super.dispose(); - } - - Widget listTiles() { - return Container( // _tabController.index == 0 - child: ListView( - scrollDirection: Axis.vertical, - children: [ - Container( - child: searchresult.length != 0 || _controller.text.isNotEmpty - ? Column( - children: [ - for(int j = 0; j<_list.length;j++) - for(int i = 0; i[ - Color(0xff7F1AF1), - Color(0xff482384) - ]) - ), - ), - title: appBarTitle, actions: [ - new IconButton( - icon: icon, - onPressed: () { - setState(() { - if (this.icon.icon == Icons.search) { - this.icon = new Icon( - Icons.close, - color: Colors.white, - ); - this.appBarTitle = new TextField( - controller: _controller, - style: new TextStyle( - color: Colors.white, - ), - decoration: new InputDecoration( - prefixIcon: new Icon(Icons.search, color: Colors.white), - hintText: "Search...", - hintStyle: new TextStyle(color: Colors.white)), - onChanged: searchOperation, - ); - _handleSearchStart(); - } else { - _handleSearchEnd(); - } - }); - }, - ), - ]), - body: SingleChildScrollView( - child: Column( - children: [ - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - Container( - padding: EdgeInsets.only(top: (MediaQuery.of(context).size.height) * (30 / 926), bottom: (MediaQuery.of(context).size.height) * (20 / 926), - left: (MediaQuery.of(context).size.width) * (20 / 428)), - alignment: Alignment.center, - child: Text( - "Lab Values", - style: TextStyle( - color: Color(0xff232323), - fontFamily: 'Brandon-bld', - fontSize: (MediaQuery.of(context).size.height) * - (20 / 926), //38, - ), - ), - ), - Row( - children: [ - Transform.scale( - scale: 1, - child: Container( - height: (MediaQuery.of(context).size.height) *(15/926), - child: Switch( - value: _siValues, - onChanged: (value) { - setState(() { - _siValues = value; - // print(_siValues); - }); - }, - activeColor: Color(0xff3F2668), - ), - ), - ), - Container( - child: Text("Si Reference Intervals", - style: TextStyle( - color: Color(0xff483A3A), - fontFamily: 'Brandon-med', - fontSize: (MediaQuery.of(context).size.height) *(15/926) - ), - ), - ), - SizedBox(width: (MediaQuery.of(context).size.width) *(10/428)), - - ], - ), - ], - ), - Container( - margin: EdgeInsets.only(left: (MediaQuery.of(context).size.width) * (15 / 428), right: (MediaQuery.of(context).size.width) * (15 / 428)), - // padding: EdgeInsets.only(left: (MediaQuery.of(context).size.width) * (10 / 428), right: (MediaQuery.of(context).size.width) * (10 / 428)), - decoration: BoxDecoration( - border: Border(bottom: BorderSide(color: Colors.grey, width: 2)) - ), - child: TabBar( - padding: EdgeInsets.zero, - indicatorPadding: EdgeInsets.zero, - labelPadding: EdgeInsets.zero, - controller: _tabController, - tabs: [ - Tab(icon: Text( - "Blood", - style: TextStyle( - color: Color(0xff232323), - fontFamily: 'Brandon-bld', - fontSize: (MediaQuery.of(context).size.height) * - (15 / 926), //38, - ), - ),), - Tab(icon: Text( - "Hematologic", - style: TextStyle( - color: Color(0xff232323), - fontFamily: 'Brandon-bld', - fontSize: (MediaQuery.of(context).size.height) * - (15 / 926), //38, - ), - ),), - Tab(icon: Text( - "Cerebrospinal", - style: TextStyle( - color: Color(0xff232323), - fontFamily: 'Brandon-bld', - fontSize: (MediaQuery.of(context).size.height) * - (15 / 926), //38, - ), - ),), - Tab(icon: Text( - "Sweat", - style: TextStyle( - color: Color(0xff232323), - fontFamily: 'Brandon-bld', - fontSize: (MediaQuery.of(context).size.height) * - (15 / 926), //38, - ), - ),), - ], - ), - ), - SizedBox(height: (MediaQuery.of(context).size.height) * - (8 / 926),), - Row( - mainAxisAlignment: MainAxisAlignment.start, - children: [ - Container( - width: ((MediaQuery.of(context).size.width)*(2/3)), - padding: EdgeInsets.only(left: (MediaQuery.of(context).size.width) * - (20 / 428)), - child: Text( - _tabController.index == 0 ? "Blood, Plasma, Serum" : - _tabController.index == 1 ? "Serum" : - _tabController.index == 2 ? "Cerebrospinal Fluid" : - _tabController.index == 3 ? "Urine" : "Urine", - style: TextStyle( - color: Color(0xff232323), - fontFamily: 'Brandon-bld', - fontSize: (MediaQuery.of(context).size.height) * - (15 / 926), //38, - ), - ), - ), - Container( - padding: EdgeInsets.only(right: (MediaQuery.of(context).size.width) * - (20 / 428)), - child: Text( - _siValues == true ? "Si Reference Interval" : "Reference Range", - style: TextStyle( - color: Color(0xff232323), - fontFamily: 'Brandon-bld', - fontSize: (MediaQuery.of(context).size.height) * - (15 / 926), //38, - ), - ), - ), - ], - ), - Container( - padding: EdgeInsets.only(left: (MediaQuery.of(context).size.width) * (15 / 428), right: (MediaQuery.of(context).size.width) * (15 / 428)), - child: Divider(thickness: 0.4, color: Colors.grey,)), - Container( - padding: EdgeInsets.only(left: (MediaQuery.of(context).size.width) * (15 / 428), right: (MediaQuery.of(context).size.width) * (15 / 428)), - height: MediaQuery.of(context).size.height * 0.6, - child: TabBarView( - controller: _tabController, - children: [ - //Tab 1 - listTiles(), - //Tab 2 - listTiles(), - //Tab 3 - listTiles(), - //Tab 4 - listTiles(), - ], - ), - ), - ], - ), - )), - ); - } - - - void _handleSearchStart() { - setState(() { - _isSearching = true; - }); - } - - void _handleSearchEnd() { - setState(() { - this.icon = new Icon( - Icons.search, - color: Colors.white, - ); - this.appBarTitle = new Text( - "Search Values", - style: new TextStyle(color: Colors.white), - ); - _isSearching = false; - _controller.clear(); - }); - } - - void searchOperation(String searchText) { - searchresult.clear(); - if (_isSearching != null) { - for (int i = 0; i < _list.length; i++) { - String data = _list[i]; - if (data.toLowerCase().contains(searchText.toLowerCase())) { - searchresult.add(data); - } - } - } - } -} diff --git a/lib/screens/Welcome/side_menu_bar.dart b/lib/screens/Welcome/side_menu_bar.dart deleted file mode 100644 index 0112a3f..0000000 --- a/lib/screens/Welcome/side_menu_bar.dart +++ /dev/null @@ -1,80 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:testify/screens/Welcome/GenerateQuiz/generate_quiz.dart'; - -import 'PreviousQuiz/previous_quiz.dart'; - -class SideMenuBar extends StatelessWidget { - @override - Widget build(BuildContext context) { - return Container( - width: (MediaQuery.of(context).size.width) *0.7, - child: Drawer( - child: ListView( - // Remove padding - padding: EdgeInsets.zero, - children: [ - Container( - padding: EdgeInsets.only(top: MediaQuery.of(context).padding.top), - height: (MediaQuery.of(context).size.height), - decoration: const BoxDecoration( - gradient: LinearGradient( - begin: Alignment.topRight, - end: Alignment.bottomLeft, - colors: [Color(0xff3F2668), Color(0xff482384)])), - width: (MediaQuery.of(context).size.width) *0.7, - child: Column( - children: [ - ListTile( - leading: Icon(Icons.arrow_back, color: Colors.white,), - title: Text('Close', style: TextStyle(color: Colors.white),), - onTap: () => Navigator.pop(context), - ), - Divider(), - ListTile( - leading: Icon(Icons.quiz_outlined, color: Colors.white,), - title: Text('Generate Quiz', style: TextStyle(color: Colors.white),), - onTap: () async { - // Navigator.of(context).pop(); - Navigator.of(context) - .popUntil(ModalRoute.withName("/home")); - final result = await Navigator.push( - context, - MaterialPageRoute(builder: (context) => GenerateQuiz()), - ); - // final result = Navigator.pushAndRemoveUntil( - // context, - // MaterialPageRoute(builder: (BuildContext context) => GenerateQuiz()), - // ModalRoute.withName('/home'), - // ); - }, - ), - ListTile( - leading: Icon(Icons.quiz_outlined, color: Colors.white,), - title: Text('Previous Quiz', style: TextStyle(color: Colors.white),), - onTap: () async { - // Navigator.of(context).pop(); - - Navigator.of(context) - .popUntil(ModalRoute.withName("/home")); - final result = await Navigator.push( - context, - MaterialPageRoute(builder: (context) => PreviousQuiz()), - ); - - // final result = Navigator.pushAndRemoveUntil( - // context, - // MaterialPageRoute(builder: (BuildContext context) => PreviousQuiz()), - // ModalRoute.withName('/home'), - // ); - }, - ), - ], - ), - ), - //Divider(), - ], - ), - ), - ); - } -} \ No newline at end of file diff --git a/lib/screens/home.dart b/lib/screens/home.dart deleted file mode 100644 index 503f884..0000000 --- a/lib/screens/home.dart +++ /dev/null @@ -1,168 +0,0 @@ -import 'dart:async'; -import 'dart:convert'; - -import 'package:flutter/material.dart'; -import 'package:flutter_svg/svg.dart'; -import 'package:shared_preferences/shared_preferences.dart'; -import 'package:testify/auth_storage.dart'; -import 'package:testify/screens/Authentication/login.dart'; -import 'package:testify/screens/Welcome/side_menu_bar.dart'; -import 'package:testify/screens/Welcome/QuizModule/search_bar.dart'; -import 'package:http/http.dart' as http; - -class Home extends StatefulWidget { - const Home({Key? key}) : super(key: key); - - @override - _HomeState createState() => _HomeState(); -} - -class _HomeState extends State with WidgetsBindingObserver{ - - AppLifecycleState? _lastLifecycleState; - - @override - void initState() { - super.initState(); - WidgetsBinding.instance!.addObserver(this); - } - - @override - void dispose() { - WidgetsBinding.instance!.removeObserver(this); - super.dispose(); - } - - @override - void didChangeAppLifecycleState(AppLifecycleState state) async { - super.didChangeAppLifecycleState(state); - - // if(state == AppLifecycleState.detached){ - // - // } - - final isBackground = state == AppLifecycleState.paused; - final isClosed = state == AppLifecycleState.detached; - if(isBackground) { - print("xD in Background"); - - - - } - if(isClosed) { - print("xD Closed"); - - - } - } - - @override - Widget build(BuildContext context) { - return WillPopScope( - onWillPop: () async { - ScaffoldMessenger.of(context) - ..removeCurrentSnackBar() - ..showSnackBar(SnackBar(content: Text("Press Logout Button"))); - return false; - }, - child: Scaffold( - backgroundColor: Colors.white, - drawer: SideMenuBar(), - appBar: AppBar( - backgroundColor: Color(0xff3F2668), - elevation: 2, - centerTitle: true, - flexibleSpace: Container( - decoration: BoxDecoration( - gradient: LinearGradient( - begin: Alignment.topCenter, - end: Alignment.bottomCenter, - colors: [ - Color(0xff7F1AF1), - Color(0xff482384) - ]) - ), - ), - title: const Text("Home", - style: TextStyle( - color: Color(0xffFFFEFE), - fontFamily: 'Brandon-bld', - ), - ), - actions: [ - TextButton( - onPressed: () async { - // Use this where ever Navigated to Login - final result = Navigator.pushAndRemoveUntil( - context, - MaterialPageRoute(builder: (BuildContext context) => const Login(fromWhere:"Home")), - ModalRoute.withName('/'), - ); - - }, - child: SvgPicture.asset( - "assets/Images/logout.svg", - height: (MediaQuery.of(context).size.height) *(32/926), - ), - ), - ], - ), - // body: TextButton( - // onPressed: () async { - // // final result = Navigator.push( - // // context, - // // MaterialPageRoute(builder: (context) => SearchListExample()), - // // ); - // - // - // SharedPreferences prefs = await SharedPreferences.getInstance(); - // var quizID = prefs.getInt("quizId"); - // var _token = prefs.getString('token')!; - // // print(quizID); - // final String apiUrlGenerateQuiz = "https://demo.pookidevs.com/quiz/solver/saveQuiz"; - // await http.post(Uri.parse(apiUrlGenerateQuiz), headers: { - // 'Content-type': 'application/json; charset=UTF-8', 'Authorization' : _token.toString(), - // }, body: json.encode( - // { - // "data": - // { - // "quiz" : { - // "quizId": 387155.toString(), - // "quizTitle": "First quiz", - // "quizDate": DateTime.now().toString(), - // "quizScore": "2", - // "quizTotalQuestions": "5", - // "quizStatus": "Completed", - // "quizQuestions": "[15, 18, 91, 20, 22]", - // "quizMode": "tutor", - // "quizTime": "900", - // "isTimed": false, - // "omittedQuestions": [], - // "SelectedOptionsArray": [] - // }, - // "userId": 7.toString() - // } - // }) - // ).then((response) { - // print(jsonDecode(response.body).toString()); - // if((response.statusCode == 200) & (json.decode(response.body).toString().substring(0,14) != "{status: false")) { - // - // } - // else { // Token Invalid - // final result = Navigator.pushAndRemoveUntil( - // context, - // MaterialPageRoute(builder: (BuildContext context) => const Login(fromWhere:"Home")), - // ModalRoute.withName('/'), - // ); - // } - // } - // ); - // - // - // }, - // child: Text("Search Bar"), - // ), - ), - ); - } -} From a3ed9743cdbdffd9dc45071fbcd41c5af4ba5d6f Mon Sep 17 00:00:00 2001 From: TheYoungWolf <68595463+TheYoungWolf-Productions@users.noreply.github.com> Date: Sat, 30 Apr 2022 17:17:46 +0500 Subject: [PATCH 22/23] Add notes module via file upload --- lib/auth_storage.dart | 41 + lib/generated_plugin_registrant.dart | 16 + lib/main.dart | 40 + .../QuizModuleModels/generate_quiz_model.dart | 97 + .../get_system_categories_successful.dart | 97 + .../get_system_categories_unsuccessful.dart | 29 + .../ResumeQuiz/resume_quiz_model.dart | 257 +++ .../get_previous_quizzes_model.dart | 97 + lib/models/NotesModel/notes_model.dart | 81 + lib/models/user_model_successful_login.dart | 57 + lib/models/user_model_unsuccessful_login.dart | 45 + lib/screens/Authentication/login.dart | 599 ++++++ .../Welcome/GenerateQuiz/generate_quiz.dart | 1598 ++++++++++++++ lib/screens/Welcome/Notes/noteDetails.dart | 424 ++++ lib/screens/Welcome/Notes/notes.dart | 251 +++ lib/screens/Welcome/Notes/notesTile.dart | 42 + .../Welcome/PreviousQuiz/previous_quiz.dart | 609 ++++++ .../Welcome/PreviousQuiz/test_details.dart | 482 +++++ lib/screens/Welcome/PreviousQuiz/tile.dart | 137 ++ lib/screens/Welcome/QuizModule/buttons.dart | 55 + .../Welcome/QuizModule/calculator.dart | 179 ++ .../QuizModule/question_explanation.dart | 372 ++++ .../Welcome/QuizModule/quiz_final.dart | 10 + .../Welcome/QuizModule/quiz_module.dart | 1827 +++++++++++++++++ .../Welcome/QuizModule/search_bar.dart | 861 ++++++++ lib/screens/Welcome/side_menu_bar.dart | 93 + lib/screens/home.dart | 168 ++ 27 files changed, 8564 insertions(+) create mode 100644 lib/auth_storage.dart create mode 100644 lib/generated_plugin_registrant.dart create mode 100644 lib/main.dart create mode 100644 lib/models/GenerateQuizModels/QuizModuleModels/generate_quiz_model.dart create mode 100644 lib/models/GenerateQuizModels/get_system_categories_successful.dart create mode 100644 lib/models/GenerateQuizModels/get_system_categories_unsuccessful.dart create mode 100644 lib/models/GetPreviousQuizzesModel/ResumeQuiz/resume_quiz_model.dart create mode 100644 lib/models/GetPreviousQuizzesModel/get_previous_quizzes_model.dart create mode 100644 lib/models/NotesModel/notes_model.dart create mode 100644 lib/models/user_model_successful_login.dart create mode 100644 lib/models/user_model_unsuccessful_login.dart create mode 100644 lib/screens/Authentication/login.dart create mode 100644 lib/screens/Welcome/GenerateQuiz/generate_quiz.dart create mode 100644 lib/screens/Welcome/Notes/noteDetails.dart create mode 100644 lib/screens/Welcome/Notes/notes.dart create mode 100644 lib/screens/Welcome/Notes/notesTile.dart create mode 100644 lib/screens/Welcome/PreviousQuiz/previous_quiz.dart create mode 100644 lib/screens/Welcome/PreviousQuiz/test_details.dart create mode 100644 lib/screens/Welcome/PreviousQuiz/tile.dart create mode 100644 lib/screens/Welcome/QuizModule/buttons.dart create mode 100644 lib/screens/Welcome/QuizModule/calculator.dart create mode 100644 lib/screens/Welcome/QuizModule/question_explanation.dart create mode 100644 lib/screens/Welcome/QuizModule/quiz_final.dart create mode 100644 lib/screens/Welcome/QuizModule/quiz_module.dart create mode 100644 lib/screens/Welcome/QuizModule/search_bar.dart create mode 100644 lib/screens/Welcome/side_menu_bar.dart create mode 100644 lib/screens/home.dart diff --git a/lib/auth_storage.dart b/lib/auth_storage.dart new file mode 100644 index 0000000..03a99db --- /dev/null +++ b/lib/auth_storage.dart @@ -0,0 +1,41 @@ +import 'package:path_provider/path_provider.dart'; +import 'dart:io'; + + +class AuthStorage { + Future getLocalPath() async { + var dir = await getApplicationDocumentsDirectory(); + return dir.path; + } + + Future getLocalFile() async { + String path = await getLocalPath(); + return File('$path/auth.txt'); + } + + Future writeAuth(String email, String password) async { + File file = await getLocalFile(); + return file.writeAsString('$email' + ' ' + '$password'); + } + + Future readAuth() async { + try { + final file = await getLocalFile(); + String content = await file.readAsString(); + return content; + } catch(e) { + return ""; + } + } + + Future deleteFile() async { + try { + final file = await getLocalFile(); + + await file.delete(); + return ""; + } catch (e) { + return ""; + } + } +} \ No newline at end of file diff --git a/lib/generated_plugin_registrant.dart b/lib/generated_plugin_registrant.dart new file mode 100644 index 0000000..ff43303 --- /dev/null +++ b/lib/generated_plugin_registrant.dart @@ -0,0 +1,16 @@ +// +// Generated file. Do not edit. +// + +// ignore_for_file: directives_ordering +// ignore_for_file: lines_longer_than_80_chars + +import 'package:shared_preferences_web/shared_preferences_web.dart'; + +import 'package:flutter_web_plugins/flutter_web_plugins.dart'; + +// ignore: public_member_api_docs +void registerPlugins(Registrar registrar) { + SharedPreferencesPlugin.registerWith(registrar); + registrar.registerMessageHandler(); +} diff --git a/lib/main.dart b/lib/main.dart new file mode 100644 index 0000000..1e0f65d --- /dev/null +++ b/lib/main.dart @@ -0,0 +1,40 @@ +import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; +import 'package:testify/auth_storage.dart'; +import 'package:testify/screens/Authentication/login.dart'; +import 'package:testify/screens/Welcome/GenerateQuiz/generate_quiz.dart'; +import 'package:testify/screens/Welcome/QuizModule/quiz_module.dart'; +import 'package:testify/screens/home.dart'; + +void main() async { + WidgetsFlutterBinding.ensureInitialized(); + SystemChrome.setPreferredOrientations([ + DeviceOrientation.portraitUp, + DeviceOrientation.portraitDown, + ]); + + runApp(MyApp()); +} + +class MyApp extends StatefulWidget { + // This widget is the root of your application. + @override + State createState() => _MyAppState(); +} + +class _MyAppState extends State { + + @override + Widget build(BuildContext context) { + return MaterialApp( + initialRoute: '/', + routes: { + // When navigating to the "/" route, build the FirstScreen widget. + '/': (context) => Login(fromWhere: "main",), + // When navigating to the "/second" route, build the SecondScreen widget. + '/home': (context) => Home(), + }, + // home: Login(fromWhere: "main",) + ); + } +} \ No newline at end of file diff --git a/lib/models/GenerateQuizModels/QuizModuleModels/generate_quiz_model.dart b/lib/models/GenerateQuizModels/QuizModuleModels/generate_quiz_model.dart new file mode 100644 index 0000000..562990a --- /dev/null +++ b/lib/models/GenerateQuizModels/QuizModuleModels/generate_quiz_model.dart @@ -0,0 +1,97 @@ +// To parse this JSON data, do +// +// final generateQuizSuccessful = generateQuizSuccessfulFromJson(jsonString); + +import 'dart:convert'; + +GenerateQuizSuccessful generateQuizSuccessfulFromJson(String str) => GenerateQuizSuccessful.fromJson(json.decode(str)); + +String generateQuizSuccessfulToJson(GenerateQuizSuccessful data) => json.encode(data.toJson()); + +class GenerateQuizSuccessful { + GenerateQuizSuccessful({ + required this.data, + }); + + Data data; + + factory GenerateQuizSuccessful.fromJson(Map json) => GenerateQuizSuccessful( + data: Data.fromJson(json["data"]), + ); + + Map toJson() => { + "data": data.toJson(), + }; +} + +class Data { + Data({ + required this.status, + required this.questions, + required this.totalQuestions, + required this.quizId, + }); + + bool status; + List questions; + int totalQuestions; + int quizId; + + factory Data.fromJson(Map json) => Data( + status: json["status"], + questions: List.from(json["questions"].map((x) => Question.fromJson(x))), + totalQuestions: json["totalQuestions"], + quizId: json["quizId"], + ); + + Map toJson() => { + "status": status, + "questions": List.from(questions.map((x) => x.toJson())), + "totalQuestions": totalQuestions, + "quizId": quizId, + }; +} + +class Question { + Question({ + required this.id, + required this.title, + required this.question, + required this.correctMsg, + required this.answerType, + required this.postId, + required this.options, + required this.statistics, + }); + + int id; + String title; + String question; + String correctMsg; + String answerType; + int postId; + List options; + List statistics; + + factory Question.fromJson(Map json) => Question( + id: json["id"], + title: json["title"], + question: json["question"], + correctMsg: json["correct_msg"], + answerType: json["answer_type"], + postId: json["postId"], + options: List.from(json["options"].map((x) => x)), + statistics: List.from(json["statistics"].map((x) => x)), + ); + + Map toJson() => { + "id": id, + "title": title, + "question": question, + "correct_msg": correctMsg, + "answer_type": answerType, + "postId": postId, + "options": List.from(options.map((x) => x)), + "statistics": List.from(statistics.map((x) => x)), + }; +} diff --git a/lib/models/GenerateQuizModels/get_system_categories_successful.dart b/lib/models/GenerateQuizModels/get_system_categories_successful.dart new file mode 100644 index 0000000..6ec60af --- /dev/null +++ b/lib/models/GenerateQuizModels/get_system_categories_successful.dart @@ -0,0 +1,97 @@ +// To parse this JSON data, do +// +// final getSystemCategoriesSuccessfulModel = getSystemCategoriesSuccessfulModelFromJson(jsonString); + +import 'dart:convert'; + +GetSystemCategoriesSuccessfulModel getSystemCategoriesSuccessfulModelFromJson(String str) => GetSystemCategoriesSuccessfulModel.fromJson(json.decode(str)); + +String getSystemCategoriesSuccessfulModelToJson(GetSystemCategoriesSuccessfulModel data) => json.encode(data.toJson()); + +class GetSystemCategoriesSuccessfulModel { + GetSystemCategoriesSuccessfulModel({ + required this.data, + }); + + Data data; + + factory GetSystemCategoriesSuccessfulModel.fromJson(Map json) => GetSystemCategoriesSuccessfulModel( + data: Data.fromJson(json["data"]), + ); + + Map toJson() => { + "data": data.toJson(), + }; +} + +class Data { + Data({ + required this.status, + required this.categories, + required this.totalQuestions, + required this.questions, + }); + + bool status; + List categories; + int totalQuestions; + List questions; + + factory Data.fromJson(Map json) => Data( + status: json["status"], + categories: List.from(json["categories"].map((x) => Category.fromJson(x))), + totalQuestions: json["totalQuestions"], + questions: List.from(json["questions"].map((x) => x)), + ); + + Map toJson() => { + "status": status, + "categories": List.from(categories.map((x) => x.toJson())), + "totalQuestions": totalQuestions, + "questions": List.from(questions.map((x) => x)), + }; +} + +class Category { + Category({ + required this.parentCategory, + required this.subCategories, + }); + + String parentCategory; + List subCategories; + + factory Category.fromJson(Map json) => Category( + parentCategory: json["parentCategory"], + subCategories: List.from(json["subCategories"].map((x) => SubCategory.fromJson(x))), + ); + + Map toJson() => { + "parentCategory": parentCategory, + "subCategories": List.from(subCategories.map((x) => x.toJson())), + }; +} + +class SubCategory { + SubCategory({ + required this.id, + required this.title, + required this.questions, + }); + + String id; + String title; + int questions; + + factory SubCategory.fromJson(Map json) => SubCategory( + id: json["ID"], + title: json["Title"], + questions: json["Questions"], + ); + + Map toJson() => { + "ID": id, + "Title": title, + "Questions": questions, + }; +} diff --git a/lib/models/GenerateQuizModels/get_system_categories_unsuccessful.dart b/lib/models/GenerateQuizModels/get_system_categories_unsuccessful.dart new file mode 100644 index 0000000..fbea9f6 --- /dev/null +++ b/lib/models/GenerateQuizModels/get_system_categories_unsuccessful.dart @@ -0,0 +1,29 @@ +// To parse this JSON data, do +// +// final getSystemCategoriesUnsuccessfulModel = getSystemCategoriesUnsuccessfulModelFromJson(jsonString); + +import 'dart:convert'; + +GetSystemCategoriesUnsuccessfulModel getSystemCategoriesUnsuccessfulModelFromJson(String str) => GetSystemCategoriesUnsuccessfulModel.fromJson(json.decode(str)); + +String getSystemCategoriesUnsuccessfulModelToJson(GetSystemCategoriesUnsuccessfulModel data) => json.encode(data.toJson()); + +class GetSystemCategoriesUnsuccessfulModel { + GetSystemCategoriesUnsuccessfulModel({ + required this.status, + required this.msg, + }); + + bool status; + String msg; + + factory GetSystemCategoriesUnsuccessfulModel.fromJson(Map json) => GetSystemCategoriesUnsuccessfulModel( + status: json["status"], + msg: json["msg"], + ); + + Map toJson() => { + "status": status, + "msg": msg, + }; +} diff --git a/lib/models/GetPreviousQuizzesModel/ResumeQuiz/resume_quiz_model.dart b/lib/models/GetPreviousQuizzesModel/ResumeQuiz/resume_quiz_model.dart new file mode 100644 index 0000000..6e0a4af --- /dev/null +++ b/lib/models/GetPreviousQuizzesModel/ResumeQuiz/resume_quiz_model.dart @@ -0,0 +1,257 @@ +// To parse this JSON data, do +// +// final resumeQuizModel = resumeQuizModelFromJson(jsonString); + +import 'dart:convert'; + +ResumeQuizModel resumeQuizModelFromJson(String str) => ResumeQuizModel.fromJson(json.decode(str)); + +String resumeQuizModelToJson(ResumeQuizModel data) => json.encode(data.toJson()); + +class ResumeQuizModel { + ResumeQuizModel({ + required this.data, + }); + + Data data; + + factory ResumeQuizModel.fromJson(Map json) => ResumeQuizModel( + data: Data.fromJson(json["data"]), + ); + + Map toJson() => { + "data": data.toJson(), + }; +} + +class Data { + Data({ + required this.status, + required this.questions, + required this.previousQuizzes, + }); + + bool status; + List questions; + List previousQuizzes; + + factory Data.fromJson(Map json) => Data( + status: json["status"], + questions: List.from(json["questions"].map((x) => Question.fromJson(x))), + previousQuizzes: List.from(json["previousQuizzes"].map((x) => PreviousQuizz.fromJson(x))), + ); + + Map toJson() => { + "status": status, + "questions": List.from(questions.map((x) => x.toJson())), + "previousQuizzes": List.from(previousQuizzes.map((x) => x.toJson())), + }; +} + +class PreviousQuizz { + PreviousQuizz({ + required this.quizId, + required this.userId, + required this.quizMeta, + required this.sortId, + this.examId, + }); + + int quizId; + int userId; + QuizMeta quizMeta; + DateTime sortId; + dynamic examId; + + factory PreviousQuizz.fromJson(Map json) => PreviousQuizz( + quizId: json["quiz_id"], + userId: json["user_id"], + quizMeta: QuizMeta.fromJson(json["quiz_meta"]), + sortId: DateTime.parse(json["sortId"]), + examId: json["exam_id"], + ); + + Map toJson() => { + "quiz_id": quizId, + "user_id": userId, + "quiz_meta": quizMeta.toJson(), + "sortId": sortId.toIso8601String(), + "exam_id": examId, + }; +} + +class QuizMeta { + QuizMeta({ + required this.quizId, + required this.quizTitle, + required this.quizDate, + required this.quizScore, + required this.quizTotalQuestions, + required this.quizStatus, + required this.quizQuestions, + required this.quizMode, + required this.quizTime, + required this.isTimed, + required this.omittedQuestions, + required this.selectedOptionsArray, + }); + + // int quizId; + // String quizTitle; + // DateTime quizDate; + // String quizScore; + // int quizTotalQuestions; + // String quizStatus; + // String quizQuestions; + // String quizMode; + // String quizTime; + // bool isTimed; + // List omittedQuestions; + // List selectedOptionsArray; + + dynamic quizId; // Problem + String quizTitle; + DateTime quizDate; + dynamic quizScore; // Problem + int quizTotalQuestions; + String quizStatus; + String quizQuestions; + String quizMode; + String quizTime; + bool isTimed; + List omittedQuestions; + // List selectedOptionsArray; + List selectedOptionsArray; + + factory QuizMeta.fromJson(Map json) => QuizMeta( + quizId: json["quizId"], + quizTitle: json["quizTitle"], + quizDate: DateTime.parse(json["quizDate"]), + quizScore: json["quizScore"], + quizTotalQuestions: json["quizTotalQuestions"], + quizStatus: json["quizStatus"], + quizQuestions: json["quizQuestions"], + quizMode: json["quizMode"], + quizTime: json["quizTime"], + isTimed: json["isTimed"], + omittedQuestions: List.from(json["omittedQuestions"].map((x) => x)), + // selectedOptionsArray: List.from(json["selectedOptionsArray"].map((x) => x)), + selectedOptionsArray: List.from(json["selectedOptionsArray"].map((x) => SelectedOptionsArray.fromJson(x))), + ); + + Map toJson() => { + "quizId": quizId, + "quizTitle": quizTitle, + "quizDate": quizDate.toIso8601String(), + "quizScore": quizScore, + "quizTotalQuestions": quizTotalQuestions, + "quizStatus": quizStatus, + "quizQuestions": quizQuestions, + "quizMode": quizMode, + "quizTime": quizTime, + "isTimed": isTimed, + "omittedQuestions": List.from(omittedQuestions.map((x) => x)), + // "selectedOptionsArray": List.from(selectedOptionsArray.map((x) => x)), + "selectedOptionsArray": List.from(selectedOptionsArray.map((x) => x.toJson())), + }; +} + +class SelectedOptionsArray { + SelectedOptionsArray({ + this.index, + this.correctanswerindex, + this.correct, + this.optionIndexSelected, + }); + + dynamic index; + dynamic correctanswerindex; + dynamic correct; + dynamic optionIndexSelected; + + factory SelectedOptionsArray.fromJson(Map json) => SelectedOptionsArray( + index: json["index"] == null ? null : json["index"], + correctanswerindex: json["Correctanswerindex"] == null ? null : json["Correctanswerindex"], + correct: json["correct"] == null ? null : json["correct"], + optionIndexSelected: json["optionIndexSelected"] == null ? null : json["optionIndexSelected"], + ); + + Map toJson() => { + "index": index, + "Correctanswerindex": correctanswerindex, + "correct": correct, + "optionIndexSelected": optionIndexSelected, + }; +} + +class Question { + Question({ + required this.id, + required this.title, + required this.question, + required this.correctMsg, + required this.answerType, + required this.postId, + this.userId, + this.submitData, + this.notes, + this.questionId, + this.noteId, + this.noteMeta, + required this.marked, + required this.options, + required this.statistics, + }); + + int id; + String title; + String question; + String correctMsg; + String answerType; + int postId; + dynamic userId; + dynamic submitData; + dynamic notes; + dynamic questionId; + dynamic noteId; + dynamic noteMeta; + int marked; + List options; + List statistics; + + factory Question.fromJson(Map json) => Question( + id: json["id"], + title: json["title"], + question: json["question"], + correctMsg: json["correct_msg"], + answerType: json["answer_type"], + postId: json["postId"], + userId: json["user_id"] == null ? null : json["user_id"], + submitData: json["submitData"] == null ? null : json["submitData"], + notes: json["notes"] == null ? null : json["notes"], + questionId: json["questionId"] == null ? null : json["questionId"], + noteId: json["noteId"] == null ? null : json["noteId"], + noteMeta: json["note_meta"] == null ? null : json["note_meta"], + marked: json["marked"], + options: List.from(json["options"].map((x) => x)), + statistics: List.from(json["statistics"].map((x) => x)), + ); + + Map toJson() => { + "id": id, + "title": title, + "question": question, + "correct_msg": correctMsg, + "answer_type": answerType, + "postId": postId, + "user_id": userId == null ? null : userId, + "submitData": submitData == null ? null : submitData, + "notes": notes, + "questionId": questionId, + "noteId": noteId, + "note_meta": noteMeta, + "marked": marked, + "options": List.from(options.map((x) => x)), + "statistics": List.from(statistics.map((x) => x)), + }; +} diff --git a/lib/models/GetPreviousQuizzesModel/get_previous_quizzes_model.dart b/lib/models/GetPreviousQuizzesModel/get_previous_quizzes_model.dart new file mode 100644 index 0000000..a3aa346 --- /dev/null +++ b/lib/models/GetPreviousQuizzesModel/get_previous_quizzes_model.dart @@ -0,0 +1,97 @@ +// To parse this JSON data, do +// +// final getPreviousQuizzesModel = getPreviousQuizzesModelFromJson(jsonString); + +import 'dart:convert'; + +GetPreviousQuizzesModel getPreviousQuizzesModelFromJson(String str) => GetPreviousQuizzesModel.fromJson(json.decode(str)); + +String getPreviousQuizzesModelToJson(GetPreviousQuizzesModel data) => json.encode(data.toJson()); + +class GetPreviousQuizzesModel { + GetPreviousQuizzesModel({ + required this.data, + }); + + Data data; + + factory GetPreviousQuizzesModel.fromJson(Map json) => GetPreviousQuizzesModel( + data: Data.fromJson(json["data"]), + ); + + Map toJson() => { + "data": data.toJson(), + }; +} + +class Data { + Data({ + required this.status, + required this.quizzes, + }); + + bool status; + List quizzes; + + factory Data.fromJson(Map json) => Data( + status: json["status"], + quizzes: List.from(json["quizzes"].map((x) => Quiz.fromJson(x))), + ); + + Map toJson() => { + "status": status, + "quizzes": List.from(quizzes.map((x) => x.toJson())), + }; +} + +class Quiz { + Quiz({ + required this.quizId, + required this.name, + required this.score, + required this.date, + required this.status, + required this.questions, + required this.totalQuestions, + required this.subjects, + required this.systems, + required this.topics, + }); + + int quizId; + String name; + String score; + String date; + String status; + List questions; + String totalQuestions; + List subjects; + List systems; + List topics; + + factory Quiz.fromJson(Map json) => Quiz( + quizId: json["quizId"], + name: json["name"], + score: json["score"], + date: json["date"], + status: json["status"], + questions: List.from(json["questions"].map((x) => x)), + totalQuestions: json["totalQuestions"], + subjects: List.from(json["subjects"].map((x) => x)), + systems: List.from(json["systems"].map((x) => x)), + topics: List.from(json["topics"].map((x) => x)), + ); + + Map toJson() => { + "quizId": quizId, + "name": name, + "score": score, + "date": date, + "status": status, + "questions": List.from(questions.map((x) => x)), + "totalQuestions": totalQuestions, + "subjects": List.from(subjects.map((x) => x)), + "systems": List.from(systems.map((x) => x)), + "topics": List.from(topics.map((x) => x)), + }; +} diff --git a/lib/models/NotesModel/notes_model.dart b/lib/models/NotesModel/notes_model.dart new file mode 100644 index 0000000..703b87d --- /dev/null +++ b/lib/models/NotesModel/notes_model.dart @@ -0,0 +1,81 @@ +// To parse this JSON data, do +// +// final notesModel = notesModelFromJson(jsonString); + +import 'dart:convert'; + +NotesModel notesModelFromJson(String str) => NotesModel.fromJson(json.decode(str)); + +String notesModelToJson(NotesModel data) => json.encode(data.toJson()); + +class NotesModel { + NotesModel({ + required this.data, + }); + + Data data; + + factory NotesModel.fromJson(Map json) => NotesModel( + data: Data.fromJson(json["data"]), + ); + + Map toJson() => { + "data": data.toJson(), + }; +} + +class Data { + Data({ + required this.status, + required this.notes, + }); + + bool status; + List notes; + + factory Data.fromJson(Map json) => Data( + status: json["status"], + notes: List.from(json["notes"].map((x) => Note.fromJson(x))), + ); + + Map toJson() => { + "status": status, + "notes": List.from(notes.map((x) => x.toJson())), + }; +} + +class Note { + Note({ + required this.idpsasUserNotes, + required this.questionId, + required this.userId, + required this.quizId, + required this.notes, + required this.noteMeta, + }); + + int idpsasUserNotes; + int questionId; + int userId; + int quizId; + String notes; + String noteMeta; + + factory Note.fromJson(Map json) => Note( + idpsasUserNotes: json["idpsas_user_notes"], + questionId: json["question_id"], + userId: json["user_id"], + quizId: json["quiz_id"], + notes: json["notes"], + noteMeta: json["note_meta"], + ); + + Map toJson() => { + "idpsas_user_notes": idpsasUserNotes, + "question_id": questionId, + "user_id": userId, + "quiz_id": quizId, + "notes": notes, + "note_meta": noteMeta, + }; +} diff --git a/lib/models/user_model_successful_login.dart b/lib/models/user_model_successful_login.dart new file mode 100644 index 0000000..f179778 --- /dev/null +++ b/lib/models/user_model_successful_login.dart @@ -0,0 +1,57 @@ +// To parse this JSON data, do +// +// final userModelSuccessfulLogin = userModelSuccessfulLoginFromJson(jsonString); + +import 'dart:convert'; + +UserModelSuccessfulLogin userModelSuccessfulLoginFromJson(String str) => UserModelSuccessfulLogin.fromJson(json.decode(str)); + +String userModelSuccessfulLoginToJson(UserModelSuccessfulLogin data) => json.encode(data.toJson()); + +class UserModelSuccessfulLogin { + UserModelSuccessfulLogin({ + required this.data, + }); + + Data data; + + factory UserModelSuccessfulLogin.fromJson(Map json) => UserModelSuccessfulLogin( + data: Data.fromJson(json["data"]), + ); + + Map toJson() => { + "data": data.toJson(), + }; +} + +class Data { + Data({ + required this.status, + required this.id, + required this.username, + required this.ifAdmin, + required this.token, + }); + + bool status; + int id; + String username; + bool ifAdmin; + String token; + + factory Data.fromJson(Map json) => Data( + status: json["status"], + id: json["ID"], + username: json["username"], + ifAdmin: json["ifAdmin"], + token: json["token"], + ); + + Map toJson() => { + "status": status, + "ID": id, + "username": username, + "ifAdmin": ifAdmin, + "token": token, + }; +} diff --git a/lib/models/user_model_unsuccessful_login.dart b/lib/models/user_model_unsuccessful_login.dart new file mode 100644 index 0000000..6eb9603 --- /dev/null +++ b/lib/models/user_model_unsuccessful_login.dart @@ -0,0 +1,45 @@ +// To parse this JSON data, do +// +// final userModelUnsuccessfulLogin = userModelUnsuccessfulLoginFromJson(jsonString); + +import 'dart:convert'; + +UserModelUnsuccessfulLogin userModelUnsuccessfulLoginFromJson(String str) => UserModelUnsuccessfulLogin.fromJson(json.decode(str)); + +String userModelUnsuccessfulLoginToJson(UserModelUnsuccessfulLogin data) => json.encode(data.toJson()); + +class UserModelUnsuccessfulLogin { + UserModelUnsuccessfulLogin({ + required this.data, + }); + + Data data; + + factory UserModelUnsuccessfulLogin.fromJson(Map json) => UserModelUnsuccessfulLogin( + data: Data.fromJson(json["data"]), + ); + + Map toJson() => { + "data": data.toJson(), + }; +} + +class Data { + Data({ + required this.status, + required this.message, + }); + + bool status; + String message; + + factory Data.fromJson(Map json) => Data( + status: json["status"], + message: json["message"], + ); + + Map toJson() => { + "status": status, + "message": message, + }; +} diff --git a/lib/screens/Authentication/login.dart b/lib/screens/Authentication/login.dart new file mode 100644 index 0000000..3687098 --- /dev/null +++ b/lib/screens/Authentication/login.dart @@ -0,0 +1,599 @@ +import 'dart:convert'; +import 'dart:io'; + +import 'package:flutter/material.dart'; +import 'package:flutter_svg/flutter_svg.dart'; +import 'package:http/http.dart' as http; +import 'package:path_provider/path_provider.dart'; +import 'package:shared_preferences/shared_preferences.dart'; +import 'package:testify/auth_storage.dart'; +import 'package:testify/models/user_model_successful_login.dart'; +import 'package:testify/models/user_model_unsuccessful_login.dart'; +import 'package:testify/screens/home.dart'; + +class Login extends StatefulWidget { + const Login({Key? key, required this.fromWhere}) : super(key: key); + + final String fromWhere; + @override + State createState() => _LoginState(); +} + +class _LoginState extends State { + //Data Fields: + final _formKey = GlobalKey(); + String _email = ""; + String _password = ""; + bool _isChecked = false; + //To start animation + bool _loaded = false; + var _duration = const Duration(milliseconds: 450); + var _dataPreviouslyStored = false; + late UserModelSuccessfulLogin _successfulUser; + late UserModelUnsuccessfulLogin _unsuccessfulUser; + var _invalidUsername = false; + var _invalidPassword = false; + bool _isLoggingIn = false; // To start and finish CircularProgress Indicator + + //The data gets stored to local storage. Continue from there. + AuthStorage storage = new AuthStorage(); + + @override + void initState() { + super.initState(); + //To delete the auth file when the user logs out. + if(widget.fromWhere == "Home") { + storage.deleteFile(); + print("Deleted + :" + storage.readAuth().toString()); + setState(() { + _email = ""; + _password = ""; + _isChecked = false; + _dataPreviouslyStored = false; + }); + } + else { + storage.readAuth().then((value) { + if(value.length != 0) { + var temp = value.split(" "); + print(temp); + setState(() { + _email = temp[0]; + _password = temp[1]; + _dataPreviouslyStored = true; + }); + print("Email + Password: " + _email + _password); + } + else { + + } + }); + } + // Future.delayed(Duration(milliseconds: 1), () { + // setState(() { + // _loaded = true; + // }); + // }); + Future.delayed(Duration(microseconds: 0), () { + setState(() { + _loaded = true; + }); + }); + } + + //https://demo.pookidevs.com/auth/login + Future getUserData(BuildContext context, String email, String password) async { + setState(() { + _isLoggingIn = true; + }); + SharedPreferences prefs = await SharedPreferences.getInstance(); + final String apiUrl = "https://demo.pookidevs.com/auth/login"; + http.post(Uri.parse(apiUrl), headers: { + 'Content-type': 'application/json; charset=UTF-8', + }, body: json.encode( + { + "user": + { + "user_email": email, + "user_pass": password + } + }) + ).then((response) { + if(response.statusCode == 200) { + //The entered credentials are correct. + if(json.decode(response.body).toString().substring(0,20) == "{data: {status: true") { + final responseString = (response.body); + var loginData = userModelSuccessfulLoginFromJson(responseString); + final UserModelSuccessfulLogin successfulUser = loginData; + setState(() { + _successfulUser = successfulUser; + _isLoggingIn = false; + }); + //Saves Token to use later. + prefs.setString('token', _successfulUser.data.token); + prefs.setInt("userId", _successfulUser.data.id); + _navigateAndDisplaySelection(context); + print(_successfulUser.data.status); + } + //Credentials are incorrect + else if(json.decode(response.body).toString().substring(0,21) == "{data: {status: false") { + final responseString = (response.body); + var loginData = userModelUnsuccessfulLoginFromJson(responseString); + final UserModelUnsuccessfulLogin unsuccessfulUser = loginData; + setState(() { + _unsuccessfulUser = unsuccessfulUser; + }); + print(_unsuccessfulUser.data.status); + ScaffoldMessenger.of(context) + ..removeCurrentSnackBar() + ..showSnackBar(SnackBar(content: Text(_unsuccessfulUser.data.message))); + _navigateAndDisplaySelection(context); + var splitMessage = (_unsuccessfulUser.data.message).split(" "); + print(splitMessage); + if(splitMessage.length == 4) { + setState(() { + _invalidPassword = true; + _invalidUsername = true; + }); + } + else if(splitMessage.length == 2) { + setState(() { + _invalidPassword = true; + }); + } + } + //loginData = userModelLoginFromJson(responseString); + } else { + + } + }); + + } + + //After form validation navigation to next screen. + void _navigateAndDisplaySelection(BuildContext context) async { + if(_successfulUser.data.status == true) { + if(_isChecked == true) { + storage.writeAuth(_email, _password); + print("Email + Password: " + _email + _password); + // final result = await Navigator.push( + // context, + // MaterialPageRoute(builder: (context) => const Home()), + // ); + Navigator.pushNamed(context, '/home'); + } + else { + storage.writeAuth(_email, _password); + storage.deleteFile(); + print("Email + Password: " + _email + _password); + // final result = await Navigator.push( + // context, + // MaterialPageRoute(builder: (context) => const Home()), + // ); + Navigator.pushNamed(context, '/home'); + } + } + /*ScaffoldMessenger.of(context) + ..removeCurrentSnackBar() + ..showSnackBar(SnackBar(content: Text(_unsuccessfulUser.data.message)));*/ + } + + @override + Widget build(BuildContext context) { + return WillPopScope( + onWillPop: () async { + // ScaffoldMessenger.of(context) + // ..removeCurrentSnackBar() + // ..showSnackBar(SnackBar(content: Text(""))); + return false; + }, + child: GestureDetector( + onTap: () { + FocusScopeNode currentFocus = FocusScope.of(context); + + if (!currentFocus.hasPrimaryFocus) { + currentFocus.unfocus(); + } + }, + child: Scaffold( + backgroundColor: Color(0xff3F2668),//Color copied from xD=#3F2668 + body: SingleChildScrollView( + child: Container( + height: (MediaQuery.of(context).size.height), + child: Column( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + AnimatedCrossFade( + crossFadeState: _loaded ? CrossFadeState.showFirst : CrossFadeState.showSecond, + duration: _duration, + firstChild: Container( + height: (MediaQuery.of(context).size.height) *0.3, + color: Colors.transparent, + child: Align( + alignment: Alignment.topLeft, + child: Image( + image: AssetImage("assets/Images/login_topLeftBubble_1.png"), + ), + ), + ), + secondChild: Container( + height: (MediaQuery.of(context).size.height) *0.3, + color: Colors.transparent, + child: Text(""), + ), + ), + SizedBox(height: (MediaQuery.of(context).size.height) *0.02159,), + AnimatedCrossFade( + crossFadeState: _loaded ? CrossFadeState.showFirst : CrossFadeState.showSecond, + duration: _duration, + secondChild: Text(""), + firstChild: Container( + child: Form( + key: _formKey, + child: Stack( + alignment: Alignment.bottomCenter, + children: [ + Column(//Add extra space at the end of the container(the one that has TextFormField) so that the login button can be aligned. + children: [ + Container(//For Borders of lighter area //Main Container to add Welcome, TextFormFields and Login. + //tbd: Get the color right! + margin: EdgeInsets.only(top: 0, bottom: 0, left: (MediaQuery.of(context).size.width) *(31/428), right: (MediaQuery.of(context).size.width) *(31/428),), + padding: EdgeInsets.only(top: 0, bottom: (MediaQuery.of(context).size.height) *0.0179, left: 0, right: 0,), + decoration: BoxDecoration( + color: Color.fromRGBO(176, 166, 194, 210),//0xffB0A6C2, rgba(176, 166, 194, 1) + borderRadius: BorderRadius.all(Radius.circular(10)), + border: Border.all( + color: Color(0xff757575), + width: 0, + ), + boxShadow: [ + BoxShadow( + color: Color(0xff0000004D), + ), + ], + ), + child: Column( + children: [ + Container( + padding: EdgeInsets.only(top: (MediaQuery.of(context).size.height) *0.020518, bottom: 0, left: 0, right: 0,), + child: Text("Welcome!", + style: TextStyle( + color: Color(0xffFFFEFE), + fontFamily: 'Brandon-bld', + fontSize: (MediaQuery.of(context).size.height) *0.0410,//38, + ),), + ), + Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Container( + padding: EdgeInsets.only(top: 0, bottom: 0, left: 0, right: 0,), + child: Text("Don't have an account?", + style: TextStyle( + color: Color.fromRGBO(255, 255, 255, 100), + fontFamily: 'Brandon-med', + fontSize: (MediaQuery.of(context).size.height)*0.0194, + ),), + ), + Container( + padding: EdgeInsets.only(top: 0, bottom: 0, left: 0, right: 0,), + child: Text(" Sign Up", + style: TextStyle( + color: Color(0xffFFFEFE), + fontFamily: 'Brandon-med', + fontSize: (MediaQuery.of(context).size.height)*0.0194, + ),), + ), + ], + ), + SizedBox(height: (MediaQuery.of(context).size.height)*0.04535,), + Container( + //color: Colors.white, + height: (MediaQuery.of(context).size.height)*0.055, + //padding: EdgeInsets.fromLTRB(20.0, (MediaQuery.of(context).size.height - MediaQuery.of(context).padding.top)*0.0037797, 20.0, (MediaQuery.of(context).size.height - MediaQuery.of(context).padding.top)*0.0037797), + margin: EdgeInsets.only(top: 0, bottom: 0, left: (MediaQuery.of(context).size.width) *(45/428), right: (MediaQuery.of(context).size.width) *(45/428),), + decoration: BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.all(Radius.circular(10)), + border: Border.all( + color: _invalidUsername == true ? Colors.red : Color(0xff757575), + width: _invalidUsername == true ? 3 : 1, + ), + boxShadow: [ + BoxShadow( + color: Color(0xff0000004D), + ), + ], + ), + child: TextFormField( + keyboardType: TextInputType.emailAddress, + decoration: InputDecoration( + suffixIcon: _invalidUsername == true ? Text("! ", + style: TextStyle( + color: Colors.red, + fontSize: (MediaQuery.of(context).size.height)*(20/926), + fontFamily: 'Brandon-med', + ),) : Text(""), + suffixIconConstraints: BoxConstraints(minWidth: 0, minHeight: 0), + hintText: _dataPreviouslyStored == null ? "Loading..." : (_dataPreviouslyStored ? _email : "Username"), + hintStyle: TextStyle(color: _dataPreviouslyStored ? Color(0xff171616) : Color(0xffAEAEAE), + fontSize: (MediaQuery.of(context).size.height)*(20/926), + fontFamily: 'Brandon-med',), + contentPadding: EdgeInsets.fromLTRB(20.0, (MediaQuery.of(context).size.height)*0.0037797, 20.0, (MediaQuery.of(context).size.height)*0.0037797), + enabledBorder: OutlineInputBorder( + borderSide: BorderSide( + color: Colors.transparent, + width: 0.0, + ), + borderRadius: BorderRadius.circular(10.0), + ), + focusedBorder: OutlineInputBorder( + borderSide: BorderSide( + color: Colors.transparent, + width: 0.0, + ), + ), + ), + //validator: (val) => val!.isEmpty ? "Please enter a Username." : null, + onChanged: (val) { + _dataPreviouslyStored == null ? val = "" : + (_dataPreviouslyStored ? val = _email : _email = val); + //_email = val; + }, + style: TextStyle( + color: Colors.black, + fontSize: (MediaQuery.of(context).size.height)*(20/926), + fontFamily: 'Brandon-med', + ), + ), + ), + SizedBox(height: (MediaQuery.of(context).size.height)*0.0226781,), + Container( + //color: Colors.white, + height: (MediaQuery.of(context).size.height)*0.055, + margin: EdgeInsets.only(top: 0, bottom: 0, left: (MediaQuery.of(context).size.width) *(45/428), right: (MediaQuery.of(context).size.width) *(45/428),), + decoration: BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.all(Radius.circular(10)), + border: Border.all( + color: _invalidPassword == true ? Colors.red : Color(0xff757575), + width: _invalidPassword == true ? 3 : 1, + ), + boxShadow: [ + BoxShadow( + color: Color(0xff0000004D), + ), + ], + ), + child: TextFormField( + //keyboardType: TextInputType.visiblePassword, + obscureText: true, + decoration: InputDecoration( + suffixIcon: _invalidPassword == true ? Text("! ", + style: TextStyle( + color: Colors.red, + fontSize: (MediaQuery.of(context).size.height)*(20/926), + fontFamily: 'Brandon-med', + ),) : Text(""), + suffixIconConstraints: BoxConstraints(minWidth: 0, minHeight: 0), + hintText: _dataPreviouslyStored == null ? "Loading..." : (_dataPreviouslyStored ? _password : "Password"), + hintStyle: TextStyle(color: _dataPreviouslyStored ? Colors.black : Color(0xffAEAEAE), + fontSize: (MediaQuery.of(context).size.height)*(20/926), + fontFamily: 'Brandon-med',), + contentPadding: EdgeInsets.fromLTRB(20.0, (MediaQuery.of(context).size.height)*0.0037797, 20.0, (MediaQuery.of(context).size.height)*0.0037797), + enabledBorder: OutlineInputBorder( + borderSide: BorderSide( + color: Colors.transparent, + width: 0.0, + ), + borderRadius: BorderRadius.circular(10.0), + ), + focusedBorder: OutlineInputBorder( + borderSide: BorderSide( + color: Colors.transparent, + width: 0.0, + ), + ), + ), + //validator: (val) => val!.isEmpty ? "Please enter a Password." : null, + onChanged: (val) { + setState(() { + _dataPreviouslyStored == null ? val = "" : + (_dataPreviouslyStored ? val = _password : _password = val); + }); + }, + style: TextStyle( + color: Colors.black, + fontSize: (MediaQuery.of(context).size.height)*(20/926), + fontFamily: 'Brandon-med', + ), + ), + ), + SizedBox(height: (MediaQuery.of(context).size.height)*0.024838,), + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + GestureDetector( + onTap: () { + if(_isChecked == false) + setState(() { + _isChecked = true; + }); + else if(_isChecked == true) + setState(() { + _isChecked = false; + }); + }, + child: Row( + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Container( + margin: EdgeInsets.only(top: 0, bottom: 0, left: (MediaQuery.of(context).size.width) *(45/428), right: 0,), + height: (MediaQuery.of(context).size.height)*0.0167, + width: (MediaQuery.of(context).size.height)*0.0167, + color: Colors.white, + child: Transform.scale( + scale: (MediaQuery.of(context).size.height)*0.001, + child: Checkbox( + side: BorderSide( + color: Color(0xffB0A6C2), + width: 0, + ), + checkColor: Colors.white, + value: _isChecked, + onChanged: (bool? value) { + setState(() { + _isChecked = value!; + }); + }, + ), + ), + ), + Container( + padding: EdgeInsets.only(top: 0, bottom: 0, left: (MediaQuery.of(context).size.width) *(5/428), right: 0,), + child: Text("Remember me!", + style: TextStyle( + color: Color.fromRGBO(255, 255, 255, 100), + fontFamily: 'Brandon-med', + fontSize: (MediaQuery.of(context).size.height)*0.0161987, + ),), + ), + ], + ), + ), + Container( + padding: EdgeInsets.only(top: 0, bottom: 0, left: 0, right: (MediaQuery.of(context).size.width) *(45/428),), + child: Text("Forgot Password?", + style: TextStyle( + color: Color(0xffFFFEFE), + fontFamily: 'Brandon-med', + fontSize: (MediaQuery.of(context).size.height)*0.0161987, + ),), + ), + ], + ), + _isLoggingIn ? Container() : SizedBox(height: (MediaQuery.of(context).size.height) *0.0864,), + _isLoggingIn ? Container( + height: (MediaQuery.of(context).size.height) *0.0864, + child: Container( + alignment: Alignment.center, + height: (MediaQuery.of(context).size.height) *0.0664, + child: CircularProgressIndicator(color: Colors.white,)), + ) : Container(), + ], + ), + ), + SizedBox(height: (MediaQuery.of(context).size.height) *(25/926),), + ], + ), + // GestureDetector( + // child: Container(//Login button + // child: Align( + // alignment: Alignment.center, + // child: SvgPicture.asset( + // "assets/Images/login.svg", + // height: (MediaQuery.of(context).size.height) *0.0486, + // ), + // ), + // ), + // onTap: () { + // if(_formKey.currentState!.validate()) { + // //_navigateAndDisplaySelection(context); + // //print(_isChecked); + // getUserData(context, _email, _password); + // } + // }, + // ), + Container( + height: (MediaQuery.of(context).size.height) *(45/926), + width: (MediaQuery.of(context).size.width) *(150/428), + decoration: BoxDecoration( + gradient: LinearGradient( + begin: Alignment.centerLeft, + end: Alignment.centerRight, + colors: [ + Color(0xff7F1AF1), + Color(0xff482384) + ]), + borderRadius: new BorderRadius.only( + bottomLeft: const Radius.circular(20.0), + topRight: const Radius.circular(20.0), + ) + ), + child: TextButton( + style: TextButton.styleFrom( + padding: EdgeInsets.zero, + ), + onPressed: () { + // setState(() { + // _isLoggingIn = !_isLoggingIn; + // }); + if(_formKey.currentState!.validate()) { + //_navigateAndDisplaySelection(context); + // print(_isChecked); + getUserData(context, _email, _password); + } + }, + child: Text("Login", + style: TextStyle( + color: Color(0xffFFFEFE), + fontFamily: 'Brandon-bld', + fontSize: (MediaQuery.of(context).size.height)*(25/926), + ),), + ), + ), + ], + ), + ), + ), + ), + AnimatedCrossFade( + crossFadeState: _loaded ? CrossFadeState.showFirst : CrossFadeState.showSecond, + duration: _duration, + secondChild: Container( + height: (MediaQuery.of(context).size.height) *0.183, + child: Text("")), + firstChild: Row( + mainAxisAlignment: MainAxisAlignment.end, + //crossAxisAlignment: CrossAxisAlignment.end, + children: [ + Stack( + //alignment: Alignment.centerRight, + children: [ + Positioned( + left: (MediaQuery.of(context).size.height) *(80/926), + top: (MediaQuery.of(context).size.height) *(50/926), + child: Align( + alignment: Alignment.bottomRight, + child: SvgPicture.asset( + "assets/Images/login_bottomRight.svg", + height: (MediaQuery.of(context).size.height) *0.183, + width: (MediaQuery.of(context).size.height) *0.183, + ), + ), + ), + Positioned(//Remove and add again + child: Align( + alignment: Alignment.bottomRight, + child: SvgPicture.asset( + "assets/Images/login_bottomRight.svg", + height: (MediaQuery.of(context).size.height) *0.183, + width: (MediaQuery.of(context).size.height) *0.183, + color: Colors.transparent, + ), + ), + ), + ], + ), + ], + ), + ), + ], + ), + ), + ), + ), + ), + ); + } +} diff --git a/lib/screens/Welcome/GenerateQuiz/generate_quiz.dart b/lib/screens/Welcome/GenerateQuiz/generate_quiz.dart new file mode 100644 index 0000000..0326fc7 --- /dev/null +++ b/lib/screens/Welcome/GenerateQuiz/generate_quiz.dart @@ -0,0 +1,1598 @@ +import 'dart:convert'; +import 'package:flutter/services.dart'; + +import 'package:flutter/cupertino.dart'; +import 'package:http/http.dart' as http; + +import 'package:flutter/material.dart'; +import 'package:flutter_svg/flutter_svg.dart'; +import 'package:shared_preferences/shared_preferences.dart'; +import 'package:testify/models/GenerateQuizModels/get_system_categories_successful.dart'; +import 'package:testify/models/GenerateQuizModels/get_system_categories_unsuccessful.dart'; +import 'package:testify/screens/Authentication/login.dart'; +import 'package:testify/screens/Welcome/QuizModule/quiz_module.dart'; +import 'package:testify/screens/Welcome/side_menu_bar.dart'; +import 'dart:math' as math; + +class GenerateQuiz extends StatefulWidget { + @override + State createState() => _GenerateQuizState(); +} + +class _GenerateQuizState extends State with SingleTickerProviderStateMixin { + late TabController _tabController; + + // Once the data is loaded only then it shows the containers. + bool _hasDataLoaded = false; + + //Total Questions returned by the API. + // First gets its value when getUserData is run and then gets updated as getQuestionCounts is run. + int _totalQuestions = 0; + List _questions = []; + + //Tab 1 Data: + //Not allowing Subjects or topics to be selected if Systems is empty + bool _systemsDisabled = true; + bool _topicsDisabled = true; + //Title, ID, questions(total questions available), isSelected(which checkbox is clicked), finalTitles(titles that work on getQuestionsCount). + var systemsEverything = { + "title": [], // Saves titles + "finalTitles": [], // Save the final titles that are to be sent to getQuestionsCount + "ID": [], // Saves IDs + "questions": [], // Saves questions + "isSelected": [] // Whichever checkbox is true that bool turns true. + }; + + // Tab 2 Data: + var subjectsEverything = { + "title": [], + "finalTitles": [], // Save the final titles that are to be sent to getQuestionsCount + "ID": [], + "questions": [], + "isSelected": [] + }; + + // Tab 3 Data: + var topicsEverything = { + "title": [], + "finalTitles": [], // Save the final titles that are to be sent to getQuestionsCount + "ID": [], + "questions": [], + "isSelected": [] + }; + + //Tab 4 Data: + //If no option is selected everything stays false and zero is sent. + /*None is not populated*/ + List _questionTypesTitle = ["None", "Unused Questions", "Incorrect Questions", "Correct Questions", "Omitted Questions", "Marked Questions", "All"]; + List _questionTypeSelectedBool = [true, false, false, false, false, false, false]; + int _questionTypeInt = 0; + + //Tab 5 Data: + List _difficultyLevelTitle = ["Very Easy", "Easy", "Medium", "Hard", "Very Hard"]; + List _difficultyLevelBool = [false, false, false, false, false]; + List _difficultyLevel = []; + //Generate Quiz + bool _tutorMode = true; + bool _timedMode = false; + // Just a form key for the questionCount + final _numberOfQuestionsKey = GlobalKey(); + var _questionsCount; + + //Shared Pref + var _token; + var _userId; + + // Token Valid + var _getSystemCategoriesSuccessful; + // Token Incorrect + var _getSystemCategoriesUnsuccessful; + + //When getQuestionCount is run(Just used to get the totalQuestions + var _getQuestionsCountCategoriesSuccessful; + var _getQuestionsCountCategoriesUnsuccessful; + + @override + void initState() { + super.initState(); + _tabController = TabController(vsync: this, length: 5); + getUserDataSST(); + } + + //This is run only once. + Future getUserDataSST() async { + SharedPreferences prefs = await SharedPreferences.getInstance(); + final String apiUrlSystemCategories = "https://demo.pookidevs.com/quiz/generator/getAllCategories"; + _token = prefs.getString('token')!; + _userId = prefs.getInt("userId")!; + http.get(Uri.parse(apiUrlSystemCategories), headers: { + 'Content-type': 'application/json; charset=UTF-8', 'Authorization' : _token.toString(), + },).then((response) { + // print(jsonDecode(response.body).toString()); + if(response.statusCode == 200) { + if(json.decode(response.body).toString().substring(0,20) == "{data: {status: true") { + final responseString = (response.body); + var systemCategoriesDataSuccessful = getSystemCategoriesSuccessfulModelFromJson(responseString); + final GetSystemCategoriesSuccessfulModel getSystemCategoriesSuccessful = systemCategoriesDataSuccessful; + setState(() { + _getSystemCategoriesSuccessful = getSystemCategoriesSuccessful; + _hasDataLoaded = true; + _totalQuestions = _getSystemCategoriesSuccessful.data.totalQuestions; + _questions = _getSystemCategoriesSuccessful.data.questions; + }); + // print(_questions); + } else { + + } + //Adds data to lists + categorizeUserData(); + } + else { // Status Code is 401 here that is why if written in the above if statement it would not work. + //Token is Invalid + if(json.decode(response.body).toString().substring(0,14) == "{status: false") { + final responseString = (response.body); + var systemCategoriesDataUnsuccessful = getSystemCategoriesUnsuccessfulModelFromJson(responseString); + final GetSystemCategoriesUnsuccessfulModel getSystemCategoriesUnsuccessful = systemCategoriesDataUnsuccessful; + setState(() { + _getSystemCategoriesUnsuccessful = getSystemCategoriesUnsuccessful; + }); + print(_getSystemCategoriesUnsuccessful.msg); + ScaffoldMessenger.of(context) + ..removeCurrentSnackBar() + ..showSnackBar(SnackBar(content: Text("Token Expired!"))); + final result = Navigator.push( + context, + MaterialPageRoute(builder: (context) => const Login(fromWhere:"Home")), + ); + } + else { + + } + } + } + ); + } + + Future getQuestionsCount() async { + // print(subjectsEverything["finalTitles"]); + // print(systemsEverything["finalTitles"]); + // print(topicsEverything["finalTitles"]); + // print(_userId); + // print(_questionTypeInt); + // print(_difficultyLevel); + + final String apiUrl = "https://demo.pookidevs.com/quiz/generator/getQuestionCounts"; + http.post(Uri.parse(apiUrl), headers: { + 'Content-type': 'application/json; charset=UTF-8', 'Authorization' : _token.toString(), + }, body: json.encode( + { + "data": + { + "subjects": subjectsEverything["finalTitles"], + "systems": systemsEverything["finalTitles"], + "topics": topicsEverything["finalTitles"], + "userId": _userId, // Add _userId here. + "statusLevels": _questionTypeInt, // Add _questionType here + "difficultyLevels": _difficultyLevel, // Add _difficultyLevels here + } + }) + ).then((response) { + if(response.statusCode == 200) { + // print("getQuestionsCount() : " + response.body.toString()); + if(json.decode(response.body).toString().substring(0,20) == "{data: {status: true") { + final responseString = (response.body); + var QuestionsCountCategoriesSuccessful = getSystemCategoriesSuccessfulModelFromJson(responseString); + final GetSystemCategoriesSuccessfulModel getQuestionsCountCategoriesSuccessful = QuestionsCountCategoriesSuccessful; + setState(() { + _getQuestionsCountCategoriesSuccessful = getQuestionsCountCategoriesSuccessful; + _totalQuestions = _getQuestionsCountCategoriesSuccessful.data.totalQuestions; + _questions = _getQuestionsCountCategoriesSuccessful.data.questions; + }); + // print(_getSystemCategoriesSuccessful); + print(_totalQuestions); + print(_questions); + } else { + + } + } else { + //Token is Invalid + if(json.decode(response.body).toString().substring(0,14) == "{status: false") { + final responseString = (response.body); + var QuestionsCountCategoriesDataUnsuccessful = getSystemCategoriesUnsuccessfulModelFromJson(responseString); + final GetSystemCategoriesUnsuccessfulModel getQuestionsCountCategoriesUnsuccessful = QuestionsCountCategoriesDataUnsuccessful; + setState(() { + _getQuestionsCountCategoriesUnsuccessful = getQuestionsCountCategoriesUnsuccessful; + }); + print(_getQuestionsCountCategoriesUnsuccessful.msg); + ScaffoldMessenger.of(context) + ..removeCurrentSnackBar() + ..showSnackBar(SnackBar(content: Text("Token Expired!"))); + final result = Navigator.push( + context, + MaterialPageRoute(builder: (context) => const Login(fromWhere:"Home")), + ); + } + else { + + } + } + }); + + } + + //Add data to lists. Only done the first time. + categorizeUserData() { + //To clear any past data + int c = 0; + while((c<_getSystemCategoriesSuccessful.data.categories.toList().length) & (_getSystemCategoriesSuccessful.data.categories.toList().length > 0)) { + var tempLength = _getSystemCategoriesSuccessful.data.categories.toList().length; + if(_getSystemCategoriesSuccessful.data.categories[c].subCategories != null) { + if(_getSystemCategoriesSuccessful.data.categories[c].parentCategory.toString() == "systems") { + //Gets the length of subjects(Number of Subjects) + var lenSystems = _getSystemCategoriesSuccessful.data.categories[c].subCategories.toList().length; + int i = 0; + setState(() { + while((lenSystems>0) & (i0) & (i0) & (i[ + Color(0xff7F1AF1), + Color(0xff482384) + ]) + ), + ), + title: const Text("Generate Quiz", + style: TextStyle( + color: Color(0xffFFFEFE), + fontFamily: 'Brandon-bld', + ), + ), + actions: [ + TextButton( + onPressed: () async { + final result = await Navigator.push( + context, + MaterialPageRoute(builder: (context) => const Login(fromWhere:"Home")), + ); + }, + child: SvgPicture.asset( + "assets/Images/logout.svg", + height: (MediaQuery.of(context).size.height) *(32/926), + ), + ), + ], + ), + body: SingleChildScrollView( + child: Container( + padding: EdgeInsets.only(top:(MediaQuery.of(context).size.height) *(15/926), + bottom: (MediaQuery.of(context).size.height) *(8/926), + left: (MediaQuery.of(context).size.width) *(18/428), + right: (MediaQuery.of(context).size.width) *(18/428)), + child: Column( + children: [ + Row( + children: [ + Container( + width: (MediaQuery.of(context).size.width) *(221/428), + //height: (MediaQuery.of(context).size.height) *(91/926), + child: Column( + children: [ + Align( + alignment: Alignment.topLeft, + child: Text("Create Quiz", + style: TextStyle( + color: Color(0xff232323), + fontFamily: 'Brandon-bld', + fontSize: (MediaQuery.of(context).size.height) *(25/926),//38, + ),), + ), + SizedBox(height: (MediaQuery.of(context).size.height) *(2/926),), + Text("Lorem ipsum dolor sit amet, consectetur adipiscing elit. Cras imperdiet finibus elit non luctus. Morbi auctor mattis ante.", + style: TextStyle( + color: Color(0xFF483A3A), + fontFamily: 'Brandon-med', + fontSize: (MediaQuery.of(context).size.height) *(13/926),//38, + ),), + ], + ), + ), + SizedBox(width: (MediaQuery.of(context).size.width) *(39/428),), + Container( + //color: Colors.transparent, + child: SvgPicture.asset( + "assets/Images/create_quiz.svg", + height: (MediaQuery.of(context).size.height) *(100/926), + //width: (MediaQuery.of(context).size.width) *(132/428), + ), + ), + ], + ), + SizedBox(height: (MediaQuery.of(context).size.height) *(25/926),), + SizedBox(height: (MediaQuery.of(context).size.height) *(13.28/926),), + Container( + height: (MediaQuery.of(context).size.height) *(596/926), + width: double.infinity, + child: TabBarView( + // physics: NeverScrollableScrollPhysics(), + controller: _tabController, + children: [ + //Tab1: Subjects + Column( + children: [ + Container( + height: (MediaQuery.of(context).size.height) *(40.32/926), + width: (MediaQuery.of(context).size.width) *(386/428), + decoration: BoxDecoration( + color: Color(0xFF3F2668), + borderRadius: BorderRadius.only(bottomLeft: Radius.circular(15.0), topRight: Radius.circular(15.0),), + boxShadow: [ + BoxShadow( + color: Colors.black12, + spreadRadius: 2, + blurRadius: 2, + offset: Offset(0, 0), + ), + ], + ), + child: Center( + child: Text("Select Subjects", + style: TextStyle( + color: Colors.white, + fontFamily: 'Brandon-bld', + fontSize: (MediaQuery.of(context).size.height) *(26.31/926),//38, + ),), + ), + ), + SizedBox(height: (MediaQuery.of(context).size.height) *(33/926)), + Container( + padding: EdgeInsets.only(left: (MediaQuery.of(context).size.width) *(10/428), right: (MediaQuery.of(context).size.width) *(10/428)), + width: (MediaQuery.of(context).size.width) *(366/428), + child: _hasDataLoaded == false ? + Container(height: (MediaQuery.of(context).size.height) *(460/926),child: Center(child: CircularProgressIndicator(color: Color(0xFF3F2668),))) + : + Container( + height: (MediaQuery.of(context).size.height) *(460/926), + child: ListView( + scrollDirection: Axis.vertical, + children: [ + Container( + height: (MediaQuery.of(context).size.height) *(120.9/926), + child: GridView( + gridDelegate: SliverGridDelegateWithFixedCrossAxisCount( + crossAxisCount: 2, + crossAxisSpacing: (MediaQuery.of(context).size.width) *(30/428), + mainAxisExtent: (MediaQuery.of(context).size.height) *(40.224/926),), + children: [ + for(int i = 0; i 0) { + setState(() { + _systemsDisabled = false; + }); + } + + //Unchecking the previously checked boxes. + if(subjectsEverything["isSelected"]![i] == false) { + if(systemsEverything["isSelected"]!.length > 0) { + for(int i = 0; i 0) { + for(int i = 0; i[ + for(int i = 0; i 0) { + setState(() { + _topicsDisabled = false; + }); + } + + //Unchecking the previously checked boxes. + if(systemsEverything["isSelected"]![i] == false) { + // topicsEverything + if(topicsEverything["isSelected"]!.length > 0) { + for(int i = 0; i AlertDialog( + content: Text( + 'Select Subjects First!', + style: TextStyle( + color: Color(0xffA1A1A1), + fontFamily: 'Brandon-bld', + fontSize: (MediaQuery.of(context).size.height) * (21 / 926), + ), + ), + actions: [ + Divider(), + TextButton( + onPressed: () { + Navigator.of(context).pop(); + }, + child: Text('Okay', + style: TextStyle( + color: Color(0xff3F2668), + fontFamily: 'Brandon-bld', + fontSize: + (MediaQuery.of(context).size.height) * (21 / 926), + )), + ), + ], + ), + ); + } + }, + ), + ), + ], + ) + ), + ], + ), + ), + ), + SizedBox(height: (MediaQuery.of(context).size.height) *(10.74/926),), + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + InkWell( + child: Container( + height: (MediaQuery.of(context).size.height) *(42/926), + width: (MediaQuery.of(context).size.width) *(68/428), + decoration: BoxDecoration( + color: Color(0xff3F2668),//0xffB0A6C2, rgba(176, 166, 194, 1) + borderRadius: BorderRadius.all(Radius.circular(3)), + boxShadow: [ + BoxShadow( + color: Colors.black12,//Color(0xff00000029), + spreadRadius: 2, + blurRadius: 2, + offset: Offset(0, 0), + ), + ], + ), + child: TextButton( + onPressed: () { + //Animates to next tab + _backTab(); + }, + child: Center( + child: Text("Back", + style: TextStyle( + color: Colors.white, + fontFamily: 'Brandon-med', + ), + ), + ), + ), + ), + ), + InkWell( + child: Container( + height: (MediaQuery.of(context).size.height) *(42/926), + width: (MediaQuery.of(context).size.width) *(68/428), + decoration: BoxDecoration( + color: Color(0xff3F2668),//0xffB0A6C2, rgba(176, 166, 194, 1) + borderRadius: BorderRadius.all(Radius.circular(3)), + boxShadow: [ + BoxShadow( + color: Colors.black12,//Color(0xff00000029), + spreadRadius: 2, + blurRadius: 2, + offset: Offset(0, 0), + ), + ], + ), + child: TextButton( + onPressed: () { + //Animates to next tab + _nextTab(); + }, + child: Center( + child: Text("Next", + style: TextStyle( + color: Colors.white, + fontFamily: 'Brandon-med', + ), + ), + ), + ), + ), + ), + ], + ), + ], + ), + + //Tab3: Topics + Column( + children: [ + Container( + height: (MediaQuery.of(context).size.height) *(40.32/926), + width: (MediaQuery.of(context).size.width) *(366/428), + //color: Colors.red, + decoration: BoxDecoration( + color: Color(0xFF3F2668),//0xffB0A6C2, rgba(176, 166, 194, 1) + borderRadius: BorderRadius.only(bottomLeft: Radius.circular(15.0), topRight: Radius.circular(15.0),), + boxShadow: [ + BoxShadow( + color: Colors.black12,//Color(0xff00000029), + spreadRadius: 2, + blurRadius: 2, + offset: Offset(0, 0), + ), + ], + ), + child: Center( + child: Text("Select Topics", + style: TextStyle( + color: Colors.white, + fontFamily: 'Brandon-bld', + fontSize: (MediaQuery.of(context).size.height) *(26.31/926),//38, + ),), + ), + ), + SizedBox(height: (MediaQuery.of(context).size.height) *(33/926)), + Container( + padding: EdgeInsets.only(left: (MediaQuery.of(context).size.width) *(10/428), right: (MediaQuery.of(context).size.width) *(10/428)), + width: (MediaQuery.of(context).size.width) *(366/428), + child: Container( + height: (MediaQuery.of(context).size.height) *(460/926), + child: _hasDataLoaded == false ? Text("") : ListView( + scrollDirection: Axis.vertical, + children: [ + Container( + height: (MediaQuery.of(context).size.height) *(120.9/926), + child: GridView( + gridDelegate: SliverGridDelegateWithFixedCrossAxisCount( + crossAxisCount: 2, + crossAxisSpacing: (MediaQuery.of(context).size.width) *(30/428), + mainAxisExtent: (MediaQuery.of(context).size.height) *(40.224/926),), + children: [ + for(int i = 0; i AlertDialog( + content: Text( + 'Select Systems First!', + style: TextStyle( + color: Color(0xffA1A1A1), + fontFamily: 'Brandon-bld', + fontSize: (MediaQuery.of(context).size.height) * (21 / 926), + ), + ), + actions: [ + Divider(), + TextButton( + onPressed: () { + Navigator.of(context).pop(); + }, + child: Text('Okay', + style: TextStyle( + color: Color(0xff3F2668), + fontFamily: 'Brandon-bld', + fontSize: + (MediaQuery.of(context).size.height) * (21 / 926), + )), + ), + ], + ), + ); + } + // print(subjectsEverything["finalTitles"]); + // print(systemsEverything["finalTitles"]); + // print(topicsEverything["finalTitles"]); + getQuestionsCount(); + }, + ), + ), + ], + ) + ), + ], + ), + ), + ), + SizedBox(height: (MediaQuery.of(context).size.height) *(10.74/926),), + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + InkWell( + child: Container( + height: (MediaQuery.of(context).size.height) *(42/926), + width: (MediaQuery.of(context).size.width) *(68/428), + decoration: BoxDecoration( + color: Color(0xff3F2668),//0xffB0A6C2, rgba(176, 166, 194, 1) + borderRadius: BorderRadius.all(Radius.circular(3)), + boxShadow: [ + BoxShadow( + color: Colors.black12,//Color(0xff00000029), + spreadRadius: 2, + blurRadius: 2, + offset: Offset(0, 0), + ), + ], + ), + child: TextButton( + onPressed: () { + //Animates to next tab + _backTab(); + }, + child: Center( + child: Text("Back", + style: TextStyle( + color: Colors.white, + fontFamily: 'Brandon-med', + ), + ), + ), + ), + ), + ), + InkWell( + child: Container( + height: (MediaQuery.of(context).size.height) *(42/926), + width: (MediaQuery.of(context).size.width) *(68/428), + decoration: BoxDecoration( + color: Color(0xff3F2668),//0xffB0A6C2, rgba(176, 166, 194, 1) + borderRadius: BorderRadius.all(Radius.circular(3)), + boxShadow: [ + BoxShadow( + color: Colors.black12,//Color(0xff00000029), + spreadRadius: 2, + blurRadius: 2, + offset: Offset(0, 0), + ), + ], + ), + child: TextButton( + onPressed: () { + //Animates to next tab + _nextTab(); + }, + child: Center( + child: Text("Next", + style: TextStyle( + color: Colors.white, + fontFamily: 'Brandon-med', + ), + ), + ), + ), + ), + ), + ], + ), + ], + ), + + //Tab4: Question Types + Column( + children: [ + Container( + height: (MediaQuery.of(context).size.height) *(40.32/926), + width: (MediaQuery.of(context).size.width) *(386/428), + //color: Colors.red, + decoration: BoxDecoration( + color: Color(0xFF3F2668),//0xffB0A6C2, rgba(176, 166, 194, 1) + borderRadius: BorderRadius.only(bottomLeft: Radius.circular(15.0), topRight: Radius.circular(15.0),), + boxShadow: [ + BoxShadow( + color: Colors.black12,//Color(0xff00000029), + spreadRadius: 2, + blurRadius: 2, + offset: Offset(0, 0), + ), + ], + ), + child: Center( + child: Text("Select Question Types", + style: TextStyle( + color: Colors.white, + fontFamily: 'Brandon-bld', + fontSize: (MediaQuery.of(context).size.height) *(26.31/926),//38, + ),), + ), + ), + SizedBox(height: (MediaQuery.of(context).size.height) *(33/926)), + Container( + padding: EdgeInsets.only(left: (MediaQuery.of(context).size.width) *(10/428), right: (MediaQuery.of(context).size.width) *(10/428)), + width: (MediaQuery.of(context).size.width) *(366/428), + height: (MediaQuery.of(context).size.height) *(460/926), + child: Column( + children: [ + for(int i = 1; i<7; i++) + Column( + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Container( + height: (MediaQuery.of(context).size.height) *(40.224/926), + width: (MediaQuery.of(context).size.width) *(302/428), + color: _questionTypeSelectedBool[i] == false ? Colors.white : Color(0xFF3F2668), + child: TextButton( + style: TextButton.styleFrom( + padding: EdgeInsets.zero,), + child: Text(_questionTypesTitle[i], + style: TextStyle( + color: _questionTypeSelectedBool[i] == false ? Color(0xFF3F3D56) : Colors.white, + fontFamily: 'Brandon-med', + fontSize: (MediaQuery.of(context).size.height)*(15/926), + ),), + onPressed: () { + _questionTypesLogic(i); + getQuestionsCount(); + }, + ), + ), + _questionTypeSelectedBool[i] == false ? + GestureDetector( + onTap: () { + _questionTypesLogic(i); + getQuestionsCount(); + }, + child: Container( + height: (MediaQuery.of(context).size.height) *(34.224/926), + width: (MediaQuery.of(context).size.height) *(34.224/926), + // width: (MediaQuery.of(context).size.width) *(29.224/428), + decoration: BoxDecoration( + border: Border.all(width: 9, color: Color(0xFFA1A1A1)), + borderRadius: BorderRadius.all(Radius.circular(50)), + ), + ), + ) + : + GestureDetector( + onTap: () { + _questionTypesLogic(i); + getQuestionsCount(); + }, + child: Container( + child: Icon(Icons.check, + size: (MediaQuery.of(context).size.height) *(34.224/926), + color: Color(0xFF3F2668),) + ), + ), + ], + ), + SizedBox(height: (MediaQuery.of(context).size.height) *(25.224/926)), + ], + ), + ], + ), + ), + SizedBox(height: (MediaQuery.of(context).size.height) *(10.74/926),), + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + InkWell( + child: Container( + height: (MediaQuery.of(context).size.height) *(42/926), + width: (MediaQuery.of(context).size.width) *(68/428), + decoration: BoxDecoration( + color: Color(0xff3F2668),//0xffB0A6C2, rgba(176, 166, 194, 1) + borderRadius: BorderRadius.all(Radius.circular(3)), + boxShadow: [ + BoxShadow( + color: Colors.black12,//Color(0xff00000029), + spreadRadius: 2, + blurRadius: 2, + offset: Offset(0, 0), + ), + ], + ), + child: TextButton( + onPressed: () { + //Animates to next tab + _backTab(); + }, + child: Center( + child: Text("Back", + style: TextStyle( + color: Colors.white, + fontFamily: 'Brandon-med', + ), + ), + ), + ), + ), + ), + InkWell( + child: Container( + height: (MediaQuery.of(context).size.height) *(42/926), + width: (MediaQuery.of(context).size.width) *(68/428), + decoration: BoxDecoration( + color: Color(0xff3F2668),//0xffB0A6C2, rgba(176, 166, 194, 1) + borderRadius: BorderRadius.all(Radius.circular(3)), + boxShadow: [ + BoxShadow( + color: Colors.black12,//Color(0xff00000029), + spreadRadius: 2, + blurRadius: 2, + offset: Offset(0, 0), + ), + ], + ), + child: TextButton( + onPressed: () { + //Animates to next tab + _nextTab(); + }, + child: Center( + child: Text("Next", + style: TextStyle( + color: Colors.white, + fontFamily: 'Brandon-med', + ), + ), + ), + ), + ), + ), + ], + ), + ], + ), + + //Tab5: Generate Quiz + Column( + children: [ + Container( + height: (MediaQuery.of(context).size.height) *(40.32/926), + width: (MediaQuery.of(context).size.width) *(386/428), + //color: Colors.red, + decoration: BoxDecoration( + color: Color(0xFF3F2668),//0xffB0A6C2, rgba(176, 166, 194, 1) + borderRadius: BorderRadius.only(bottomLeft: Radius.circular(15.0), topRight: Radius.circular(15.0),), + boxShadow: [ + BoxShadow( + color: Colors.black12,//Color(0xff00000029), + spreadRadius: 2, + blurRadius: 2, + offset: Offset(0, 0), + ), + ], + ), + child: Center( + child: Text("Generate Quiz", + style: TextStyle( + color: Colors.white, + fontFamily: 'Brandon-bld', + fontSize: (MediaQuery.of(context).size.height) *(26.31/926),//38, + ),), + ), + ), + SizedBox(height: (MediaQuery.of(context).size.height) *(22.8/926)), + Container( + width: (MediaQuery.of(context).size.width) *(386/428), // 460/926 + height: (MediaQuery.of(context).size.height) *(460/926), + child: Column( + children: [ + Center( + child: Text("Set Difficulty Level", + style: TextStyle( + color: Color(0xFF232323), + fontFamily: 'Brandon-med', + fontSize: (MediaQuery.of(context).size.height) *(16/926), + ), + ), + ), + SizedBox(height: (MediaQuery.of(context).size.height) *(26.59/926),), + Row( + children: [ + for(int i = 1; i<6; i++) + Row( + children: [ + Container( + height: (MediaQuery.of(context).size.height) *(40.224/926), + width: (MediaQuery.of(context).size.width) *((60)/428), + color: _difficultyLevelBool[i-1] == false ? Color(0xFFE4E4E4) : Color(0xFF7F1AF1), + child: TextButton( + style: TextButton.styleFrom( + padding: EdgeInsets.zero,), + child: Text(_difficultyLevelTitle[i-1], + style: TextStyle( + color: _difficultyLevelBool[i-1] == false ? Color(0xFF3F2668) : Colors.white, + fontFamily: 'Brandon-med', + fontSize: (MediaQuery.of(context).size.height)*(13/926), + ),), + onPressed: () { + setState(() { + if(_difficultyLevelBool[i-1] == false) { + _difficultyLevelBool[i-1] = true; + _difficultyLevel.add(i); + } + else if(_difficultyLevelBool[i-1] == true) { + _difficultyLevelBool[i-1] = false; + _difficultyLevel.remove(i); + } + }); + getQuestionsCount(); + }, + ), + ), + if(i != 5) + // SizedBox(width: (MediaQuery.of(context).size.width) *(46/926)), + for(int j = 0; j<6; j++) + Row( + children: [ + Container( + child: Container( + height: (MediaQuery.of(context).size.height) *(2/926), + width: (MediaQuery.of(context).size.width) *(3.55/428), + decoration: BoxDecoration( + color: Color(0xFFE4E4E4), + shape: BoxShape.circle, + ), + ), + ), + ], + ) + ], + ), + ], + ), + SizedBox(height: (MediaQuery.of(context).size.height) *(48/926),), + Center( + child: Text("Generate Quiz", + style: TextStyle( + color: Color(0xFF232323), + fontFamily: 'Brandon-med', + fontSize: (MediaQuery.of(context).size.height) *(16/926), + ), + ), + ), + SizedBox(height: (MediaQuery.of(context).size.height) *(28/926),), + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Row( + children: [ + Container( + height: (MediaQuery.of(context).size.height) *(30/926), + width: (MediaQuery.of(context).size.width) *(98/428), + padding: EdgeInsets.zero, + margin: EdgeInsets.zero, + decoration: BoxDecoration( + color: _tutorMode? Color(0xff3F2668) : Colors.white, + border: Border.all(color: Color(0xff3F2668)), + borderRadius: BorderRadius.only(topLeft: Radius.circular(3), bottomLeft: Radius.circular(3)), + ), + //color: Colors.red, + child: InkWell( + onTap: () { + if(_tutorMode == false) { + setState(() { + _tutorMode = true; + print(_tutorMode); + }); + } + }, + child: Center( + child: Text("Tutor Mode", + style: TextStyle( + color: _tutorMode? Colors.white : Color(0xff3F2668), + fontFamily: 'Brandon-med', + fontSize: (MediaQuery.of(context).size.height) *(15/926) + ), + ), + ), + ) + ), + Container( + height: (MediaQuery.of(context).size.height) *(30/926), + width: (MediaQuery.of(context).size.width) *(98/428), + padding: EdgeInsets.zero, + margin: EdgeInsets.zero, + decoration: BoxDecoration( + color: _tutorMode? Colors.white : Color(0xff3F2668), + border: Border.all(color: Color(0xff3F2668)), + borderRadius: BorderRadius.only(topRight: Radius.circular(3), bottomRight: Radius.circular(3)), + ), + //color: Colors.red, + child: InkWell( + onTap: () { + if(_tutorMode == true) { + setState(() { + _tutorMode = false; + // print(_tutorMode); + }); + } + }, + child: Center( + child: Text("Exam Mode", + style: TextStyle( + color: _tutorMode? Color(0xff3F2668) : Colors.white, + fontFamily: 'Brandon-med', + fontSize: (MediaQuery.of(context).size.height) *(15/926) + ), + ), + ), + ) + ), + ], + ), + Row( + children: [ + Transform.scale( + scale: 1, + child: Container( + height: (MediaQuery.of(context).size.height) *(20/926), + child: Switch( + value: _timedMode, + onChanged: (value) { + setState(() { + _timedMode = value; + // print(_timedMode); + }); + }, + activeColor: Color(0xff3F2668), + ), + ), + ), + Container( + child: Text("Timed Mode", + style: TextStyle( + color: Color(0xff483A3A), + fontFamily: 'Brandon-med', + fontSize: (MediaQuery.of(context).size.height) *(15/926) + ), + ), + ), + SizedBox(width: (MediaQuery.of(context).size.width) *(10/428)), + + ], + ), + ], + ), + SizedBox(height: (MediaQuery.of(context).size.height) *(40/926)), + Container( + padding: EdgeInsets.only(bottom: (MediaQuery.of(context).size.height) *(15/926)), + child: Row( + children: [ + Text("Enter The Number Of Questions: ", + style: TextStyle( + color: Color(0xff3F3D56), + fontFamily: 'Brandon-med', + fontSize: (MediaQuery.of(context).size.height) *(15/926) + ), + ), + Container( + height: (MediaQuery.of(context).size.height) *(24/926), + width: (MediaQuery.of(context).size.width) *(40.01/428), + color: Colors.white, + child: Form( + key: _numberOfQuestionsKey, + child: TextField( + keyboardType: TextInputType.number, + inputFormatters: [ + FilteringTextInputFormatter.digitsOnly + ], // Only numbers can be entered + textAlign: TextAlign.center, + decoration: InputDecoration( + hintText: "4", + hintStyle: TextStyle(color: Color(0xffAEAEAE), + fontSize: (MediaQuery.of(context).size.height)*(15/926), + fontFamily: 'Brandon-med',), + contentPadding: EdgeInsets.fromLTRB(2.0, 1, 2.0, 1), + enabledBorder: OutlineInputBorder( + borderSide: BorderSide( + color: Color(0xFF7070709E), + width: 1.0, + ), + borderRadius: BorderRadius.circular(3.0), + ), + focusedBorder: OutlineInputBorder( + borderSide: BorderSide( + color: Colors.transparent, + width: 0.0, + ), + ), + ), + style: TextStyle( + color: Colors.black, + fontSize: (MediaQuery.of(context).size.height)*(15/926), + fontFamily: 'Brandon-med', + ), + onChanged: (val) { + final number = num.tryParse(val); + if(number != null) { + var totalQuestions; + try { + totalQuestions = _totalQuestions; + } catch (error) { + ScaffoldMessenger.of(context) + ..removeCurrentSnackBar() + ..showSnackBar(SnackBar(content: Text("Error"))); + } + if((int.parse(val)>totalQuestions) || (int.parse(val)>=40)) { + ScaffoldMessenger.of(context) + ..removeCurrentSnackBar() + ..showSnackBar(SnackBar(content: Text("Enter a smaller number"))); + setState(() { + _questionsCount = 0; + }); + } + else{ + setState(() { + _questionsCount = int.parse(val); + }); + } + } + }, + ), + ), + ), + Text(" /" + _totalQuestions.toString(), + style: TextStyle( + color: Color(0xFF98A4A4), + fontSize: (MediaQuery.of(context).size.height)*(15/926), + fontFamily: 'Brandon-med', + ),), + ], + ), + ), + ], + ), + ), + SizedBox(height: (MediaQuery.of(context).size.height) *(21/926),), + + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + InkWell( + child: Container( + height: (MediaQuery.of(context).size.height) *(42/926), + width: (MediaQuery.of(context).size.width) *(68/428), + decoration: BoxDecoration( + color: Color(0xff3F2668),//0xffB0A6C2, rgba(176, 166, 194, 1) + borderRadius: BorderRadius.all(Radius.circular(3)), + boxShadow: [ + BoxShadow( + color: Colors.black12,//Color(0xff00000029), + spreadRadius: 2, + blurRadius: 2, + offset: Offset(0, 0), + ), + ], + ), + child: TextButton( + onPressed: () { + //Animates to next tab + _backTab(); + }, + child: Center( + child: Text("Back", + style: TextStyle( + color: Colors.white, + fontFamily: 'Brandon-med', + ), + ), + ), + ), + ), + ), + InkWell( + child: Container( + height: (MediaQuery.of(context).size.height) *(42/926), + width: (MediaQuery.of(context).size.width) *(100/428), + decoration: BoxDecoration( + color: Color(0xff3F2668),//0xffB0A6C2, rgba(176, 166, 194, 1) + borderRadius: BorderRadius.all(Radius.circular(3)), + boxShadow: [ + BoxShadow( + color: Colors.black12,//Color(0xff00000029), + spreadRadius: 2, + blurRadius: 2, + offset: Offset(0, 0), + ), + ], + ), + child: TextButton( + onPressed: () { + print("adsdsa"); + // print(num.tryParse(_questionsCount)); + if(_questionsCount > 0) { + final result = Navigator.push( + context, + MaterialPageRoute(builder: (context) => QuizModule(totalQuestions: _questionsCount, questions: _questions, timedMode: _timedMode, mode: _tutorMode ? "tutor" : "exam", whatsDone: "new",)), + ); + } + }, + child: Center( + child: Text("Create Quiz", + style: TextStyle( + color: Colors.white, + fontFamily: 'Brandon-med', + ), + ), + ), + ), + ), + ), + ], + ), + ], + ), + ], + ), + ), + ], + ), + ), + ), + ); + } +} \ No newline at end of file diff --git a/lib/screens/Welcome/Notes/noteDetails.dart b/lib/screens/Welcome/Notes/noteDetails.dart new file mode 100644 index 0000000..d906b01 --- /dev/null +++ b/lib/screens/Welcome/Notes/noteDetails.dart @@ -0,0 +1,424 @@ +import 'dart:convert'; + +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_svg/svg.dart'; +import 'package:http/http.dart' as http; +import 'package:shared_preferences/shared_preferences.dart'; +import 'package:testify/screens/Welcome/Notes/notes.dart'; + +import '../../Authentication/login.dart'; +import '../side_menu_bar.dart'; +class NoteDetails extends StatefulWidget { + final int noteId; + final String noteText; + NoteDetails({required this.noteId,required this.noteText}); + + @override + State createState() => _NoteDetailsState(); +} + +class _NoteDetailsState extends State { + var _note; + late TextEditingController _textController; + + //Shared Pref + var _token; + + @override + void initState() { + super.initState(); + _textController = TextEditingController(); + } + + @override + void dispose() { + _textController.dispose(); + super.dispose(); + } + + Future editNotesAPI() async { + SharedPreferences prefs = await SharedPreferences.getInstance(); + _token = prefs.getString('token')!; + final String editNotesAPI = "https://demo.pookidevs.com/quiz/notes/editNotes"; + http.post(Uri.parse(editNotesAPI), headers: { + 'Content-type': 'application/json; charset=UTF-8', 'Authorization' : _token.toString(), + }, body: json.encode( + { + "note": { + "noteId": widget.noteId, + "description": _note + } + } + ) + ).then((response) { + print(jsonDecode(response.body).toString()); + // print(json.decode(response.body).toString().substring(json.decode(response.body).toString().length-12,json.decode(response.body).toString().length)); + if((response.statusCode == 200) & (json.decode(response.body).toString().substring(json.decode(response.body).toString().length-13,json.decode(response.body).toString().length) == "Note Edited}}")) { + ScaffoldMessenger.of(context) + ..removeCurrentSnackBar() + ..showSnackBar(SnackBar(content: Text("Note Edited!"))); + Navigator.of(context).pop(); + } + else if((response.statusCode == 200) & (json.decode(response.body).toString().substring(0,14) == "{status: false")) { // Token Invalid + ScaffoldMessenger.of(context) + ..removeCurrentSnackBar() + ..showSnackBar(SnackBar(content: Text("Token Expired!"))); + final result = Navigator.push( + context, + MaterialPageRoute(builder: (context) => const Login(fromWhere:"Home")), + ); + } + else { + ScaffoldMessenger.of(context) + ..removeCurrentSnackBar() + ..showSnackBar(SnackBar(content: Text("Note not Edited!"))); + } + } + ); + } + + Future deleteNotesAPI() async { + SharedPreferences prefs = await SharedPreferences.getInstance(); + _token = prefs.getString('token')!; + final String editNotesAPI = "https://demo.pookidevs.com/quiz/notes/editNotes"; + http.post(Uri.parse(editNotesAPI), headers: { + 'Content-type': 'application/json; charset=UTF-8', 'Authorization' : _token.toString(), + }, body: json.encode( + { + "noteId": widget.noteId + } + ) + ).then((response) { + print(jsonDecode(response.body).toString()); + // print(json.decode(response.body).toString().substring(json.decode(response.body).toString().length-12,json.decode(response.body).toString().length)); + if((response.statusCode == 200) & (json.decode(response.body).toString().substring(json.decode(response.body).toString().length-14,json.decode(response.body).toString().length) == "Note Deleted}}")) { + ScaffoldMessenger.of(context) + ..removeCurrentSnackBar() + ..showSnackBar(SnackBar(content: Text("Note Deleted!"))); + Navigator.of(context).pop(); + } + else if((response.statusCode == 200) & (json.decode(response.body).toString().substring(0,14) == "{status: false")) { // Token Invalid + ScaffoldMessenger.of(context) + ..removeCurrentSnackBar() + ..showSnackBar(SnackBar(content: Text("Token Expired!"))); + final result = Navigator.push( + context, + MaterialPageRoute(builder: (context) => const Login(fromWhere:"Home")), + ); + } + else { + ScaffoldMessenger.of(context) + ..removeCurrentSnackBar() + ..showSnackBar(SnackBar(content: Text("Note not Deleted!"))); + } + } + ); + } + + Widget editNotes(BuildContext context) { + return SizedBox( + child: AlertDialog( + contentPadding: EdgeInsets.all(MediaQuery.of(context).size.width*(15/428)), + content: Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + 'Take Notes', + style: TextStyle( + color: Color(0xffB0A6C2), + fontFamily: 'Brandon-bld', + fontSize: (MediaQuery.of(context).size.height) * (18 / 926), + ), + ), + IconButton(icon:Icon(Icons.cancel),iconSize:23,color: Color(0xFF3F2668),onPressed: () { + Navigator.of(context).pop(); + },), + ], + ), + Divider(), + TextField( + controller: _textController, + keyboardType: TextInputType.multiline, + minLines: 1,//Normal textInputField will be displayed + maxLines: 5,// when user presses enter it will adapt to it + decoration: InputDecoration( + hintText: "Add notes here...", + hintStyle: TextStyle(color: Color(0xffAEAEAE), + fontSize: (MediaQuery.of(context).size.height)*(15/926), + fontFamily: 'Brandon-med',), + contentPadding: EdgeInsets.fromLTRB(2.0, 1, 2.0, 1), + focusedBorder: OutlineInputBorder( + borderSide: BorderSide( + color: Colors.transparent, + width: 0.0, + ), + ), + ), + style: TextStyle( + color: Colors.black, + fontSize: (MediaQuery.of(context).size.height)*(15/926), + fontFamily: 'Brandon-med', + ), + onChanged: (String value) { + setState(() { + _note = value; + }); + }, + ), + Row( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + IconButton(onPressed:(){ + setState((){ + _note=''; + _textController.clear(); + } + ); + } , iconSize: 21 ,icon: Icon(Icons.refresh,color: Color(0xFF3F2668))), + TextButton( + onPressed: () { + editNotesAPI(); + _textController.clear(); + }, + style: TextButton.styleFrom( + padding: EdgeInsets.zero,), + child: Container( + height: (MediaQuery.of(context).size.height) * (31 / 926), + width:(MediaQuery.of(context).size.width) * (97 / 428), + decoration: BoxDecoration(borderRadius:BorderRadius.circular(4),color: Color(0xFFDDDAE2),), + child:Row( + mainAxisAlignment: MainAxisAlignment.center, + children:[ + Icon(Icons.save,color: Color(0xFF3F2668),), + SizedBox( + height: (MediaQuery.of(context).size.width) * + (14 / 428), + ), + Text( + 'Save', + style: TextStyle( + color: Color(0xff3F2668), + fontFamily: 'Brandon-bld', + fontSize: (MediaQuery.of(context).size.height) * (19 / 926), + ), + ), + ]) + ),) + ], + ) + ], + ), + ),);} + + Widget deleteNote(BuildContext context) { + return SizedBox( + child: AlertDialog( + contentPadding: EdgeInsets.all(MediaQuery.of(context).size.width*(15/428)), + content: Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + 'Delete Note', + style: TextStyle( + color: Color(0xffB0A6C2), + fontFamily: 'Brandon-bld', + fontSize: (MediaQuery.of(context).size.height) * (18 / 926), + ), + ), + IconButton(icon:Icon(Icons.cancel),iconSize:23,color: Color(0xFF3F2668),onPressed: () { + Navigator.of(context).pop(); + },), + ], + ), + Divider(), + Text("Are you sure you want to delete this note?", + ), + ], + ), + actions: [ + Divider(), + Row( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + TextButton( + onPressed: () { + Navigator.of(context).pop(); + }, + child: Text('No', + style: TextStyle( + color: Color(0xff3F2668), + fontFamily: 'Brandon-bld', + fontSize: + (MediaQuery.of(context).size.height) * (21 / 926), + )), + ), + Divider(), + TextButton( + onPressed: () { + deleteNotesAPI(); + // print(questionsData["id"]![questionNumber].toString()); + // BookmarkQuestionAPI(); + }, + child: Text('Yes', + style: TextStyle( + color: Color(0xff3F2668), + fontFamily: 'Brandon-bld', + fontSize: + (MediaQuery.of(context).size.height) * (21 / 926), + )), + ), + ], + ), + ], + ), + ); + } + + @override + Widget build(BuildContext context) { + return WillPopScope( + onWillPop: () async { + ScaffoldMessenger.of(context) + ..removeCurrentSnackBar() + ..showSnackBar(SnackBar(content: Text("Press back button!"))); + return false; + }, + child: Scaffold( + backgroundColor: Color(0xffF8F9FB), + drawer: SideMenuBar(), + appBar: AppBar( + toolbarHeight: (MediaQuery.of(context).size.height) *(73.52/926), + backgroundColor: Color(0xff3F2668), + elevation: 2, + centerTitle: true, + flexibleSpace: Container( + decoration: const BoxDecoration( + gradient: LinearGradient( + begin: Alignment.topCenter, + end: Alignment.bottomCenter, + colors: [ + Color(0xff7F1AF1), + Color(0xff482384) + ]) + ), + ), + title: const Text("Notes", + style: TextStyle( + color: Color(0xffFFFEFE), + fontFamily: 'Brandon-bld', + ), + ), + actions: [ + TextButton( + onPressed: () async { + final result = await Navigator.push( + context, + MaterialPageRoute(builder: (context) => const Login(fromWhere:"Home")), + ); + }, + child: SvgPicture.asset( + "assets/Images/logout.svg", + height: (MediaQuery.of(context).size.height) *(32/926), + ), + ), + ], + ), + body: SingleChildScrollView( + padding: EdgeInsets.only(top:(MediaQuery.of(context).size.height) *(28/926), + bottom: (MediaQuery.of(context).size.height) *(28/926), + left: (MediaQuery.of(context).size.width) *(24/428), + right: (MediaQuery.of(context).size.width) *(24/428)), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text('Notes',style: TextStyle(color: Color(0xFF3F2668),fontFamily: 'Brandon-bld',fontSize: MediaQuery.of(context).size.height*20/926),), + SizedBox(height: (MediaQuery.of(context).size.height) *(10/926),), + Container( + height: (MediaQuery.of(context).size.height) *(488/926), + padding: EdgeInsets.all( (MediaQuery.of(context).size.height) *(25/926)), + decoration: BoxDecoration( + color: Color(0xffB0A6C2), + ), + child: Column( + children: [ + Container(height:(MediaQuery.of(context).size.height*380/926),child: Text(_note != null ? _note : widget.noteText,style: TextStyle(color: Color(0xFF3F2668),fontFamily: 'Brandon-med',fontSize: MediaQuery.of(context).size.height*18/926),)), + Row( + mainAxisAlignment:MainAxisAlignment.center,children: [ + GestureDetector( + onTap: () { + showDialog( + context: context, + builder: (BuildContext context) => + deleteNote(context), + ); + }, + child: Column( + children: [ + Container(decoration: BoxDecoration(shape: BoxShape.circle,color: Color(0xFF3F2668) ), + child: Padding( + padding: EdgeInsets.all(MediaQuery.of(context).size.height*5/926), + child: Icon(Icons.delete,size: MediaQuery.of(context).size.height*25/926,color: Colors.white,), + ),), + Text('Delete',style: TextStyle(color: Color(0xFF3F2668),fontFamily: 'Brandon-med',fontSize: MediaQuery.of(context).size.height*10/926)) + ], + ), + ), + SizedBox( + width: (MediaQuery.of(context).size.width) * (20 / 428), + ), + GestureDetector( + onTap: () { + showDialog( + context: context, + builder: (BuildContext context) => + editNotes(context), + ); + }, + child: Column( + children: [ + Container(decoration: BoxDecoration(shape: BoxShape.circle,color: Color(0xFF3F2668) ), + child: Padding( + padding: EdgeInsets.all(MediaQuery.of(context).size.height*5/926), + child: Icon(Icons.edit,size: MediaQuery.of(context).size.height*25/926,color: Colors.white,), + ),), + Text('Edit',style: TextStyle(color: Color(0xFF3F2668),fontFamily: 'Brandon-med',fontSize: MediaQuery.of(context).size.height*10/926)) + ], + ), + )],) + ], + ), + + ), + TextButton( + onPressed: () async { + Navigator.of(context) + .popUntil(ModalRoute.withName("/home")); + final result = await Navigator.push( + context, + MaterialPageRoute(builder: (context) => Notes()), + ); + }, + child: Row( + children: [ + Icon(Icons.arrow_back_ios_outlined, color: Color(0xFF3F2668), size: MediaQuery.of(context).size.height*(18/926),), + SizedBox(width: 3,), + Text('Back',style: TextStyle(color: Color(0xFF3F2668),fontFamily: 'Brandon-med',fontSize: MediaQuery.of(context).size.height*15/926)), + ], + ), + ) + ], + ), + ), + ), + ); + } +} diff --git a/lib/screens/Welcome/Notes/notes.dart b/lib/screens/Welcome/Notes/notes.dart new file mode 100644 index 0000000..86da528 --- /dev/null +++ b/lib/screens/Welcome/Notes/notes.dart @@ -0,0 +1,251 @@ +import 'dart:convert'; + +import 'package:flutter/material.dart'; +import 'package:flutter_svg/flutter_svg.dart'; +import 'package:shared_preferences/shared_preferences.dart'; +import 'package:testify/models/NotesModel/notes_model.dart'; +import 'package:testify/screens/Welcome/Notes/notesTile.dart'; +import 'package:http/http.dart' as http; + +import '../../Authentication/login.dart'; +import '../side_menu_bar.dart'; +class Notes extends StatefulWidget { + @override + _NotesState createState() => _NotesState(); +} + +class _NotesState extends State { + + bool _hasNotesDataLoaded = false; + + //Shared Pref + var _token; + var _userId; + + var _notesSuccessful; + + var _notesData = { + "idpsas_user_notes": [], + "question_id": [], + "user_id": [], + "quiz_id": [], + "notes": [], + "note_meta": [], + }; + + @override + void initState() { + super.initState(); + getNotes(); + } + + Future getNotes() async { + SharedPreferences prefs = await SharedPreferences.getInstance(); + final String NotesAPI = "https://demo.pookidevs.com/quiz/notes/getNotes"; + _token = prefs.getString('token')!; + _userId = prefs.getInt("userId")!; + http.get(Uri.parse(NotesAPI), headers: { + 'Content-type': 'application/json; charset=UTF-8', 'Authorization' : _token.toString(), + },).then((response) { + // print(jsonDecode(response.body)); + if(response.statusCode == 200) { + if(json.decode(response.body).toString().substring(0,20) == "{data: {status: true"){ + final responseString = (response.body); + var getNotes = notesModelFromJson(responseString); + final NotesModel getNotesSuccessful = getNotes; + setState(() { + _notesSuccessful = getNotesSuccessful; + }); + print(_notesSuccessful); + // print(_getPreviousQuizzesSuccessful.data.quizzes[0].quizId); + categorizeNotesData(); + } + } + else { + //Token is Invalid + ScaffoldMessenger.of(context) + ..removeCurrentSnackBar() + ..showSnackBar(SnackBar(content: Text("Token Expired!"))); + final result = Navigator.pushAndRemoveUntil( + context, + MaterialPageRoute(builder: (BuildContext context) => const Login(fromWhere:"Home")), + ModalRoute.withName('/'), + ); + } + } + ); + } + + categorizeNotesData() { + var noteMetaEntry = { + "noteTopic": "", + "noteSystem": "", + "noteSubject": "" + }; + String notesMetaString; + var decodeNotesMetaString; + int c = 0; + while((c<_notesSuccessful.data.notes.toList().length) & (_notesSuccessful.data.notes.toList().length > 0)) { + setState(() { + _notesData["idpsas_user_notes"]!.add(_notesSuccessful.data.notes[c].idpsasUserNotes); + _notesData["question_id"]!.add(_notesSuccessful.data.notes[c].questionId); + _notesData["user_id"]!.add(_notesSuccessful.data.notes[c].userId); + _notesData["quiz_id"]!.add(_notesSuccessful.data.notes[c].quizId); + _notesData["notes"]!.add(_notesSuccessful.data.notes[c].notes); + notesMetaString = _notesSuccessful.data.notes[c].noteMeta; + notesMetaString = notesMetaString.replaceAll("\\", ""); + decodeNotesMetaString = jsonDecode(notesMetaString); + noteMetaEntry["noteTopic"] = decodeNotesMetaString["noteTopic"]; + noteMetaEntry["noteSystem"] = decodeNotesMetaString["noteSystem"]; + noteMetaEntry["noteSubject"] = decodeNotesMetaString["noteSubject"]; + _notesData["note_meta"]!.add(noteMetaEntry); + }); + c++; + } + setState(() { + _hasNotesDataLoaded = true; + }); + print(_notesData); + } + + + @override + Widget build(BuildContext context) { + return Scaffold( + backgroundColor: Color(0xffF8F9FB), + drawer: SideMenuBar(), + appBar: AppBar( + toolbarHeight: (MediaQuery.of(context).size.height) *(73.52/926), + backgroundColor: Color(0xff3F2668), + elevation: 2, + centerTitle: true, + flexibleSpace: Container( + decoration: const BoxDecoration( + gradient: LinearGradient( + begin: Alignment.topCenter, + end: Alignment.bottomCenter, + colors: [ + Color(0xff7F1AF1), + Color(0xff482384) + ]) + ), + ), + title: const Text("Notes", + style: TextStyle( + color: Color(0xffFFFEFE), + fontFamily: 'Brandon-bld', + ), + ), + actions: [ + TextButton( + onPressed: () async { + final result = await Navigator.push( + context, + MaterialPageRoute(builder: (context) => const Login(fromWhere:"Home")), + ); + }, + child: SvgPicture.asset( + "assets/Images/logout.svg", + height: (MediaQuery.of(context).size.height) *(32/926), + ), + ), + ], + ), + body:SingleChildScrollView( + padding: EdgeInsets.only(top:(MediaQuery.of(context).size.height) *(15/926), + bottom: (MediaQuery.of(context).size.height) *(8/926), + left: (MediaQuery.of(context).size.width) *(18/428), + right: (MediaQuery.of(context).size.width) *(18/428)), + child: Column( + children: [ + Row( + children: [ + Container( + width: (MediaQuery.of(context).size.width) *(221/428), + //height: (MediaQuery.of(context).size.height) *(91/926), + child: Column( + children: [ + Align( + alignment: Alignment.topLeft, + child: Text("Notes", + style: TextStyle( + color: Color(0xff232323), + fontFamily: 'Brandon-bld', + fontSize: (MediaQuery.of(context).size.height) *(25/926),//38, + ),), + ), + SizedBox(height: (MediaQuery.of(context).size.height) *(2/926),), + Text("Lorem ipsum dolor sit amet, consectetur adipiscing elit. Cras imperdiet finibus elit non luctus. Morbi auctor mattis ante.", + style: TextStyle( + color: Color(0xFF483A3A), + fontFamily: 'Brandon-med', + fontSize: (MediaQuery.of(context).size.height) *(13/926),//38, + ),), + ], + ), + ), + SizedBox(width: (MediaQuery.of(context).size.width) *(39/428),), + Container( + //color: Colors.transparent, + child: SvgPicture.asset( + "assets/Images/notes_screen.svg", + height: (MediaQuery.of(context).size.height) *(100/926), + //width: (MediaQuery.of(context).size.width) *(132/428), + ), + ), + ], + ), + SizedBox(height: (MediaQuery.of(context).size.height)*(30/926),), + Padding( + padding: const EdgeInsets.all(8.0), + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + _hasNotesDataLoaded == false ? CircularProgressIndicator(color: Color(0xFF3F2668)) : + GridView.count(shrinkWrap:true,crossAxisCount: 2,crossAxisSpacing:(MediaQuery.of(context).size.width) *(68/428) ,mainAxisSpacing: (MediaQuery.of(context).size.height) *(41/926),childAspectRatio: 1,children: [ + for(int i = 0; i<_notesData["idpsas_user_notes"]!.length; i++) + NotesTile(noteId: _notesData["idpsas_user_notes"]![i], noteText: _notesData["notes"]![i]), + ],), + // SizedBox(height: (MediaQuery.of(context).size.height)*(92/926),), + // InkWell( + // child: Container( + // height: (MediaQuery.of(context).size.height) *(30/926), + // width: (MediaQuery.of(context).size.width) *(110/428), + // decoration: BoxDecoration( + // color: Color(0xff3F2668),//0xffB0A6C2, rgba(176, 166, 194, 1) + // borderRadius: BorderRadius.all(Radius.circular(2)), + // boxShadow: [ + // BoxShadow( + // color: Colors.black12,//Color(0xff00000029), + // spreadRadius: 2, + // blurRadius: 2, + // offset: Offset(0, 0), + // ), + // ], + // ), + // child: TextButton( + // onPressed: () { + // + // }, + // child: Center( + // child: Text("Show More", + // style: TextStyle( + // color: Colors.white, + // fontFamily: 'Brandon-med', + // fontSize: (MediaQuery.of(context).size.height) *(20/926) + // ), + // ), + // ), + // ), + // ), + // ), + ], + ), + ) + + ], + ), + ), + ); + } +} diff --git a/lib/screens/Welcome/Notes/notesTile.dart b/lib/screens/Welcome/Notes/notesTile.dart new file mode 100644 index 0000000..39b77d3 --- /dev/null +++ b/lib/screens/Welcome/Notes/notesTile.dart @@ -0,0 +1,42 @@ +import 'package:flutter/material.dart'; +import 'package:testify/screens/Welcome/Notes/noteDetails.dart'; +class NotesTile extends StatelessWidget { + final int noteId; + final String noteText; + NotesTile({required this.noteId,required this.noteText}); + @override + Widget build(BuildContext context) { + String substring; + if (noteText.length>100){substring=noteText.substring(0,100);} + else substring=noteText; + return InkWell( + onTap: ()async{ + await Navigator.push( + context, + MaterialPageRoute(builder: (context) => NoteDetails(noteId: noteId, noteText: noteText)), + ); + }, + child: Container( + padding: EdgeInsets.symmetric(vertical: MediaQuery.of(context).size.height*(20/926),horizontal:(MediaQuery.of(context).size.width) *(20/428) ), + height: MediaQuery.of(context).size.height*(137/926), + width:MediaQuery.of(context).size.height*(137/926) , + decoration: BoxDecoration(color: Color(0xff3F2668),borderRadius: BorderRadius.circular(MediaQuery.of(context).size.height*10/926)), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text('Note Id: '+noteId.toString(),style: TextStyle( + color: Color(0xffB0A6C2), + fontFamily: 'Brandon-med', + fontSize: (MediaQuery.of(context).size.height) *(15/926),//38, + ),), + Text(substring,textAlign:TextAlign.justify,style: TextStyle( + color: Colors.white70, + fontFamily: 'Brandon-med', + fontSize: (MediaQuery.of(context).size.height) *(13/926),//38, + ),) + ], + ), + ), + ); + } +} diff --git a/lib/screens/Welcome/PreviousQuiz/previous_quiz.dart b/lib/screens/Welcome/PreviousQuiz/previous_quiz.dart new file mode 100644 index 0000000..6523ef5 --- /dev/null +++ b/lib/screens/Welcome/PreviousQuiz/previous_quiz.dart @@ -0,0 +1,609 @@ + +import 'package:flutter/material.dart'; +import 'package:flutter_svg/flutter_svg.dart'; +import 'package:shared_preferences/shared_preferences.dart'; +import 'package:testify/models/GenerateQuizModels/get_system_categories_successful.dart'; +import 'package:testify/models/GenerateQuizModels/get_system_categories_unsuccessful.dart'; +import 'package:testify/models/GetPreviousQuizzesModel/get_previous_quizzes_model.dart'; +import 'package:testify/screens/Authentication/login.dart'; +import 'package:testify/screens/Welcome/PreviousQuiz/test_details.dart'; +import 'package:testify/screens/Welcome/PreviousQuiz/tile.dart'; +import '../side_menu_bar.dart'; +import 'package:http/http.dart' as http; +import 'dart:convert'; + +class PreviousQuiz extends StatefulWidget { + @override + _PreviousQuizState createState() => _PreviousQuizState(); +} + +class _PreviousQuizState extends State { + final filterList=['Filter By','Subjects','Systems','Topics']; + int filterIndex = 0; + String _currentfilter='Filter By'; + String _currentsubfilter='Filter By'; + int subFilterIndex = 0; + List subFilterList=['option1','option2']; + List subjectsSubFilterList = ["Select"]; + List systemsSubFilterList = ["Select"]; + List topicsSubFilterList = ["Select"]; + List filterSubFilterSelected = ["",""]; // 0: Filter, 1: SubFilter. + double? _swipeStartX; + String? _swipeDirection; + + bool hasPreviousQuizzesDataLoaded = false; + var previousQuizzesData = { + "quizId": [], + "name": [], + "score": [], + "date": [], + "status": [], + "questions": [], + "totalQuestions": [], + "subjects": [], + "systems": [], + "topics": [], + }; + + var previousQuizzesDataFiltered = { + "quizId": [], + "name": [], + "score": [], + "date": [], + "status": [], + "questions": [], + "totalQuestions": [], + "subjects": [], + "systems": [], + "topics": [], + }; + + //Shared Pref + var _token; + var _userId; + + // Token Valid + var _getSystemCategoriesSuccessful; + // Token Incorrect + var _getSystemCategoriesUnsuccessful; + + //Get Previous Quizzes + var _getPreviousQuizzesSuccessful; + + @override + void initState() { + super.initState(); + getPreviousQuizzes(); + getUserDataSST(); + } + + Future getPreviousQuizzes() async { + SharedPreferences prefs = await SharedPreferences.getInstance(); + final String apiUrlSystemCategories = "https://demo.pookidevs.com/quiz/generator/getPreviousQuizzes"; + _token = prefs.getString('token')!; + _userId = prefs.getInt("userId")!; + http.get(Uri.parse(apiUrlSystemCategories), headers: { + 'Content-type': 'application/json; charset=UTF-8', 'Authorization' : _token.toString(), + },).then((response) { + // print(jsonDecode(response.body)); + if(response.statusCode == 200) { + if(json.decode(response.body).toString().substring(0,20) == "{data: {status: true"){ + final responseString = (response.body); + var getPrevQuiz = getPreviousQuizzesModelFromJson(responseString); + final GetPreviousQuizzesModel getPreviousQuizzesSuccessful = getPrevQuiz; + setState(() { + _getPreviousQuizzesSuccessful = getPreviousQuizzesSuccessful; + }); + // print(_getPreviousQuizzesSuccessful.data.quizzes[0].quizId); + categorizePreviousQuizzesData(); + } + } + else { + //Token is Invalid + ScaffoldMessenger.of(context) + ..removeCurrentSnackBar() + ..showSnackBar(SnackBar(content: Text("Token Expired!"))); + final result = Navigator.push( + context, + MaterialPageRoute(builder: (context) => const Login(fromWhere:"Home")), + ); + } + } + ); + } + + categorizePreviousQuizzesData() { + int c = 0; + while((c<_getPreviousQuizzesSuccessful.data.quizzes.toList().length) & (_getPreviousQuizzesSuccessful.data.quizzes.toList().length > 0)) { + setState(() { + previousQuizzesData["quizId"]!.add(_getPreviousQuizzesSuccessful.data.quizzes[c].quizId); + previousQuizzesData["name"]!.add(_getPreviousQuizzesSuccessful.data.quizzes[c].name); + previousQuizzesData["score"]!.add(_getPreviousQuizzesSuccessful.data.quizzes[c].score); + previousQuizzesData["date"]!.add(_getPreviousQuizzesSuccessful.data.quizzes[c].date); + previousQuizzesData["status"]!.add(_getPreviousQuizzesSuccessful.data.quizzes[c].status); + previousQuizzesData["questions"]!.add(_getPreviousQuizzesSuccessful.data.quizzes[c].questions); + previousQuizzesData["totalQuestions"]!.add(_getPreviousQuizzesSuccessful.data.quizzes[c].totalQuestions); + previousQuizzesData["subjects"]!.add(_getPreviousQuizzesSuccessful.data.quizzes[c].subjects); + previousQuizzesData["systems"]!.add(_getPreviousQuizzesSuccessful.data.quizzes[c].systems); + previousQuizzesData["topics"]!.add(_getPreviousQuizzesSuccessful.data.quizzes[c].topics); + }); + c++; + } + setState(() { + hasPreviousQuizzesDataLoaded = true; + }); + // print(previousQuizzesData); + } + + applyingPreviousQuizzesFilters() { + setState(() { + previousQuizzesDataFiltered["quizId"] = []; + previousQuizzesDataFiltered["name"] = []; + previousQuizzesDataFiltered["score"] = []; + previousQuizzesDataFiltered["date"] = []; + previousQuizzesDataFiltered["status"] = []; + previousQuizzesDataFiltered["questions"] = []; + previousQuizzesDataFiltered["totalQuestions"] = []; + previousQuizzesDataFiltered["subjects"] = []; + previousQuizzesDataFiltered["systems"] = []; + previousQuizzesDataFiltered["topics"] = []; + }); + if(filterSubFilterSelected[0] == "Subjects") { + for(int j = 0; j getUserDataSST() async { + SharedPreferences prefs = await SharedPreferences.getInstance(); + final String apiUrlSystemCategories = "https://demo.pookidevs.com/quiz/generator/getAllCategories"; + _token = prefs.getString('token')!; + _userId = prefs.getInt("userId")!; + // print(_userId); + // print(_token); + http.get(Uri.parse(apiUrlSystemCategories), headers: { + 'Content-type': 'application/json; charset=UTF-8', 'Authorization' : _token.toString(), + },).then((response) { + // print(jsonDecode(response.body).toString()); + if(response.statusCode == 200) { + if(json.decode(response.body).toString().substring(0,20) == "{data: {status: true") { + final responseString = (response.body); + var systemCategoriesDataSuccessful = getSystemCategoriesSuccessfulModelFromJson(responseString); + final GetSystemCategoriesSuccessfulModel getSystemCategoriesSuccessful = systemCategoriesDataSuccessful; + setState(() { + _getSystemCategoriesSuccessful = getSystemCategoriesSuccessful; + }); + // print(_questions); + } else { + + } + //Adds data to lists + categorizeUserData(); + } + else { // Status Code is 401 here that is why if written in the above if statement it would not work. + //Token is Invalid + if(json.decode(response.body).toString().substring(0,14) == "{status: false") { + final responseString = (response.body); + var systemCategoriesDataUnsuccessful = getSystemCategoriesUnsuccessfulModelFromJson(responseString); + final GetSystemCategoriesUnsuccessfulModel getSystemCategoriesUnsuccessful = systemCategoriesDataUnsuccessful; + setState(() { + _getSystemCategoriesUnsuccessful = getSystemCategoriesUnsuccessful; + }); + print(_getSystemCategoriesUnsuccessful.msg); + ScaffoldMessenger.of(context) + ..removeCurrentSnackBar() + ..showSnackBar(SnackBar(content: Text("Token Expired!"))); + final result = Navigator.push( + context, + MaterialPageRoute(builder: (context) => const Login(fromWhere:"Home")), + ); + } + else { + + } + } + } + ); + } + + //Add data to lists. Only done the first time. + categorizeUserData() { + //To clear any past data + int c = 0; + while((c<_getSystemCategoriesSuccessful.data.categories.toList().length) & (_getSystemCategoriesSuccessful.data.categories.toList().length > 0)) { + var tempLength = _getSystemCategoriesSuccessful.data.categories.toList().length; + if(_getSystemCategoriesSuccessful.data.categories[c].subCategories != null) { + if(_getSystemCategoriesSuccessful.data.categories[c].parentCategory.toString() == "systems") { + //Gets the length of subjects(Number of Subjects) + var lenSystems = _getSystemCategoriesSuccessful.data.categories[c].subCategories.toList().length; + int i = 0; + setState(() { + while((lenSystems>0) & (i0) & (i0) & (i[ + Color(0xff7F1AF1), + Color(0xff482384) + ]) + ), + ), + title: const Text("Previous Quiz", + style: TextStyle( + color: Color(0xffFFFEFE), + fontFamily: 'Brandon-bld', + ), + ), + actions: [ + TextButton( + onPressed: () async { + final result = await Navigator.push( + context, + MaterialPageRoute(builder: (context) => const Login(fromWhere:"Home")), + ); + }, + child: SvgPicture.asset( + "assets/Images/logout.svg", + height: (MediaQuery.of(context).size.height) *(32/926), + ), + ), + ], + ), + body: SingleChildScrollView( + child: Container( + padding: EdgeInsets.only(top:(MediaQuery.of(context).size.height) *(15/926), + bottom: (MediaQuery.of(context).size.height) *(8/926), + left: (MediaQuery.of(context).size.width) *(18/428), + right: (MediaQuery.of(context).size.width) *(18/428)), + child: Column( + children: [ + Row( + children: [ + Container( + width: (MediaQuery.of(context).size.width) *(221/428), + //height: (MediaQuery.of(context).size.height) *(91/926), + child: Column( + children: [ + Align( + alignment: Alignment.topLeft, + child: Text("Previous Quiz", + style: TextStyle( + color: Color(0xff232323), + fontFamily: 'Brandon-bld', + fontSize: (MediaQuery.of(context).size.height) *(25/926),//38, + ),), + ), + SizedBox(height: (MediaQuery.of(context).size.height) *(2/926),), + Text("Lorem ipsum dolor sit amet, consectetur adipiscing elit. Cras imperdiet finibus elit non luctus. Morbi auctor mattis ante.", + style: TextStyle( + color: Color(0xFF483A3A), + fontFamily: 'Brandon-med', + fontSize: (MediaQuery.of(context).size.height) *(13/926),//38, + ),), + ], + ), + ), + SizedBox(width: (MediaQuery.of(context).size.width) *(39/428),), + Container( + //color: Colors.transparent, + child: SvgPicture.asset( + "assets/Images/prevQuiz.svg", + height: (MediaQuery.of(context).size.height) *(100/926), + //width: (MediaQuery.of(context).size.width) *(132/428), + ), + ), + ], + ), + SizedBox(height: (MediaQuery.of(context).size.height)*(30/926),), + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Row( + children: [ + Text("Filter By: ", + style: TextStyle( + color: Color(0xFF483A3A), + fontFamily: 'Brandon-med', + fontSize: (MediaQuery.of(context).size.height) *(16/926),//38, + ),), + DropdownButton( + value: filterList[filterIndex], + underline: Container(), + iconEnabledColor: Color(0xff3F2668), + dropdownColor:Colors.white , + onChanged: (newValue) { + setState(() { + // print(newValue); + _currentfilter = newValue as String; + if(_currentfilter == filterList[1]){ + filterIndex = 1; + subFilterIndex = 0; + subFilterList = subjectsSubFilterList;} + else if(_currentfilter == filterList[2]){ + filterIndex = 2; + subFilterIndex = 0; + subFilterList = systemsSubFilterList;} + else if(_currentfilter == filterList[3]){ + filterIndex = 3; + subFilterIndex = 0; + subFilterList = topicsSubFilterList;} + else if(_currentfilter == filterList[0]){ + filterIndex = 0; + subFilterIndex = 0;} + filterSubFilterSelected[0] = _currentfilter; + applyingPreviousQuizzesFilters(); + // print(filterSubFilterSelected); + }); + }, + items: filterList.map((filter){ + return DropdownMenuItem( + child: Text(filter,style: TextStyle( + color: Color(0xff3F2668), + fontFamily: 'Brandon-bld', + fontSize: + (MediaQuery.of(context).size.height) * (16 / 926), + ),), + value: filter, + ); + }).toList(), + + + ), + ], + ), + // This below row is just for the if statement + if(_currentfilter != "Filter By") + Row( + children: [ + //SizedBox(width: (MediaQuery.of(context).size.width)*(40/428),), + Text(_currentfilter + ": ", + style: TextStyle( + color: Color(0xFF483A3A), + fontFamily: 'Brandon-med', + fontSize: (MediaQuery.of(context).size.height) *(16/926),//38, + ),), + DropdownButton( + value: (subFilterList.length<(subFilterIndex+1)) ? subFilterList[0] : subFilterList[subFilterIndex], + underline: Container(), + iconEnabledColor: Color(0xff3F2668), + dropdownColor:Colors.white , + onChanged: (newValue) { + setState(() { + // print(newValue); + subFilterIndex = 0; + _currentsubfilter = newValue as String; + for(int i = 0; i _swipeStartX!) ? "Right" : "Left"; + }, + onHorizontalDragEnd: (e) async { + if (_swipeDirection == "Right") + print("left"); + else if (_swipeDirection == "Left") { + print(previousQuizzesDataFiltered["system"]![i].toString()); + // final result = await Navigator.push( + // context, + // MaterialPageRoute( + // builder: (context) => TestDetails( + // quizId: previousQuizzesData["quizId"]![i], + // system: previousQuizzesData["system"]![i], + // subject: previousQuizzesData["subject"]![i], + // topic: previousQuizzesData["topic"]![i], + // score: previousQuizzesData["score"]![i], + // status: previousQuizzesData["status"]![i]))); + } + },), + ], + ) : + Column( + children: [ + SizedBox(height: (MediaQuery.of(context).size.height)*(30/926),), + GestureDetector(child: Tile( + name: previousQuizzesData["name"]![i], + quizId: previousQuizzesData["quizId"]![i], + status: previousQuizzesData["status"]![i], + score: previousQuizzesData["score"]![i], + systems: previousQuizzesData["systems"]![i], + questions: previousQuizzesData["questions"]![i], + date: previousQuizzesData["date"]![i], + topics: previousQuizzesData["topics"]![i], + subjects: previousQuizzesData["subjects"]![i], + totalQuestions: previousQuizzesData["totalQuestions"]![i],), + onHorizontalDragStart: (e) { + _swipeStartX = e.globalPosition.dx; + }, + onHorizontalDragUpdate: (e) { + _swipeDirection = + (e.globalPosition.dx > _swipeStartX!) ? "Right" : "Left"; + }, + onHorizontalDragEnd: (e) async { + if (_swipeDirection == "Right") + print("left"); + else if (_swipeDirection == "Left") { + print(previousQuizzesData["system"]![i].toString()); + // final result = await Navigator.push( + // context, + // MaterialPageRoute( + // builder: (context) => TestDetails( + // quizId: previousQuizzesData["quizId"]![i], + // system: previousQuizzesData["system"]![i], + // subject: previousQuizzesData["subject"]![i], + // topic: previousQuizzesData["topic"]![i], + // score: previousQuizzesData["score"]![i], + // status: previousQuizzesData["status"]![i]))); + } + },), + ], + ), + SizedBox(height: (MediaQuery.of(context).size.height)*(30/926),), + + ], + ), + ), + ), + ); + } +} diff --git a/lib/screens/Welcome/PreviousQuiz/test_details.dart b/lib/screens/Welcome/PreviousQuiz/test_details.dart new file mode 100644 index 0000000..ac2df98 --- /dev/null +++ b/lib/screens/Welcome/PreviousQuiz/test_details.dart @@ -0,0 +1,482 @@ +import 'dart:convert'; + +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_svg/svg.dart'; +import 'package:shared_preferences/shared_preferences.dart'; +import 'package:testify/models/GetPreviousQuizzesModel/ResumeQuiz/resume_quiz_model.dart'; +import 'package:testify/screens/Welcome/PreviousQuiz/previous_quiz.dart'; +import 'package:http/http.dart' as http; +import 'package:testify/screens/Welcome/QuizModule/quiz_module.dart'; +import '../../Authentication/login.dart'; +import '../side_menu_bar.dart'; + +class TestDetails extends StatefulWidget { + final int quizId; + final List system; + final List subject; + final List topic; + final String status; + final String score; + TestDetails( + {required this.quizId, + required this.system, + required this.subject, + required this.topic, + required this.status, + required this.score}); + + @override + State createState() => _TestDetailsState(); +} + +class _TestDetailsState extends State { + var _token; + var _userId; + var _resumeQuizSuccessful; + bool _isResumeQuizLoading = true; + + @override + void initState() { + super.initState(); + ResumeQuizAPI(); + } + + Future ResumeQuizAPI() async { + SharedPreferences prefs = await SharedPreferences.getInstance(); + final String apiUrlGenerateQuiz = "https://demo.pookidevs.com/quiz/solver/resumeQuiz"; + _token = prefs.getString('token')!; + print(_token); + _userId = prefs.getInt("userId")!; + http.post(Uri.parse(apiUrlGenerateQuiz), headers: { + 'Content-type': 'application/json; charset=UTF-8', 'Authorization' : _token.toString(), + }, body: json.encode( + { + "quizId": widget.quizId + }) + ).then((response) { + // print(jsonDecode(response.body).toString()); + if((response.statusCode == 200) & (json.decode(response.body).toString().substring(0,14) != "{status: false")) { + final responseString = (response.body); + var resumeQuizSuccessful1 = resumeQuizModelFromJson(responseString); + final ResumeQuizModel resumeQuizSuccessful = resumeQuizSuccessful1; + setState(() { + _resumeQuizSuccessful = resumeQuizSuccessful; + _isResumeQuizLoading = false; + // print(_resumeQuizSuccessful.data.previousQuizzes[0].quizMeta.quizMode); + // print(_resumeQuizSuccessful.data.previousQuizzes[0].quizMeta.quizTotalQuestions); + // print(_resumeQuizSuccessful.data.previousQuizzes[0].quizMeta.quizQuestions); + // print(_resumeQuizSuccessful.data.previousQuizzes[0].quizMeta.quizStatus); + // print(_resumeQuizSuccessful.data.previousQuizzes[0].quizMeta.isTimed); + // print(_resumeQuizSuccessful.data.previousQuizzes[0].quizMeta.quizId.runtimeType); + // print(_resumeQuizSuccessful.data.previousQuizzes[0].quizMeta.quizScore.runtimeType); + // _quizId = _getGenerateQuizSuccessful.data.quizId; + // print(_quizId); + }); + // categoriesGenerateQuizData(); + } + else { // Token Invalid + + } + } + ); + } + + @override + Widget build(BuildContext context) { + return Scaffold( + backgroundColor: Color(0xffF8F9FB), + drawer: SideMenuBar(), + appBar: AppBar( + toolbarHeight: (MediaQuery.of(context).size.height) * (73.52 / 926), + backgroundColor: Color(0xff3F2668), + elevation: 2, + centerTitle: true, + flexibleSpace: Container( + decoration: const BoxDecoration( + gradient: LinearGradient( + begin: Alignment.topCenter, + end: Alignment.bottomCenter, + colors: [Color(0xff7F1AF1), Color(0xff482384)])), + ), + title: const Text( + "Test Details", + style: TextStyle( + color: Color(0xffFFFEFE), + fontFamily: 'Brandon-bld', + ), + ), + actions: [ + TextButton( + onPressed: () async { + final result = await Navigator.push( + context, + MaterialPageRoute( + builder: (context) => const Login(fromWhere: "Home")), + ); + }, + child: SvgPicture.asset( + "assets/Images/logout.svg", + height: (MediaQuery.of(context).size.height) * (32 / 926), + ), + ), + ], + ), + body: SingleChildScrollView( + child: Padding( + padding: const EdgeInsets.symmetric(vertical: 100), + child: Column( + children: [ + Center( + child: Container( + // height: (MediaQuery.of(context).size.height) * (488 / 926), + width: (MediaQuery.of(context).size.width) * (385 / 428), + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(2), + color: Colors.white, + boxShadow: [ + BoxShadow(color: Colors.grey, offset: Offset(0, 4), blurRadius: 6) + ], + ), + child: Column( + children: [ + + Container( + height: (MediaQuery.of(context).size.height) * (59 / 926), + width: (MediaQuery.of(context).size.width) * (385 / 428), + color: Color(0xff6D5A8D), + child: Center( + child: Text( + 'Test Details', + style: TextStyle( + color: Colors.white, + fontFamily: 'Brandon-bld', + fontSize: (MediaQuery.of(context).size.height) * (20 / 926), + ), + ), + ), + ), + Container( + // height: (MediaQuery.of(context).size.height) * (310 / 926), + width: (MediaQuery.of(context).size.width) * (385 / 428), + padding: EdgeInsets.all(25), + child: Table( + columnWidths: {0:FixedColumnWidth((MediaQuery.of(context).size.width) * (25 / 428)), + 1:FixedColumnWidth((MediaQuery.of(context).size.width) * (200 / 428))}, + border: TableBorder.all(color: Colors.transparent), + children: [ + TableRow(children: [ + Padding( + padding: const EdgeInsets.only(top:8.0), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + 'Quiz ID:', + style: TextStyle( + color: Color(0xff3F2668), + fontFamily: 'Brandon-bld', + fontSize: (MediaQuery.of(context).size.height) * + (16 / 926), + ), + ), + ], + ), + ), + Padding( + padding: const EdgeInsets.only(top:8.0), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text(widget.quizId.toString(), + textAlign: TextAlign.start, + style: TextStyle( + color: Colors.black, + fontFamily: 'Brandon-med', + fontSize: (MediaQuery.of(context).size.height) * + (16 / 926), + )) + ], + ), + ) + ]), + TableRow(children: [ + Padding( + padding: const EdgeInsets.only(top:8.0), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + 'System:', + style: TextStyle( + color: Color(0xff3F2668), + fontFamily: 'Brandon-bld', + fontSize: (MediaQuery.of(context).size.height) * + (16 / 926), + ), + ), + ], + ), + ), + Padding( + padding: const EdgeInsets.only(top:8.0), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text(widget.system.toString().substring(1, widget.system.toString().length-1) == "" ? "-" : widget.system.toString().substring(1, widget.system.toString().length-1), + style: TextStyle( + color: Colors.black, + fontFamily: 'Brandon-med', + fontSize: (MediaQuery.of(context).size.height) * + (16 / 926), + )) + ], + ), + ) + ]), + TableRow(children: [ + Padding( + padding: const EdgeInsets.only(top:8.0), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + 'Subject:', + style: TextStyle( + color: Color(0xff3F2668), + fontFamily: 'Brandon-bld', + fontSize: (MediaQuery.of(context).size.height) * + (16 / 926), + ), + ), + ], + ), + ), + Padding( + padding: const EdgeInsets.only(top:8.0), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text(widget.subject.toString().substring(1, widget.subject.toString().length-1) == "" ? "-" : widget.subject.toString().substring(1, widget.subject.toString().length-1), + style: TextStyle( + color: Colors.black, + fontFamily: 'Brandon-med', + fontSize: (MediaQuery.of(context).size.height) * + (16 / 926), + )) + ], + ), + ) + ]), + TableRow(children: [ + Padding( + padding: const EdgeInsets.only(top:8.0), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + 'Topic:', + style: TextStyle( + color: Color(0xff3F2668), + fontFamily: 'Brandon-bld', + fontSize: (MediaQuery.of(context).size.height) * + (16 / 926), + ), + ), + ], + ), + ), + Padding( + padding: const EdgeInsets.only(top:8.0), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text(widget.topic.toString().substring(1, widget.topic.toString().length-1) == "" ? "-" : widget.topic.toString().substring(1, widget.topic.toString().length-1), + style: TextStyle( + color: Colors.black, + fontFamily: 'Brandon-med', + fontSize: (MediaQuery.of(context).size.height) * + (16 / 926), + )) + ], + ), + ) + ]), + TableRow(children: [ + Padding( + padding: const EdgeInsets.only(top:8.0), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + 'Score:', + style: TextStyle( + color: Color(0xff3F2668), + fontFamily: 'Brandon-bld', + fontSize: (MediaQuery.of(context).size.height) * + (16 / 926), + ), + ), + ], + ), + ), + Padding( + padding: const EdgeInsets.only(top:8.0), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text(widget.score, + style: TextStyle( + color: Colors.black, + fontFamily: 'Brandon-med', + fontSize: (MediaQuery.of(context).size.height) * + (16 / 926), + )) + ], + ), + ) + ]), + TableRow(children: [ + Padding( + padding: const EdgeInsets.only(top:8.0), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + 'Status:', + style: TextStyle( + color: Color(0xff3F2668), + fontFamily: 'Brandon-bld', + fontSize: (MediaQuery.of(context).size.height) * + (16 / 926), + ), + ), + ], + ), + ), + Padding( + padding: const EdgeInsets.only(top:8.0), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text(widget.status, + style: TextStyle( + color: Colors.black, + fontFamily: 'Brandon-med', + fontSize: (MediaQuery.of(context).size.height) * + (16 / 926), + )) + ], + ), + ) + ]) + ], + ), + ), + + Container( + height: (MediaQuery.of(context).size.height) * (70 / 926), + width: (MediaQuery.of(context).size.width) * (385 / 428), + child: _isResumeQuizLoading ? Center(child: CircularProgressIndicator(color: Color(0xff7F1AF1),)) : Row( + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + children: [ + Column( + children: [ + Container(height:40,width:40,decoration: BoxDecoration(color: Color(0xff7F1AF1),borderRadius: BorderRadius.circular(20)), + child: Icon(Icons.show_chart_outlined,size: 20,color:Colors.white)) + ,Text('Test Analysis',style: TextStyle( + color: Color(0xff7F1AF1), + fontFamily: 'Brandon-med', + fontSize: (MediaQuery.of(context).size.height) * (15 / 926), + ),) + ], + ), + Column( + children: [ + Container(height:40,width:40,decoration: BoxDecoration(color: Color(0xff7F1AF1),borderRadius: BorderRadius.circular(20)), + child: Icon(Icons.event_note_outlined,size: 20,color:Colors.white)) + ,Text('Test Results',style: TextStyle( + color: Color(0xff7F1AF1), + fontFamily: 'Brandon-med', + fontSize: (MediaQuery.of(context).size.height) * (15 / 926), + ),) + ], + ), + GestureDetector( + onTap: () async { + if(_resumeQuizSuccessful.data.previousQuizzes[0].quizMeta.quizStatus == "suspended") { + // print(_resumeQuizSuccessful.data.previousQuizzes[0].quizMeta.quizMode); + // print(_resumeQuizSuccessful.data.previousQuizzes[0].quizMeta.quizTotalQuestions); + // print(_resumeQuizSuccessful.data.previousQuizzes[0].quizMeta.quizQuestions); + // print(_resumeQuizSuccessful.data.previousQuizzes[0].quizMeta.isTimed); + SharedPreferences prefs = await SharedPreferences.getInstance(); + prefs.setInt("quizId", widget.quizId); + List _quizQuestions = []; + for(int i = 0; i<_resumeQuizSuccessful.data.questions.length; i++) { + _quizQuestions.add(_resumeQuizSuccessful.data.questions[i].id); + } + + // Navigator.of(context) + // .popUntil(ModalRoute.withName("/home")); + final result = Navigator.push( + context, + MaterialPageRoute(builder: (context) => QuizModule(totalQuestions: _resumeQuizSuccessful.data.previousQuizzes[0].quizMeta.quizTotalQuestions, + questions: _quizQuestions, + timedMode: _resumeQuizSuccessful.data.previousQuizzes[0].quizMeta.isTimed, + mode: _resumeQuizSuccessful.data.previousQuizzes[0].quizMeta.quizMode.toString(), + whatsDone: "resumed",)), + ); + } + }, + child: Column( + children: [ + Container(height:40,width:40,decoration: BoxDecoration(color: Color(0xff7F1AF1),borderRadius: BorderRadius.circular(20)), + child: Icon(Icons.arrow_right,size: 40,color:Colors.white)) + ,Text(_resumeQuizSuccessful.data.previousQuizzes[0].quizMeta.quizStatus == "suspended" ? 'Resume' : 'Review',style: TextStyle( + color: Color(0xff7F1AF1), + fontFamily: 'Brandon-med', + fontSize: (MediaQuery.of(context).size.height) * (15 / 926), + ),) + ], + ), + ), + ], + ), + ) + + ], + ), + ), + ), + Padding( + padding: const EdgeInsets.all(20.0), + child: InkWell( + onTap:() async { + // Navigator.of(context).pop(); + Navigator.of(context) + .popUntil(ModalRoute.withName("/home")); + final result = await Navigator.push( + context, + MaterialPageRoute(builder: (context) => PreviousQuiz()), + ); + }, + child:Container( + child: Row( + children: [Icon(Icons.arrow_back,color: Color(0xff7F1AF1),size: 15,),Text('Back',style: TextStyle( + color: Color(0xff7F1AF1), + fontFamily: 'Brandon-bld', + fontSize: (MediaQuery.of(context).size.height) * + (13 / 926), + ),)], + + ), + )), + ) + ], + ), + ), + ), + ); + + } +} diff --git a/lib/screens/Welcome/PreviousQuiz/tile.dart b/lib/screens/Welcome/PreviousQuiz/tile.dart new file mode 100644 index 0000000..3b4e78f --- /dev/null +++ b/lib/screens/Welcome/PreviousQuiz/tile.dart @@ -0,0 +1,137 @@ +import 'package:flutter/material.dart'; +import 'package:testify/screens/Welcome/PreviousQuiz/test_details.dart'; + +class Tile extends StatelessWidget { + final String name; + final int quizId; + final String status; + final String score; + final String date; + final List questions; + final String totalQuestions; + final List subjects; + final List systems; + final List topics; + Tile({required this.name, required this.quizId, required this.status, required this.score, required this.totalQuestions, required this.questions, required this.date, required this.subjects, required this.systems, required this.topics}); + @override + Widget build(BuildContext context) { + return Container( + height: (MediaQuery.of(context).size.height) * (84 / 926), + width: (MediaQuery.of(context).size.width) * (385 / 428), + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(2), + color: Colors.white, + boxShadow: [ + BoxShadow(color: Colors.grey, offset: Offset(0, 4), blurRadius: 6) + ], + ), + child: Row( + children: [ + Container( + height: (MediaQuery.of(context).size.height) * (84 / 926), + width: (MediaQuery.of(context).size.width) * (87 / 428), + color: Color(0xff6D5A8D), + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Text( + 'Quiz ID', + style: TextStyle( + color: Colors.white, + fontFamily: 'Brandon-bld', + fontSize: + (MediaQuery.of(context).size.height) * (18 / 926), + ), + ), + Text(quizId.toString(), + style: TextStyle( + color: Colors.white, + fontFamily: 'Brandon-med', + fontSize: + (MediaQuery.of(context).size.height) * (17 / 926), + )) + ], + )), + Container( + height: (MediaQuery.of(context).size.height) * (84 / 926), + width: (MediaQuery.of(context).size.width) * (248 / 428), + color: Colors.white, + padding: EdgeInsets.all( + (MediaQuery.of(context).size.height) * (16 / 926)), + child: Column( + children: [ + Row( + children: [ + Icon( + Icons.sticky_note_2_rounded, + color: Colors.grey, + ), + SizedBox( + width: (MediaQuery.of(context).size.width) * (12 / 428), + ), + Text( + (name.length >= 22) ? name.substring(0, 22) : name, + style: TextStyle( + color: Colors.black, + fontFamily: 'Brandon-med', + fontSize: + (MediaQuery.of(context).size.height) * (18 / 926), + ), + ) + ], + ), + Divider( + height: 1.5, + ), + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + score + ' / ' + totalQuestions, + style: TextStyle( + color: Color(0xff6C63FF), + fontFamily: 'Brandon-med', + fontSize: + (MediaQuery.of(context).size.height) * (14 / 926), + ), + ), + Text( + status, + style: TextStyle( + color: Color(0xff6C63FF), + fontFamily: 'Brandon-med', + fontSize: + (MediaQuery.of(context).size.height) * (14 / 926), + ), + ), + ], + ) + ], + ), + ), + Container( + height: (MediaQuery.of(context).size.height) * (84 / 926), + width: (MediaQuery.of(context).size.width) * (50 / 428), + color: Colors.white, + child: IconButton( + icon: Icon(Icons.arrow_right, + color: Color(0xff6D5A8D), + size: (MediaQuery.of(context).size.height) * (60 / 926)), + onPressed: () async { + Navigator.of(context).pop(); + final result = await Navigator.push( + context, + MaterialPageRoute( + builder: (context) => TestDetails( + quizId: quizId, + system: systems, + subject: subjects, + topic: topics, + score: score, + status: status))); + })), + ], + ), + ); + } +} diff --git a/lib/screens/Welcome/QuizModule/buttons.dart b/lib/screens/Welcome/QuizModule/buttons.dart new file mode 100644 index 0000000..55e4e7c --- /dev/null +++ b/lib/screens/Welcome/QuizModule/buttons.dart @@ -0,0 +1,55 @@ +import 'package:flutter/material.dart'; + +// creating Stateless Widget for buttons +class MyButton extends StatelessWidget { + +// declaring variables + final color; + final textColor; + final String buttonText; + final buttontapped; + +//Constructor + MyButton({this.color, this.textColor, required this.buttonText, this.buttontapped}); + + @override + Widget build(BuildContext context) { + return Scaffold( + body: GestureDetector( + onTap: buttontapped, + child: Center( + child: Container( + height: 35, + width: 35, + decoration: BoxDecoration( + color: Colors.white, + boxShadow: [ + BoxShadow( + offset: Offset(0, 4), + blurRadius: 6, + color: Colors.black45//Color(0xFFF9F8F9), // background color + ), + ], + borderRadius: BorderRadius.circular(5), + ), + + child: Center( + child: Text( + buttonText, + style: TextStyle( + color: Colors.black, + fontFamily: 'Brandon-bld', + fontSize: (MediaQuery.of(context).size.height*(20/926)), + fontWeight: FontWeight.bold, + ), + ), + ), + ), + ), + ), + + + ); + } +} + diff --git a/lib/screens/Welcome/QuizModule/calculator.dart b/lib/screens/Welcome/QuizModule/calculator.dart new file mode 100644 index 0000000..d7529cb --- /dev/null +++ b/lib/screens/Welcome/QuizModule/calculator.dart @@ -0,0 +1,179 @@ +import 'package:flutter/material.dart'; +import 'buttons.dart'; +import 'package:math_expressions/math_expressions.dart'; +class Calculator extends StatefulWidget { + @override + _CalculatorState createState() => _CalculatorState(); +} + +class _CalculatorState extends State { + var userInput = ''; + var answer = ''; + final List buttons = [ + '7', + '8', + '9', + '%', + 'C', + '4', + '5', + '6', + 'x', + 'DEL', + '1', + '2', + '3', + '+', + '/', + '.', + '0', + '=', + '-', + + ]; + bool isOperator(String x) { + if (x == '/' || x == 'x' || x == '-' || x == '+' || x == '=') { + return true; + } + return false; + } +// function to calculate the input operation + void equalPressed() { + String finaluserinput = userInput; + finaluserinput = userInput.replaceAll('x', '*'); + + Parser p = Parser(); + Expression exp = p.parse(finaluserinput); + ContextModel cm = ContextModel(); + double eval = exp.evaluate(EvaluationType.REAL, cm); + answer = eval.toString(); + } + @override + Widget build(BuildContext context) { + return AlertDialog( + content: SizedBox( + height: (MediaQuery.of(context).size.height)*(310/926), + width: (MediaQuery.of(context).size.width)*(237/428), + child: Container( + padding: EdgeInsets.all(0), + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(5), + color: Colors.white + ), + child: Column( + children: [ + + Container( + width: (MediaQuery.of(context).size.width)*(237/428), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Container( + alignment: Alignment.centerLeft, + child: Text( + userInput, + style: TextStyle( + color: Color(0xff7F1AF1), + fontFamily: 'Brandon-bld', + fontSize: (MediaQuery.of(context).size.height) * (20 / 926), + ), + ),), + Spacer(), + Container( + alignment: Alignment.centerRight, + child: Text( + answer, + style: TextStyle( + color: Color(0xff7F1AF1), + fontFamily: 'Brandon-bld', + fontSize: (MediaQuery.of(context).size.height) * (29 / 926), + ), + ), + ), + + ]), + ), + Divider(), + Container( + height: (MediaQuery.of(context).size.height)*(237/926), + width: (MediaQuery.of(context).size.width)*(310/428), + padding: EdgeInsets.all(8), + child: GridView.builder(itemCount: buttons.length,gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 5, crossAxisSpacing: 2.0, + mainAxisSpacing: 2.0,mainAxisExtent: 40), itemBuilder: (BuildContext context, int index) { + // Clear Button + if (index == 4) { + return MyButton( + buttontapped: () { + setState(() { + userInput = ''; + answer = '0'; + }); + }, + buttonText: buttons[index], + + ); + } + + // % Button + else if (index == 3) { + return MyButton( + buttontapped: () { + setState(() { + userInput += buttons[index]; + }); + }, + buttonText: buttons[index], + + ); + } + // Delete Button + else if (index == 9) { + return MyButton( + buttontapped: () { + setState(() { + userInput = + userInput.substring(0, userInput.length - 1); + }); + }, + buttonText: buttons[index], + + );} + // Equal_to Button + else if (index == 17) { + return MyButton( + buttontapped: () { + setState(() { + equalPressed(); + }); + }, + buttonText: buttons[index], + + ); + } + // other buttons + else { + return MyButton( + buttontapped: () { + setState(() { + userInput += buttons[index]; + }); + }, + buttonText: buttons[index], + + ); + } + }), + ) + + ], + ), + ), + ), + ); + } + + + } + + + diff --git a/lib/screens/Welcome/QuizModule/question_explanation.dart b/lib/screens/Welcome/QuizModule/question_explanation.dart new file mode 100644 index 0000000..183609f --- /dev/null +++ b/lib/screens/Welcome/QuizModule/question_explanation.dart @@ -0,0 +1,372 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_countdown_timer/flutter_countdown_timer.dart'; +import 'package:flutter_svg/svg.dart'; +import 'package:testify/screens/Welcome/side_menu_bar.dart'; + +class QuestionExplanation extends StatefulWidget { + const QuestionExplanation({Key? key, required this.questionId, required this.question, required this.correctAnswer, required this.explanation}) : super(key: key); + + final int questionId; + final String question; + final String correctAnswer; + final String explanation; + + @override + State createState() => _QuestionExplanationState(); +} + +class _QuestionExplanationState extends State { + int endTime = DateTime.now().millisecondsSinceEpoch + 1000 * 30; + + void onEnd() { + print('onEnd'); + } + + @override + Widget build(BuildContext context) { + // print(widget.questionId); + // print(widget.question); + // print(widget.correctAnswer); + // print(widget.explanation); + return Scaffold( + backgroundColor: Color(0xffF8F9FB), + drawer: SideMenuBar(), + // drawer: moreMenu(), + appBar: AppBar( + toolbarHeight: (MediaQuery.of(context).size.height) * (73.52 / 926), + backgroundColor: Color(0xff3F2668), + elevation: 2, + centerTitle: true, + title: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Text( + 'Question ', + style: TextStyle( + color: Color(0xffffffff), + fontFamily: 'Brandon-bld', + fontSize: (MediaQuery.of(context).size.height) * (20 / 926), + ), + ), + ], + ), + flexibleSpace: Container( + decoration: const BoxDecoration( + gradient: LinearGradient( + begin: Alignment.topCenter, + end: Alignment.bottomCenter, + colors: [Color(0xff7F1AF1), Color(0xff482384)])), + ), + actions: [ + TextButton( + onPressed: () async { + }, + child: SvgPicture.asset( + "assets/Images/logout.svg", + height: (MediaQuery.of(context).size.height) *(32/926), + ), + ), + ], + ), + body: Column( + children: [ + Container( + height: ((MediaQuery.of(context).size.height) * ((926-73.52-50.88-(MediaQuery.of(context).padding.top)-8.1) / 926)), + child: ListView( + scrollDirection: Axis.vertical, + children: [ + Container( + padding: EdgeInsets.only( + top: (MediaQuery.of(context).size.height) * (15 / 926), + bottom: (MediaQuery.of(context).size.height) * (8 / 926), + left: (MediaQuery.of(context).size.width) * (18 / 428), + right: (MediaQuery.of(context).size.width) * (18 / 428)), + child: Column( + children: [ + Row( + children: [ + Container( + width: (MediaQuery.of(context).size.width) * (221 / 428), + //height: (MediaQuery.of(context).size.height) *(91/926), + child: Column( + children: [ + Align( + alignment: Alignment.topLeft, + child: Text( + "Attempt Your Quiz", + style: TextStyle( + color: Color(0xff232323), + fontFamily: 'Brandon-bld', + fontSize: (MediaQuery.of(context).size.height) * + (20 / 926), //38, + ), + ), + ), + SizedBox( + height: (MediaQuery.of(context).size.height) * + (2 / 926), + ), + Align( + alignment: Alignment.topLeft, + child: Text( + "Question ID: " + widget.questionId.toString(), // questionNumber + style: TextStyle( + color: Color(0xFF7F1AF1), + fontFamily: 'Brandon-med', + fontSize: (MediaQuery.of(context).size.height) * + (13 / 926), //38, + ), + ), + ) + ], + ), + ), + SizedBox( + width: (MediaQuery.of(context).size.width) * (39 / 428), + ), + // for timer + Container( + height: (MediaQuery.of(context).size.height) * (25 / 926), + width: (MediaQuery.of(context).size.width) * (107 / 428), + color: Color(0xFF3F2668), + child: Row( + children: [ + Text(' Time Left ', + style: TextStyle( + color: Color(0xFFFFFFFF), + fontFamily: 'Brandon-med', + fontSize: (MediaQuery.of(context).size.height) * + (7 / 926), + )), + CountdownTimer( + textStyle: TextStyle( + color: Color(0xFFFFFFFF), + fontFamily: 'Brandon-med', + fontSize: (MediaQuery.of(context).size.height) * + (13 / 926), + ), + endTime: endTime, + onEnd: onEnd, + endWidget: Text( + "00 : 00 : 00", + style: TextStyle( + color: Color(0xFFFFFFFF), + fontFamily: 'Brandon-med', + fontSize: (MediaQuery.of(context).size.height) * + (13 / 926), + ), + ), + ), + ], + ), + ) + ], + ), + SizedBox( + height: (MediaQuery.of(context).size.height) * (35.47 / 926), + ), + Text( + widget.question, + style: TextStyle( + color: Color(0xFF483A3A), + fontFamily: 'Brandon-med', + fontSize: + (MediaQuery.of(context).size.height) * (18 / 926), //38, + ), + ), + SizedBox( + height: (MediaQuery.of(context).size.height) * (25 / 926), + ), + Align( + alignment: Alignment.topLeft, + child: Text( + "Correct Answer: ", // questionNumber + style: TextStyle( + color: Color(0xFF7F1AF1), + fontFamily: 'Brandon-med', + fontSize: (MediaQuery.of(context).size.height) * + (13 / 926), //38, + ), + ), + ), + SizedBox( + height: (MediaQuery.of(context).size.height) * (10.75 / 926), + ), + Container( + // height: (MediaQuery.of(context).size.height) * (50 / 926), + // width: (MediaQuery.of(context).size.width) * (385 / 428), + padding: EdgeInsets.only( + top: (MediaQuery.of(context).size.height) * (8 / 928), + left: (MediaQuery.of(context).size.width) * (13 / 428), + bottom: (MediaQuery.of(context).size.height) * (8 / 928), + ), + decoration: BoxDecoration( + color: Color(0xFF3F2668), + border: Border.all( + color: Color(0xFF3F2668), + ), + borderRadius: BorderRadius.all(Radius.circular(0)) + ), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Container( + width: (MediaQuery.of(context).size.width) * (300 / 428), + child: Text(widget.correctAnswer, + style: TextStyle( + color: Colors.white, + fontFamily: 'Brandon-med', + fontSize: (MediaQuery.of(context).size.height) * + (18 / 926), //38, + )), + ), + ], + )), + SizedBox( + height: (MediaQuery.of(context).size.height) * (20.2 / 926), + ), + Align( + alignment: Alignment.topLeft, + child: Text( + "Explanation: ", // questionNumber + style: TextStyle( + color: Color(0xFF7F1AF1), + fontFamily: 'Brandon-med', + fontSize: (MediaQuery.of(context).size.height) * + (13 / 926), //38, + ), + ), + ), + SizedBox( + height: (MediaQuery.of(context).size.height) * (10.75 / 926), + ), + Text( + widget.explanation, + style: TextStyle( + color: Color(0xFF483A3A), + fontFamily: 'Brandon-med', + fontSize: + (MediaQuery.of(context).size.height) * (18 / 926), //38, + ), + ), + SizedBox( + height: (MediaQuery.of(context).size.height) * (20.75 / 926), + ), + TextButton( + onPressed: () { + Navigator.of(context).pop(); + }, + style: TextButton.styleFrom( + padding: EdgeInsets.zero,), + child: Row( + children: [ + Container( + child: Icon(Icons.arrow_back, + color: Color(0xFF7F1AF1), + size: (MediaQuery.of(context).size.height) * + (15 / 926),), + ), + SizedBox(width: (MediaQuery.of(context).size.width) * + (3 / 428),), + Text( + "Back to Question", // questionNumber + style: TextStyle( + color: Color(0xFF7F1AF1), + fontFamily: 'Brandon-med', + fontSize: (MediaQuery.of(context).size.height) * + (13 / 926), //38, + ), + ), + ], + ), + ), + ], + )), + ], + ), + ) , + Align( + alignment: Alignment.bottomCenter, + child: Container( + height: ((MediaQuery.of(context).size.height) * (51 / 926)), + color: Colors.grey, + // decoration: const BoxDecoration( + // gradient: LinearGradient( + // begin: Alignment.topCenter, + // end: Alignment.bottomCenter, + // colors: [Color(0xff7F1AF1), Color(0xff482384)])), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + TextButton( + onPressed: null, + style: TextButton.styleFrom( + padding: EdgeInsets.zero,), + child: Row( + children: [ + SizedBox(width: (MediaQuery.of(context).size.width) * (16 / 428)), + Container( + child: Icon(Icons.arrow_back_ios_outlined, + color: Color(0xFFE4E4E4), + size: ((MediaQuery.of(context).size.width) * (23.1 / 428)),), + ), + ], + ), + ), + TextButton( + onPressed: null, + style: TextButton.styleFrom( + padding: EdgeInsets.zero,), + child: Row( + children: [ + Container( + width: ((MediaQuery.of(context).size.height) * (15 / 926)), + decoration: BoxDecoration( + color: Color(0xFFE4E4E4), + shape: BoxShape.circle + ), + ), + SizedBox(width: (MediaQuery.of(context).size.width) * (6 / 428)), + Container( + width: ((MediaQuery.of(context).size.height) * (15 / 926)), + decoration: BoxDecoration( + color: Color(0xFFE4E4E4), + shape: BoxShape.circle + ), + ), + SizedBox(width: (MediaQuery.of(context).size.width) * (6 / 428)), + Container( + width: ((MediaQuery.of(context).size.height) * (15 / 926)), + decoration: BoxDecoration( + color: Color(0xFFE4E4E4), + shape: BoxShape.circle + ), + ), + ], + ), + ), + TextButton( + onPressed: null, + style: TextButton.styleFrom( + padding: EdgeInsets.zero,), + child: Row( + children: [ + Container( + child: Icon(Icons.arrow_forward_ios_outlined, + color: Color(0xFFE4E4E4), + size: ((MediaQuery.of(context).size.width) * (23.1 / 428)),), + ), + SizedBox(width: (MediaQuery.of(context).size.width) * (16 / 428)), + ], + ), + ), + ], + ), + ), + ) + ], + ), + ); + } +} diff --git a/lib/screens/Welcome/QuizModule/quiz_final.dart b/lib/screens/Welcome/QuizModule/quiz_final.dart new file mode 100644 index 0000000..394e98e --- /dev/null +++ b/lib/screens/Welcome/QuizModule/quiz_final.dart @@ -0,0 +1,10 @@ +import 'package:flutter/material.dart'; + +class QuizFinal extends StatelessWidget { + const QuizFinal({Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + return Scaffold(backgroundColor: Colors.deepPurpleAccent,); + } +} diff --git a/lib/screens/Welcome/QuizModule/quiz_module.dart b/lib/screens/Welcome/QuizModule/quiz_module.dart new file mode 100644 index 0000000..ac94a6f --- /dev/null +++ b/lib/screens/Welcome/QuizModule/quiz_module.dart @@ -0,0 +1,1827 @@ +import 'dart:async'; +import 'dart:convert'; +import 'dart:math' as math; + +import 'package:flutter/material.dart'; +import 'package:flutter_countdown_timer/current_remaining_time.dart'; +import 'package:flutter_countdown_timer/flutter_countdown_timer.dart'; +import 'package:http/http.dart' as http; +import 'package:testify/models/GenerateQuizModels/QuizModuleModels/generate_quiz_model.dart'; +import 'package:testify/models/GetPreviousQuizzesModel/ResumeQuiz/resume_quiz_model.dart'; +import 'package:testify/screens/Authentication/login.dart'; +import 'package:testify/screens/Welcome/QuizModule/question_explanation.dart'; +import 'package:testify/screens/Welcome/QuizModule/quiz_final.dart'; +import 'package:testify/screens/Welcome/QuizModule/search_bar.dart'; +import 'package:testify/screens/Welcome/side_menu_bar.dart'; +import 'package:testify/screens/Welcome//QuizModule/calculator.dart'; +import 'package:flutter_svg/flutter_svg.dart'; +import 'package:shared_preferences/shared_preferences.dart'; +import 'package:flutter/cupertino.dart'; + +class QuizModule extends StatefulWidget { + const QuizModule({Key? key, required this.totalQuestions, required this.questions, required this.timedMode, required this.mode, required this.whatsDone}) : super(key: key); + + final int totalQuestions; + final List questions; + final bool timedMode; + final String mode; // tutor/ exam + final String whatsDone; // new(From Generate Quiz), resumed, reviewed + @override + _QuizModuleState createState() => _QuizModuleState(); +} + +class _QuizModuleState extends State with WidgetsBindingObserver{ + int endTime = DateTime.now().millisecondsSinceEpoch + 1000 * 30; + List _questions = ['1', '2', '3', '4']; + String _currentQuestion = '1'; + int _currentSelected = 0; + String _labValues="Lorem ipsum dolor sit amet, consectetur adipiscing elit. Cras imperdiet finibus elit non luctus. Morbi auctor mattis ante. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Cras imperdiet finibus elit non luctus. Morbi auctor mattis ante."; + String _note="Lorem ipsum dolor sit amet, consectetur adipiscing elit. Cras imperdiet finibus elit non luctus. Morbi auctor mattis ante. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Cras imperdiet finibus elit non luctus. Morbi auctor mattis ante."; + late TextEditingController _textController; + double _fontSize = 18; // To change font size + bool _showTextZoom = false; // To show ths slider + + int timeElapsed = 0; + /// declare a timer + Timer? timer; + // Timer? saveQuiz; // Saves quiz every few seconds. + + //BottomNavBar + int _selectedIndex = 0; + + // This key is used to open the side drawer + final GlobalKey _scaffoldKey = new GlobalKey(); + + //Shared Pref + var _token; + var _userId; + + //Model Data + var _getGenerateQuizSuccessful; + var _resumeQuizSuccessful; + var _quizId; + + //Changing quiz questions + // This changes the array index which in turn changes the rest. + int questionNumber = 0; + + //To change Icon and color + int whichOption = 0; + + // To void null safety error + bool hasDataLoaded = false; + bool ranSaveQuizAtTheStart = false; // To auto save the quiz at the start and avoid the quizzes from being suspended + // if(hasDataLoaded = true) { + // if(ranSaveQuizAtTheStart = false) { + // SaveQuizAPI(); + // setState(() { + // ranSaveQuizAtTheStart = true; + // }); + // } + // } + + //Storing the data required to display quiz questions and store their answers + var questionsData = { + "title": [], + "id": [], + "question": [], + "correct_msg": [], // This is the explanation + "options": [], // A list would be added to this list + "statistics": [], // [1, 0, 0] + "answeredCorrectly": [], // Stores string and turns true if answered correctly. Can't be a bool since values are correct/incorrect/notAnswered + "optionSelectedInt": [], //To change Icon and color + "notes": [], + "submitData": [], + "SelectedOptionsArray": [] + // "isSelected": [] + }; + var addToSelectedOptionsArray = { + "index": "", + "Correctanswerindex": "", // indexOfOptionThatIsActuallyCorrect + "correct": "", // Correct = 1 if answer is correct, -1 if answer is omitted and 0 if answer is incorrect + "optionIndexSelected": "" + }; + + @override + void initState() { + super.initState(); + _textController = TextEditingController(); + WidgetsBinding.instance!.addObserver(this); + if(widget.whatsDone == "new") + GenerateQuizAPI(); + else if(widget.whatsDone == "resumed") + ResumeQuizAPI(); + + timer = Timer.periodic( + const Duration(seconds: 1), + (timer) { + setState(() { + timeElapsed++; + }); + }, + ); + + // saveQuiz = Timer.periodic( + // const Duration(seconds: 10), + // (timer) { + // SaveQuizAPI(); + // }, + // ); + } + + @override + void didChangeAppLifecycleState(AppLifecycleState state) async { + super.didChangeAppLifecycleState(state); + + final isBackground = state == AppLifecycleState.paused; + final isClosed = state == AppLifecycleState.detached; + if(isBackground) { // As soon as the user closes the app this runs. The application is still in the app switcher(ram) + print("xD in Background"); + SaveQuizAPI("suspended"); + // ScaffoldMessenger.of(context) + // ..removeCurrentSnackBar() + // ..showSnackBar(SnackBar(content: Text("The Quiz has been saved as Suspended!"))); + Navigator.of(context).pop(); + } + if(isClosed) { // When app is closed from the app switcher. Doesn't run for now for some odd reason. + print("xD Closed"); + } + } + + Future ResumeQuizAPI() async { + SharedPreferences prefs = await SharedPreferences.getInstance(); + final String apiUrlGenerateQuiz = "https://demo.pookidevs.com/quiz/solver/resumeQuiz"; + var quizID = prefs.getInt("quizId"); + _token = prefs.getString('token')!; + print(_token); + _userId = prefs.getInt("userId")!; + http.post(Uri.parse(apiUrlGenerateQuiz), headers: { + 'Content-type': 'application/json; charset=UTF-8', 'Authorization' : _token.toString(), + }, body: json.encode( + { + "quizId": quizID + }) + ).then((response) { + // print(jsonDecode(response.body).toString()); + if((response.statusCode == 200) & (json.decode(response.body).toString().substring(0,14) != "{status: false")) { + final responseString = (response.body); + var resumeQuizSuccessful1 = resumeQuizModelFromJson(responseString); + final ResumeQuizModel resumeQuizSuccessful = resumeQuizSuccessful1; + setState(() { + _resumeQuizSuccessful = resumeQuizSuccessful; + print(_resumeQuizSuccessful.data.previousQuizzes[0].quizMeta.quizMode); + print(_resumeQuizSuccessful.data.previousQuizzes[0].quizMeta.quizTotalQuestions); + print(_resumeQuizSuccessful.data.previousQuizzes[0].quizMeta.quizQuestions); + print(_resumeQuizSuccessful.data.previousQuizzes[0].quizMeta.quizStatus); + print(_resumeQuizSuccessful.data.previousQuizzes[0].quizMeta.isTimed); + // print(_resumeQuizSuccessful.data.previousQuizzes[0].quizMeta.quizId.runtimeType); + // print(_resumeQuizSuccessful.data.previousQuizzes[0].quizMeta.quizScore.runtimeType); + // _quizId = _getGenerateQuizSuccessful.data.quizId; + // print(_quizId); + }); + categoriesGenerateQuizData(); + // categoriesGenerateQuizData(); + } + else { // Token Invalid + + } + } + ); + } + + Future submitAnswerAPI(int? indexOfOptionThatIsActuallyCorrect, int? correct, int? optionIndexSelected) async { // doesn't work properly in exam mode + final String apiUrlGenerateQuiz = "https://demo.pookidevs.com/quiz/solver/submitAnswer"; + // print(_token); + SharedPreferences prefs = await SharedPreferences.getInstance(); + var _quizID = prefs.getInt("quizId"); + + print(widget.whatsDone); + print("user id: "+ _userId.toString()); + print("questionId: "+ questionsData["id"]![questionNumber].toString()); + print("quizId" + _quizID.toString()); + print("indexOfOptionThatIsActuallyCorrect: " + indexOfOptionThatIsActuallyCorrect.toString()); + print("correct: " + correct.toString()); + print("optionIndexSelected: " + optionIndexSelected.toString()); + + + + http.post(Uri.parse(apiUrlGenerateQuiz), headers: { + 'Content-type': 'application/json; charset=UTF-8', 'Authorization' : _token.toString(), + }, body: json.encode( + { + "data":{ + "userId": _userId.toString(), + "questionId": questionsData["id"]![questionNumber].toString(), + // "quizId": widget.whatsDone == "new" ? _getGenerateQuizSuccessful.data.quizId.toString() : _resumeQuizSuccessful.data.previousQuizzes[0].quizId.toString(), + "quizId": _quizID.toString(), + "answerMeta":{ + "index": questionsData["id"]![questionNumber].toString(), + "Correctanswerindex": indexOfOptionThatIsActuallyCorrect.toString(), // indexOfOptionThatIsActuallyCorrect + "correct": correct.toString(), // Correct = 1 if answer is correct, -1 if answer is omitted and 0 if answer is incorrect + "optionIndexSelected": optionIndexSelected.toString() + } + } + }) + ).then((response) { + if((response.statusCode == 200)) { + print(jsonDecode(response.body).toString()); + if((jsonDecode(response.body).toString()) == "{data: {status: true, message: Answer Submitted}}") { + + } else { + ScaffoldMessenger.of(context) + ..removeCurrentSnackBar() + ..showSnackBar(SnackBar(content: Text("Error! Answer not Saved!"))); + } + } + else { // Token Invalid + ScaffoldMessenger.of(context) + ..removeCurrentSnackBar() + ..showSnackBar(SnackBar(content: Text("Token Invalid!"))); + final result = Navigator.pushAndRemoveUntil( + context, + MaterialPageRoute(builder: (BuildContext context) => const Login(fromWhere:"Home")), + ModalRoute.withName('/'), + ); + } + } + ); + } + + + Future SaveQuizAPI(String saveAs, [bool? hasUserClicked]) async { + SharedPreferences prefs = await SharedPreferences.getInstance(); + widget.whatsDone == "new" ? prefs.setInt("quizId", _getGenerateQuizSuccessful.data.quizId) : null; + var _quizID = widget.whatsDone == "new" ? _getGenerateQuizSuccessful.data.quizId.toString() : _resumeQuizSuccessful.data.previousQuizzes[0].quizId.toString(); + final String apiUrlGenerateQuiz = "https://demo.pookidevs.com/quiz/solver/saveQuiz"; + print(widget.totalQuestions); + var date = new DateTime.now().toString().split("."); + date = date[0].split(" "); + print(date); + int quizScore = 0; + var addToOmittedQuestionsArray = []; + var finalSelectedOptionsArray = []; + var totalQuizTime = timeElapsed.toString(); + for(int i = 0; i{ + 'Content-type': 'application/json; charset=UTF-8', 'Authorization' : _token.toString(), + }, body: json.encode( + { + "data": + { + "quiz" : { + "quizId": widget.whatsDone == "new" ? _getGenerateQuizSuccessful.data.quizId.toString() : _resumeQuizSuccessful.data.previousQuizzes[0].quizId.toString(), + "quizTitle": "Custom Quiz" + date[0].toString(), // "Custom Quiz" + Date.now() + "quizDate": date[0].toString(), // "Custom Quiz" + "quizScore": quizScore.toString(), // total correct + "quizTotalQuestions": widget.totalQuestions.toString(), + "quizStatus": saveAs, // == "completed" ? "completed" : "suspended", // "completed", "suspended" + "quizQuestions": questionsData["id"].toString(), // Question IDs + "quizMode": widget.mode, // "tutor", "exam" + "quizTime": totalQuizTime.toString(), // total quiz time in seconds + "isTimed": widget.timedMode, // bool true or false + "omittedQuestions": addToOmittedQuestionsArray, // Don't send anything here + "SelectedOptionsArray": widget.mode == "exam" ? finalSelectedOptionsArray : [] // Don't send anything here + }, + "userId": _userId.toString() + } + } + + ) + ).then((response) async { + print(jsonDecode(response.body).toString()); + if((response.statusCode == 200) & (json.decode(response.body).toString().substring(0,14) != "{status: false")) { + + } + else { // Token Invalid + ScaffoldMessenger.of(context) + ..removeCurrentSnackBar() + ..showSnackBar(SnackBar(content: Text("Token Invalid!"))); + final result = Navigator.pushAndRemoveUntil( + context, + MaterialPageRoute(builder: (BuildContext context) => const Login(fromWhere:"Home")), + ModalRoute.withName('/'), + ); + } + } + ).whenComplete(() { + if(hasUserClicked == true) { + ScaffoldMessenger.of(context) + ..removeCurrentSnackBar() + ..showSnackBar(SnackBar(content: Text("The Quiz has been saved as $saveAs!"))); + Navigator.of(context) + .popUntil(ModalRoute.withName("/home")); + final result = Navigator.push( + context, + MaterialPageRoute(builder: (context) => QuizFinal()), + ); + } + }); + + } + + Future GenerateQuizAPI() async { + print("Mode: " + widget.mode.toString()); + SharedPreferences prefs = await SharedPreferences.getInstance(); + final String apiUrlGenerateQuiz = "https://demo.pookidevs.com/quiz/generator/generateQuiz"; + _token = prefs.getString('token')!; + _userId = prefs.getInt("userId")!; + http.post(Uri.parse(apiUrlGenerateQuiz), headers: { + 'Content-type': 'application/json; charset=UTF-8', 'Authorization' : _token.toString(), + }, body: json.encode( + { + "data": + { + "questionIds": widget.questions, + "count": widget.totalQuestions + } + }) + ).then((response) { + // print("This is: " + jsonDecode(response.body).toString()); + if((response.statusCode == 200) & (json.decode(response.body).toString().substring(0,14) != "{status: false")) { + final responseString = (response.body); + var generateQuizSuccessful = generateQuizSuccessfulFromJson(responseString); + final GenerateQuizSuccessful getGenerateQuizSuccessful = generateQuizSuccessful; + setState(() { + _getGenerateQuizSuccessful = getGenerateQuizSuccessful; + _quizId = _getGenerateQuizSuccessful.data.quizId; + print(_quizId); + }); + categoriesGenerateQuizData(); + } + else { // Token Invalid + + } + } + ); + } + + Future BookmarkQuestionAPI() async { + final String apiUrlGenerateQuiz = "https://demo.pookidevs.com/quiz/solver/markQuestion"; + http.post(Uri.parse(apiUrlGenerateQuiz), headers: { + 'Content-type': 'application/json; charset=UTF-8', 'Authorization' : _token.toString(), + }, body: json.encode( + { + "data": { + "userId": _userId, + "questionId": questionsData["id"]![questionNumber].toString(), + "tableName": "marked_questions", + "isMarked": true + } + }) + ).then((response) { + if((response.statusCode == 200)) { // & (json.decode(response.body).toString().substring(0,14) != "{status: false")) { + print(jsonDecode(response.body).toString()); + } + else { // Token Invalid + ScaffoldMessenger.of(context) + ..removeCurrentSnackBar() + ..showSnackBar(SnackBar(content: Text("Token Invalid!"))); + final result = Navigator.pushAndRemoveUntil( + context, + MaterialPageRoute(builder: (BuildContext context) => const Login(fromWhere:"Home")), + ModalRoute.withName('/'), + ); + } + } + ); + } + + Future addNotesAPI() async { + // print(_userId); + // print(questionsData["id"]![questionNumber].toString()); + // print(_quizId); + // print(_note); + final String apiUrlGenerateQuiz = "https://demo.pookidevs.com/quiz/notes/addNotes"; + http.post(Uri.parse(apiUrlGenerateQuiz), headers: { + 'Content-type': 'application/json; charset=UTF-8', 'Authorization' : _token.toString(), + }, body: json.encode( + { + "data": { + "userId": _userId, + "questionId": questionsData["id"]![questionNumber].toString(), + "quizId": _quizId, + "note": _note, + "tableName": "notes" + } + } + ) + ).then((response) { + // print(jsonDecode(response.body).toString()); + // print(json.decode(response.body).toString().substring(json.decode(response.body).toString().length-12,json.decode(response.body).toString().length)); + if((response.statusCode == 200) & (json.decode(response.body).toString().substring(json.decode(response.body).toString().length-12,json.decode(response.body).toString().length) == "Note Added}}")) { + ScaffoldMessenger.of(context) + ..removeCurrentSnackBar() + ..showSnackBar(SnackBar(content: Text("Note Added!"))); + } + else if((response.statusCode == 200) & (json.decode(response.body).toString().substring(0,14) == "{status: false")) { // Token Invalid + ScaffoldMessenger.of(context) + ..removeCurrentSnackBar() + ..showSnackBar(SnackBar(content: Text("Token Expired!"))); + final result = Navigator.push( + context, + MaterialPageRoute(builder: (context) => const Login(fromWhere:"Home")), + ); + } + else { + ScaffoldMessenger.of(context) + ..removeCurrentSnackBar() + ..showSnackBar(SnackBar(content: Text("Note not Added!"))); + } + } + ); + } + + void categoriesGenerateQuizData() async { + setState(() { + questionsData["id"] = []; + questionsData["question"] = []; + questionsData["options"] = []; + questionsData["statistics"] = []; + questionsData["correct_msg"] = []; + questionsData["answeredCorrectly"] = []; + questionsData["optionSelectedInt"] = []; + questionsData["notes"] = []; + questionsData["submitData"] = []; + questionsData["SelectedOptionsArray"] = []; + _questions = []; + }); + if(widget.whatsDone == "new") + { + int c = 0; + if (_getGenerateQuizSuccessful != null) { + while ((c < _getGenerateQuizSuccessful.data.questions.toList().length) & + (_getGenerateQuizSuccessful.data.questions.toList().length > 0)) { + // questionsData + setState(() { + questionsData["id"]! + .add(_getGenerateQuizSuccessful.data.questions[c].id); + questionsData["question"]! + .add(_getGenerateQuizSuccessful.data.questions[c].question); + questionsData["options"]! + .add(_getGenerateQuizSuccessful.data.questions[c].options); + questionsData["statistics"]! + .add(_getGenerateQuizSuccessful.data.questions[c].statistics); + questionsData["correct_msg"]!.add(_getGenerateQuizSuccessful + .data.questions[c].correctMsg); //answeredCorrectly + questionsData["answeredCorrectly"]!.add("notAnswered"); + questionsData["optionSelectedInt"]!.add(0); + questionsData["SelectedOptionsArray"]!.add(addToSelectedOptionsArray); + _questions.add((c + 1).toString()); + }); + c++; + } + setState(() { + hasDataLoaded = true; + }); + if (hasDataLoaded == true) { + if (ranSaveQuizAtTheStart == false) { + SaveQuizAPI("suspended"); + setState(() { + ranSaveQuizAtTheStart = true; + }); + } + } + } + } + // print(questionsData); + else if(widget.whatsDone == "resumed") + { // Have to complete Exam Mode + int c = 0; + if (_resumeQuizSuccessful != null) { + while ((c < _resumeQuizSuccessful.data.questions.length) & + (_resumeQuizSuccessful.data.questions.length > 0)) { + // questionsData + setState(() { + questionsData["id"]! + .add(_resumeQuizSuccessful.data.questions[c].id); + questionsData["question"]! + .add(_resumeQuizSuccessful.data.questions[c].question); + questionsData["options"]! + .add(_resumeQuizSuccessful.data.questions[c].options); + questionsData["statistics"]! + .add(_resumeQuizSuccessful.data.questions[c].statistics); + questionsData["correct_msg"]!.add(_resumeQuizSuccessful + .data.questions[c].correctMsg); //answeredCorrectly + questionsData["answeredCorrectly"]!.add("notAnswered"); + questionsData["optionSelectedInt"]!.add(0); + // questionsData["SelectedOptionsArray"]![c] = _resumeQuizSuccessful.data.previousQuizzes[0].quiz_meta.selectedOptionsArray + _questions.add((c + 1).toString()); + if(widget.mode == "exam") { + questionsData["SelectedOptionsArray"]!.add(addToSelectedOptionsArray); + // print(_resumeQuizSuccessful.data.previousQuizzes[0].quizMeta.selectedOptionsArray); + } + if(_resumeQuizSuccessful.data.questions[c].notes != null) { // notes + questionsData["notes"]!.add(_resumeQuizSuccessful + .data.questions[c].notes); + } else { + questionsData["notes"]!.add(""); + } + if(_resumeQuizSuccessful.data.questions[c].submitData != null) { // submitData + String str = _resumeQuizSuccessful.data.questions[c].submitData; + str = str.replaceAll("\\", ""); + var strMap = json.decode(str); + // print(strMap); + if(strMap['correct'] == '1') { + questionsData["answeredCorrectly"]![c] = "correct"; + } + else if (strMap['correct'] == '0') { + questionsData["answeredCorrectly"]![c] = "incorrect"; + } + questionsData["optionSelectedInt"]![c] = int.parse(strMap['optionIndexSelected']); + questionsData["submitData"]!.add(_resumeQuizSuccessful + .data.questions[c].submitData); + } else { + questionsData["submitData"]!.add(""); + } + }); + c++; + } + // Adding data to questionsData["SelectedOptionsArray"] + if(widget.mode == "exam") { + if((_resumeQuizSuccessful.data.previousQuizzes[0].quizMeta.selectedOptionsArray != null) || (_resumeQuizSuccessful.data.previousQuizzes[0].quizMeta.selectedOptionsArray != [])) { + for(int i = 0; i<_resumeQuizSuccessful.data.questions.length; i++) { + for(int j = 0; j<_resumeQuizSuccessful.data.previousQuizzes[0].quizMeta.selectedOptionsArray.length; j++) { + if(_resumeQuizSuccessful.data.questions[i].id.toString() == _resumeQuizSuccessful.data.previousQuizzes[0].quizMeta.selectedOptionsArray[j].index) { + if(_resumeQuizSuccessful.data.questions[i].submitData != null) { + setState(() { + questionsData["SelectedOptionsArray"]![i] = { + "index": _resumeQuizSuccessful.data.previousQuizzes[0].quizMeta.selectedOptionsArray[j].index, + "Correctanswerindex": _resumeQuizSuccessful.data.previousQuizzes[0].quizMeta.selectedOptionsArray[j].correctanswerindex, // indexOfOptionThatIsActuallyCorrect + "correct": _resumeQuizSuccessful.data.previousQuizzes[0].quizMeta.selectedOptionsArray[j].correct, // Correct = 1 if answer is correct, -1 if answer is omitted and 0 if answer is incorrect + "optionIndexSelected": _resumeQuizSuccessful.data.previousQuizzes[0].quizMeta.selectedOptionsArray[j].optionIndexSelected + }; + }); + } + } + } + } + } + } + print(questionsData["SelectedOptionsArray"]); + print(questionsData["answeredCorrectly"]); + setState(() { + hasDataLoaded = true; + }); + if (hasDataLoaded == true) { + if (ranSaveQuizAtTheStart == false) { + SaveQuizAPI("suspended"); + setState(() { + ranSaveQuizAtTheStart = true; + }); + } + } + } + } + // print(_resumeQuizSuccessful.data.previousQuizzes[0].quizMeta.quizMode); + } + + // To change text size - text zoom + Widget _textZoom(BuildContext context) { + return GestureDetector( + onTap: () { + }, + child: Container( + height: ((MediaQuery.of(context).size.height) * (51 / 926)), + decoration: const BoxDecoration( + gradient: LinearGradient( + begin: Alignment.topCenter, + end: Alignment.bottomCenter, + colors: [Color(0xff7F1AF1), Color(0xff482384)])), + child: new Slider( + value: _fontSize, + activeColor: Colors.white, + inactiveColor: Colors.red, + onChanged: (double value) { + setState(() { + _fontSize = value; + print(_fontSize); + }); + }, + divisions: 4, + min: 14.0, + max: 22.0, + ), + ), + ); + } + + + void onEnd() { + print('onEnd'); + } + + Widget bookmarkQuestion(BuildContext context) { + return SizedBox( + child: AlertDialog( + contentPadding: EdgeInsets.all(MediaQuery.of(context).size.width*(15/428)), + content: Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + 'Bookmark', + style: TextStyle( + color: Color(0xffB0A6C2), + fontFamily: 'Brandon-bld', + fontSize: (MediaQuery.of(context).size.height) * (18 / 926), + ), + ), + IconButton(icon:Icon(Icons.cancel),iconSize:23,color: Color(0xFF3F2668),onPressed: () { + Navigator.of(context).pop(); + },), + ], + ), + Divider(), + Text("Are you sure you want to bookmark this question", + ), + ], + ), + actions: [ + Divider(), + Row( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + TextButton( + onPressed: () { + Navigator.of(context).pop(); + }, + child: Text('No', + style: TextStyle( + color: Color(0xff3F2668), + fontFamily: 'Brandon-bld', + fontSize: + (MediaQuery.of(context).size.height) * (21 / 926), + )), + ), + Divider(), + TextButton( + onPressed: () { + Navigator.of(context).pop(); + print(questionsData["id"]![questionNumber].toString()); + BookmarkQuestionAPI(); + }, + child: Text('Yes', + style: TextStyle( + color: Color(0xff3F2668), + fontFamily: 'Brandon-bld', + fontSize: + (MediaQuery.of(context).size.height) * (21 / 926), + )), + ), + ], + ), + ], + ), + ); + } + + Widget labValues(BuildContext context) { + return SizedBox( + child: AlertDialog( + contentPadding: EdgeInsets.all(MediaQuery.of(context).size.width*(15/428)), + content: Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + 'Lab Values', + style: TextStyle( + color: Color(0xffB0A6C2), + fontFamily: 'Brandon-bld', + fontSize: (MediaQuery.of(context).size.height) * (18 / 926), + ), + ), + IconButton(icon:Icon(Icons.cancel),iconSize:23,color: Color(0xFF3F2668),onPressed: () { + Navigator.of(context).pop(); + },), + ], + ), + Divider(), + Text(_labValues), + ], + ), + ), + ); + } + Widget moreMenu() { + return Container( + width: (MediaQuery.of(context).size.width) * 0.3, + child: Drawer( + child: Container( + decoration: const BoxDecoration( + gradient: LinearGradient( + begin: Alignment.topRight, + end: Alignment.bottomLeft, + colors: [Color(0xff3F2668), Color(0xff482384)])), + child: ListView( + // Remove padding + padding: EdgeInsets.zero, + children: [ + Container( + padding: EdgeInsets.only( + top: MediaQuery.of(context).padding.top), + height: (MediaQuery.of(context).size.height), + color: Colors.transparent, + child: Column( + children: [ + ListTile( + leading: Icon( + Icons.close, + color: Colors.white, + ), + onTap: () => Navigator.pop(context), + ), + SizedBox( + height: + (MediaQuery.of(context).size.height) * (47 / 926), + ), + InkWell( + onTap: () { + Navigator.of(context).pop(); + // showDialog( + // context: context, + // builder: (BuildContext context) => + // labValues(context), + // ); + final result = Navigator.push( + context, + MaterialPageRoute(builder: (context) => SearchListExample()), + ); + }, + child: Container( + alignment: Alignment.center, + child: Column( + children: [ + SvgPicture.asset( + 'assets/Images/lab.svg', + height: (MediaQuery.of(context).size.height) * + (37 / 926), + color: Colors.white, + ), + SizedBox( + height: (MediaQuery.of(context).size.height) * + (10 / 926), + ), + Text( + 'Lab Values', + style: TextStyle( + color: Colors.white, + fontFamily: 'Brandon-bld', + fontSize: + (MediaQuery.of(context).size.height) * + (15 / 926), + ), + ) + ], + ), + ) + + //Divider(), + ), + SizedBox( + height: + (MediaQuery.of(context).size.height) * (47 / 926), + ), + InkWell( + onTap: () { + Navigator.of(context).pop(); + // bookmarkQuestion + showDialog( + context: context, + builder: (BuildContext context) => + bookmarkQuestion(context), + ); + }, + child: Container( + alignment: Alignment.center, + child: Column( + children: [ + Icon( + Icons.bookmark, + size: 37, + color: Colors.white, + ), + SizedBox( + height: (MediaQuery.of(context).size.height) * + (10 / 926), + ), + Text( + 'Bookmarks', + style: TextStyle( + color: Colors.white, + fontFamily: 'Brandon-bld', + fontSize: + (MediaQuery.of(context).size.height) * + (15 / 926), + ), + ) + ], + ), + ) + + //Divider(), + ), + SizedBox( + height: + (MediaQuery.of(context).size.height) * (47 / 926), + ), + InkWell( + onTap: () { + Navigator.of(context).pop(); + showDialog( + context: context, + builder: (BuildContext context) => + notes(context), + ); + }, + child: Container( + alignment: Alignment.center, + child: Column( + children: [ + Icon( + Icons.note_rounded, + size: 37, + color: Colors.white, + ), + SizedBox( + height: + (MediaQuery.of(context).size.height) * + (10 / 926), + ), + Text( + 'Notes', + style: TextStyle( + color: Colors.white, + fontFamily: 'Brandon-bld', + fontSize: + (MediaQuery.of(context).size.height) * + (15 / 926), + ), + ) + ], + ), + ) + + //Divider(), + ), + SizedBox( + height: + (MediaQuery.of(context).size.height) * (47 / 926), + ), + InkWell( + onTap:() {Navigator.of(context).pop(); + showDialog( + context: context, + builder: (BuildContext context) => + Calculator(), + );}, + child: Container( + alignment: Alignment.center, + child: Column( + children: [ + SvgPicture.asset('assets/Images/calculator.svg', + height: (MediaQuery.of(context).size.height) * + (37 / 926)), + SizedBox( + height: (MediaQuery.of(context).size.height) * + (10 / 926), + ), + Text( + 'Calculator', + style: TextStyle( + color: Colors.white, + fontFamily: 'Brandon-bld', + fontSize: + (MediaQuery.of(context).size.height) * + (15 / 926), + ), + ) + ], + ), + )), + SizedBox( + height: + (MediaQuery.of(context).size.height) * (47 / 926), + ), + InkWell( + onTap: () { + Navigator.of(context).pop(); + setState(() { + _showTextZoom = true; + }); + }, + child: Container( + alignment: Alignment.center, + child: Column( + children: [ + SvgPicture.asset('assets/Images/zoom.svg', + height: (MediaQuery.of(context).size.height) * + (37 / 926)), + SizedBox( + height: (MediaQuery.of(context).size.height) * + (10 / 926), + ), + Text( + 'Text Zoom', + style: TextStyle( + color: Colors.white, + fontFamily: 'Brandon-bld', + fontSize: + (MediaQuery.of(context).size.height) * + (15 / 926), + ), + ) + ], + ), + )) + ], + ), + ), + ]), + ))); + } + Widget notes(BuildContext context) { + return SizedBox( + child: AlertDialog( + contentPadding: EdgeInsets.all(MediaQuery.of(context).size.width*(15/428)), + content: Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + 'Take Notes', + style: TextStyle( + color: Color(0xffB0A6C2), + fontFamily: 'Brandon-bld', + fontSize: (MediaQuery.of(context).size.height) * (18 / 926), + ), + ), + IconButton(icon:Icon(Icons.cancel),iconSize:23,color: Color(0xFF3F2668),onPressed: () { + Navigator.of(context).pop(); + },), + ], + ), + Divider(), + TextField( + controller: _textController, + keyboardType: TextInputType.multiline, + minLines: 1,//Normal textInputField will be displayed + maxLines: 5,// when user presses enter it will adapt to it + decoration: InputDecoration( + hintText: "Add notes here...", + hintStyle: TextStyle(color: Color(0xffAEAEAE), + fontSize: (MediaQuery.of(context).size.height)*(15/926), + fontFamily: 'Brandon-med',), + contentPadding: EdgeInsets.fromLTRB(2.0, 1, 2.0, 1), + focusedBorder: OutlineInputBorder( + borderSide: BorderSide( + color: Colors.transparent, + width: 0.0, + ), + ), + ), + style: TextStyle( + color: Colors.black, + fontSize: (MediaQuery.of(context).size.height)*(15/926), + fontFamily: 'Brandon-med', + ), + onChanged: (String value) { + setState(() { + _note = value; + }); + }, + ), + Row( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + IconButton(onPressed:(){ + setState((){ + _note=''; + _textController.clear(); + } + ); + } , iconSize: 21 ,icon: Icon(Icons.refresh,color: Color(0xFF3F2668))), + TextButton( + onPressed: () { + addNotesAPI(); + _textController.clear(); + Navigator.of(context).pop(); + }, + style: TextButton.styleFrom( + padding: EdgeInsets.zero,), + child: Container( + height: (MediaQuery.of(context).size.height) * (31 / 926), + width:(MediaQuery.of(context).size.width) * (97 / 428), + decoration: BoxDecoration(borderRadius:BorderRadius.circular(4),color: Color(0xFFDDDAE2),), + child:Row( + mainAxisAlignment: MainAxisAlignment.center, + children:[ + Icon(Icons.save,color: Color(0xFF3F2668),), + SizedBox( + height: (MediaQuery.of(context).size.width) * + (14 / 428), + ), + Text( + 'Save', + style: TextStyle( + color: Color(0xff3F2668), + fontFamily: 'Brandon-bld', + fontSize: (MediaQuery.of(context).size.height) * (19 / 926), + ), + ), + ]) + ),) + ], + ) + ], + ), + ),);} + Future _onQuit() async { + return (await showDialog( + context: context, + builder: (context) => AlertDialog( + content: Text( + 'Mark Quiz as', + style: TextStyle( + color: Color(0xffA1A1A1), + fontFamily: 'Brandon-bld', + fontSize: (MediaQuery.of(context).size.height) * (21 / 926), + ), + ), + actions: [ + TextButton( + onPressed: () async { + await SaveQuizAPI("suspended", true); + // ScaffoldMessenger.of(context) + // ..removeCurrentSnackBar() + // ..showSnackBar(SnackBar(content: Text("The Quiz has been saved as Suspended!"))); + // Navigator.of(context).pop(); + // Navigator.of(context).pop(); + }, + child: Text('Suspended', + style: TextStyle( + color: Color(0xff3F2668), + fontFamily: 'Brandon-bld', + fontSize: + (MediaQuery.of(context).size.height) * (21 / 926), + )), + ), + TextButton( + onPressed: () async { + await SaveQuizAPI("completed", true); + // Navigator.of(context).pop(); + // Navigator.of(context).pop(); // Uncomment when "completed" and omittedQuestionsArray work again. + }, + child: Text('Completed', + style: TextStyle( + color: Color(0xff3F2668), + fontFamily: 'Brandon-bld', + fontSize: + (MediaQuery.of(context).size.height) * (21 / 926), + )), + ), + ], + ), + )) ?? + false; + } + + @override + void dispose() { + _textController.dispose(); + timer?.cancel(); + WidgetsBinding.instance!.removeObserver(this); + // saveQuiz?.cancel(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + return WillPopScope( + onWillPop: () async { + // ScaffoldMessenger.of(context) + // ..removeCurrentSnackBar() + // ..showSnackBar(SnackBar(content: Text("Click on Quit Quiz!"))); + return true; + }, + child: Scaffold( + resizeToAvoidBottomInset: false, + backgroundColor: Color(0xffF8F9FB), + drawer: SideMenuBar(), + // drawer: moreMenu(), + endDrawer: moreMenu(), + appBar: AppBar( + toolbarHeight: (MediaQuery.of(context).size.height) * (73.52 / 926), + backgroundColor: Color(0xff3F2668), + elevation: 2, + centerTitle: true, + title: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Text( + 'Question ', + style: TextStyle( + color: Color(0xffffffff), + fontFamily: 'Brandon-bld', + fontSize: (MediaQuery.of(context).size.height) * (20 / 926), + ), + ), + DropdownButton( + value: (questionNumber + 1).toString(), + underline: Container(), + iconEnabledColor: Colors.white, + dropdownColor: Color(0xff3F2668), + onChanged: (newValue) { + setState(() { + // print(newValue); + _currentQuestion = newValue as String; + questionNumber = int.parse(newValue) - 1; + }); + }, + items: _questions.map((question) { + return DropdownMenuItem( + child: new Text( + question + ' / ' + widget.totalQuestions.toString(), + style: TextStyle( + color: Colors.white, + fontFamily: 'Brandon-bld', + fontSize: + (MediaQuery.of(context).size.height) * (20 / 926), + ), + ), + value: question, + ); + }).toList(), + ), + ], + ), + flexibleSpace: Container( + decoration: const BoxDecoration( + gradient: LinearGradient( + begin: Alignment.topCenter, + end: Alignment.bottomCenter, + colors: [Color(0xff7F1AF1), Color(0xff482384)])), + ), + actions: [ + TextButton( + onPressed: () async { + SaveQuizAPI("suspended", false); + }, + child: SvgPicture.asset( + "assets/Images/logout.svg", + height: (MediaQuery.of(context).size.height) *(32/926), + ), + ), + ], + ), + body: hasDataLoaded == false ? Center(child: CircularProgressIndicator()) : Column( + children: [ + GestureDetector( + onTap: () { + setState(() { + _showTextZoom = false; + }); + }, + child: Container( + height: ((MediaQuery.of(context).size.height) * ((926-73.52-50.88-(MediaQuery.of(context).padding.top)-8.1) / 926)), + child: ListView( + scrollDirection: Axis.vertical, + children: [ + Container( + padding: EdgeInsets.only( + top: (MediaQuery.of(context).size.height) * (15 / 926), + bottom: (MediaQuery.of(context).size.height) * (8 / 926), + left: (MediaQuery.of(context).size.width) * (18 / 428), + right: (MediaQuery.of(context).size.width) * (18 / 428)), + child: Column( + children: [ + Row( + children: [ + Container( + width: (MediaQuery.of(context).size.width) * (221 / 428), + //height: (MediaQuery.of(context).size.height) *(91/926), + child: Column( + children: [ + Align( + alignment: Alignment.topLeft, + child: Text( + "Attempt Your Quiz", + style: TextStyle( + color: Color(0xff232323), + fontFamily: 'Brandon-bld', + fontSize: (MediaQuery.of(context).size.height) * + (20 / 926), //38, + ), + ), + ), + SizedBox( + height: (MediaQuery.of(context).size.height) * + (2 / 926), + ), + Align( + alignment: Alignment.topLeft, + child: Text( + "Question ID: " + questionsData["id"]![questionNumber].toString(), // questionNumber + style: TextStyle( + color: Color(0xFF7F1AF1), + fontFamily: 'Brandon-med', + fontSize: (MediaQuery.of(context).size.height) * + (13 / 926), //38, + ), + ), + ) + ], + ), + ), + SizedBox( + width: (MediaQuery.of(context).size.width) * (39 / 428), + ), + // for timer + Container( + height: (MediaQuery.of(context).size.height) * (25 / 926), + width: (MediaQuery.of(context).size.width) * (87 / 428), + color: Color(0xFF3F2668), + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Text('', + style: TextStyle( + color: Color(0xFFFFFFFF), + fontFamily: 'Brandon-med', + fontSize: (MediaQuery.of(context).size.height) * + (7 / 926), + )), + CountdownTimer( + textStyle: TextStyle( + color: Color(0xFFFFFFFF), + fontFamily: 'Brandon-med', + fontSize: (MediaQuery.of(context).size.height) * + (13 / 926), + ), + endTime: endTime, + onEnd: onEnd, + endWidget: Text( + "00 : 00 : 00", + style: TextStyle( + color: Color(0xFFFFFFFF), + fontFamily: 'Brandon-med', + fontSize: (MediaQuery.of(context).size.height) * + (13 / 926), + ), + ), + ), + ], + ), + ) + ], + ), + SizedBox( + height: (MediaQuery.of(context).size.height) * (25 / 926), + ), + Text( + questionsData["question"]![questionNumber].toString(), + style: TextStyle( + color: Color(0xFF483A3A), + fontFamily: 'Brandon-med', + fontSize: + (MediaQuery.of(context).size.height) * (_fontSize / 926), //38, + ), + ), + SizedBox( + height: (MediaQuery.of(context).size.height) * (25 / 926), + ), + if(questionsData["options"] != null) + for(int i = 0; i QuestionExplanation(question: questionsData["question"]![questionNumber].toString(), correctAnswer: correctAns.toString(), questionId: questionsData["id"]![questionNumber], explanation: questionsData["correct_msg"]![questionNumber].toString(),)), + ); + }, + child: Container( + alignment: Alignment.topRight, + child: Text( + "See Explanation", + style: TextStyle( + color: Color(0xFF7F1AF1), + fontFamily: 'Brandon-med', + fontSize: (MediaQuery.of(context).size.height) * + (13 / 926), //38, + ), + ), + ), + ) : Container(), + SizedBox( + height: (MediaQuery.of(context).size.height) * (20 / 926), + ), + ], + ) : + Column( // Exam Mode! + children: [ + TextButton( + onPressed: () { + // print("i: " + i.toString()); + // if(questionsData["answeredCorrectly"]![questionNumber] == "notAnswered") { + if((questionsData["answeredCorrectly"]![questionNumber] == "notAnswered") || (questionsData["answeredCorrectly"]![questionNumber] != "notAnswered")) { + int? indexOfOptionThatIsActuallyCorrect; + int? correct; + // whichOption = i; optionSelectedInt + setState(() { + questionsData["optionSelectedInt"]![questionNumber] = i; + }); + int j = 0; + for(j = 0; j<10; j++) { + if(questionsData["options"]![questionNumber][i].toString() == questionsData["options"]![questionNumber][j].toString()) { + break; + } + } + if(questionsData["statistics"]![questionNumber][j] == 1) { + setState(() { + questionsData["answeredCorrectly"]![questionNumber] = "correct"; + }); + correct = 1; + // print("correct: " + correct.toString()); + // print(questionsData["answeredCorrectly"]); + } + else if(questionsData["statistics"]![questionNumber][j] == 0) { + setState(() { + questionsData["answeredCorrectly"]![questionNumber] = "incorrect"; + }); + correct = 0; + // print(questionsData["answeredCorrectly"]); + } + for(int c = 0; c QuestionExplanation(question: questionsData["question"]![questionNumber].toString(), correctAnswer: correctAns.toString(), questionId: questionsData["id"]![questionNumber], explanation: questionsData["correct_msg"]![questionNumber].toString(),)), + // ); + // }, + // child: Container( + // alignment: Alignment.topRight, + // child: Text( + // "See Explanation", + // style: TextStyle( + // color: Color(0xFF7F1AF1), + // fontFamily: 'Brandon-med', + // fontSize: (MediaQuery.of(context).size.height) * + // (13 / 926), //38, + // ), + // ), + // ), + // ) : Container(), + SizedBox( + height: (MediaQuery.of(context).size.height) * (20 / 926), + ), + ], + ),// here + SizedBox( + height: (MediaQuery.of(context).size.height) * (5 / 926), + ), + SizedBox( + height: (MediaQuery.of(context).size.height) * (96 / 926), + ), + Row( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + Container( + alignment: Alignment.bottomRight, + child: InkWell( + child: Icon(Icons.power_settings_new, + color: Color(0xFF7F1AF1), + size: (MediaQuery.of(context).size.height) * + (23 / 926),), + ), + ), + SizedBox( + width: (MediaQuery.of(context).size.width) * (5 / 428), + ), + Container( + alignment: Alignment.bottomRight, + child: InkWell( + child: Text( + "Quit Quiz", + style: TextStyle( + color: Color(0xFF7F1AF1), + fontFamily: 'Brandon-bld', + fontSize: (MediaQuery.of(context).size.height) * + (13 / 926), //38, + ), + ), + onTap: () => _onQuit())), + ], + ), + SizedBox( + height: (MediaQuery.of(context).size.height) * (26 / 926), + ), + ], + )), + ], + ), + ), + ) , + Align( + alignment: Alignment.bottomCenter, + child: Container( + height: ((MediaQuery.of(context).size.height) * (51 / 926)), + decoration: const BoxDecoration( + gradient: LinearGradient( + begin: Alignment.topCenter, + end: Alignment.bottomCenter, + colors: [Color(0xff7F1AF1), Color(0xff482384)])), + child: _showTextZoom == true ? _textZoom(context) : Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + TextButton( + onPressed: () { + if(questionNumber > 0) { + setState(() { + questionNumber--; + }); + } + }, + style: TextButton.styleFrom( + padding: EdgeInsets.zero,), + child: Row( + children: [ + SizedBox(width: (MediaQuery.of(context).size.width) * (16 / 428)), + Container( + child: Icon(Icons.arrow_back_ios_outlined, + color: Colors.white, + size: ((MediaQuery.of(context).size.width) * (23.1 / 428)),), + ), + ], + ), + ), + Builder( + builder: (context) => TextButton( + onPressed: () { Scaffold.of(context).openEndDrawer(); }, + style: TextButton.styleFrom( + padding: EdgeInsets.zero,), + child: Row( + children: [ + Container( + width: ((MediaQuery.of(context).size.height) * (15 / 926)), + decoration: BoxDecoration( + color: Colors.white, + shape: BoxShape.circle + ), + ), + SizedBox(width: (MediaQuery.of(context).size.width) * (6 / 428)), + Container( + width: ((MediaQuery.of(context).size.height) * (15 / 926)), + decoration: BoxDecoration( + color: Colors.white, + shape: BoxShape.circle + ), + ), + SizedBox(width: (MediaQuery.of(context).size.width) * (6 / 428)), + Container( + width: ((MediaQuery.of(context).size.height) * (15 / 926)), + decoration: BoxDecoration( + color: Colors.white, + shape: BoxShape.circle + ), + ), + ], + ), + ), + ), + TextButton( + onPressed: () { + if(questionNumber < (widget.totalQuestions - 1)) { + setState(() { + questionNumber++; + }); + } + }, + style: TextButton.styleFrom( + padding: EdgeInsets.zero,), + child: Row( + children: [ + Container( + child: Icon(Icons.arrow_forward_ios_outlined, + color: Colors.white, + size: ((MediaQuery.of(context).size.width) * (23.1 / 428)),), + ), + SizedBox(width: (MediaQuery.of(context).size.width) * (16 / 428)), + ], + ), + ), + ], + ), + ), + ) + ], + ), + ), + ); + } +} diff --git a/lib/screens/Welcome/QuizModule/search_bar.dart b/lib/screens/Welcome/QuizModule/search_bar.dart new file mode 100644 index 0000000..6f925a0 --- /dev/null +++ b/lib/screens/Welcome/QuizModule/search_bar.dart @@ -0,0 +1,861 @@ +import 'package:flutter/material.dart'; + +class SearchListExample extends StatefulWidget { + @override + _SearchListExampleState createState() => new _SearchListExampleState(); +} + +class _SearchListExampleState extends State with SingleTickerProviderStateMixin { + + final bloodLabValues = [ + {"title": 'Alanine aminotransferase (ALT), serum', "value": '8-40 U/L', "siValue": '8-40 U/L', + "subtitle": [{"title": '', "value": ''}] + }, + {"title": 'Alkaline phosphatase, serum ', "value": '', "siValue": '', + "subtitle": [ + {"title": 'Male', "value": '30-100 U/L', "siValue": '30-100 U/L'}, + {"title": 'Female', "value": '45-115 U/L', "siValue": '45-115 U/L'}, + ] + }, + {"title": 'Amylase, serum', "value": '25-125 U/L', "subtitle": [], "siValue": '25-125 U/L' }, + {"title": 'Aspartate aminotransferase (AST), serum', "value": '8-40 U/L', "subtitle": [], "siValue": '8-40 U/L'}, + {"title": 'Bilirubin, serum (adult)' , "value": '', "siValue": '', + "subtitle": [ + {"title": 'Total', "value": '0.1-1.0 mg/dL', "siValue": '2-17 μmol/L'}, + {"title": 'Direct', "value": '0.0-0.3 mg/dL', "siValue": '0.0-0.05 μmol/L'}, + ] + }, + {"title": 'Calcium, serum (total)', "value": '8.4-10.2 mg/dL', "subtitle": [], "siValue": '2.1-2.8 mmol/L'}, + {"title": 'Cholesterol, serum' , "value": '', "siValue": '', + "subtitle": [ + {"title": 'Total', "value": '150-240 mg/dL', "siValue": '3.9-6.2 mmol/L'}, + {"title": 'HDL', "value": '0-70 mg/dL', "siValue": '0.8-1.8 mmol/L'}, + {"title": 'LDL', "value": '<160 mg/dL', "siValue": '<4.2 mmol/L'}, + ] + }, + {"title": 'Cortisol, serum', "value": '', "siValue": '', + "subtitle": [ + {"title": '0800 h', "value": '5-23 μg/dL', "siValue": '138-635 nmol/L'}, + {"title": '1600 h', "value": '3-15 μg/dL', "siValue": '82-413 nmol/L'}, + {"title": '2000 h', "value": '50% of 0800 h', "siValue": 'Fraction of 0800 h: ≤0.50'}, + ] + }, + {"title": 'Creatine kinase, serum', "value": '', "siValue": 'L', + "subtitle": [ + {"title": 'Male', "value": '25-90 U/L', "siValue": '25-90 U/L'}, + {"title": 'Female', "value": '10-70 U/L', "siValue": '10-70 U/L'}, + ] + }, + {"title": 'Creatinine, serum', "value": '0.6-1.2 mg/dL', "subtitle": [], "siValue": '53-106 μmol/L'}, + {"title": 'Electrolytes, serum', "value": '', "siValue": '', + "subtitle": [ + {"title": 'Sodium (Na+)', "value": '136-145 mEq/L', "siValue": '136-145 mEq/L'}, + {"title": 'Potassium (K+)', "value": '3.5-5.0 mEq/L', "siValue": '95-105 mmol/L'}, + {"title": 'Chloride (Cl-)', "value": '95-105 mEq/L', "siValue": '3.5-5.0 mmol/L'}, + {"title": 'Bicarbonate (HCO3-)', "value": '22-28 mEq/L', "siValue": '22-28 mEq/L'}, + {"title": 'Magnesium (Mg2+)', "value": '1.5-2.0 mEq/L', "siValue": '0.75-1.0 mmol/L'}, + ] + }, + {"title": 'Estriol, total, serum (in pregnancy)', "value": '', "siValue": '', + "subtitle": [ + {"title": '24-28 wks', "value": '30-170 ng/mL', "siValue": '104-590 nmol/L'}, + {"title": '28-32 wks', "value": '40-220 ng/mL', "siValue": '140-760 nmol/L'}, + {"title": '32-36 wks', "value": '60-280 ng/mL', "siValue": '208-970 nmol/L'}, + {"title": '36-40 wks', "value": '80-350 ng/mL', "siValue": '280-1210 nmol/L'}, + ] + }, + + {"title": 'Ferritin, serum', "value": '', "siValue": '', + "subtitle": [ + {"title": 'Male', "value": '15-200 ng/mL', "siValue": '15-200 ng/mL'}, + {"title": 'Female', "value": '12-150 ng/mL', "siValue": '12-150 ng/mL'}, + ] + }, + {"title": 'Follicle-stimulating hormone, serum/plasma', "value": '', "siValue": '', + "subtitle": [ + {"title": 'Male', "value": '4-25 mIU/mL', "siValue": '4-25 mIU/mL'}, + {"title": 'Female', "value": '', "siValue": ''}, + {"title": 'premenopause', "value": '4-30 mIU/mL', "siValue": '4-30 mIU/mL'}, + {"title": 'midcycle peak', "value": '10-90 mIU/mLL', "siValue": '10-90 mIU/mLL'}, + {"title": 'postmenopause', "value": '40-250 mIU/mL', "siValue": '40-250 mIU/mL'}, + ] + }, + {"title": 'Gases, arterial blood (room air)', "value": '', "siValue": '', + "subtitle": [ + {"title": 'pH', "value": '7.35-7.45', "siValue": '[H+] 36-44 nmol/L'}, + {"title": 'Pco2', "value": '33-45 mm Hg', "siValue": '4.4-5.9 kPa'}, + {"title": 'Po2', "value": '75-105 mm Hg', "siValue": '10.0-14.0 kPa'}, + ] + }, + {"title": 'Glucose, serum', "value": '', "siValue": '', + "subtitle": [ + {"title": 'Fasting', "value": '70-110 mg/dL', "siValue": '3.8-6.1 mmol/L'}, + {"title": '2-h postprandial', "value": '<120 mg/dL', "siValue": '<6.6 mmol/L'}, + ] + }, + {"title": 'Growth hormone- arginine stimulation', "value": '', "siValue": '', + "subtitle": [ + {"title": 'Fasting', "value": '<5 ng/mL', "siValue": '<5 ng/mL'}, + {"title": 'Provocative stimuli', "value": '>7 ng/mL', "siValue": '>7 μg/L'}, + ] + }, + {"title": 'Immunoglobulins, serum', "value": '', "siValue": '', + "subtitle": [ + {"title": 'IgA', "value": '76-390 mg/dL', "siValue": '0.76-3.90 g/L'}, + {"title": 'IgE', "value": '0-380 IU/mL', "siValue": '0-380 kIU/L'}, + {"title": 'IgG', "value": '650-1,500 mg/dL', "siValue": '6.5-15 g/L'}, + {"title": 'IgM', "value": '40-345 mg/dL', "siValue": '0.4-3.45 g/L'}, + ] + }, + {"title": 'Iron', "value": '50-170 μg/dL', "subtitle": [], "siValue": '9-30 μmol/LL'}, + {"title": 'Lactate dehydrogenase, serum', "value": '45-90 U/L (100-250 IU/L)', "siValue": '45-90 U/L (100-250 IU/L)', + "subtitle": [] + }, + {"title": 'Luteinizing hormone, serum/plasma', "value": '', "siValue": '', + "subtitle": [ + {"title": 'Male', "value": '6-23 mIU/mL', "siValue": '6-23 U/L'}, + {"title": 'Female', "value": '', "siValue": ''}, + {"title": 'follicular phase', "value": '5-30 mIU/mL', "siValue": '5-30 U/L'}, + {"title": 'midcycle', "value": '75-150 mIU/mL', "siValue": '75-150 U/L'}, + {"title": 'postmenopause', "value": '30-200 mIU/mL', "siValue": '30-200 U/L'}, + ] + }, + {"title": 'Osmolality, serum', "value": '275-295 mOsmol/kg H2O', "siValue": '275-295 mOsmol/kg H2O', + "subtitle": [] + }, + {"title": 'Parathyroid hormone, serum, N-terminal', "value": '10-65 pg/mL', "siValue": '10-65 pg/mL', + "subtitle": [] + }, + {"title": 'Phosphate (alkaline), serum (p-NPP at 30° C)', "value": '20-70 U/L', "siValue": '20-70 U/L', + "subtitle": [] + }, + {"title": 'Phosphorus (inorganic), serum', "value": '3.0-4.5 mg/dL', "siValue": '1.0-1.5 mmol/L', + "subtitle": [] + }, + + {"title": 'Prolactin, serum (hPRL) ', "value": '<20 ng/mL', "siValue": '<20 ng/mL', + "subtitle": [] + }, + {"title": 'Proteins, serum', "value": '', "siValue": '', + "subtitle": [ + {"title": 'Total (recumbent)', "value": '6.0-7.8 g/dL', "siValue": '60-78 g/L'}, + {"title": 'Albumin', "value": '3.5-5.5 g/dL', "siValue": '35-55 g/L'}, + {"title": 'Globulin', "value": '2.3-3.5 g/dL', "siValue": '23-35 g/L'}, + ] + }, + {"title": 'Thyroid-stimulating hormone (TSH), serum', "value": '0.5-5.0 μU/mL', "siValue": '0.5-5.0 μU/mL', + "subtitle": [] + }, + {"title": 'Thyroidal iodine (123I) uptake', "value": '8%-30% of administered dose/24 h', "siValue": '0.08-0.30 fraction of administered dose/24 h', + "subtitle": [] + }, + {"title": 'Thyroxine (T4), serum', "value": '5-12 μg/dL', "siValue": '64-155 nmol/L', + "subtitle": [] + }, + {"title": 'Triglycerides, serum', "value": '35-160 mg/dL', "siValue": '0.4-1.81 mmol/L', + "subtitle": [] + }, + {"title": 'Triiodothyronine (T3), serum (RIA)', "value": '115-190 ng/dL', "siValue": '1.8-2.9 nmol/L', + "subtitle": [] + }, + {"title": 'Triiodothyronine (T3) resin uptake', "value": '25%-35%', "siValue": '0.25-0.35', + "subtitle": [] + }, + {"title": 'Urea nitrogen, serum (BUN)', "value": '7-18 mg/dL', "siValue": '1.2-3.0 mmol/L', + "subtitle": [] + }, + {"title": 'Uric acid, serum', "value": '3.0-8.2 mg/dL', "siValue": '0.18-0.48 mmol/L', + "subtitle": [] + }, + + ]; + final HematologicLabValues = [ + {"title": 'Bleeding time (template)', "value": '2-7 minutes', "siValue": '2-7 minutes', + "subtitle": [] + }, + {"title": 'CD4+ T-lymphocyte count', "value": '>500 mm^3', "siValue": '>500 x 106/L', + "subtitle": [] + }, + {"title": 'Erythrocyte count', "value": '', "siValue": '', + "subtitle": [ + {"title": 'Male', "value": '4.3-5.9 million/mm^3', "siValue": '4.3-5.9 x 10^12/L'}, + {"title": 'Female', "value": '3.5-5.5 million/mm^3', "siValue": '3.5-5.5 x 10^12/L'}, + ] + }, + {"title": 'Erythrocyte sedimentation rate (Westergren)', "value": '', "siValue": '', + "subtitle": [ + {"title": 'Male', "value": '0-15 mm/h', "siValue": '0-15 mm/h'}, + {"title": 'Female', "value": '0-20 mm/h', "siValue": '0-20 mm/h'}, + ] + }, + {"title": 'Hematocrit', "value": '', "siValue": '', + "subtitle": [ + {"title": 'Male', "value": '41%-53%', "siValue": '0.41-0.53'}, + {"title": 'Female', "value": '36%-46%', "siValue": '0.36-0.46'}, + ] + }, + {"title": 'Hemoglobin A1c', "value": '≤6%', "siValue": '≤0.06', + "subtitle": [] + }, + {"title": 'Hemoglobin, blood', "value": '', "siValue": '', + "subtitle": [ + {"title": 'Male', "value": '13.5-17.5 g/dL', "siValue": '2.09-2.71 mmol/L'}, + {"title": 'Female', "value": '12.0-16.0 g/dL', "siValue": '1.86-2.48 mmol/L'}, + ] + }, + {"title": 'Leukocyte count and differential', "value": '', "siValue": '', + "subtitle": [ + {"title": 'Leukocyte count', "value": '4,500-11,000/mm^3', "siValue": '4.5-11.0 x 10^9/L'}, + {"title": 'Neutrophils, segmented', "value": '54%-62%', "siValue": '0.54-0.62'}, + {"title": 'Neutrophils, banded', "value": '3%-5%', "siValue": '0.03-0.05'}, + {"title": 'Eosinophils', "value": '1%-3%', "siValue": '0.01-0.03'}, + {"title": 'Basophils', "value": '0%-0.75%', "siValue": '0-0.0075'}, + {"title": 'Lymphocytes', "value": '25%-33%', "siValue": '0.25-0.33'}, + {"title": 'Monocytes', "value": '3%-7%', "siValue": '0.03-0.07'}, + ] + }, + {"title": 'Mean corpuscular hemoglobin (MCH)', "value": '25.4-34.6 pg/cell', "siValue": '0.39-0.54 fmol/cell', + "subtitle": [] + }, + {"title": 'Mean corpuscular hemoglobin concentration (MCHC)', "value": '31%-36% Hb/cell', "siValue": '4.81-5.58 mmol Hb/L', + "subtitle": [] + }, + {"title": 'Mean corpuscular volume (MCV)', "value": '80-100 μm3', "siValue": '80-100 fL', + "subtitle": [] + }, + {"title": 'Partial thromboplastin time (activated)', "value": '25-40 seconds', "siValue": '25-40 seconds', + "subtitle": [] + }, + {"title": 'Platelet count', "value": '150,000-400,000/mm^3', "siValue": '150-400 x 10^9/L', + "subtitle": [] + }, + {"title": 'Prothrombin time', "value": '11-15 seconds', "siValue": '11-15 seconds', + "subtitle": [] + }, + {"title": 'Reticulocyte count', "value": '0.5%-1.5% of red cells', "siValue": '0.005-0.015 fraction of red cells', + "subtitle": [] + }, + {"title": 'Thrombin time', "value": '<2 seconds deviation from control', "siValue": '<2 seconds deviation from control', + "subtitle": [] + }, + {"title": 'Volume', "value": '', "siValue": '', + "subtitle": [ + {"title": 'Plasma', "value": '', "siValue": ''}, + {"title": 'Male', "value": '25-43 mL/kg', "siValue": '0.005-0.015 fraction of red cells' }, + {"title": 'Female', "value": '28-45 mL/kg', "siValue": '0.028-0.045 L/kg'}, + {"title": 'Red cell', "value": '', "siValue": ''}, + {"title": 'Male', "value": '20-36 mL/kg', "siValue": '0.020-0.036 L/kg'}, + {"title": 'Female', "value": '19-31 mL/kg', "siValue": '0.019-0.031 L/kg'}, + ] + }, + + + ]; + final CerebrospinalLabValues = [ + {"title": 'Cell count', "value": '0-5/mm^3', "siValue": '0-5 x 10^6/L', + "subtitle": [] + }, + {"title": 'Chloride', "value": '118-132 mEq/L', "siValue": '118-132 mmol/L', + "subtitle": [] + }, + {"title": 'Gamma globulin', "value": '3%-12% of total proteins', "siValue": '0.03-0.12 of total proteins', + "subtitle": [] + }, + {"title": 'Glucose', "value": '40-70 mg/dL', "siValue": '2.2-3.9 mmol/L', + "subtitle": [] + }, + {"title": 'Pressure', "value": '70-180 mm H2O', "siValue": '70-180 mm H2O', + "subtitle": [] + }, + {"title": 'Proteins, total', "value": '<40 mg/dL', "siValue": '<0.40 g/L', + "subtitle": [] + }, + ]; + final sweatLabValues = [ + {"title": 'Calcium', "value": '100-300 mg/24 h', "siValue": '2.5-7.5 mmol/24 h', + "subtitle": [] + }, + {"title": 'Chloride', "value": '1Varies with intake', "siValue": '1Varies with intake', + "subtitle": [] + }, + {"title": 'Creatine clearance', "value": '', "siValue": '', + "subtitle": [ + {"title": 'Male', "value": '97-137 mL/min', "siValue": '1.62-2.29 mL/s'}, + {"title": 'Female', "value": '88-128 mL/min', "siValue": '1.47-2.14 mL/s'}, + ] + }, + {"title": 'Estriol, total (in pregnancy)', "value": '', "siValue": '', + "subtitle": [ + {"title": '30 wks', "value": '6-18 mg/24 h', "siValue": '21-62 μmol/24 h'}, + {"title": '35 wks', "value": '9-28 mg/24 h', "siValue": '31-97 μmol/24 h'}, + {"title": '40 wks', "value": '13-42 mg/24 h', "siValue": '45-146 μmol/24 h'}, + ] + }, + {"title": '17-hydroxycorticosteroids', "value": '', "siValue": '', + "subtitle": [ + {"title": 'Male', "value": '3.0-10.0 mg/24 h', "siValue": '8.2-27.6 μmol/24 h'}, + {"title": 'Female', "value": '2.0-8.0 mg/24 h', "siValue": '5.5-22.0 μmol/24 h'}, + ] + }, + {"title": '17-ketosteroids, total', "value": '', "siValue": '', + "subtitle": [ + {"title": 'Male', "value": '8-20 mg/24 h', "siValue": '28-70 μmol/24 h'}, + {"title": 'Female', "value": '6-15 mg/24 h', "siValue": '21-52 μmol/24 h'}, + ] + }, + {"title": 'Osmolality', "value": '50-1,400 mOsmol/kg H2O', "siValue": '50-1,400 mmol/kg', + "subtitle": [] + }, + {"title": 'Oxalate', "value": '8-40 μg/mL', "siValue": '90-445 μmol/L', + "subtitle": [] + }, + {"title": 'Proteins, total', "value": '<150 mg/24 h', "siValue": '<0.15 g/24 h', + "subtitle": [] + }, + {"title": 'Sodium, total', "value": 'varies with diet', "siValue": 'varies with diet', + "subtitle": [] + }, + {"title": 'Uric acid', "value": 'varies with diet', "siValue": 'varies with diet', + "subtitle": [] + }, + {"title": 'Body Mass Index (Adult)', "value": '19-25 kg/m^2', "siValue": '19-25 kg/m^2', + "subtitle": [] + }, + ]; + + + + Widget appBarTitle = new Text( + "Search Values", + style: new TextStyle(color: Colors.white), + ); + Icon icon = new Icon( + Icons.search, + color: Colors.white, + ); + final globalKey = new GlobalKey(); + final TextEditingController _controller = new TextEditingController(); + List _list = []; // = ["Indian rupee", "United States dollar", "Australian dollar", "Euro", "British pound", "Yemeni rial", "Japanese yen", "Hong Kong dollar"]; + bool _isSearching = false; + String _searchText = ""; + List searchresult = []; + bool _siValues = false; + late TabController _tabController; + + var bloodLabValuesData = { + "title" : [], + "value" : [], + "siValue" : [] + }; + var HematologicLabValuesData = { + "title" : [], + "value" : [], + "siValue" : [] + }; + var CerebrospinalLabValuesData = { + "title" : [], + "value" : [], + "siValue" : [] + }; + var sweatLabValuesData = { + "title" : [], + "value" : [], + "siValue" : [] + }; + + var LabValuesList = { + "title" : [], + "value" : [], + "siValue" : [] + }; + + categorizebloodLabValues() { + for(int i = 0; i; + }); + // print(CerebrospinalLabValuesData["title"]); + // print(_list); + } + + _SearchListExampleState() { + _controller.addListener(() { + if (_controller.text.isEmpty) { + setState(() { + _isSearching = false; + _searchText = ""; + }); + } else { + setState(() { + _isSearching = true; + _searchText = _controller.text; + }); + } + }); + } + + @override + void initState() { + super.initState(); + _tabController = TabController(vsync: this, length: 4) + ..addListener(() { + setState(() { + if(_tabController.index == 0){ + // print(_tabController.index); + setState(() { + _handleSearchEnd(); + if(bloodLabValuesData["title"] != null) + _list = bloodLabValuesData["title"] as List; + _isSearching = false; + _searchText = ""; + searchOperation(""); + }); + } + else if(_tabController.index == 1){ + // print(_tabController.index); + setState(() { + _handleSearchEnd(); + if(HematologicLabValuesData["title"] != null) + _list = HematologicLabValuesData["title"] as List; + _isSearching = false; + _searchText = ""; + searchOperation(""); + }); + } + else if(_tabController.index == 2){ + // print(_tabController.index); + setState(() { + _handleSearchEnd(); + if(CerebrospinalLabValuesData["title"] != null) + _list = CerebrospinalLabValuesData["title"] as List; + _isSearching = false; + _searchText = ""; + searchOperation(""); + }); + } + else if(_tabController.index == 3){ + // print(_tabController.index); + setState(() { + _handleSearchEnd(); + if(sweatLabValuesData["title"] != null) + _list = sweatLabValuesData["title"] as List; + _isSearching = false; + _searchText = ""; + searchOperation(""); + }); + } + }); + }); + categorizebloodLabValues(); + _isSearching = false; + } + + @override + void dispose() { + _tabController.dispose(); + super.dispose(); + } + + Widget listTiles() { + return Container( // _tabController.index == 0 + child: ListView( + scrollDirection: Axis.vertical, + children: [ + Container( + child: searchresult.length != 0 || _controller.text.isNotEmpty + ? Column( + children: [ + for(int j = 0; j<_list.length;j++) + for(int i = 0; i[ + Color(0xff7F1AF1), + Color(0xff482384) + ]) + ), + ), + title: appBarTitle, actions: [ + new IconButton( + icon: icon, + onPressed: () { + setState(() { + if (this.icon.icon == Icons.search) { + this.icon = new Icon( + Icons.close, + color: Colors.white, + ); + this.appBarTitle = new TextField( + controller: _controller, + style: new TextStyle( + color: Colors.white, + ), + decoration: new InputDecoration( + prefixIcon: new Icon(Icons.search, color: Colors.white), + hintText: "Search...", + hintStyle: new TextStyle(color: Colors.white)), + onChanged: searchOperation, + ); + _handleSearchStart(); + } else { + _handleSearchEnd(); + } + }); + }, + ), + ]), + body: SingleChildScrollView( + child: Column( + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Container( + padding: EdgeInsets.only(top: (MediaQuery.of(context).size.height) * (30 / 926), bottom: (MediaQuery.of(context).size.height) * (20 / 926), + left: (MediaQuery.of(context).size.width) * (20 / 428)), + alignment: Alignment.center, + child: Text( + "Lab Values", + style: TextStyle( + color: Color(0xff232323), + fontFamily: 'Brandon-bld', + fontSize: (MediaQuery.of(context).size.height) * + (20 / 926), //38, + ), + ), + ), + Row( + children: [ + Transform.scale( + scale: 1, + child: Container( + height: (MediaQuery.of(context).size.height) *(15/926), + child: Switch( + value: _siValues, + onChanged: (value) { + setState(() { + _siValues = value; + // print(_siValues); + }); + }, + activeColor: Color(0xff3F2668), + ), + ), + ), + Container( + child: Text("Si Reference Intervals", + style: TextStyle( + color: Color(0xff483A3A), + fontFamily: 'Brandon-med', + fontSize: (MediaQuery.of(context).size.height) *(15/926) + ), + ), + ), + SizedBox(width: (MediaQuery.of(context).size.width) *(10/428)), + + ], + ), + ], + ), + Container( + margin: EdgeInsets.only(left: (MediaQuery.of(context).size.width) * (15 / 428), right: (MediaQuery.of(context).size.width) * (15 / 428)), + // padding: EdgeInsets.only(left: (MediaQuery.of(context).size.width) * (10 / 428), right: (MediaQuery.of(context).size.width) * (10 / 428)), + decoration: BoxDecoration( + border: Border(bottom: BorderSide(color: Colors.grey, width: 2)) + ), + child: TabBar( + padding: EdgeInsets.zero, + indicatorPadding: EdgeInsets.zero, + labelPadding: EdgeInsets.zero, + controller: _tabController, + tabs: [ + Tab(icon: Text( + "Blood", + style: TextStyle( + color: Color(0xff232323), + fontFamily: 'Brandon-bld', + fontSize: (MediaQuery.of(context).size.height) * + (15 / 926), //38, + ), + ),), + Tab(icon: Text( + "Hematologic", + style: TextStyle( + color: Color(0xff232323), + fontFamily: 'Brandon-bld', + fontSize: (MediaQuery.of(context).size.height) * + (15 / 926), //38, + ), + ),), + Tab(icon: Text( + "Cerebrospinal", + style: TextStyle( + color: Color(0xff232323), + fontFamily: 'Brandon-bld', + fontSize: (MediaQuery.of(context).size.height) * + (15 / 926), //38, + ), + ),), + Tab(icon: Text( + "Sweat", + style: TextStyle( + color: Color(0xff232323), + fontFamily: 'Brandon-bld', + fontSize: (MediaQuery.of(context).size.height) * + (15 / 926), //38, + ), + ),), + ], + ), + ), + SizedBox(height: (MediaQuery.of(context).size.height) * + (8 / 926),), + Row( + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Container( + width: ((MediaQuery.of(context).size.width)*(2/3)), + padding: EdgeInsets.only(left: (MediaQuery.of(context).size.width) * + (20 / 428)), + child: Text( + _tabController.index == 0 ? "Blood, Plasma, Serum" : + _tabController.index == 1 ? "Serum" : + _tabController.index == 2 ? "Cerebrospinal Fluid" : + _tabController.index == 3 ? "Urine" : "Urine", + style: TextStyle( + color: Color(0xff232323), + fontFamily: 'Brandon-bld', + fontSize: (MediaQuery.of(context).size.height) * + (15 / 926), //38, + ), + ), + ), + Container( + padding: EdgeInsets.only(right: (MediaQuery.of(context).size.width) * + (20 / 428)), + child: Text( + _siValues == true ? "Si Reference Interval" : "Reference Range", + style: TextStyle( + color: Color(0xff232323), + fontFamily: 'Brandon-bld', + fontSize: (MediaQuery.of(context).size.height) * + (15 / 926), //38, + ), + ), + ), + ], + ), + Container( + padding: EdgeInsets.only(left: (MediaQuery.of(context).size.width) * (15 / 428), right: (MediaQuery.of(context).size.width) * (15 / 428)), + child: Divider(thickness: 0.4, color: Colors.grey,)), + Container( + padding: EdgeInsets.only(left: (MediaQuery.of(context).size.width) * (15 / 428), right: (MediaQuery.of(context).size.width) * (15 / 428)), + height: MediaQuery.of(context).size.height * 0.6, + child: TabBarView( + controller: _tabController, + children: [ + //Tab 1 + listTiles(), + //Tab 2 + listTiles(), + //Tab 3 + listTiles(), + //Tab 4 + listTiles(), + ], + ), + ), + ], + ), + )), + ); + } + + + void _handleSearchStart() { + setState(() { + _isSearching = true; + }); + } + + void _handleSearchEnd() { + setState(() { + this.icon = new Icon( + Icons.search, + color: Colors.white, + ); + this.appBarTitle = new Text( + "Search Values", + style: new TextStyle(color: Colors.white), + ); + _isSearching = false; + _controller.clear(); + }); + } + + void searchOperation(String searchText) { + searchresult.clear(); + if (_isSearching != null) { + for (int i = 0; i < _list.length; i++) { + String data = _list[i]; + if (data.toLowerCase().contains(searchText.toLowerCase())) { + searchresult.add(data); + } + } + } + } +} diff --git a/lib/screens/Welcome/side_menu_bar.dart b/lib/screens/Welcome/side_menu_bar.dart new file mode 100644 index 0000000..1553495 --- /dev/null +++ b/lib/screens/Welcome/side_menu_bar.dart @@ -0,0 +1,93 @@ +import 'package:flutter/material.dart'; +import 'package:testify/screens/Welcome/GenerateQuiz/generate_quiz.dart'; +import 'package:testify/screens/Welcome/Notes/notes.dart'; + +import 'PreviousQuiz/previous_quiz.dart'; + +class SideMenuBar extends StatelessWidget { + @override + Widget build(BuildContext context) { + return Container( + width: (MediaQuery.of(context).size.width) *0.7, + child: Drawer( + child: ListView( + // Remove padding + padding: EdgeInsets.zero, + children: [ + Container( + padding: EdgeInsets.only(top: MediaQuery.of(context).padding.top), + height: (MediaQuery.of(context).size.height), + decoration: const BoxDecoration( + gradient: LinearGradient( + begin: Alignment.topRight, + end: Alignment.bottomLeft, + colors: [Color(0xff3F2668), Color(0xff482384)])), + width: (MediaQuery.of(context).size.width) *0.7, + child: Column( + children: [ + ListTile( + leading: Icon(Icons.arrow_back, color: Colors.white,), + title: Text('Close', style: TextStyle(color: Colors.white),), + onTap: () => Navigator.pop(context), + ), + Divider(), + ListTile( + leading: Icon(Icons.quiz_outlined, color: Colors.white,), + title: Text('Generate Quiz', style: TextStyle(color: Colors.white),), + onTap: () async { + // Navigator.of(context).pop(); + Navigator.of(context) + .popUntil(ModalRoute.withName("/home")); + final result = await Navigator.push( + context, + MaterialPageRoute(builder: (context) => GenerateQuiz()), + ); + // final result = Navigator.pushAndRemoveUntil( + // context, + // MaterialPageRoute(builder: (BuildContext context) => GenerateQuiz()), + // ModalRoute.withName('/home'), + // ); + }, + ), + ListTile( + leading: Icon(Icons.quiz_outlined, color: Colors.white,), + title: Text('Previous Quiz', style: TextStyle(color: Colors.white),), + onTap: () async { + // Navigator.of(context).pop(); + + Navigator.of(context) + .popUntil(ModalRoute.withName("/home")); + final result = await Navigator.push( + context, + MaterialPageRoute(builder: (context) => PreviousQuiz()), + ); + + // final result = Navigator.pushAndRemoveUntil( + // context, + // MaterialPageRoute(builder: (BuildContext context) => PreviousQuiz()), + // ModalRoute.withName('/home'), + // ); + }, + ), + ListTile( + leading: Icon(Icons.notes_outlined, color: Colors.white,), + title: Text('Notes', style: TextStyle(color: Colors.white),), + onTap: () async { + Navigator.of(context) + .popUntil(ModalRoute.withName("/home")); + final result = await Navigator.push( + context, + MaterialPageRoute(builder: (context) => Notes()), + ); + }, + ), + ], + ), + ), + //Divider(), + ], + ), + ), + ); + } +} \ No newline at end of file diff --git a/lib/screens/home.dart b/lib/screens/home.dart new file mode 100644 index 0000000..503f884 --- /dev/null +++ b/lib/screens/home.dart @@ -0,0 +1,168 @@ +import 'dart:async'; +import 'dart:convert'; + +import 'package:flutter/material.dart'; +import 'package:flutter_svg/svg.dart'; +import 'package:shared_preferences/shared_preferences.dart'; +import 'package:testify/auth_storage.dart'; +import 'package:testify/screens/Authentication/login.dart'; +import 'package:testify/screens/Welcome/side_menu_bar.dart'; +import 'package:testify/screens/Welcome/QuizModule/search_bar.dart'; +import 'package:http/http.dart' as http; + +class Home extends StatefulWidget { + const Home({Key? key}) : super(key: key); + + @override + _HomeState createState() => _HomeState(); +} + +class _HomeState extends State with WidgetsBindingObserver{ + + AppLifecycleState? _lastLifecycleState; + + @override + void initState() { + super.initState(); + WidgetsBinding.instance!.addObserver(this); + } + + @override + void dispose() { + WidgetsBinding.instance!.removeObserver(this); + super.dispose(); + } + + @override + void didChangeAppLifecycleState(AppLifecycleState state) async { + super.didChangeAppLifecycleState(state); + + // if(state == AppLifecycleState.detached){ + // + // } + + final isBackground = state == AppLifecycleState.paused; + final isClosed = state == AppLifecycleState.detached; + if(isBackground) { + print("xD in Background"); + + + + } + if(isClosed) { + print("xD Closed"); + + + } + } + + @override + Widget build(BuildContext context) { + return WillPopScope( + onWillPop: () async { + ScaffoldMessenger.of(context) + ..removeCurrentSnackBar() + ..showSnackBar(SnackBar(content: Text("Press Logout Button"))); + return false; + }, + child: Scaffold( + backgroundColor: Colors.white, + drawer: SideMenuBar(), + appBar: AppBar( + backgroundColor: Color(0xff3F2668), + elevation: 2, + centerTitle: true, + flexibleSpace: Container( + decoration: BoxDecoration( + gradient: LinearGradient( + begin: Alignment.topCenter, + end: Alignment.bottomCenter, + colors: [ + Color(0xff7F1AF1), + Color(0xff482384) + ]) + ), + ), + title: const Text("Home", + style: TextStyle( + color: Color(0xffFFFEFE), + fontFamily: 'Brandon-bld', + ), + ), + actions: [ + TextButton( + onPressed: () async { + // Use this where ever Navigated to Login + final result = Navigator.pushAndRemoveUntil( + context, + MaterialPageRoute(builder: (BuildContext context) => const Login(fromWhere:"Home")), + ModalRoute.withName('/'), + ); + + }, + child: SvgPicture.asset( + "assets/Images/logout.svg", + height: (MediaQuery.of(context).size.height) *(32/926), + ), + ), + ], + ), + // body: TextButton( + // onPressed: () async { + // // final result = Navigator.push( + // // context, + // // MaterialPageRoute(builder: (context) => SearchListExample()), + // // ); + // + // + // SharedPreferences prefs = await SharedPreferences.getInstance(); + // var quizID = prefs.getInt("quizId"); + // var _token = prefs.getString('token')!; + // // print(quizID); + // final String apiUrlGenerateQuiz = "https://demo.pookidevs.com/quiz/solver/saveQuiz"; + // await http.post(Uri.parse(apiUrlGenerateQuiz), headers: { + // 'Content-type': 'application/json; charset=UTF-8', 'Authorization' : _token.toString(), + // }, body: json.encode( + // { + // "data": + // { + // "quiz" : { + // "quizId": 387155.toString(), + // "quizTitle": "First quiz", + // "quizDate": DateTime.now().toString(), + // "quizScore": "2", + // "quizTotalQuestions": "5", + // "quizStatus": "Completed", + // "quizQuestions": "[15, 18, 91, 20, 22]", + // "quizMode": "tutor", + // "quizTime": "900", + // "isTimed": false, + // "omittedQuestions": [], + // "SelectedOptionsArray": [] + // }, + // "userId": 7.toString() + // } + // }) + // ).then((response) { + // print(jsonDecode(response.body).toString()); + // if((response.statusCode == 200) & (json.decode(response.body).toString().substring(0,14) != "{status: false")) { + // + // } + // else { // Token Invalid + // final result = Navigator.pushAndRemoveUntil( + // context, + // MaterialPageRoute(builder: (BuildContext context) => const Login(fromWhere:"Home")), + // ModalRoute.withName('/'), + // ); + // } + // } + // ); + // + // + // }, + // child: Text("Search Bar"), + // ), + ), + ); + } +} From 38cc026a591376ccda844bda3800db06b0253da1 Mon Sep 17 00:00:00 2001 From: theYoungWolf-Productions Date: Tue, 31 May 2022 18:21:18 +0500 Subject: [PATCH 23/23] Upload final project --- ios/Flutter/Debug.xcconfig | 1 + ios/Flutter/Release.xcconfig | 1 + ios/Podfile | 41 + lib/generated_plugin_registrant.dart | 1 + .../dashboard_stats_model.dart | 113 + .../ResumeQuiz/resume_quiz_model.dart | 8 +- .../test_analysis_model.dart | 133 + .../get_performance_stats_model.dart | 113 + .../resultDetails/result_details_model.dart | 113 + lib/screens/Authentication/login.dart | 324 ++- lib/screens/Components/styles.dart | 23 + .../Welcome/GenerateQuiz/generate_quiz.dart | 2326 +++++++++-------- lib/screens/Welcome/Notes/noteDetails.dart | 67 +- lib/screens/Welcome/Notes/notes.dart | 51 +- .../TestAnalysis/analysisDetails.dart | 407 +++ .../TestAnalysis/mainTestAnalysisScreen.dart | 567 ++++ .../TestAnalysis/testAnalysis.dart | 174 ++ .../TestResults/mainResultDetailsScreen.dart | 362 +++ .../TestResults/resultDetails.dart | 402 +++ .../PreviousQuiz/TestResults/testResults.dart | 184 ++ .../Welcome/PreviousQuiz/previous_quiz.dart | 27 +- .../Welcome/PreviousQuiz/test_details.dart | 756 +++--- lib/screens/Welcome/PreviousQuiz/tile.dart | 2 +- .../Welcome/QuizModule/quiz_module.dart | 2103 ++++++++++----- lib/screens/home.dart | 562 +++- pubspec.lock | 161 +- pubspec.yaml | 5 + 27 files changed, 6569 insertions(+), 2458 deletions(-) create mode 100644 ios/Podfile create mode 100644 lib/models/DashboardStatsModel/dashboard_stats_model.dart create mode 100644 lib/models/GetPreviousQuizzesModel/TestAnalysisModel/test_analysis_model.dart create mode 100644 lib/models/PerformanceModels/get_performance_stats_model.dart create mode 100644 lib/models/resultDetails/result_details_model.dart create mode 100644 lib/screens/Components/styles.dart create mode 100644 lib/screens/Welcome/PreviousQuiz/TestAnalysis/analysisDetails.dart create mode 100644 lib/screens/Welcome/PreviousQuiz/TestAnalysis/mainTestAnalysisScreen.dart create mode 100644 lib/screens/Welcome/PreviousQuiz/TestAnalysis/testAnalysis.dart create mode 100644 lib/screens/Welcome/PreviousQuiz/TestResults/mainResultDetailsScreen.dart create mode 100644 lib/screens/Welcome/PreviousQuiz/TestResults/resultDetails.dart create mode 100644 lib/screens/Welcome/PreviousQuiz/TestResults/testResults.dart diff --git a/ios/Flutter/Debug.xcconfig b/ios/Flutter/Debug.xcconfig index 0b2d479..dfd2626 100644 --- a/ios/Flutter/Debug.xcconfig +++ b/ios/Flutter/Debug.xcconfig @@ -1 +1,2 @@ +#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig" #include "Generated.xcconfig" diff --git a/ios/Flutter/Release.xcconfig b/ios/Flutter/Release.xcconfig index 0b2d479..a97381a 100644 --- a/ios/Flutter/Release.xcconfig +++ b/ios/Flutter/Release.xcconfig @@ -1 +1,2 @@ +#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig" #include "Generated.xcconfig" diff --git a/ios/Podfile b/ios/Podfile new file mode 100644 index 0000000..1e8c3c9 --- /dev/null +++ b/ios/Podfile @@ -0,0 +1,41 @@ +# Uncomment this line to define a global platform for your project +# platform :ios, '9.0' + +# CocoaPods analytics sends network stats synchronously affecting flutter build latency. +ENV['COCOAPODS_DISABLE_STATS'] = 'true' + +project 'Runner', { + 'Debug' => :debug, + 'Profile' => :release, + 'Release' => :release, +} + +def flutter_root + generated_xcode_build_settings_path = File.expand_path(File.join('..', 'Flutter', 'Generated.xcconfig'), __FILE__) + unless File.exist?(generated_xcode_build_settings_path) + raise "#{generated_xcode_build_settings_path} must exist. If you're running pod install manually, make sure flutter pub get is executed first" + end + + File.foreach(generated_xcode_build_settings_path) do |line| + matches = line.match(/FLUTTER_ROOT\=(.*)/) + return matches[1].strip if matches + end + raise "FLUTTER_ROOT not found in #{generated_xcode_build_settings_path}. Try deleting Generated.xcconfig, then run flutter pub get" +end + +require File.expand_path(File.join('packages', 'flutter_tools', 'bin', 'podhelper'), flutter_root) + +flutter_ios_podfile_setup + +target 'Runner' do + use_frameworks! + use_modular_headers! + + flutter_install_all_ios_pods File.dirname(File.realpath(__FILE__)) +end + +post_install do |installer| + installer.pods_project.targets.each do |target| + flutter_additional_ios_build_settings(target) + end +end diff --git a/lib/generated_plugin_registrant.dart b/lib/generated_plugin_registrant.dart index ff43303..4d2b808 100644 --- a/lib/generated_plugin_registrant.dart +++ b/lib/generated_plugin_registrant.dart @@ -4,6 +4,7 @@ // ignore_for_file: directives_ordering // ignore_for_file: lines_longer_than_80_chars +// ignore_for_file: depend_on_referenced_packages import 'package:shared_preferences_web/shared_preferences_web.dart'; diff --git a/lib/models/DashboardStatsModel/dashboard_stats_model.dart b/lib/models/DashboardStatsModel/dashboard_stats_model.dart new file mode 100644 index 0000000..e4b5a6b --- /dev/null +++ b/lib/models/DashboardStatsModel/dashboard_stats_model.dart @@ -0,0 +1,113 @@ +// To parse this JSON data, do +// +// final dashboardStatsModel = dashboardStatsModelFromJson(jsonString); + +import 'dart:convert'; + +DashboardStatsModel dashboardStatsModelFromJson(String str) => DashboardStatsModel.fromJson(json.decode(str)); + +String dashboardStatsModelToJson(DashboardStatsModel data) => json.encode(data.toJson()); + +class DashboardStatsModel { + DashboardStatsModel({ + required this.data, + }); + + Data data; + + factory DashboardStatsModel.fromJson(Map json) => DashboardStatsModel( + data: Data.fromJson(json["data"]), + ); + + Map toJson() => { + "data": data.toJson(), + }; +} + +class Data { + Data({ + required this.status, + required this.totalQuestions, + required this.usedQuestions, + required this.unUsedQuestions, + required this.totalQuizzes, + required this.completedQuizzes, + required this.suspendedQuizzes, + required this.answeredQuestions, + required this.correctQuestions, + required this.incorrectQuestions, + required this.omittedQuestions, + required this.bestSubject, + required this.worstSubject, + required this.allQuizScores, + }); + + bool status; + int totalQuestions; + int usedQuestions; + int unUsedQuestions; + int totalQuizzes; + int completedQuizzes; + int suspendedQuizzes; + int answeredQuestions; + int correctQuestions; + int incorrectQuestions; + int omittedQuestions; + String bestSubject; + String worstSubject; + List allQuizScores; + + factory Data.fromJson(Map json) => Data( + status: json["status"], + totalQuestions: json["totalQuestions"], + usedQuestions: json["usedQuestions"], + unUsedQuestions: json["unUsedQuestions"], + totalQuizzes: json["totalQuizzes"], + completedQuizzes: json["completedQuizzes"], + suspendedQuizzes: json["suspendedQuizzes"], + answeredQuestions: json["answeredQuestions"], + correctQuestions: json["correctQuestions"], + incorrectQuestions: json["incorrectQuestions"], + omittedQuestions: json["omittedQuestions"], + bestSubject: json["bestSubject"], + worstSubject: json["worstSubject"], + allQuizScores: List.from(json["allQuizScores"].map((x) => AllQuizScore.fromJson(x))), + ); + + Map toJson() => { + "status": status, + "totalQuestions": totalQuestions, + "usedQuestions": usedQuestions, + "unUsedQuestions": unUsedQuestions, + "totalQuizzes": totalQuizzes, + "completedQuizzes": completedQuizzes, + "suspendedQuizzes": suspendedQuizzes, + "answeredQuestions": answeredQuestions, + "correctQuestions": correctQuestions, + "incorrectQuestions": incorrectQuestions, + "omittedQuestions": omittedQuestions, + "bestSubject": bestSubject, + "worstSubject": worstSubject, + "allQuizScores": List.from(allQuizScores.map((x) => x.toJson())), + }; +} + +class AllQuizScore { + AllQuizScore({ + required this.id, + required this.score, + }); + + int id; + double score; + + factory AllQuizScore.fromJson(Map json) => AllQuizScore( + id: json["ID"], + score: json["Score"].toDouble(), + ); + + Map toJson() => { + "ID": id, + "Score": score, + }; +} diff --git a/lib/models/GetPreviousQuizzesModel/ResumeQuiz/resume_quiz_model.dart b/lib/models/GetPreviousQuizzesModel/ResumeQuiz/resume_quiz_model.dart index 6e0a4af..f292d4b 100644 --- a/lib/models/GetPreviousQuizzesModel/ResumeQuiz/resume_quiz_model.dart +++ b/lib/models/GetPreviousQuizzesModel/ResumeQuiz/resume_quiz_model.dart @@ -1,6 +1,3 @@ -// To parse this JSON data, do -// -// final resumeQuizModel = resumeQuizModelFromJson(jsonString); import 'dart:convert'; @@ -162,18 +159,21 @@ class SelectedOptionsArray { this.correctanswerindex, this.correct, this.optionIndexSelected, + this.time }); dynamic index; dynamic correctanswerindex; dynamic correct; dynamic optionIndexSelected; + dynamic time; factory SelectedOptionsArray.fromJson(Map json) => SelectedOptionsArray( index: json["index"] == null ? null : json["index"], correctanswerindex: json["Correctanswerindex"] == null ? null : json["Correctanswerindex"], correct: json["correct"] == null ? null : json["correct"], optionIndexSelected: json["optionIndexSelected"] == null ? null : json["optionIndexSelected"], + time: json["time"] == null ? null : json["time"], ); Map toJson() => { @@ -244,7 +244,7 @@ class Question { "correct_msg": correctMsg, "answer_type": answerType, "postId": postId, - "user_id": userId == null ? null : userId, + "user_id": userId ?? null, "submitData": submitData == null ? null : submitData, "notes": notes, "questionId": questionId, diff --git a/lib/models/GetPreviousQuizzesModel/TestAnalysisModel/test_analysis_model.dart b/lib/models/GetPreviousQuizzesModel/TestAnalysisModel/test_analysis_model.dart new file mode 100644 index 0000000..5ba7209 --- /dev/null +++ b/lib/models/GetPreviousQuizzesModel/TestAnalysisModel/test_analysis_model.dart @@ -0,0 +1,133 @@ +// To parse this JSON data, do +// +// final testAnalysisModel = testAnalysisModelFromJson(jsonString); + +import 'dart:convert'; + +TestAnalysisModel testAnalysisModelFromJson(String str) => TestAnalysisModel.fromJson(json.decode(str)); + +String testAnalysisModelToJson(TestAnalysisModel data) => json.encode(data.toJson()); + +class TestAnalysisModel { + TestAnalysisModel({ + required this.data, + }); + + Data data; + + factory TestAnalysisModel.fromJson(Map json) => TestAnalysisModel( + data: Data.fromJson(json["data"]), + ); + + Map toJson() => { + "data": data.toJson(), + }; +} + +class Data { + Data({ + required this.status, + required this.bestSubject, + required this.worstSubject, + required this.timeTaken, + required this.totalQuestionsAnswered, + required this.totalCorrect, + required this.totalIncorrect, + required this.totalOmitted, + required this.totalCorrectToCorrect, + required this.totalCorrectToIncorrect, + required this.totalIncorrectToCorrect, + required this.totalIncorrectToIncorrect, + required this.subjects, + required this.systems, + required this.topics, + }); + + bool status; + String bestSubject; + String worstSubject; + String timeTaken; + int totalQuestionsAnswered; + int totalCorrect; + int totalIncorrect; + int totalOmitted; + int totalCorrectToCorrect; + int totalCorrectToIncorrect; + int totalIncorrectToCorrect; + int totalIncorrectToIncorrect; + List subjects; + List systems; + List topics; + + factory Data.fromJson(Map json) => Data( + status: json["status"], + bestSubject: json["bestSubject"], + worstSubject: json["worstSubject"], + timeTaken: json["timeTaken"], + totalQuestionsAnswered: json["totalQuestionsAnswered"], + totalCorrect: json["totalCorrect"], + totalIncorrect: json["totalIncorrect"], + totalOmitted: json["totalOmitted"], + totalCorrectToCorrect: json["totalCorrectToCorrect"], + totalCorrectToIncorrect: json["totalCorrectToIncorrect"], + totalIncorrectToCorrect: json["totalIncorrectToCorrect"], + totalIncorrectToIncorrect: json["totalIncorrectToIncorrect"], + subjects: List.from(json["subjects"].map((x) => Subject.fromJson(x))), + systems: List.from(json["systems"].map((x) => Subject.fromJson(x))), + topics: List.from(json["topics"].map((x) => Subject.fromJson(x))), + ); + + Map toJson() => { + "status": status, + "bestSubject": bestSubject, + "worstSubject": worstSubject, + "timeTaken": timeTaken, + "totalQuestionsAnswered": totalQuestionsAnswered, + "totalCorrect": totalCorrect, + "totalIncorrect": totalIncorrect, + "totalOmitted": totalOmitted, + "totalCorrectToCorrect": totalCorrectToCorrect, + "totalCorrectToIncorrect": totalCorrectToIncorrect, + "totalIncorrectToCorrect": totalIncorrectToCorrect, + "totalIncorrectToIncorrect": totalIncorrectToIncorrect, + "subjects": List.from(subjects.map((x) => x.toJson())), + "systems": List.from(systems.map((x) => x.toJson())), + "topics": List.from(topics.map((x) => x.toJson())), + }; +} + +class Subject { + Subject({ + required this.srNo, + this.category, + required this.totalQuestions, + required this.correctQuestions, + required this.incorrectQuestions, + required this.omittedQuestions, + }); + + int srNo; + dynamic category; + int totalQuestions; + int correctQuestions; + int incorrectQuestions; + int omittedQuestions; + + factory Subject.fromJson(Map json) => Subject( + srNo: json["SrNo"], + category: json["Category"] == null ? null : json["Category"], + totalQuestions: json["TotalQuestions"], + correctQuestions: json["CorrectQuestions"], + incorrectQuestions: json["IncorrectQuestions"], + omittedQuestions: json["OmittedQuestions"], + ); + + Map toJson() => { + "SrNo": srNo, + "Category": category == null ? null : category, + "TotalQuestions": totalQuestions, + "CorrectQuestions": correctQuestions, + "IncorrectQuestions": incorrectQuestions, + "OmittedQuestions": omittedQuestions, + }; +} diff --git a/lib/models/PerformanceModels/get_performance_stats_model.dart b/lib/models/PerformanceModels/get_performance_stats_model.dart new file mode 100644 index 0000000..059b0f0 --- /dev/null +++ b/lib/models/PerformanceModels/get_performance_stats_model.dart @@ -0,0 +1,113 @@ +// To parse this JSON data, do +// +// final getPerformanceStatsModel = getPerformanceStatsModelFromJson(jsonString); + +import 'dart:convert'; + +GetPerformanceStatsModel getPerformanceStatsModelFromJson(String str) => GetPerformanceStatsModel.fromJson(json.decode(str)); + +String getPerformanceStatsModelToJson(GetPerformanceStatsModel data) => json.encode(data.toJson()); + +class GetPerformanceStatsModel { + GetPerformanceStatsModel({ + required this.data, + }); + + Data data; + + factory GetPerformanceStatsModel.fromJson(Map json) => GetPerformanceStatsModel( + data: Data.fromJson(json["data"]), + ); + + Map toJson() => { + "data": data.toJson(), + }; +} + +class Data { + Data({ + required this.status, + required this.bestSubject, + required this.worstSubject, + required this.omittedSubject, + required this.totalQuizzes, + required this.completedQuizzes, + required this.suspendedQuizzes, + required this.subjects, + required this.systems, + required this.topics, + }); + + bool status; + String bestSubject; + String worstSubject; + String omittedSubject; + int totalQuizzes; + int completedQuizzes; + int suspendedQuizzes; + List subjects; + List systems; + List topics; + + factory Data.fromJson(Map json) => Data( + status: json["status"], + bestSubject: json["bestSubject"], + worstSubject: json["worstSubject"], + omittedSubject: json["omittedSubject"], + totalQuizzes: json["totalQuizzes"], + completedQuizzes: json["completedQuizzes"], + suspendedQuizzes: json["suspendedQuizzes"], + subjects: List.from(json["subjects"].map((x) => Subject.fromJson(x))), + systems: List.from(json["systems"].map((x) => Subject.fromJson(x))), + topics: List.from(json["topics"].map((x) => Subject.fromJson(x))), + ); + + Map toJson() => { + "status": status, + "bestSubject": bestSubject, + "worstSubject": worstSubject, + "omittedSubject": omittedSubject, + "totalQuizzes": totalQuizzes, + "completedQuizzes": completedQuizzes, + "suspendedQuizzes": suspendedQuizzes, + "subjects": List.from(subjects.map((x) => x.toJson())), + "systems": List.from(systems.map((x) => x.toJson())), + "topics": List.from(topics.map((x) => x.toJson())), + }; +} + +class Subject { + Subject({ + required this.srNo, + required this.category, + required this.totalQuestions, + required this.correctQuestions, + required this.incorrectQuestions, + required this.omittedQuestions, + }); + + int srNo; + dynamic category; + int totalQuestions; + int correctQuestions; + int incorrectQuestions; + int omittedQuestions; + + factory Subject.fromJson(Map json) => Subject( + srNo: json["SrNo"], + category: json["Category"] == null ? null : json["Category"], + totalQuestions: json["TotalQuestions"], + correctQuestions: json["CorrectQuestions"], + incorrectQuestions: json["IncorrectQuestions"], + omittedQuestions: json["OmittedQuestions"], + ); + + Map toJson() => { + "SrNo": srNo, + "Category": category == null ? null : category, + "TotalQuestions": totalQuestions, + "CorrectQuestions": correctQuestions, + "IncorrectQuestions": incorrectQuestions, + "OmittedQuestions": omittedQuestions, + }; +} diff --git a/lib/models/resultDetails/result_details_model.dart b/lib/models/resultDetails/result_details_model.dart new file mode 100644 index 0000000..d3b8d72 --- /dev/null +++ b/lib/models/resultDetails/result_details_model.dart @@ -0,0 +1,113 @@ +// To parse this JSON data, do +// +// final resultDetailsModel = resultDetailsModelFromJson(jsonString); + +import 'dart:convert'; + +ResultDetailsModel resultDetailsModelFromJson(String str) => ResultDetailsModel.fromJson(json.decode(str)); + +String resultDetailsModelToJson(ResultDetailsModel data) => json.encode(data.toJson()); + +class ResultDetailsModel { + ResultDetailsModel({ + required this.data, + }); + + Data data; + + factory ResultDetailsModel.fromJson(Map json) => ResultDetailsModel( + data: Data.fromJson(json["data"]), + ); + + Map toJson() => { + "data": data.toJson(), + }; +} + +class Data { + Data({ + required this.status, + required this.quizId, + required this.score, + required this.timeTaken, + required this.totalQuestions, + required this.answeredQuestions, + required this.totalCorrect, + required this.totalIncorrect, + required this.totalOmitted, + required this.quizResults, + }); + + String status; + int quizId; + int score; + String timeTaken; + int totalQuestions; + int answeredQuestions; + int totalCorrect; + int totalIncorrect; + int totalOmitted; + List quizResults; + + factory Data.fromJson(Map json) => Data( + status: json["status"], + quizId: json["quizId"], + score: json["score"], + timeTaken: json["timeTaken"], + totalQuestions: json["totalQuestions"], + answeredQuestions: json["answeredQuestions"], + totalCorrect: json["totalCorrect"], + totalIncorrect: json["totalIncorrect"], + totalOmitted: json["totalOmitted"], + quizResults: List.from(json["quizResults"].map((x) => QuizResult.fromJson(x))), + ); + + Map toJson() => { + "status": status, + "quizId": quizId, + "score": score, + "timeTaken": timeTaken, + "totalQuestions": totalQuestions, + "answeredQuestions": answeredQuestions, + "totalCorrect": totalCorrect, + "totalIncorrect": totalIncorrect, + "totalOmitted": totalOmitted, + "quizResults": List.from(quizResults.map((x) => x.toJson())), + }; +} + +class QuizResult { + QuizResult({ + required this.questionId, + required this.subject, + required this.system, + required this.topic, + required this.status, + required this.averageCorrectToOthers, + }); + + int questionId; + String subject; + String system; + dynamic topic; + int status; + int averageCorrectToOthers; + + factory QuizResult.fromJson(Map json) => QuizResult( + questionId: json["QuestionID"], + subject: json["Subject"], + system: json["System"], + topic: json["Topic"], + status: json["Status"], + averageCorrectToOthers: json["AverageCorrectToOthers"], + ); + + Map toJson() => { + "QuestionID": questionId, + "Subject": subject, + "System": system, + "Topic": topic, + "Status": status, + "AverageCorrectToOthers": averageCorrectToOthers, + }; +} diff --git a/lib/screens/Authentication/login.dart b/lib/screens/Authentication/login.dart index 3687098..6b394b7 100644 --- a/lib/screens/Authentication/login.dart +++ b/lib/screens/Authentication/login.dart @@ -27,16 +27,22 @@ class _LoginState extends State { bool _isChecked = false; //To start animation bool _loaded = false; - var _duration = const Duration(milliseconds: 450); + final _duration = const Duration(milliseconds: 450); var _dataPreviouslyStored = false; late UserModelSuccessfulLogin _successfulUser; late UserModelUnsuccessfulLogin _unsuccessfulUser; + // var _successfulUser; + // var _unsuccessfulUser; var _invalidUsername = false; var _invalidPassword = false; bool _isLoggingIn = false; // To start and finish CircularProgress Indicator //The data gets stored to local storage. Continue from there. - AuthStorage storage = new AuthStorage(); + AuthStorage storage = AuthStorage(); + + //Controllers + final _emailController = TextEditingController(); + final _passwordController = TextEditingController(); @override void initState() { @@ -44,37 +50,35 @@ class _LoginState extends State { //To delete the auth file when the user logs out. if(widget.fromWhere == "Home") { storage.deleteFile(); - print("Deleted + :" + storage.readAuth().toString()); setState(() { _email = ""; _password = ""; _isChecked = false; _dataPreviouslyStored = false; + _emailController.text = ""; + _passwordController.text = ""; }); } else { storage.readAuth().then((value) { - if(value.length != 0) { + if(value.isNotEmpty) { var temp = value.split(" "); - print(temp); setState(() { _email = temp[0]; _password = temp[1]; _dataPreviouslyStored = true; + _emailController.text = temp[0]; + _passwordController.text = temp[1]; }); - print("Email + Password: " + _email + _password); + } else { } }); } - // Future.delayed(Duration(milliseconds: 1), () { - // setState(() { - // _loaded = true; - // }); - // }); - Future.delayed(Duration(microseconds: 0), () { + + Future.delayed(const Duration(microseconds: 0), () { setState(() { _loaded = true; }); @@ -87,19 +91,23 @@ class _LoginState extends State { _isLoggingIn = true; }); SharedPreferences prefs = await SharedPreferences.getInstance(); - final String apiUrl = "https://demo.pookidevs.com/auth/login"; + const String apiUrl = "https://demo.pookidevs.com/auth/login"; http.post(Uri.parse(apiUrl), headers: { 'Content-type': 'application/json; charset=UTF-8', }, body: json.encode( { - "user": - { - "user_email": email, - "user_pass": password - } + "user": + { + "user_email": email, + "user_pass": password + } }) ).then((response) { + // print(json.decode(response.body).toString()); if(response.statusCode == 200) { + setState(() { + _isLoggingIn = false; + }); //The entered credentials are correct. if(json.decode(response.body).toString().substring(0,20) == "{data: {status: true") { final responseString = (response.body); @@ -113,7 +121,6 @@ class _LoginState extends State { prefs.setString('token', _successfulUser.data.token); prefs.setInt("userId", _successfulUser.data.id); _navigateAndDisplaySelection(context); - print(_successfulUser.data.status); } //Credentials are incorrect else if(json.decode(response.body).toString().substring(0,21) == "{data: {status: false") { @@ -122,14 +129,13 @@ class _LoginState extends State { final UserModelUnsuccessfulLogin unsuccessfulUser = loginData; setState(() { _unsuccessfulUser = unsuccessfulUser; + _isLoggingIn = false; }); - print(_unsuccessfulUser.data.status); ScaffoldMessenger.of(context) ..removeCurrentSnackBar() ..showSnackBar(SnackBar(content: Text(_unsuccessfulUser.data.message))); - _navigateAndDisplaySelection(context); + // _navigateAndDisplaySelection(context); var splitMessage = (_unsuccessfulUser.data.message).split(" "); - print(splitMessage); if(splitMessage.length == 4) { setState(() { _invalidPassword = true; @@ -138,13 +144,40 @@ class _LoginState extends State { } else if(splitMessage.length == 2) { setState(() { + _invalidUsername = false; _invalidPassword = true; }); } } - //loginData = userModelLoginFromJson(responseString); } else { - + setState(() { + _isLoggingIn = false; + }); + } + }).catchError((error){ + setState(() { + _isLoggingIn = false; + }); + var errorSplit = error.toString().split(":"); + if(errorSplit[0].toLowerCase() == "socketexception") { + ScaffoldMessenger.of(context) + ..removeCurrentSnackBar() + ..showSnackBar(SnackBar(content: Text("No Internet Connection"))); + } + // else if(errorSplit[0].toLowerCase() == "httpexception") { + // ScaffoldMessenger.of(context) + // ..removeCurrentSnackBar() + // ..showSnackBar(SnackBar(content: Text("Couldn't find the said thing."))); + // } + else if(errorSplit[0].toLowerCase() == "formatexception") { + ScaffoldMessenger.of(context) + ..removeCurrentSnackBar() + ..showSnackBar(SnackBar(content: Text("Bad Response Format"))); + } + else { + ScaffoldMessenger.of(context) + ..removeCurrentSnackBar() + ..showSnackBar(SnackBar(content: Text(error.toString()))); } }); @@ -155,31 +188,27 @@ class _LoginState extends State { if(_successfulUser.data.status == true) { if(_isChecked == true) { storage.writeAuth(_email, _password); - print("Email + Password: " + _email + _password); - // final result = await Navigator.push( - // context, - // MaterialPageRoute(builder: (context) => const Home()), - // ); Navigator.pushNamed(context, '/home'); } else { storage.writeAuth(_email, _password); storage.deleteFile(); - print("Email + Password: " + _email + _password); - // final result = await Navigator.push( - // context, - // MaterialPageRoute(builder: (context) => const Home()), - // ); Navigator.pushNamed(context, '/home'); } } - /*ScaffoldMessenger.of(context) - ..removeCurrentSnackBar() - ..showSnackBar(SnackBar(content: Text(_unsuccessfulUser.data.message)));*/ + } + + @override + void dispose() { + _emailController.dispose(); + _passwordController.dispose(); + super.dispose(); } @override Widget build(BuildContext context) { + var height=MediaQuery.of(context).size.height/926; + var width=MediaQuery.of(context).size.width/428; return WillPopScope( onWillPop: () async { // ScaffoldMessenger.of(context) @@ -190,7 +219,6 @@ class _LoginState extends State { child: GestureDetector( onTap: () { FocusScopeNode currentFocus = FocusScope.of(context); - if (!currentFocus.hasPrimaryFocus) { currentFocus.unfocus(); } @@ -306,6 +334,7 @@ class _LoginState extends State { ], ), child: TextFormField( + controller: _emailController, keyboardType: TextInputType.emailAddress, decoration: InputDecoration( suffixIcon: _invalidUsername == true ? Text("! ", @@ -315,7 +344,7 @@ class _LoginState extends State { fontFamily: 'Brandon-med', ),) : Text(""), suffixIconConstraints: BoxConstraints(minWidth: 0, minHeight: 0), - hintText: _dataPreviouslyStored == null ? "Loading..." : (_dataPreviouslyStored ? _email : "Username"), + hintText: "Username", hintStyle: TextStyle(color: _dataPreviouslyStored ? Color(0xff171616) : Color(0xffAEAEAE), fontSize: (MediaQuery.of(context).size.height)*(20/926), fontFamily: 'Brandon-med',), @@ -336,8 +365,11 @@ class _LoginState extends State { ), //validator: (val) => val!.isEmpty ? "Please enter a Username." : null, onChanged: (val) { - _dataPreviouslyStored == null ? val = "" : - (_dataPreviouslyStored ? val = _email : _email = val); + setState(() { + _dataPreviouslyStored == null ? val = "" : + (_dataPreviouslyStored ? val = _email : _email = val); + _email = val; + }); //_email = val; }, style: TextStyle( @@ -366,7 +398,7 @@ class _LoginState extends State { ], ), child: TextFormField( - //keyboardType: TextInputType.visiblePassword, + controller: _passwordController, obscureText: true, decoration: InputDecoration( suffixIcon: _invalidPassword == true ? Text("! ", @@ -376,7 +408,7 @@ class _LoginState extends State { fontFamily: 'Brandon-med', ),) : Text(""), suffixIconConstraints: BoxConstraints(minWidth: 0, minHeight: 0), - hintText: _dataPreviouslyStored == null ? "Loading..." : (_dataPreviouslyStored ? _password : "Password"), + hintText: "Password", hintStyle: TextStyle(color: _dataPreviouslyStored ? Colors.black : Color(0xffAEAEAE), fontSize: (MediaQuery.of(context).size.height)*(20/926), fontFamily: 'Brandon-med',), @@ -398,8 +430,12 @@ class _LoginState extends State { //validator: (val) => val!.isEmpty ? "Please enter a Password." : null, onChanged: (val) { setState(() { - _dataPreviouslyStored == null ? val = "" : - (_dataPreviouslyStored ? val = _password : _password = val); + // ignore: unnecessary_null_comparison + setState(() { + _dataPreviouslyStored == null ? val = "" : + (_dataPreviouslyStored ? val = _password : _password = val); + _password = val; + }); }); }, style: TextStyle( @@ -411,136 +447,98 @@ class _LoginState extends State { ), SizedBox(height: (MediaQuery.of(context).size.height)*0.024838,), Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - GestureDetector( - onTap: () { - if(_isChecked == false) - setState(() { - _isChecked = true; - }); - else if(_isChecked == true) - setState(() { - _isChecked = false; - }); - }, - child: Row( - mainAxisAlignment: MainAxisAlignment.start, - children: [ - Container( - margin: EdgeInsets.only(top: 0, bottom: 0, left: (MediaQuery.of(context).size.width) *(45/428), right: 0,), - height: (MediaQuery.of(context).size.height)*0.0167, - width: (MediaQuery.of(context).size.height)*0.0167, - color: Colors.white, - child: Transform.scale( - scale: (MediaQuery.of(context).size.height)*0.001, - child: Checkbox( - side: BorderSide( - color: Color(0xffB0A6C2), - width: 0, - ), - checkColor: Colors.white, - value: _isChecked, - onChanged: (bool? value) { - setState(() { - _isChecked = value!; - }); - }, + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + GestureDetector( + onTap: () { + if(_isChecked == false) { + setState(() { + _isChecked = true; + }); + } else if(_isChecked == true) { + setState(() { + _isChecked = false; + }); + } + }, + child: Row( + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Container( + margin: EdgeInsets.only(top: 0, bottom: 0, left: (MediaQuery.of(context).size.width) *(45/428), right: 0,), + height: (MediaQuery.of(context).size.height)*0.0167, + width: (MediaQuery.of(context).size.height)*0.0167, + color: Colors.white, + child: Transform.scale( + scale: (MediaQuery.of(context).size.height)*0.001, + child: Checkbox( + side: BorderSide( + color: Color(0xffB0A6C2), + width: 0, ), + checkColor: Color(0xff3F2668), + activeColor: Colors.white, + value: _isChecked, + onChanged: (bool? value) { + setState(() { + _isChecked = value!; + }); + }, ), - ), - Container( - padding: EdgeInsets.only(top: 0, bottom: 0, left: (MediaQuery.of(context).size.width) *(5/428), right: 0,), - child: Text("Remember me!", - style: TextStyle( - color: Color.fromRGBO(255, 255, 255, 100), - fontFamily: 'Brandon-med', - fontSize: (MediaQuery.of(context).size.height)*0.0161987, - ),), - ), - ], - ), - ), - Container( - padding: EdgeInsets.only(top: 0, bottom: 0, left: 0, right: (MediaQuery.of(context).size.width) *(45/428),), - child: Text("Forgot Password?", - style: TextStyle( - color: Color(0xffFFFEFE), - fontFamily: 'Brandon-med', - fontSize: (MediaQuery.of(context).size.height)*0.0161987, - ),), + ), + ), + Container( + padding: EdgeInsets.only(top: 0, bottom: 0, left: (MediaQuery.of(context).size.width) *(5/428), right: 0,), + child: Text("Remember me!", + style: TextStyle( + color: Color.fromRGBO(255, 255, 255, 100), + fontFamily: 'Brandon-med', + fontSize: (MediaQuery.of(context).size.height)*0.0161987, + ),), + ), + ], ), - ], - ), - _isLoggingIn ? Container() : SizedBox(height: (MediaQuery.of(context).size.height) *0.0864,), - _isLoggingIn ? Container( - height: (MediaQuery.of(context).size.height) *0.0864, + ), + Container( + padding: EdgeInsets.only(top: 0, bottom: 0, left: 0, right: (MediaQuery.of(context).size.width) *(45/428),), + child: Text("Forgot Password?", + style: TextStyle( + color: Color(0xffFFFEFE), + fontFamily: 'Brandon-med', + fontSize: (MediaQuery.of(context).size.height)*0.0161987, + ),), + ), + ], + ), + _isLoggingIn ? Container() : SizedBox(height: height*80), + _isLoggingIn ? SizedBox( + height: height*80, child: Container( - alignment: Alignment.center, - height: (MediaQuery.of(context).size.height) *0.0664, - child: CircularProgressIndicator(color: Colors.white,)), + alignment: Alignment.center, + height: height*5, + child: SizedBox(height: height*25,width:height*25,child: const CircularProgressIndicator(color: Colors.white,strokeWidth: 1,))), ) : Container(), - ], + ], ), ), SizedBox(height: (MediaQuery.of(context).size.height) *(25/926),), ], ), - // GestureDetector( - // child: Container(//Login button - // child: Align( - // alignment: Alignment.center, - // child: SvgPicture.asset( - // "assets/Images/login.svg", - // height: (MediaQuery.of(context).size.height) *0.0486, - // ), - // ), - // ), - // onTap: () { - // if(_formKey.currentState!.validate()) { - // //_navigateAndDisplaySelection(context); - // //print(_isChecked); - // getUserData(context, _email, _password); - // } - // }, - // ), - Container( - height: (MediaQuery.of(context).size.height) *(45/926), - width: (MediaQuery.of(context).size.width) *(150/428), - decoration: BoxDecoration( - gradient: LinearGradient( - begin: Alignment.centerLeft, - end: Alignment.centerRight, - colors: [ - Color(0xff7F1AF1), - Color(0xff482384) - ]), - borderRadius: new BorderRadius.only( - bottomLeft: const Radius.circular(20.0), - topRight: const Radius.circular(20.0), - ) - ), - child: TextButton( - style: TextButton.styleFrom( - padding: EdgeInsets.zero, + GestureDetector( + child: Container(//Login button + child: Align( + alignment: Alignment.center, + child: SvgPicture.asset( + "assets/Images/login.svg", + height: (MediaQuery.of(context).size.height) *0.0486, + ), ), - onPressed: () { - // setState(() { - // _isLoggingIn = !_isLoggingIn; - // }); - if(_formKey.currentState!.validate()) { - //_navigateAndDisplaySelection(context); - // print(_isChecked); - getUserData(context, _email, _password); - } - }, - child: Text("Login", - style: TextStyle( - color: Color(0xffFFFEFE), - fontFamily: 'Brandon-bld', - fontSize: (MediaQuery.of(context).size.height)*(25/926), - ),), ), + onTap: () { + if(_formKey.currentState!.validate()) { + getUserData(context, _emailController.text, _passwordController.text); + } + }, ), ], ), diff --git a/lib/screens/Components/styles.dart b/lib/screens/Components/styles.dart new file mode 100644 index 0000000..a25f7a5 --- /dev/null +++ b/lib/screens/Components/styles.dart @@ -0,0 +1,23 @@ +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; + +class Styles{ +static Color appBg=Color(0XFFF8F9FB); +static Color darkPurple=Color(0xFF3F2668); +static Color lightPurple=Color(0xFF6D5A8D); +static Color darkGrey=Color(0xFF3F3F3F); +static Gradient purpleGradient=LinearGradient( + begin: Alignment.topLeft, + end: Alignment.bottomRight, + colors: [ + lightPurple, + darkPurple + ]); +static BoxShadow boxShad= BoxShadow( + color: Colors.black12,//Color(0xff00000029), + spreadRadius: 2, + blurRadius: 4, + offset: Offset(0, 0), + ); + +} \ No newline at end of file diff --git a/lib/screens/Welcome/GenerateQuiz/generate_quiz.dart b/lib/screens/Welcome/GenerateQuiz/generate_quiz.dart index 0326fc7..9ead0ea 100644 --- a/lib/screens/Welcome/GenerateQuiz/generate_quiz.dart +++ b/lib/screens/Welcome/GenerateQuiz/generate_quiz.dart @@ -21,6 +21,7 @@ class GenerateQuiz extends StatefulWidget { class _GenerateQuizState extends State with SingleTickerProviderStateMixin { late TabController _tabController; + late TextEditingController _textCountController; // Once the data is loaded only then it shows the containers. bool _hasDataLoaded = false; @@ -29,6 +30,7 @@ class _GenerateQuizState extends State with SingleTickerProviderSt // First gets its value when getUserData is run and then gets updated as getQuestionCounts is run. int _totalQuestions = 0; List _questions = []; + bool _gettingQuestionsCount = false; //Tab 1 Data: //Not allowing Subjects or topics to be selected if Systems is empty @@ -95,6 +97,7 @@ class _GenerateQuizState extends State with SingleTickerProviderSt @override void initState() { super.initState(); + _textCountController = TextEditingController(); _tabController = TabController(vsync: this, length: 5); getUserDataSST(); } @@ -150,7 +153,32 @@ class _GenerateQuizState extends State with SingleTickerProviderSt } } } - ); + ).catchError((error){ + setState(() { + _hasDataLoaded = true; + }); + var errorSplit = error.toString().split(":"); + if(errorSplit[0].toLowerCase() == "socketexception") { + ScaffoldMessenger.of(context) + ..removeCurrentSnackBar() + ..showSnackBar(SnackBar(content: Text("No Internet Connection"))); + } + // else if(errorSplit[0].toLowerCase() == "httpexception") { + // ScaffoldMessenger.of(context) + // ..removeCurrentSnackBar() + // ..showSnackBar(SnackBar(content: Text("Couldn't find the said thing."))); + // } + else if(errorSplit[0].toLowerCase() == "formatexception") { + ScaffoldMessenger.of(context) + ..removeCurrentSnackBar() + ..showSnackBar(SnackBar(content: Text("Bad Response Format"))); + } + else { + ScaffoldMessenger.of(context) + ..removeCurrentSnackBar() + ..showSnackBar(SnackBar(content: Text(error.toString()))); + } + }); } Future getQuestionsCount() async { @@ -160,6 +188,9 @@ class _GenerateQuizState extends State with SingleTickerProviderSt // print(_userId); // print(_questionTypeInt); // print(_difficultyLevel); + setState(() { + _gettingQuestionsCount = true; + }); final String apiUrl = "https://demo.pookidevs.com/quiz/generator/getQuestionCounts"; http.post(Uri.parse(apiUrl), headers: { @@ -177,6 +208,9 @@ class _GenerateQuizState extends State with SingleTickerProviderSt } }) ).then((response) { + setState(() { + _gettingQuestionsCount = false; + }); if(response.statusCode == 200) { // print("getQuestionsCount() : " + response.body.toString()); if(json.decode(response.body).toString().substring(0,20) == "{data: {status: true") { @@ -216,6 +250,31 @@ class _GenerateQuizState extends State with SingleTickerProviderSt } } + }).catchError((error){ + setState(() { + _hasDataLoaded = true; + }); + var errorSplit = error.toString().split(":"); + if(errorSplit[0].toLowerCase() == "socketexception") { + ScaffoldMessenger.of(context) + ..removeCurrentSnackBar() + ..showSnackBar(SnackBar(content: Text("No Internet Connection"))); + } + // else if(errorSplit[0].toLowerCase() == "httpexception") { + // ScaffoldMessenger.of(context) + // ..removeCurrentSnackBar() + // ..showSnackBar(SnackBar(content: Text("Couldn't find the said thing."))); + // } + else if(errorSplit[0].toLowerCase() == "formatexception") { + ScaffoldMessenger.of(context) + ..removeCurrentSnackBar() + ..showSnackBar(SnackBar(content: Text("Bad Response Format"))); + } + else { + ScaffoldMessenger.of(context) + ..removeCurrentSnackBar() + ..showSnackBar(SnackBar(content: Text(error.toString()))); + } }); } @@ -332,1264 +391,1337 @@ class _GenerateQuizState extends State with SingleTickerProviderSt @override void dispose() { _tabController.dispose(); + _textCountController.dispose(); super.dispose(); } @override Widget build(BuildContext context) { - return Scaffold( - backgroundColor: Color(0xffF8F9FB), - drawer: SideMenuBar(), - appBar: AppBar( - toolbarHeight: (MediaQuery.of(context).size.height) *(73.52/926), - backgroundColor: Color(0xff3F2668), - elevation: 2, - centerTitle: true, - flexibleSpace: Container( - decoration: const BoxDecoration( - gradient: LinearGradient( - begin: Alignment.topCenter, - end: Alignment.bottomCenter, - colors: [ - Color(0xff7F1AF1), - Color(0xff482384) - ]) - ), - ), - title: const Text("Generate Quiz", - style: TextStyle( - color: Color(0xffFFFEFE), - fontFamily: 'Brandon-bld', + var h=MediaQuery.of(context).size.height/926; + var w=MediaQuery.of(context).size.width/428; + return GestureDetector( + onTap: () { + FocusScopeNode currentFocus = FocusScope.of(context); + + if (!currentFocus.hasPrimaryFocus) { + currentFocus.unfocus(); + } + }, + child: Scaffold( + backgroundColor: Color(0xffF8F9FB), + drawer: SideMenuBar(), + appBar: AppBar( + toolbarHeight: (MediaQuery.of(context).size.height) *(73.52/926), + backgroundColor: Color(0xff3F2668), + elevation: 2, + centerTitle: true, + flexibleSpace: Container( + decoration: const BoxDecoration( + gradient: LinearGradient( + begin: Alignment.topCenter, + end: Alignment.bottomCenter, + colors: [ + Color(0xff7F1AF1), + Color(0xff482384) + ]) + ), ), - ), - actions: [ - TextButton( - onPressed: () async { - final result = await Navigator.push( - context, - MaterialPageRoute(builder: (context) => const Login(fromWhere:"Home")), - ); - }, - child: SvgPicture.asset( - "assets/Images/logout.svg", - height: (MediaQuery.of(context).size.height) *(32/926), + title: const Text("Generate Quiz", + style: TextStyle( + color: Color(0xffFFFEFE), + fontFamily: 'Brandon-bld', ), ), - ], - ), - body: SingleChildScrollView( - child: Container( - padding: EdgeInsets.only(top:(MediaQuery.of(context).size.height) *(15/926), - bottom: (MediaQuery.of(context).size.height) *(8/926), - left: (MediaQuery.of(context).size.width) *(18/428), - right: (MediaQuery.of(context).size.width) *(18/428)), - child: Column( - children: [ - Row( - children: [ - Container( - width: (MediaQuery.of(context).size.width) *(221/428), - //height: (MediaQuery.of(context).size.height) *(91/926), - child: Column( - children: [ - Align( - alignment: Alignment.topLeft, - child: Text("Create Quiz", + actions: [ + TextButton( + onPressed: () async { + final result = await Navigator.push( + context, + MaterialPageRoute(builder: (context) => const Login(fromWhere:"Home")), + ); + }, + child: SvgPicture.asset( + "assets/Images/logout.svg", + height: (MediaQuery.of(context).size.height) *(32/926), + ), + ), + ], + ), + body: SingleChildScrollView( + child: Container( + padding: EdgeInsets.only(top:(MediaQuery.of(context).size.height) *(15/926), + bottom: (MediaQuery.of(context).size.height) *(8/926), + left: (MediaQuery.of(context).size.width) *(18/428), + right: (MediaQuery.of(context).size.width) *(18/428)), + child: Column( + children: [ + Row( + children: [ + Container( + width: (MediaQuery.of(context).size.width) *(221/428), + //height: (MediaQuery.of(context).size.height) *(91/926), + child: Column( + children: [ + Align( + alignment: Alignment.topLeft, + child: Text("Create Quiz", + style: TextStyle( + color: Color(0xff232323), + fontFamily: 'Brandon-bld', + fontSize: (MediaQuery.of(context).size.height) *(25/926),//38, + ),), + ), + SizedBox(height: (MediaQuery.of(context).size.height) *(2/926),), + Text("Lorem ipsum dolor sit amet, consectetur adipiscing elit. Cras imperdiet finibus elit non luctus. Morbi auctor mattis ante.", style: TextStyle( - color: Color(0xff232323), - fontFamily: 'Brandon-bld', - fontSize: (MediaQuery.of(context).size.height) *(25/926),//38, + color: Color(0xFF483A3A), + fontFamily: 'Brandon-med', + fontSize: (MediaQuery.of(context).size.height) *(13/926),//38, ),), + ], + ), + ), + SizedBox(width: (MediaQuery.of(context).size.width) *(39/428),), + Container( + //color: Colors.transparent, + child: SvgPicture.asset( + "assets/Images/create_quiz.svg", + height: (MediaQuery.of(context).size.height) *(100/926), + //width: (MediaQuery.of(context).size.width) *(132/428), ), - SizedBox(height: (MediaQuery.of(context).size.height) *(2/926),), - Text("Lorem ipsum dolor sit amet, consectetur adipiscing elit. Cras imperdiet finibus elit non luctus. Morbi auctor mattis ante.", - style: TextStyle( - color: Color(0xFF483A3A), - fontFamily: 'Brandon-med', - fontSize: (MediaQuery.of(context).size.height) *(13/926),//38, - ),), - ], ), - ), - SizedBox(width: (MediaQuery.of(context).size.width) *(39/428),), - Container( - //color: Colors.transparent, - child: SvgPicture.asset( - "assets/Images/create_quiz.svg", - height: (MediaQuery.of(context).size.height) *(100/926), - //width: (MediaQuery.of(context).size.width) *(132/428), - ), - ), - ], - ), - SizedBox(height: (MediaQuery.of(context).size.height) *(25/926),), - SizedBox(height: (MediaQuery.of(context).size.height) *(13.28/926),), - Container( - height: (MediaQuery.of(context).size.height) *(596/926), - width: double.infinity, - child: TabBarView( - // physics: NeverScrollableScrollPhysics(), - controller: _tabController, - children: [ - //Tab1: Subjects - Column( - children: [ - Container( - height: (MediaQuery.of(context).size.height) *(40.32/926), - width: (MediaQuery.of(context).size.width) *(386/428), - decoration: BoxDecoration( - color: Color(0xFF3F2668), - borderRadius: BorderRadius.only(bottomLeft: Radius.circular(15.0), topRight: Radius.circular(15.0),), - boxShadow: [ - BoxShadow( - color: Colors.black12, - spreadRadius: 2, - blurRadius: 2, - offset: Offset(0, 0), + ], + ), + SizedBox(height: (MediaQuery.of(context).size.height) *(25/926),), + SizedBox(height: (MediaQuery.of(context).size.height) *(13.28/926),), + Container( + height: (MediaQuery.of(context).size.height) *(596/926), + width: double.infinity, + child: TabBarView( + // physics: NeverScrollableScrollPhysics(), + controller: _tabController, + children: [ + //Tab1: Subjects + Column( + children: [ + Container( + height: (MediaQuery.of(context).size.height) *(40.32/926), + width: (MediaQuery.of(context).size.width) *(386/428), + decoration: BoxDecoration( + color: Color(0xFF3F2668), + borderRadius: BorderRadius.only(bottomLeft: Radius.circular(15.0), topRight: Radius.circular(15.0),), + boxShadow: [ + BoxShadow( + color: Colors.black12, + spreadRadius: 2, + blurRadius: 2, + offset: Offset(0, 0), + ), + ], + ), + child: Center( + child: Text("Select Subjects", + style: TextStyle( + color: Colors.white, + fontFamily: 'Brandon-bld', + fontSize: (MediaQuery.of(context).size.height) *(26.31/926),//38, + ),), + ), + ), + SizedBox(height: (MediaQuery.of(context).size.height) *(33/926)), + Container( + padding: EdgeInsets.only(left: (MediaQuery.of(context).size.width) *(10/428), right: (MediaQuery.of(context).size.width) *(10/428)), + width: (MediaQuery.of(context).size.width) *(366/428), + child: _hasDataLoaded == false ? + Container(height: (MediaQuery.of(context).size.height) *(460/926),child: Center(child: CircularProgressIndicator(color: Color(0xFF3F2668),))) + : + Container( + height: (MediaQuery.of(context).size.height) *(460/926), + child: subjectsEverything["title"]!.length <= 0 ? Container( + child: Align( + alignment: Alignment.topCenter, + child: Text("No Subjects Available!", + style: TextStyle( + color: Color(0xffAEAEAE), + fontFamily: 'Brandon-bld', + fontSize: (MediaQuery.of(context).size.height) *(15/926),//38, + ),), + ), + ) : + Container( + height: (MediaQuery.of(context).size.height) *(460/926), + child: GridView( + gridDelegate: SliverGridDelegateWithFixedCrossAxisCount( + crossAxisCount: 2, + crossAxisSpacing: + w * 30, + mainAxisExtent: + h * 50, + mainAxisSpacing: h*50 + ), + children: [ + for(int i = 0; i 0) { + setState(() { + _systemsDisabled = false; + }); + } + + //Unchecking the previously checked boxes. + if(subjectsEverything["isSelected"]![i] == false) { + if(systemsEverything["isSelected"]!.length > 0) { + for(int i = 0; i 0) { + for(int i = 0; i[ - for(int i = 0; i 0) { - setState(() { - _systemsDisabled = false; }); - } - //Unchecking the previously checked boxes. - if(subjectsEverything["isSelected"]![i] == false) { - if(systemsEverything["isSelected"]!.length > 0) { - for(int i = 0; i 0) { - for(int i = 0; i 0) { + setState(() { + _topicsDisabled = false; + }); + } + + //Unchecking the previously checked boxes. + if(systemsEverything["isSelected"]![i] == false) { + // topicsEverything + if(topicsEverything["isSelected"]!.length > 0) { + for(int i = 0; i AlertDialog( + content: Text( + 'Select Subjects First!', + style: TextStyle( + color: Color(0xffA1A1A1), + fontFamily: 'Brandon-bld', + fontSize: (MediaQuery.of(context).size.height) * (21 / 926), + ), + ), + actions: [ + Divider(), + TextButton( + onPressed: () { + Navigator.of(context).pop(); + }, + child: Text('Okay', + style: TextStyle( + color: Color(0xff3F2668), + fontFamily: 'Brandon-bld', + fontSize: + (MediaQuery.of(context).size.height) * (21 / 926), + )), + ), + ], + ), + ); } - // print(subjectsEverything["finalTitles"]); - // print(systemsEverything["finalTitles"]); - // print(topicsEverything["finalTitles"]); - getQuestionsCount(); }, ), ), ], ) ), - ], - ), ), - ), - SizedBox(height: (MediaQuery.of(context).size.height) *(10.74/926)), - Row( - mainAxisAlignment: MainAxisAlignment.end, - children: [ - InkWell( - child: Container( - height: (MediaQuery.of(context).size.height) *(42/926), - width: (MediaQuery.of(context).size.width) *(68/428), - decoration: BoxDecoration( - color: Color(0xff3F2668),//0xffB0A6C2, rgba(176, 166, 194, 1) - borderRadius: BorderRadius.all(Radius.circular(3)), - boxShadow: [ - BoxShadow( - color: Colors.black12,//Color(0xff00000029), - spreadRadius: 2, - blurRadius: 2, - offset: Offset(0, 0), + ), + SizedBox(height: (MediaQuery.of(context).size.height) *(10.74/926),), + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + InkWell( + child: Container( + margin: EdgeInsets.symmetric( + horizontal: w * 25), + height: (MediaQuery.of(context).size.height) *(42/926), + width: (MediaQuery.of(context).size.width) *(68/428), + decoration: BoxDecoration( + color: Color(0xff3F2668),//0xffB0A6C2, rgba(176, 166, 194, 1) + borderRadius: BorderRadius.all(Radius.circular(3)), + boxShadow: [ + BoxShadow( + color: Colors.black12,//Color(0xff00000029), + spreadRadius: 2, + blurRadius: 2, + offset: Offset(0, 0), + ), + ], + ), + child: TextButton( + onPressed: () { + //Animates to next tab + _backTab(); + }, + child: Center( + child: Text("Back", + style: TextStyle( + color: Colors.white, + fontFamily: 'Brandon-med', + ), + ), ), - ], + ), ), - child: TextButton( - onPressed: () { - //Animates to next tab - _nextTab(); - }, - child: Center( - child: Text("Next", - style: TextStyle( - color: Colors.white, - fontFamily: 'Brandon-med', + ), + InkWell( + child: Container( + margin: EdgeInsets.symmetric( + horizontal: w * 25), + height: (MediaQuery.of(context).size.height) *(42/926), + width: (MediaQuery.of(context).size.width) *(68/428), + decoration: BoxDecoration( + color: Color(0xff3F2668), + borderRadius: + BorderRadius.circular(h * 7), + ), + child: TextButton( + style: TextButton.styleFrom( + padding: + EdgeInsets.zero), + onPressed: () { + //Animates to next tab + _nextTab(); + }, + child: Center( + child: Text( + "Next", + style: TextStyle( + color: Colors.white, + fontFamily: 'Brandon-med', + fontSize: h * 20, + ), ), ), ), ), ), - ), - ], - ), - ], - ), - //Tab 1 is complete. - - //Tab2: Systems - Column( - children: [ - Container( - height: (MediaQuery.of(context).size.height) *(40.32/926), - width: (MediaQuery.of(context).size.width) *(386/428), - //color: Colors.red, - decoration: BoxDecoration( - color: Color(0xFF3F2668),//0xffB0A6C2, rgba(176, 166, 194, 1) - borderRadius: BorderRadius.only(bottomLeft: Radius.circular(15.0), topRight: Radius.circular(15.0),), - boxShadow: [ - BoxShadow( - color: Colors.black12,//Color(0xff00000029), - spreadRadius: 2, - blurRadius: 2, - offset: Offset(0, 0), - ), ], ), - child: Center( - child: Text("Select Systems", - style: TextStyle( - color: Colors.white, - fontFamily: 'Brandon-bld', - fontSize: (MediaQuery.of(context).size.height) *(26.31/926),//38, - ),), + ], + ), + + //Tab3: Topics + Column( + children: [ + Container( + height: (MediaQuery.of(context).size.height) *(40.32/926), + width: (MediaQuery.of(context).size.width) *(366/428), + //color: Colors.red, + decoration: BoxDecoration( + color: Color(0xFF3F2668),//0xffB0A6C2, rgba(176, 166, 194, 1) + borderRadius: BorderRadius.only(bottomLeft: Radius.circular(15.0), topRight: Radius.circular(15.0),), + boxShadow: [ + BoxShadow( + color: Colors.black12,//Color(0xff00000029), + spreadRadius: 2, + blurRadius: 2, + offset: Offset(0, 0), + ), + ], + ), + child: Center( + child: Text("Select Topics", + style: TextStyle( + color: Colors.white, + fontFamily: 'Brandon-bld', + fontSize: (MediaQuery.of(context).size.height) *(26.31/926),//38, + ),), + ), ), - ), - SizedBox(height: (MediaQuery.of(context).size.height) *(33/926)), - Container( - padding: EdgeInsets.only(left: (MediaQuery.of(context).size.width) *(10/428), right: (MediaQuery.of(context).size.width) *(10/428)), - width: (MediaQuery.of(context).size.width) *(366/428), - child: Container( - height: (MediaQuery.of(context).size.height) *(460/926), - child: _hasDataLoaded == false ? Text("") : ListView( - scrollDirection: Axis.vertical, - children: [ - Container( - height: (MediaQuery.of(context).size.height) *(120.9/926), - child: GridView( - gridDelegate: SliverGridDelegateWithFixedCrossAxisCount( - crossAxisCount: 2, - crossAxisSpacing: (MediaQuery.of(context).size.width) *(30/428), - mainAxisExtent: (MediaQuery.of(context).size.height) *(40.224/926),), - children: [ - for(int i = 0; i[ + for(int i = 0; i 0) { - setState(() { - _topicsDisabled = false; }); } - - //Unchecking the previously checked boxes. - if(systemsEverything["isSelected"]![i] == false) { - // topicsEverything - if(topicsEverything["isSelected"]!.length > 0) { - for(int i = 0; i AlertDialog( + content: Text( + 'Select Systems First!', + style: TextStyle( + color: Color(0xffA1A1A1), + fontFamily: 'Brandon-bld', + fontSize: (MediaQuery.of(context).size.height) * (21 / 926), + ), + ), + actions: [ + Divider(), + TextButton( + onPressed: () { + Navigator.of(context).pop(); + }, + child: Text('Okay', + style: TextStyle( + color: Color(0xff3F2668), + fontFamily: 'Brandon-bld', + fontSize: + (MediaQuery.of(context).size.height) * (21 / 926), + )), + ), + ], + ), + ); } // print(subjectsEverything["finalTitles"]); // print(systemsEverything["finalTitles"]); // print(topicsEverything["finalTitles"]); getQuestionsCount(); - } - else { - showDialog( - context: context, - builder: (context) => AlertDialog( - content: Text( - 'Select Subjects First!', - style: TextStyle( - color: Color(0xffA1A1A1), - fontFamily: 'Brandon-bld', - fontSize: (MediaQuery.of(context).size.height) * (21 / 926), - ), - ), - actions: [ - Divider(), - TextButton( - onPressed: () { - Navigator.of(context).pop(); - }, - child: Text('Okay', - style: TextStyle( - color: Color(0xff3F2668), - fontFamily: 'Brandon-bld', - fontSize: - (MediaQuery.of(context).size.height) * (21 / 926), - )), - ), - ], - ), - ); - } - }, + }, + ), ), - ), - ], - ) - ), - ], + ], + ) + ), ), ), - ), - SizedBox(height: (MediaQuery.of(context).size.height) *(10.74/926),), - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - InkWell( - child: Container( - height: (MediaQuery.of(context).size.height) *(42/926), - width: (MediaQuery.of(context).size.width) *(68/428), - decoration: BoxDecoration( - color: Color(0xff3F2668),//0xffB0A6C2, rgba(176, 166, 194, 1) - borderRadius: BorderRadius.all(Radius.circular(3)), - boxShadow: [ - BoxShadow( - color: Colors.black12,//Color(0xff00000029), - spreadRadius: 2, - blurRadius: 2, - offset: Offset(0, 0), - ), - ], - ), - child: TextButton( - onPressed: () { - //Animates to next tab - _backTab(); - }, - child: Center( - child: Text("Back", - style: TextStyle( - color: Colors.white, - fontFamily: 'Brandon-med', + SizedBox(height: (MediaQuery.of(context).size.height) *(10.74/926),), + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + InkWell( + child: Container( + margin: EdgeInsets.symmetric( + horizontal: w * 25), + height: (MediaQuery.of(context).size.height) *(42/926), + width: (MediaQuery.of(context).size.width) *(68/428), + decoration: BoxDecoration( + color: Color(0xff3F2668),//0xffB0A6C2, rgba(176, 166, 194, 1) + borderRadius: BorderRadius.all(Radius.circular(3)), + boxShadow: [ + BoxShadow( + color: Colors.black12,//Color(0xff00000029), + spreadRadius: 2, + blurRadius: 2, + offset: Offset(0, 0), + ), + ], + ), + child: TextButton( + onPressed: () { + //Animates to next tab + _backTab(); + }, + child: Center( + child: Text("Back", + style: TextStyle( + color: Colors.white, + fontFamily: 'Brandon-med', + ), ), ), ), ), ), - ), - InkWell( - child: Container( - height: (MediaQuery.of(context).size.height) *(42/926), - width: (MediaQuery.of(context).size.width) *(68/428), - decoration: BoxDecoration( - color: Color(0xff3F2668),//0xffB0A6C2, rgba(176, 166, 194, 1) - borderRadius: BorderRadius.all(Radius.circular(3)), - boxShadow: [ - BoxShadow( - color: Colors.black12,//Color(0xff00000029), - spreadRadius: 2, - blurRadius: 2, - offset: Offset(0, 0), - ), - ], - ), - child: TextButton( - onPressed: () { - //Animates to next tab - _nextTab(); - }, - child: Center( - child: Text("Next", - style: TextStyle( - color: Colors.white, - fontFamily: 'Brandon-med', + InkWell( + child: Container( + margin: EdgeInsets.symmetric( + horizontal: w * 25), + height: (MediaQuery.of(context).size.height) *(42/926), + width: (MediaQuery.of(context).size.width) *(68/428), + decoration: BoxDecoration( + color: Color(0xff3F2668),//0xffB0A6C2, rgba(176, 166, 194, 1) + borderRadius: BorderRadius.all(Radius.circular(3)), + boxShadow: [ + BoxShadow( + color: Colors.black12,//Color(0xff00000029), + spreadRadius: 2, + blurRadius: 2, + offset: Offset(0, 0), + ), + ], + ), + child: TextButton( + onPressed: () { + //Animates to next tab + _nextTab(); + }, + child: Center( + child: Text("Next", + style: TextStyle( + color: Colors.white, + fontFamily: 'Brandon-med', + ), ), ), ), ), ), - ), - ], - ), - ], - ), - - //Tab3: Topics - Column( - children: [ - Container( - height: (MediaQuery.of(context).size.height) *(40.32/926), - width: (MediaQuery.of(context).size.width) *(366/428), - //color: Colors.red, - decoration: BoxDecoration( - color: Color(0xFF3F2668),//0xffB0A6C2, rgba(176, 166, 194, 1) - borderRadius: BorderRadius.only(bottomLeft: Radius.circular(15.0), topRight: Radius.circular(15.0),), - boxShadow: [ - BoxShadow( - color: Colors.black12,//Color(0xff00000029), - spreadRadius: 2, - blurRadius: 2, - offset: Offset(0, 0), - ), ], ), - child: Center( - child: Text("Select Topics", - style: TextStyle( - color: Colors.white, - fontFamily: 'Brandon-bld', - fontSize: (MediaQuery.of(context).size.height) *(26.31/926),//38, - ),), + ], + ), + + //Tab4: Question Types + Column( + children: [ + Container( + height: (MediaQuery.of(context).size.height) *(40.32/926), + width: (MediaQuery.of(context).size.width) *(386/428), + //color: Colors.red, + decoration: BoxDecoration( + color: Color(0xFF3F2668),//0xffB0A6C2, rgba(176, 166, 194, 1) + borderRadius: BorderRadius.only(bottomLeft: Radius.circular(15.0), topRight: Radius.circular(15.0),), + boxShadow: [ + BoxShadow( + color: Colors.black12,//Color(0xff00000029), + spreadRadius: 2, + blurRadius: 2, + offset: Offset(0, 0), + ), + ], + ), + child: Center( + child: Text("Select Question Types", + style: TextStyle( + color: Colors.white, + fontFamily: 'Brandon-bld', + fontSize: (MediaQuery.of(context).size.height) *(26.31/926),//38, + ),), + ), ), - ), - SizedBox(height: (MediaQuery.of(context).size.height) *(33/926)), - Container( - padding: EdgeInsets.only(left: (MediaQuery.of(context).size.width) *(10/428), right: (MediaQuery.of(context).size.width) *(10/428)), - width: (MediaQuery.of(context).size.width) *(366/428), - child: Container( + SizedBox(height: (MediaQuery.of(context).size.height) *(33/926)), + Container( + padding: EdgeInsets.only(left: (MediaQuery.of(context).size.width) *(10/428), right: (MediaQuery.of(context).size.width) *(10/428)), + width: (MediaQuery.of(context).size.width) *(366/428), height: (MediaQuery.of(context).size.height) *(460/926), - child: _hasDataLoaded == false ? Text("") : ListView( - scrollDirection: Axis.vertical, + child: Column( children: [ - Container( - height: (MediaQuery.of(context).size.height) *(120.9/926), - child: GridView( - gridDelegate: SliverGridDelegateWithFixedCrossAxisCount( - crossAxisCount: 2, - crossAxisSpacing: (MediaQuery.of(context).size.width) *(30/428), - mainAxisExtent: (MediaQuery.of(context).size.height) *(40.224/926),), - children: [ - for(int i = 0; i AlertDialog( - content: Text( - 'Select Systems First!', - style: TextStyle( - color: Color(0xffA1A1A1), - fontFamily: 'Brandon-bld', - fontSize: (MediaQuery.of(context).size.height) * (21 / 926), - ), - ), - actions: [ - Divider(), - TextButton( - onPressed: () { - Navigator.of(context).pop(); - }, - child: Text('Okay', - style: TextStyle( - color: Color(0xff3F2668), - fontFamily: 'Brandon-bld', - fontSize: - (MediaQuery.of(context).size.height) * (21 / 926), - )), - ), - ], - ), - ); - } - // print(subjectsEverything["finalTitles"]); - // print(systemsEverything["finalTitles"]); - // print(topicsEverything["finalTitles"]); - getQuestionsCount(); - }, + for(int i = 1; i<7; i++) + Column( + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Container( + height: (MediaQuery.of(context).size.height) *(40.224/926), + width: (MediaQuery.of(context).size.width) *(302/428), + color: _questionTypeSelectedBool[i] == false ? Colors.white : Color(0xFF3F2668), + child: TextButton( + style: TextButton.styleFrom( + padding: EdgeInsets.zero,), + child: Text(_questionTypesTitle[i], + style: TextStyle( + color: _questionTypeSelectedBool[i] == false ? Color(0xFF3F3D56) : Colors.white, + fontFamily: 'Brandon-med', + fontSize: (MediaQuery.of(context).size.height)*(15/926), + ),), + onPressed: () { + _questionTypesLogic(i); + getQuestionsCount(); + }, + ), + ), + _questionTypeSelectedBool[i] == false ? + GestureDetector( + onTap: () { + _questionTypesLogic(i); + getQuestionsCount(); + }, + child: Container( + height: (MediaQuery.of(context).size.height) *(34.224/926), + width: (MediaQuery.of(context).size.height) *(34.224/926), + // width: (MediaQuery.of(context).size.width) *(29.224/428), + decoration: BoxDecoration( + border: Border.all(width: 9, color: Color(0xFFA1A1A1)), + borderRadius: BorderRadius.all(Radius.circular(50)), ), ), + ) + : + GestureDetector( + onTap: () { + _questionTypesLogic(i); + getQuestionsCount(); + }, + child: Container( + child: Icon(Icons.check, + size: (MediaQuery.of(context).size.height) *(34.224/926), + color: Color(0xFF3F2668),) + ), + ), ], - ) - ), + ), + SizedBox(height: (MediaQuery.of(context).size.height) *(25.224/926)), + ], + ), ], ), ), - ), - SizedBox(height: (MediaQuery.of(context).size.height) *(10.74/926),), - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - InkWell( - child: Container( - height: (MediaQuery.of(context).size.height) *(42/926), - width: (MediaQuery.of(context).size.width) *(68/428), - decoration: BoxDecoration( - color: Color(0xff3F2668),//0xffB0A6C2, rgba(176, 166, 194, 1) - borderRadius: BorderRadius.all(Radius.circular(3)), - boxShadow: [ - BoxShadow( - color: Colors.black12,//Color(0xff00000029), - spreadRadius: 2, - blurRadius: 2, - offset: Offset(0, 0), - ), - ], - ), - child: TextButton( - onPressed: () { - //Animates to next tab - _backTab(); - }, - child: Center( - child: Text("Back", - style: TextStyle( - color: Colors.white, - fontFamily: 'Brandon-med', + SizedBox(height: (MediaQuery.of(context).size.height) *(10.74/926),), + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + InkWell( + child: Container( + margin: EdgeInsets.symmetric( + horizontal: w * 25), + height: (MediaQuery.of(context).size.height) *(42/926), + width: (MediaQuery.of(context).size.width) *(68/428), + decoration: BoxDecoration( + color: Color(0xff3F2668),//0xffB0A6C2, rgba(176, 166, 194, 1) + borderRadius: BorderRadius.all(Radius.circular(3)), + boxShadow: [ + BoxShadow( + color: Colors.black12,//Color(0xff00000029), + spreadRadius: 2, + blurRadius: 2, + offset: Offset(0, 0), ), - ), + ], ), - ), - ), - ), - InkWell( - child: Container( - height: (MediaQuery.of(context).size.height) *(42/926), - width: (MediaQuery.of(context).size.width) *(68/428), - decoration: BoxDecoration( - color: Color(0xff3F2668),//0xffB0A6C2, rgba(176, 166, 194, 1) - borderRadius: BorderRadius.all(Radius.circular(3)), - boxShadow: [ - BoxShadow( - color: Colors.black12,//Color(0xff00000029), - spreadRadius: 2, - blurRadius: 2, - offset: Offset(0, 0), - ), - ], - ), - child: TextButton( - onPressed: () { - //Animates to next tab - _nextTab(); - }, - child: Center( - child: Text("Next", - style: TextStyle( - color: Colors.white, - fontFamily: 'Brandon-med', + child: TextButton( + onPressed: () { + //Animates to next tab + _backTab(); + }, + child: Center( + child: Text("Back", + style: TextStyle( + color: Colors.white, + fontFamily: 'Brandon-med', + ), ), ), ), ), ), - ), - ], - ), - ], - ), - - //Tab4: Question Types - Column( - children: [ - Container( - height: (MediaQuery.of(context).size.height) *(40.32/926), - width: (MediaQuery.of(context).size.width) *(386/428), - //color: Colors.red, - decoration: BoxDecoration( - color: Color(0xFF3F2668),//0xffB0A6C2, rgba(176, 166, 194, 1) - borderRadius: BorderRadius.only(bottomLeft: Radius.circular(15.0), topRight: Radius.circular(15.0),), - boxShadow: [ - BoxShadow( - color: Colors.black12,//Color(0xff00000029), - spreadRadius: 2, - blurRadius: 2, - offset: Offset(0, 0), - ), - ], - ), - child: Center( - child: Text("Select Question Types", - style: TextStyle( - color: Colors.white, - fontFamily: 'Brandon-bld', - fontSize: (MediaQuery.of(context).size.height) *(26.31/926),//38, - ),), - ), - ), - SizedBox(height: (MediaQuery.of(context).size.height) *(33/926)), - Container( - padding: EdgeInsets.only(left: (MediaQuery.of(context).size.width) *(10/428), right: (MediaQuery.of(context).size.width) *(10/428)), - width: (MediaQuery.of(context).size.width) *(366/428), - height: (MediaQuery.of(context).size.height) *(460/926), - child: Column( - children: [ - for(int i = 1; i<7; i++) - Column( - children: [ - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Container( - height: (MediaQuery.of(context).size.height) *(40.224/926), - width: (MediaQuery.of(context).size.width) *(302/428), - color: _questionTypeSelectedBool[i] == false ? Colors.white : Color(0xFF3F2668), - child: TextButton( - style: TextButton.styleFrom( - padding: EdgeInsets.zero,), - child: Text(_questionTypesTitle[i], - style: TextStyle( - color: _questionTypeSelectedBool[i] == false ? Color(0xFF3F3D56) : Colors.white, - fontFamily: 'Brandon-med', - fontSize: (MediaQuery.of(context).size.height)*(15/926), - ),), - onPressed: () { - _questionTypesLogic(i); - getQuestionsCount(); - }, - ), + InkWell( + child: Container( + margin: EdgeInsets.symmetric( + horizontal: w * 25), + height: (MediaQuery.of(context).size.height) *(42/926), + width: (MediaQuery.of(context).size.width) *(68/428), + decoration: BoxDecoration( + color: Color(0xff3F2668),//0xffB0A6C2, rgba(176, 166, 194, 1) + borderRadius: BorderRadius.all(Radius.circular(3)), + boxShadow: [ + BoxShadow( + color: Colors.black12,//Color(0xff00000029), + spreadRadius: 2, + blurRadius: 2, + offset: Offset(0, 0), ), - _questionTypeSelectedBool[i] == false ? - GestureDetector( - onTap: () { - _questionTypesLogic(i); - getQuestionsCount(); - }, - child: Container( - height: (MediaQuery.of(context).size.height) *(34.224/926), - width: (MediaQuery.of(context).size.height) *(34.224/926), - // width: (MediaQuery.of(context).size.width) *(29.224/428), - decoration: BoxDecoration( - border: Border.all(width: 9, color: Color(0xFFA1A1A1)), - borderRadius: BorderRadius.all(Radius.circular(50)), - ), - ), - ) - : - GestureDetector( - onTap: () { - _questionTypesLogic(i); - getQuestionsCount(); - }, - child: Container( - child: Icon(Icons.check, - size: (MediaQuery.of(context).size.height) *(34.224/926), - color: Color(0xFF3F2668),) - ), - ), ], + ), + child: TextButton( + onPressed: () { + //Animates to next tab + _nextTab(); + }, + child: Center( + child: Text("Next", + style: TextStyle( + color: Colors.white, + fontFamily: 'Brandon-med', + ), + ), ), - SizedBox(height: (MediaQuery.of(context).size.height) *(25.224/926)), - ], + ), ), + ), ], ), - ), - SizedBox(height: (MediaQuery.of(context).size.height) *(10.74/926),), - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - InkWell( - child: Container( - height: (MediaQuery.of(context).size.height) *(42/926), - width: (MediaQuery.of(context).size.width) *(68/428), - decoration: BoxDecoration( - color: Color(0xff3F2668),//0xffB0A6C2, rgba(176, 166, 194, 1) - borderRadius: BorderRadius.all(Radius.circular(3)), - boxShadow: [ - BoxShadow( - color: Colors.black12,//Color(0xff00000029), - spreadRadius: 2, - blurRadius: 2, - offset: Offset(0, 0), - ), - ], + ], + ), + + //Tab5: Generate Quiz + Column( + children: [ + Container( + height: (MediaQuery.of(context).size.height) *(40.32/926), + width: (MediaQuery.of(context).size.width) *(386/428), + //color: Colors.red, + decoration: BoxDecoration( + color: Color(0xFF3F2668),//0xffB0A6C2, rgba(176, 166, 194, 1) + borderRadius: BorderRadius.only(bottomLeft: Radius.circular(15.0), topRight: Radius.circular(15.0),), + boxShadow: [ + BoxShadow( + color: Colors.black12,//Color(0xff00000029), + spreadRadius: 2, + blurRadius: 2, + offset: Offset(0, 0), ), - child: TextButton( - onPressed: () { - //Animates to next tab - _backTab(); - }, - child: Center( - child: Text("Back", - style: TextStyle( - color: Colors.white, - fontFamily: 'Brandon-med', - ), + ], + ), + child: Center( + child: Text("Generate Quiz", + style: TextStyle( + color: Colors.white, + fontFamily: 'Brandon-bld', + fontSize: (MediaQuery.of(context).size.height) *(26.31/926),//38, + ),), + ), + ), + SizedBox(height: (MediaQuery.of(context).size.height) *(22.8/926)), + Container( + width: (MediaQuery.of(context).size.width) *(386/428), // 460/926 + height: (MediaQuery.of(context).size.height) *(460/926), + child: Column( + children: [ + Center( + child: Text("Set Difficulty Level", + style: TextStyle( + color: Color(0xFF232323), + fontFamily: 'Brandon-med', + fontSize: (MediaQuery.of(context).size.height) *(16/926), ), ), ), - ), - ), - InkWell( - child: Container( - height: (MediaQuery.of(context).size.height) *(42/926), - width: (MediaQuery.of(context).size.width) *(68/428), - decoration: BoxDecoration( - color: Color(0xff3F2668),//0xffB0A6C2, rgba(176, 166, 194, 1) - borderRadius: BorderRadius.all(Radius.circular(3)), - boxShadow: [ - BoxShadow( - color: Colors.black12,//Color(0xff00000029), - spreadRadius: 2, - blurRadius: 2, - offset: Offset(0, 0), + SizedBox(height: (MediaQuery.of(context).size.height) *(26.59/926),), + Row( + children: [ + for(int i = 1; i<6; i++) + Row( + children: [ + Container( + height: (MediaQuery.of(context).size.height) *(40.224/926), + width: (MediaQuery.of(context).size.width) *((60)/428), + color: _difficultyLevelBool[i-1] == false ? Color(0xFFE4E4E4) : Color(0xFF7F1AF1), + child: TextButton( + style: TextButton.styleFrom( + padding: EdgeInsets.zero,), + child: Text(_difficultyLevelTitle[i-1], + style: TextStyle( + color: _difficultyLevelBool[i-1] == false ? Color(0xFF3F2668) : Colors.white, + fontFamily: 'Brandon-med', + fontSize: (MediaQuery.of(context).size.height)*(13/926), + ),), + onPressed: () { + setState(() { + if(_difficultyLevelBool[i-1] == false) { + _difficultyLevelBool[i-1] = true; + _difficultyLevel.add(i); + } + else if(_difficultyLevelBool[i-1] == true) { + _difficultyLevelBool[i-1] = false; + _difficultyLevel.remove(i); + } + }); + getQuestionsCount(); + }, + ), ), + if(i != 5) + // SizedBox(width: (MediaQuery.of(context).size.width) *(46/926)), + for(int j = 0; j<6; j++) + Row( + children: [ + Container( + child: Container( + height: (MediaQuery.of(context).size.height) *(2/926), + width: (MediaQuery.of(context).size.width) *(3.55/428), + decoration: BoxDecoration( + color: Color(0xFFE4E4E4), + shape: BoxShape.circle, + ), + ), + ), + ], + ) + ], + ), ], ), - child: TextButton( - onPressed: () { - //Animates to next tab - _nextTab(); - }, - child: Center( - child: Text("Next", - style: TextStyle( - color: Colors.white, - fontFamily: 'Brandon-med', - ), + SizedBox(height: (MediaQuery.of(context).size.height) *(48/926),), + Center( + child: Text("Generate Quiz", + style: TextStyle( + color: Color(0xFF232323), + fontFamily: 'Brandon-med', + fontSize: (MediaQuery.of(context).size.height) *(16/926), ), ), ), - ), - ), - ], - ), - ], - ), - - //Tab5: Generate Quiz - Column( - children: [ - Container( - height: (MediaQuery.of(context).size.height) *(40.32/926), - width: (MediaQuery.of(context).size.width) *(386/428), - //color: Colors.red, - decoration: BoxDecoration( - color: Color(0xFF3F2668),//0xffB0A6C2, rgba(176, 166, 194, 1) - borderRadius: BorderRadius.only(bottomLeft: Radius.circular(15.0), topRight: Radius.circular(15.0),), - boxShadow: [ - BoxShadow( - color: Colors.black12,//Color(0xff00000029), - spreadRadius: 2, - blurRadius: 2, - offset: Offset(0, 0), - ), - ], - ), - child: Center( - child: Text("Generate Quiz", - style: TextStyle( - color: Colors.white, - fontFamily: 'Brandon-bld', - fontSize: (MediaQuery.of(context).size.height) *(26.31/926),//38, - ),), - ), - ), - SizedBox(height: (MediaQuery.of(context).size.height) *(22.8/926)), - Container( - width: (MediaQuery.of(context).size.width) *(386/428), // 460/926 - height: (MediaQuery.of(context).size.height) *(460/926), - child: Column( - children: [ - Center( - child: Text("Set Difficulty Level", - style: TextStyle( - color: Color(0xFF232323), - fontFamily: 'Brandon-med', - fontSize: (MediaQuery.of(context).size.height) *(16/926), - ), - ), - ), - SizedBox(height: (MediaQuery.of(context).size.height) *(26.59/926),), - Row( - children: [ - for(int i = 1; i<6; i++) + SizedBox(height: (MediaQuery.of(context).size.height) *(28/926),), + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ Row( children: [ Container( - height: (MediaQuery.of(context).size.height) *(40.224/926), - width: (MediaQuery.of(context).size.width) *((60)/428), - color: _difficultyLevelBool[i-1] == false ? Color(0xFFE4E4E4) : Color(0xFF7F1AF1), - child: TextButton( - style: TextButton.styleFrom( - padding: EdgeInsets.zero,), - child: Text(_difficultyLevelTitle[i-1], - style: TextStyle( - color: _difficultyLevelBool[i-1] == false ? Color(0xFF3F2668) : Colors.white, - fontFamily: 'Brandon-med', - fontSize: (MediaQuery.of(context).size.height)*(13/926), - ),), - onPressed: () { - setState(() { - if(_difficultyLevelBool[i-1] == false) { - _difficultyLevelBool[i-1] = true; - _difficultyLevel.add(i); - } - else if(_difficultyLevelBool[i-1] == true) { - _difficultyLevelBool[i-1] = false; - _difficultyLevel.remove(i); - } - }); - getQuestionsCount(); - }, + height: (MediaQuery.of(context).size.height) *(30/926), + width: (MediaQuery.of(context).size.width) *(98/428), + padding: EdgeInsets.zero, + margin: EdgeInsets.zero, + decoration: BoxDecoration( + color: _tutorMode? Color(0xff3F2668) : Colors.white, + border: Border.all(color: Color(0xff3F2668)), + borderRadius: BorderRadius.only(topLeft: Radius.circular(3), bottomLeft: Radius.circular(3)), + ), + //color: Colors.red, + child: InkWell( + onTap: () { + if(_tutorMode == false) { + setState(() { + _tutorMode = true; + print(_tutorMode); + }); + } + }, + child: Center( + child: Text("Tutor Mode", + style: TextStyle( + color: _tutorMode? Colors.white : Color(0xff3F2668), + fontFamily: 'Brandon-med', + fontSize: (MediaQuery.of(context).size.height) *(15/926) + ), + ), + ), + ) ), - ), - if(i != 5) - // SizedBox(width: (MediaQuery.of(context).size.width) *(46/926)), - for(int j = 0; j<6; j++) - Row( - children: [ - Container( - child: Container( - height: (MediaQuery.of(context).size.height) *(2/926), - width: (MediaQuery.of(context).size.width) *(3.55/428), - decoration: BoxDecoration( - color: Color(0xFFE4E4E4), - shape: BoxShape.circle, + Container( + height: (MediaQuery.of(context).size.height) *(30/926), + width: (MediaQuery.of(context).size.width) *(98/428), + padding: EdgeInsets.zero, + margin: EdgeInsets.zero, + decoration: BoxDecoration( + color: _tutorMode? Colors.white : Color(0xff3F2668), + border: Border.all(color: Color(0xff3F2668)), + borderRadius: BorderRadius.only(topRight: Radius.circular(3), bottomRight: Radius.circular(3)), + ), + //color: Colors.red, + child: InkWell( + onTap: () { + if(_tutorMode == true) { + setState(() { + _tutorMode = false; + // print(_tutorMode); + }); + } + }, + child: Center( + child: Text("Exam Mode", + style: TextStyle( + color: _tutorMode? Color(0xff3F2668) : Colors.white, + fontFamily: 'Brandon-med', + fontSize: (MediaQuery.of(context).size.height) *(15/926) ), ), - ), - ], + ), ) + ), ], ), - ], - ), - SizedBox(height: (MediaQuery.of(context).size.height) *(48/926),), - Center( - child: Text("Generate Quiz", - style: TextStyle( - color: Color(0xFF232323), - fontFamily: 'Brandon-med', - fontSize: (MediaQuery.of(context).size.height) *(16/926), - ), - ), - ), - SizedBox(height: (MediaQuery.of(context).size.height) *(28/926),), - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Row( - children: [ - Container( - height: (MediaQuery.of(context).size.height) *(30/926), - width: (MediaQuery.of(context).size.width) *(98/428), - padding: EdgeInsets.zero, - margin: EdgeInsets.zero, - decoration: BoxDecoration( - color: _tutorMode? Color(0xff3F2668) : Colors.white, - border: Border.all(color: Color(0xff3F2668)), - borderRadius: BorderRadius.only(topLeft: Radius.circular(3), bottomLeft: Radius.circular(3)), - ), - //color: Colors.red, - child: InkWell( - onTap: () { - if(_tutorMode == false) { + Row( + children: [ + Transform.scale( + scale: 1, + child: Container( + height: (MediaQuery.of(context).size.height) *(20/926), + child: Switch( + value: _timedMode, + onChanged: (value) { setState(() { - _tutorMode = true; - print(_tutorMode); + _timedMode = value; + // print(_timedMode); }); - } - }, - child: Center( - child: Text("Tutor Mode", - style: TextStyle( - color: _tutorMode? Colors.white : Color(0xff3F2668), - fontFamily: 'Brandon-med', - fontSize: (MediaQuery.of(context).size.height) *(15/926) - ), - ), + }, + activeColor: Color(0xff3F2668), ), - ) - ), - Container( - height: (MediaQuery.of(context).size.height) *(30/926), - width: (MediaQuery.of(context).size.width) *(98/428), - padding: EdgeInsets.zero, - margin: EdgeInsets.zero, - decoration: BoxDecoration( - color: _tutorMode? Colors.white : Color(0xff3F2668), - border: Border.all(color: Color(0xff3F2668)), - borderRadius: BorderRadius.only(topRight: Radius.circular(3), bottomRight: Radius.circular(3)), ), - //color: Colors.red, - child: InkWell( - onTap: () { - if(_tutorMode == true) { - setState(() { - _tutorMode = false; - // print(_tutorMode); - }); - } - }, - child: Center( - child: Text("Exam Mode", - style: TextStyle( - color: _tutorMode? Color(0xff3F2668) : Colors.white, - fontFamily: 'Brandon-med', - fontSize: (MediaQuery.of(context).size.height) *(15/926) - ), - ), + ), + Container( + child: Text("Timed Mode", + style: TextStyle( + color: Color(0xff483A3A), + fontFamily: 'Brandon-med', + fontSize: (MediaQuery.of(context).size.height) *(15/926) ), - ) - ), - ], - ), - Row( - children: [ - Transform.scale( - scale: 1, - child: Container( - height: (MediaQuery.of(context).size.height) *(20/926), - child: Switch( - value: _timedMode, - onChanged: (value) { - setState(() { - _timedMode = value; - // print(_timedMode); - }); - }, - activeColor: Color(0xff3F2668), ), ), + SizedBox(width: (MediaQuery.of(context).size.width) *(10/428)), + + ], + ), + ], + ), + SizedBox(height: (MediaQuery.of(context).size.height) *(40/926)), + Container( + padding: EdgeInsets.only(bottom: (MediaQuery.of(context).size.height) *(15/926)), + child: Row( + children: [ + Text("Enter The Number Of Questions: ", + style: TextStyle( + color: Color(0xff3F3D56), + fontFamily: 'Brandon-med', + fontSize: (MediaQuery.of(context).size.height) *(15/926) + ), ), Container( - child: Text("Timed Mode", - style: TextStyle( - color: Color(0xff483A3A), + height: (MediaQuery.of(context).size.height) *(24/926), + width: (MediaQuery.of(context).size.width) *(40.01/428), + color: Colors.white, + child: Form( + key: _numberOfQuestionsKey, + child: TextField( + controller: _textCountController, + keyboardType: TextInputType.number, + inputFormatters: [ + FilteringTextInputFormatter.digitsOnly + ], // Only numbers can be entered + textAlign: TextAlign.center, + decoration: InputDecoration( + hintText: "4", + hintStyle: TextStyle(color: Color(0xffAEAEAE), + fontSize: (MediaQuery.of(context).size.height)*(15/926), + fontFamily: 'Brandon-med',), + contentPadding: EdgeInsets.fromLTRB(2.0, 1, 2.0, 1), + enabledBorder: OutlineInputBorder( + borderSide: BorderSide( + color: Color(0xFF7070709E), + width: 1.0, + ), + borderRadius: BorderRadius.circular(3.0), + ), + focusedBorder: OutlineInputBorder( + borderSide: BorderSide( + color: Colors.transparent, + width: 0.0, + ), + ), + ), + style: TextStyle( + color: Colors.black, + fontSize: (MediaQuery.of(context).size.height)*(15/926), fontFamily: 'Brandon-med', - fontSize: (MediaQuery.of(context).size.height) *(15/926) + ), + onChanged: (val) { + final number = num.tryParse(val); + if(number != null) { + var totalQuestions; + try { + totalQuestions = _totalQuestions; + } catch (error) { + ScaffoldMessenger.of(context) + ..removeCurrentSnackBar() + ..showSnackBar(SnackBar(content: Text("Error"))); + } + if((int.parse(val)>totalQuestions) || (int.parse(val)>40)) { + ScaffoldMessenger.of(context) + ..removeCurrentSnackBar() + ..showSnackBar(SnackBar(content: Text("Enter a smaller number"))); + _textCountController.clear(); + setState(() { + _questionsCount = 0; + }); + } + else if(int.parse(val) <= 0) { + ScaffoldMessenger.of(context) + ..removeCurrentSnackBar() + ..showSnackBar(SnackBar(content: Text("Enter a bigger number"))); + _textCountController.clear(); + setState(() { + _questionsCount = 0; + }); + } + else{ + setState(() { + _questionsCount = int.parse(val); + }); + } + } + }, ), ), ), - SizedBox(width: (MediaQuery.of(context).size.width) *(10/428)), + Text(" /" + (_gettingQuestionsCount ? "Loading..." : _totalQuestions.toString()), + style: TextStyle( + color: Color(0xFF98A4A4), + fontSize: (MediaQuery.of(context).size.height)*(15/926), + fontFamily: 'Brandon-med', + ),), + ], + ), + ), + ], + ), + ), + SizedBox(height: (MediaQuery.of(context).size.height) *(21/926),), + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + InkWell( + child: Container( + margin: EdgeInsets.symmetric( + horizontal: w * 25), + height: (MediaQuery.of(context).size.height) *(42/926), + width: (MediaQuery.of(context).size.width) *(68/428), + decoration: BoxDecoration( + color: Color(0xff3F2668),//0xffB0A6C2, rgba(176, 166, 194, 1) + borderRadius: BorderRadius.all(Radius.circular(3)), + boxShadow: [ + BoxShadow( + color: Colors.black12,//Color(0xff00000029), + spreadRadius: 2, + blurRadius: 2, + offset: Offset(0, 0), + ), ], ), - ], - ), - SizedBox(height: (MediaQuery.of(context).size.height) *(40/926)), - Container( - padding: EdgeInsets.only(bottom: (MediaQuery.of(context).size.height) *(15/926)), - child: Row( - children: [ - Text("Enter The Number Of Questions: ", - style: TextStyle( - color: Color(0xff3F3D56), + child: TextButton( + onPressed: () { + //Animates to next tab + _backTab(); + }, + child: Center( + child: Text("Back", + style: TextStyle( + color: Colors.white, fontFamily: 'Brandon-med', - fontSize: (MediaQuery.of(context).size.height) *(15/926) - ), - ), - Container( - height: (MediaQuery.of(context).size.height) *(24/926), - width: (MediaQuery.of(context).size.width) *(40.01/428), - color: Colors.white, - child: Form( - key: _numberOfQuestionsKey, - child: TextField( - keyboardType: TextInputType.number, - inputFormatters: [ - FilteringTextInputFormatter.digitsOnly - ], // Only numbers can be entered - textAlign: TextAlign.center, - decoration: InputDecoration( - hintText: "4", - hintStyle: TextStyle(color: Color(0xffAEAEAE), - fontSize: (MediaQuery.of(context).size.height)*(15/926), - fontFamily: 'Brandon-med',), - contentPadding: EdgeInsets.fromLTRB(2.0, 1, 2.0, 1), - enabledBorder: OutlineInputBorder( - borderSide: BorderSide( - color: Color(0xFF7070709E), - width: 1.0, - ), - borderRadius: BorderRadius.circular(3.0), - ), - focusedBorder: OutlineInputBorder( - borderSide: BorderSide( - color: Colors.transparent, - width: 0.0, - ), - ), - ), - style: TextStyle( - color: Colors.black, - fontSize: (MediaQuery.of(context).size.height)*(15/926), - fontFamily: 'Brandon-med', - ), - onChanged: (val) { - final number = num.tryParse(val); - if(number != null) { - var totalQuestions; - try { - totalQuestions = _totalQuestions; - } catch (error) { - ScaffoldMessenger.of(context) - ..removeCurrentSnackBar() - ..showSnackBar(SnackBar(content: Text("Error"))); - } - if((int.parse(val)>totalQuestions) || (int.parse(val)>=40)) { - ScaffoldMessenger.of(context) - ..removeCurrentSnackBar() - ..showSnackBar(SnackBar(content: Text("Enter a smaller number"))); - setState(() { - _questionsCount = 0; - }); - } - else{ - setState(() { - _questionsCount = int.parse(val); - }); - } - } - }, ), ), ), - Text(" /" + _totalQuestions.toString(), - style: TextStyle( - color: Color(0xFF98A4A4), - fontSize: (MediaQuery.of(context).size.height)*(15/926), - fontFamily: 'Brandon-med', - ),), - ], + ), ), ), - ], - ), - ), - SizedBox(height: (MediaQuery.of(context).size.height) *(21/926),), - - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - InkWell( - child: Container( - height: (MediaQuery.of(context).size.height) *(42/926), - width: (MediaQuery.of(context).size.width) *(68/428), - decoration: BoxDecoration( - color: Color(0xff3F2668),//0xffB0A6C2, rgba(176, 166, 194, 1) - borderRadius: BorderRadius.all(Radius.circular(3)), - boxShadow: [ - BoxShadow( - color: Colors.black12,//Color(0xff00000029), - spreadRadius: 2, - blurRadius: 2, - offset: Offset(0, 0), - ), - ], - ), - child: TextButton( - onPressed: () { - //Animates to next tab - _backTab(); - }, - child: Center( - child: Text("Back", - style: TextStyle( - color: Colors.white, - fontFamily: 'Brandon-med', + InkWell( + child: Container( + margin: EdgeInsets.symmetric( + horizontal: w * 25), + height: (MediaQuery.of(context).size.height) *(42/926), + width: (MediaQuery.of(context).size.width) *(100/428), + decoration: BoxDecoration( + color: Color(0xff3F2668),//0xffB0A6C2, rgba(176, 166, 194, 1) + borderRadius: BorderRadius.all(Radius.circular(3)), + boxShadow: [ + BoxShadow( + color: Colors.black12,//Color(0xff00000029), + spreadRadius: 2, + blurRadius: 2, + offset: Offset(0, 0), ), - ), + ], ), - ), - ), - ), - InkWell( - child: Container( - height: (MediaQuery.of(context).size.height) *(42/926), - width: (MediaQuery.of(context).size.width) *(100/428), - decoration: BoxDecoration( - color: Color(0xff3F2668),//0xffB0A6C2, rgba(176, 166, 194, 1) - borderRadius: BorderRadius.all(Radius.circular(3)), - boxShadow: [ - BoxShadow( - color: Colors.black12,//Color(0xff00000029), - spreadRadius: 2, - blurRadius: 2, - offset: Offset(0, 0), - ), - ], - ), - child: TextButton( - onPressed: () { - print("adsdsa"); - // print(num.tryParse(_questionsCount)); - if(_questionsCount > 0) { - final result = Navigator.push( - context, - MaterialPageRoute(builder: (context) => QuizModule(totalQuestions: _questionsCount, questions: _questions, timedMode: _timedMode, mode: _tutorMode ? "tutor" : "exam", whatsDone: "new",)), - ); - } - }, - child: Center( - child: Text("Create Quiz", - style: TextStyle( - color: Colors.white, - fontFamily: 'Brandon-med', + child: TextButton( + onPressed: _gettingQuestionsCount ? null : () { + print("adsdsa"); + // print(num.tryParse(_questionsCount)); + if(_questionsCount > 0) { + final result = Navigator.push( + context, + MaterialPageRoute(builder: (context) => QuizModule(totalQuestions: _questionsCount, questions: _questions, timedMode: _timedMode, mode: _tutorMode ? "tutor" : "exam", whatsDone: "new",)), + ); + } + }, + child: Center( + child: Text("Create Quiz", + style: TextStyle( + color: Colors.white, + fontFamily: 'Brandon-med', + ), ), ), ), ), ), - ), - ], - ), - ], - ), - ], + ], + ), + ], + ), + ], + ), ), - ), - ], + ], + ), ), ), ), diff --git a/lib/screens/Welcome/Notes/noteDetails.dart b/lib/screens/Welcome/Notes/noteDetails.dart index d906b01..b19afc2 100644 --- a/lib/screens/Welcome/Notes/noteDetails.dart +++ b/lib/screens/Welcome/Notes/noteDetails.dart @@ -75,13 +75,36 @@ class _NoteDetailsState extends State { ..showSnackBar(SnackBar(content: Text("Note not Edited!"))); } } - ); + ).catchError((error){ + var errorSplit = error.toString().split(":"); + if(errorSplit[0].toLowerCase() == "socketexception") { + ScaffoldMessenger.of(context) + ..removeCurrentSnackBar() + ..showSnackBar(SnackBar(content: Text("No Internet Connection"))); + } + // else if(errorSplit[0].toLowerCase() == "httpexception") { + // ScaffoldMessenger.of(context) + // ..removeCurrentSnackBar() + // ..showSnackBar(SnackBar(content: Text("Couldn't find the said thing."))); + // } + else if(errorSplit[0].toLowerCase() == "formatexception") { + ScaffoldMessenger.of(context) + ..removeCurrentSnackBar() + ..showSnackBar(SnackBar(content: Text("Bad Response Format"))); + } + else { + ScaffoldMessenger.of(context) + ..removeCurrentSnackBar() + ..showSnackBar(SnackBar(content: Text(error.toString()))); + } + }); } Future deleteNotesAPI() async { SharedPreferences prefs = await SharedPreferences.getInstance(); _token = prefs.getString('token')!; - final String editNotesAPI = "https://demo.pookidevs.com/quiz/notes/editNotes"; + final String editNotesAPI = "https://demo.pookidevs.com/quiz/notes/deleteNotes"; + print(widget.noteId.runtimeType); http.post(Uri.parse(editNotesAPI), headers: { 'Content-type': 'application/json; charset=UTF-8', 'Authorization' : _token.toString(), }, body: json.encode( @@ -96,7 +119,12 @@ class _NoteDetailsState extends State { ScaffoldMessenger.of(context) ..removeCurrentSnackBar() ..showSnackBar(SnackBar(content: Text("Note Deleted!"))); - Navigator.of(context).pop(); + Navigator.of(context) + .popUntil(ModalRoute.withName("/home")); + Navigator.push( + context, + MaterialPageRoute(builder: (context) => Notes()), + ); } else if((response.statusCode == 200) & (json.decode(response.body).toString().substring(0,14) == "{status: false")) { // Token Invalid ScaffoldMessenger.of(context) @@ -113,7 +141,29 @@ class _NoteDetailsState extends State { ..showSnackBar(SnackBar(content: Text("Note not Deleted!"))); } } - ); + ).catchError((error){ + var errorSplit = error.toString().split(":"); + if(errorSplit[0].toLowerCase() == "socketexception") { + ScaffoldMessenger.of(context) + ..removeCurrentSnackBar() + ..showSnackBar(SnackBar(content: Text("No Internet Connection"))); + } + // else if(errorSplit[0].toLowerCase() == "httpexception") { + // ScaffoldMessenger.of(context) + // ..removeCurrentSnackBar() + // ..showSnackBar(SnackBar(content: Text("Couldn't find the said thing."))); + // } + else if(errorSplit[0].toLowerCase() == "formatexception") { + ScaffoldMessenger.of(context) + ..removeCurrentSnackBar() + ..showSnackBar(SnackBar(content: Text("Bad Response Format"))); + } + else { + ScaffoldMessenger.of(context) + ..removeCurrentSnackBar() + ..showSnackBar(SnackBar(content: Text(error.toString()))); + } + }); } Widget editNotes(BuildContext context) { @@ -287,9 +337,12 @@ class _NoteDetailsState extends State { Widget build(BuildContext context) { return WillPopScope( onWillPop: () async { - ScaffoldMessenger.of(context) - ..removeCurrentSnackBar() - ..showSnackBar(SnackBar(content: Text("Press back button!"))); + Navigator.of(context) + .popUntil(ModalRoute.withName("/home")); + final result = await Navigator.push( + context, + MaterialPageRoute(builder: (context) => Notes()), + ); return false; }, child: Scaffold( diff --git a/lib/screens/Welcome/Notes/notes.dart b/lib/screens/Welcome/Notes/notes.dart index 86da528..25b3af2 100644 --- a/lib/screens/Welcome/Notes/notes.dart +++ b/lib/screens/Welcome/Notes/notes.dart @@ -73,7 +73,27 @@ class _NotesState extends State { ); } } - ); + ).catchError((error){ + setState(() { + _hasNotesDataLoaded = true; + }); + var errorSplit = error.toString().split(":"); + if(errorSplit[0].toLowerCase() == "socketexception") { + ScaffoldMessenger.of(context) + ..removeCurrentSnackBar() + ..showSnackBar(SnackBar(content: Text("No Internet Connection"))); + } + else if(errorSplit[0].toLowerCase() == "formatexception") { + ScaffoldMessenger.of(context) + ..removeCurrentSnackBar() + ..showSnackBar(SnackBar(content: Text("Bad Response Format"))); + } + else { + ScaffoldMessenger.of(context) + ..removeCurrentSnackBar() + ..showSnackBar(SnackBar(content: Text(error.toString()))); + } + }); } categorizeNotesData() { @@ -92,13 +112,13 @@ class _NotesState extends State { _notesData["user_id"]!.add(_notesSuccessful.data.notes[c].userId); _notesData["quiz_id"]!.add(_notesSuccessful.data.notes[c].quizId); _notesData["notes"]!.add(_notesSuccessful.data.notes[c].notes); - notesMetaString = _notesSuccessful.data.notes[c].noteMeta; - notesMetaString = notesMetaString.replaceAll("\\", ""); - decodeNotesMetaString = jsonDecode(notesMetaString); - noteMetaEntry["noteTopic"] = decodeNotesMetaString["noteTopic"]; - noteMetaEntry["noteSystem"] = decodeNotesMetaString["noteSystem"]; - noteMetaEntry["noteSubject"] = decodeNotesMetaString["noteSubject"]; - _notesData["note_meta"]!.add(noteMetaEntry); + // notesMetaString = _notesSuccessful.data.notes[c].noteMeta; + // notesMetaString = notesMetaString.replaceAll("\\", ""); + // decodeNotesMetaString = jsonDecode(notesMetaString); + // noteMetaEntry["noteTopic"] = decodeNotesMetaString["noteTopic"]; + // noteMetaEntry["noteSystem"] = decodeNotesMetaString["noteSystem"]; + // noteMetaEntry["noteSubject"] = decodeNotesMetaString["noteSubject"]; + // _notesData["note_meta"]!.add(noteMetaEntry); }); c++; } @@ -198,10 +218,21 @@ class _NotesState extends State { SizedBox(height: (MediaQuery.of(context).size.height)*(30/926),), Padding( padding: const EdgeInsets.all(8.0), - child: Column( + child: _hasNotesDataLoaded == false ? CircularProgressIndicator(color: Color(0xFF3F2668)) : Column( mainAxisAlignment: MainAxisAlignment.center, children: [ - _hasNotesDataLoaded == false ? CircularProgressIndicator(color: Color(0xFF3F2668)) : + if(_notesData["idpsas_user_notes"]!.length <= 0) + Container( + child: Align( + alignment: Alignment.topCenter, + child: Text("No Notes Available!", + style: TextStyle( + color: Color(0xffAEAEAE), + fontFamily: 'Brandon-bld', + fontSize: (MediaQuery.of(context).size.height) *(15/926),//38, + ),), + ), + ), GridView.count(shrinkWrap:true,crossAxisCount: 2,crossAxisSpacing:(MediaQuery.of(context).size.width) *(68/428) ,mainAxisSpacing: (MediaQuery.of(context).size.height) *(41/926),childAspectRatio: 1,children: [ for(int i = 0; i<_notesData["idpsas_user_notes"]!.length; i++) NotesTile(noteId: _notesData["idpsas_user_notes"]![i], noteText: _notesData["notes"]![i]), diff --git a/lib/screens/Welcome/PreviousQuiz/TestAnalysis/analysisDetails.dart b/lib/screens/Welcome/PreviousQuiz/TestAnalysis/analysisDetails.dart new file mode 100644 index 0000000..6b7ca74 --- /dev/null +++ b/lib/screens/Welcome/PreviousQuiz/TestAnalysis/analysisDetails.dart @@ -0,0 +1,407 @@ +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_svg/svg.dart'; +import 'package:expandable/expandable.dart'; +import 'package:shared_preferences/shared_preferences.dart'; +import 'package:testify/models/GetPreviousQuizzesModel/TestAnalysisModel/test_analysis_model.dart'; + +import '../../../Authentication/login.dart'; +import '../../side_menu_bar.dart'; + +class DetailsTile extends StatelessWidget { + final int id; + final String name; + final int totalQuestions; + final int correctQuestions; + final int incorrectQuestions; + final int omittedQuestions; + DetailsTile({required this.id, required this.name, required this.totalQuestions, required this.correctQuestions, required this.incorrectQuestions, required this.omittedQuestions}); + @override + Widget build(BuildContext context) { + return ExpandableNotifier(child: Column(children: [ + Expandable( + collapsed: ExpandableButton( + child: Container( + height: MediaQuery.of(context).size.height * (78 / 926), + width: MediaQuery.of(context).size.width * (363 / 428), + decoration: BoxDecoration( + color: Colors.white, + border: Border.all(color: Color(0xff8B8B8B)), + boxShadow: const [ + BoxShadow( + offset: Offset(0, 4), + blurRadius: 6, + color: Colors.grey // background color + ), + ], + borderRadius: BorderRadius.circular( + MediaQuery.of(context).size.height * 5 / 926)), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Container( + height: MediaQuery.of(context).size.height * (78 / 926), + width: MediaQuery.of(context).size.height * (78 / 926), + padding: EdgeInsets.symmetric( + vertical: MediaQuery.of(context).size.height * (12 / 926), + horizontal: + (MediaQuery.of(context).size.width) * (5 / 428)), + color: Color(0xff6D5A8D), + child: Text( + 'Sr.No\n' + id.toString(), + textAlign: TextAlign.center, + style: TextStyle( + color: Color(0xffFFFEFE), + fontFamily: 'Brandon-med', + fontSize: (MediaQuery.of(context).size.height) * (17 / 926), + ), + ), + ), + Container( + padding: EdgeInsets.symmetric( + vertical: MediaQuery.of(context).size.height * (12 / 926), + horizontal: + (MediaQuery.of(context).size.width) * (12 / 428)), + child: Text( + name, + textAlign: TextAlign.center, + style: TextStyle( + color: Color(0xff8B8B8B), + fontFamily: 'Brandon-med', + fontSize: + (MediaQuery.of(context).size.height) * (21 / 926), + ), + )), + Container( + padding: EdgeInsets.symmetric( + vertical: MediaQuery.of(context).size.height * (12 / 926), + horizontal: + (MediaQuery.of(context).size.width) * (12 / 428)), + child: Icon( + Icons.arrow_drop_down, + size: MediaQuery.of(context).size.height * (35 / 926), + color: Color(0xff6D5A8D), + ), + ) + ], + ), + ), + ), + expanded: ExpandableButton( + child:Column( + children: [ + Container( + height: MediaQuery.of(context).size.height * (78 / 926), + width: MediaQuery.of(context).size.width * (363 / 428), + decoration: BoxDecoration( + color: Colors.white, + border: Border.all(color:Color(0xff8B8B8B)), + boxShadow: const [ + BoxShadow( + offset: Offset(0, 4), + blurRadius: 6, + color: Colors.grey // background color + ), + ], + borderRadius: BorderRadius.circular( + MediaQuery.of(context).size.height * 5 / 926)), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Container( + height: MediaQuery.of(context).size.height * (78 / 926), + width: MediaQuery.of(context).size.height * (78 / 926), + padding: EdgeInsets.symmetric( + vertical: MediaQuery.of(context).size.height * (12 / 926), + horizontal: + (MediaQuery.of(context).size.width) * (5 / 428)), + color: Color(0xff6D5A8D), + child: Text( + 'Sr.No\n' + id.toString(), + textAlign: TextAlign.center, + style: TextStyle( + color: Color(0xffFFFEFE), + fontFamily: 'Brandon-med', + fontSize: (MediaQuery.of(context).size.height) * (17 / 926), + ), + ), + ), + Container( + padding: EdgeInsets.symmetric( + vertical: MediaQuery.of(context).size.height * (12 / 926), + horizontal: + (MediaQuery.of(context).size.width) * (12 / 428)), + child: Text( + name, + textAlign: TextAlign.center, + style: TextStyle( + color: Color(0xff8B8B8B), + fontFamily: 'Brandon-med', + fontSize: + (MediaQuery.of(context).size.height) * (21 / 926), + ), + )), + Container( + padding: EdgeInsets.symmetric( + vertical: MediaQuery.of(context).size.height * (12 / 926), + horizontal: + (MediaQuery.of(context).size.width) * (12 / 428)), + child: Icon( + Icons.arrow_drop_down, + size: MediaQuery.of(context).size.height * (35 / 926), + color: Color(0xff6D5A8D), + ), + ) + ], + ), + ), + Container( + height: MediaQuery.of(context).size.height * (78 / 926), + width: MediaQuery.of(context).size.width * (363 / 428), + color: Color(0xA4E4E4E4), + padding: EdgeInsets.symmetric( + vertical: MediaQuery.of(context).size.height * (10 / 926), + horizontal: (MediaQuery.of(context).size.width) * (10 / 428)), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + children: [ + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [Row(mainAxisAlignment: MainAxisAlignment.spaceBetween,children: [ + Text('Total Questions: ', style: TextStyle( + color: Color(0xFF3F2668) , + fontFamily: 'Brandon-med', + fontSize: (MediaQuery.of(context).size.height) * (17 / 926), + ),), + SizedBox(width:MediaQuery.of(context).size.width * (10 / 428)), + Text(totalQuestions.toString(),style: TextStyle( + color: Colors.grey , + fontFamily: 'Brandon-med', + fontSize: (MediaQuery.of(context).size.height) * (17 / 926), + ),) + ],), + + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text('Correct Questions: ', style: TextStyle( + color: Color(0xFF3F2668) , + fontFamily: 'Brandon-med', + fontSize: (MediaQuery.of(context).size.height) * (17 / 926), + ),), + SizedBox(width:MediaQuery.of(context).size.width * (10 / 428)), + Text(correctQuestions.toString(),style: TextStyle( + color: Colors.grey , + fontFamily: 'Brandon-med', + fontSize: (MediaQuery.of(context).size.height) * (17 / 926), + ),) + ],),],), + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ Row(children: [ + Text('Incorrect Questions: ', style: TextStyle( + color: Color(0xFF3F2668) , + fontFamily: 'Brandon-med', + fontSize: (MediaQuery.of(context).size.height) * (17 / 926), + ),), + SizedBox(width:MediaQuery.of(context).size.width * (10 / 428)), + Text(incorrectQuestions.toString(),style: TextStyle( + color: Colors.grey , + fontFamily: 'Brandon-med', + fontSize: (MediaQuery.of(context).size.height) * (17 / 926), + ),) + ],), + Row(children: [ + Text('Omitted Questions: ', style: TextStyle( + color: Color(0xFF3F2668) , + fontFamily: 'Brandon-med', + fontSize: (MediaQuery.of(context).size.height) * (17 / 926), + ),), + SizedBox(width:MediaQuery.of(context).size.width * (10 / 428)), + Text(omittedQuestions.toString(),style: TextStyle( + color: Colors.grey , + fontFamily: 'Brandon-med', + fontSize: (MediaQuery.of(context).size.height) * (17 / 926), + ),) + ],),],) + + + ], + ), + ) + ], + ), + )) + ],)); + } + + + // } +} + +class AnalysisDetails extends StatefulWidget { + @override + _AnalysisDetailsState createState() => _AnalysisDetailsState(); +} + +class _AnalysisDetailsState extends State { + var _getQuizAnalysis; + + @override + void initState() { + super.initState(); + getQuizAnalysis(); + } + + getQuizAnalysis() async { + SharedPreferences prefs = await SharedPreferences.getInstance(); + String? responseString = prefs.getString("getQuizAnalysisAPI"); + var getQuizAnalysis1 = testAnalysisModelFromJson(responseString!); + final TestAnalysisModel getQuizAnalysis = getQuizAnalysis1; + setState(() { + _getQuizAnalysis = getQuizAnalysis; + print(_getQuizAnalysis.data.subjects.length); + }); + } + + int index = 0; //0=subjects,1=systems,2=topics + @override + Widget build(BuildContext context) { + return SingleChildScrollView( + padding: EdgeInsets.symmetric( + vertical: MediaQuery.of(context).size.height * (20 / 926), + horizontal: (MediaQuery.of(context).size.width) * (20 / 428)), + child: Column( + children: [ + ButtonBar( + alignment: MainAxisAlignment.spaceEvenly, + buttonHeight: MediaQuery.of(context).size.height * (26 / 926), + children: [ + TextButton( + style: ButtonStyle( + splashFactory: NoSplash.splashFactory, + ), + onPressed: () { + setState(() { + index = 0; + }); + }, + child: Text( + 'Subjects', + style: TextStyle( + color: + index == 0 ? Color(0xFF3F2668) : Color(0xff7F1AF1), + fontFamily: 'Brandon-med', + ), + ), + ), + TextButton( + style: ButtonStyle( + splashFactory: NoSplash.splashFactory, + ), + onPressed: () { + setState(() { + index = 1; + }); + }, + child: Text( + 'Systems', + style: TextStyle( + color: + index == 1 ? Color(0xFF3F2668) : Color(0xff7F1AF1), + fontFamily: 'Brandon-med', + ), + ), + ), + TextButton( + style: ButtonStyle( + splashFactory: NoSplash.splashFactory, + ), + onPressed: () { + setState(() { + index = 2; + }); + }, + child: Text( + 'Topics', + style: TextStyle( + color: + index == 2 ? Color(0xFF3F2668) : Color(0xff7F1AF1), + fontFamily: 'Brandon-med', + ), + ), + ), + ], + ), + _getQuizAnalysis == null ? Center(child: CircularProgressIndicator(color: Color(0xff482384),)) : Column( + children: [ + Divider(), + if(index == 0) + for(int i = 0; i<_getQuizAnalysis.data.subjects.length; i++) + Column( + children: [ + SizedBox( + height: MediaQuery.of(context).size.height * (20 / 926), + ), + DetailsTile( + id: _getQuizAnalysis.data.subjects[i].srNo, + name: _getQuizAnalysis.data.subjects[i].category.toString(), + totalQuestions: _getQuizAnalysis.data.subjects[i].totalQuestions, + omittedQuestions: _getQuizAnalysis.data.subjects[i].omittedQuestions, + incorrectQuestions: _getQuizAnalysis.data.subjects[i].incorrectQuestions, + correctQuestions: _getQuizAnalysis.data.subjects[i].correctQuestions, + ), + ], + ), + if(index == 1) + for(int i = 0; i<_getQuizAnalysis.data.systems.length; i++) + Column( + children: [ + SizedBox( + height: MediaQuery.of(context).size.height * (20 / 926), + ), + DetailsTile( + id: _getQuizAnalysis.data.systems[i].srNo, + name: _getQuizAnalysis.data.systems[i].category.toString(), + totalQuestions: _getQuizAnalysis.data.systems[i].totalQuestions, + omittedQuestions: _getQuizAnalysis.data.systems[i].omittedQuestions, + incorrectQuestions: _getQuizAnalysis.data.systems[i].incorrectQuestions, + correctQuestions: _getQuizAnalysis.data.systems[i].correctQuestions, + ), + ], + ), + if(index == 2) + for(int i = 0; i<_getQuizAnalysis.data.topics.length; i++) + Column( + children: [ + SizedBox( + height: MediaQuery.of(context).size.height * (20 / 926), + ), + DetailsTile( + id: _getQuizAnalysis.data.topics[i].srNo, + name: _getQuizAnalysis.data.topics[i].category.toString(), + totalQuestions: _getQuizAnalysis.data.topics[i].totalQuestions, + omittedQuestions: _getQuizAnalysis.data.topics[i].omittedQuestions, + incorrectQuestions: _getQuizAnalysis.data.topics[i].incorrectQuestions, + correctQuestions: _getQuizAnalysis.data.topics[i].correctQuestions, + ), + ], + ), + ], + ) + // SizedBox( + // height: MediaQuery.of(context).size.height * (20 / 926), + // ), + // DetailsTile(id: 1234, name: "Subject 2"), + // SizedBox( + // height: MediaQuery.of(context).size.height * (20 / 926), + // ), + // DetailsTile(id: 1234, name: "Subject 3"), + // SizedBox( + // height: MediaQuery.of(context).size.height * (20 / 926), + // ), + // DetailsTile(id: 1234, name: "Subject 4"), + ], + )); + } +} diff --git a/lib/screens/Welcome/PreviousQuiz/TestAnalysis/mainTestAnalysisScreen.dart b/lib/screens/Welcome/PreviousQuiz/TestAnalysis/mainTestAnalysisScreen.dart new file mode 100644 index 0000000..994165b --- /dev/null +++ b/lib/screens/Welcome/PreviousQuiz/TestAnalysis/mainTestAnalysisScreen.dart @@ -0,0 +1,567 @@ +import 'dart:convert'; + +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_svg/svg.dart'; +import 'package:pie_chart/pie_chart.dart'; +import 'package:percent_indicator/percent_indicator.dart'; +import 'package:shared_preferences/shared_preferences.dart'; +import 'package:http/http.dart' as http; +import 'package:testify/models/GetPreviousQuizzesModel/TestAnalysisModel/test_analysis_model.dart'; +import 'package:testify/screens/Welcome/PreviousQuiz/TestAnalysis/analysisDetails.dart'; +import 'package:testify/screens/Welcome/PreviousQuiz/TestAnalysis/testAnalysis.dart'; + +import '../../../Authentication/login.dart'; +import '../../side_menu_bar.dart'; + + + +class MainTestAnalysis extends StatefulWidget { + MainTestAnalysis({required this.quizId,}); + final int quizId; + + @override + State createState() => _MainTestAnalysisState(); +} + +class _MainTestAnalysisState extends State { + + String bestSubj = "Loading..."; + String worstSubj = "Loading..."; + String timeTaken = "Loading..."; + var _timeTaken; + int total = 0; // This is the sum of Correct to Correct , Incorrect to Incorrect, Correct to Incorrect and Incorrect to Correct + Map dataMap = { + //'total': 10, + 'correct': 5, + 'incorrect': 2, + 'omitted': 3 + }; + Map legendLabels = { + //'total': 'Questions Answered ', + 'correct': 'Correct Questions', + 'incorrect': 'Incorrect Questions ', + 'omitted': 'Omitted Questions' + }; + final colorList = [ + Colors.white, + Colors.deepPurple, + Colors.grey, + + ]; + String performance = '75%'; // Just divide the questionsAnswered by totalCorrect + final centerText = 'Performance'; + final correct = 0.3; //percentage b/w 0-1 + final incorrect = 0.6; + + var _token; + var _userId; + var _getQuizAnalysis; + + String timeTakenFunction() { + // int.parse(timeTaken) < 60 ? (int.parse(timeTaken) == 1 ? (timeTaken.toString() + ' second') : (timeTaken.toString() + ' seconds')) : ((int.parse(timeTaken) ~/ 60) == 1 ? (((int.parse(timeTaken) ~/ 60).toString() + ' minute') : ((int.parse(timeTaken) ~/ 60).toString() + ' minutes')) + ((int.parse(timeTaken) % 60) == 1 ? (int.parse(timeTaken) % 60).toString() + ' second')) : ((int.parse(timeTaken) % 60).toString() + ' seconds')), + setState(() { + if(int.parse(timeTaken) < 60) { + if(int.parse(timeTaken) == 1) { + _timeTaken = timeTaken.toString() + ' sec'; + } + else { + _timeTaken = timeTaken.toString() + ' sec'; + } + } + else { + if((int.parse(timeTaken) ~/ 60) == 1) { + if((int.parse(timeTaken) % 60) == 1) { + _timeTaken = (int.parse(timeTaken) ~/ 60).toString() + ' : ' + (int.parse(timeTaken) % 60).toString() ; + } + else if((int.parse(timeTaken) % 60) != 1) { + _timeTaken = (int.parse(timeTaken) ~/ 60).toString() + ' : ' + (int.parse(timeTaken) % 60).toString() ; + } + } + if((int.parse(timeTaken) ~/ 60) != 1) { + if((int.parse(timeTaken) % 60) == 1) { + _timeTaken = (int.parse(timeTaken) ~/ 60).toString() + ' : ' + (int.parse(timeTaken) % 60).toString() ; + } + else if((int.parse(timeTaken) % 60) != 1) { + _timeTaken = (int.parse(timeTaken) ~/ 60).toString() + ' : ' + (int.parse(timeTaken) % 60).toString() ; + } + } + } + }); + return _timeTaken; + } + + @override + void initState() { + super.initState(); + getQuizAnalysis(); + } + + getQuizAnalysis() async { + SharedPreferences prefs = await SharedPreferences.getInstance(); + String? responseString = prefs.getString("getQuizAnalysisAPI"); + var getQuizAnalysis1 = testAnalysisModelFromJson(responseString!); + final TestAnalysisModel getQuizAnalysis = getQuizAnalysis1; + setState(() { + _getQuizAnalysis = getQuizAnalysis; + bestSubj = _getQuizAnalysis.data.bestSubject.toString(); + worstSubj = _getQuizAnalysis.data.worstSubject.toString(); + timeTaken = _getQuizAnalysis.data.timeTaken.toString(); + dataMap = { + //'total': _getQuizAnalysis.data.totalQuestionsAnswered.toDouble(), + 'correct': _getQuizAnalysis.data.totalCorrect.toDouble(), + 'incorrect': _getQuizAnalysis.data.totalIncorrect.toDouble(), + 'omitted': _getQuizAnalysis.data.totalOmitted.toDouble() + }; + total = _getQuizAnalysis.data.totalCorrectToCorrect + _getQuizAnalysis.data.totalCorrectToIncorrect + _getQuizAnalysis.data.totalIncorrectToCorrect + _getQuizAnalysis.data.totalIncorrectToIncorrect; + performance = (_getQuizAnalysis.data.totalQuestionsAnswered / _getQuizAnalysis.data.totalCorrect).isNaN ? '0%' : (((_getQuizAnalysis.data.totalCorrect / _getQuizAnalysis.data.totalQuestionsAnswered) * 100).toStringAsFixed(1).toString() + '%'); + print(_getQuizAnalysis.data.status); + }); + } + + + @override + Widget build(BuildContext context) { + return _getQuizAnalysis == null ? Center() : SingleChildScrollView( + child: Container( + padding: EdgeInsets.only( + top: (MediaQuery.of(context).size.height) * (15 / 926), + bottom: (MediaQuery.of(context).size.height) * (8 / 926), + left: (MediaQuery.of(context).size.width) * (18 / 428), + right: (MediaQuery.of(context).size.width) * (18 / 428)), + child: Column( + children: [ + Row( + children: [ + Container( + width: (MediaQuery.of(context).size.width) * (221 / 428), + //height: (MediaQuery.of(context).size.height) *(91/926), + child: Column( + children: [ + Align( + alignment: Alignment.topLeft, + child: Text( + "Test Analysis", + style: TextStyle( + color: Color(0xff232323), + fontFamily: 'Brandon-bld', + fontSize: (MediaQuery.of(context).size.height) * + (25 / 926), //38, + ), + ), + ), + SizedBox( + height: + (MediaQuery.of(context).size.height) * (2 / 926), + ), + Text( + "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Cras imperdiet finibus elit non luctus. Morbi auctor mattis ante.", + style: TextStyle( + color: Color(0xFF483A3A), + fontFamily: 'Brandon-med', + fontSize: (MediaQuery.of(context).size.height) * + (13 / 926), //38, + ), + ), + ], + ), + ), + SizedBox( + width: (MediaQuery.of(context).size.width) * (39 / 428), + ), + Container( + //color: Colors.transparent, + child: SvgPicture.asset( + "assets/Images/prevQuiz.svg", + height: + (MediaQuery.of(context).size.height) * (100 / 926), + //width: (MediaQuery.of(context).size.width) *(132/428), + ), + ), + ], + ), + SizedBox( + height: (MediaQuery.of(context).size.height) * (30 / 926), + ), + Column( + children: [ + PieChart( + dataMap: dataMap, + colorList: colorList, + chartType: ChartType.ring, + ringStrokeWidth: 28, + chartValuesOptions: ChartValuesOptions( + showChartValueBackground: false, showChartValues: false), + centerText: performance + '\nAverage Performance', + centerTextStyle: TextStyle( + color: Color(0xFF483A3A), + fontFamily: 'Brandon-med', + fontSize: (MediaQuery.of(context).size.height) * (16 / 926), + ), + legendLabels: legendLabels, + legendOptions: LegendOptions( + legendTextStyle: TextStyle( + color: Color(0xFF483A3A), + fontFamily: 'Brandon-med', + fontSize: (MediaQuery.of(context).size.height) * (13 / 926), + )), + ), + SizedBox( + height: (MediaQuery.of(context).size.height) * (10 / 926), + ), + Padding( + padding: EdgeInsets.symmetric( + vertical: MediaQuery.of(context).size.height * (30 / 926), + horizontal: + (MediaQuery.of(context).size.width) * (30 / 428)), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Column( + children: [ + Text( + 'Correct to Correct ' + + (((_getQuizAnalysis.data.totalCorrectToCorrect/total).isNaN ? 0 : _getQuizAnalysis.data.totalCorrectToCorrect/total) * 100).toStringAsFixed(1).toString() + + ' %', + style: TextStyle( + color: Color(0xff6D5A8D), + fontFamily: 'Brandon-med', + fontSize: (MediaQuery.of(context).size.height) * + (12 / 926), + ), + ), + LinearPercentIndicator( + width: + (MediaQuery.of(context).size.width) * (160 / 428), + lineHeight: + (MediaQuery.of(context).size.height) * (7 / 926), + percent: ((_getQuizAnalysis.data.totalCorrectToCorrect/total).isNaN ? 0 : _getQuizAnalysis.data.totalCorrectToCorrect/total), + progressColor: Color(0xff6D5A8D), + ), + ], + ), + Column( + children: [ + Text( + 'Correct to Incorrect ' + + (((_getQuizAnalysis.data.totalCorrectToIncorrect/total).isNaN ? 0 : _getQuizAnalysis.data.totalCorrectToIncorrect/total) * 100).toString() + + ' %', + style: TextStyle( + color: Color(0xff6D5A8D), + fontFamily: 'Brandon-med', + fontSize: (MediaQuery.of(context).size.height) * + (12 / 926), + ), + ), + LinearPercentIndicator( + width: + (MediaQuery.of(context).size.width) * (160 / 428), + lineHeight: + (MediaQuery.of(context).size.height) * (7 / 926), + percent: ((_getQuizAnalysis.data.totalCorrectToIncorrect/total).isNaN ? 0 : _getQuizAnalysis.data.totalCorrectToIncorrect/total), + progressColor: Color(0xff6D5A8D), + ), + ], + ), + ], + ), + ), + Padding( + padding: EdgeInsets.symmetric( + vertical: MediaQuery.of(context).size.height * (10 / 926), + horizontal: + (MediaQuery.of(context).size.width) * (30 / 428)), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Column( + children: [ + Text( + 'Incorrect to Correct ' + + (((_getQuizAnalysis.data.totalIncorrectToCorrect/total).isNaN ? 0 : _getQuizAnalysis.data.totalIncorrectToCorrect/total) * 100).toString() + + ' %', + style: TextStyle( + color: Color(0xff6D5A8D), + fontFamily: 'Brandon-med', + fontSize: (MediaQuery.of(context).size.height) * + (12 / 926), + ), + ), + LinearPercentIndicator( + width: + (MediaQuery.of(context).size.width) * (160 / 428), + lineHeight: + (MediaQuery.of(context).size.height) * (7 / 926), + percent: ((_getQuizAnalysis.data.totalIncorrectToCorrect/total).isNaN ? 0 : _getQuizAnalysis.data.totalIncorrectToCorrect/total), + progressColor: Color(0xff6D5A8D), + ), + ], + ), + Column( + children: [ + Text( + 'Incorrect to Incorrect ' + + (((_getQuizAnalysis.data.totalIncorrectToIncorrect/total).isNaN ? 0 : _getQuizAnalysis.data.totalIncorrectToIncorrect/total) * 100).toString() + + ' %', + style: TextStyle( + color: Color(0xff6D5A8D), + fontFamily: 'Brandon-med', + fontSize: (MediaQuery.of(context).size.height) * + (12 / 926), + ), + ), + LinearPercentIndicator( + width: + (MediaQuery.of(context).size.width) * (160 / 428), + lineHeight: + (MediaQuery.of(context).size.height) * (7 / 926), + percent: ((_getQuizAnalysis.data.totalIncorrectToIncorrect/total).isNaN ? 0 : _getQuizAnalysis.data.totalIncorrectToIncorrect/total), + progressColor: Color(0xff6D5A8D), + ), + ], + ), + ], + ), + ), + SizedBox( + height: (MediaQuery.of(context).size.height) * (30 / 926), + ), + Container( + height: (MediaQuery.of(context).size.height) * (45 / 926), + width: (MediaQuery.of(context).size.width) * (325 / 428), + decoration: BoxDecoration( + color: Color(0xffE4E4E4), + border: Border.all( + color: Color(0xff6D5A8D), + ), + borderRadius: BorderRadius.circular(8)), + child: Row( + children: [ + Container( + padding: EdgeInsets.all( + (MediaQuery.of(context).size.height) * (10 / 926)), + width: (MediaQuery.of(context).size.width) * (141 / 428), + height: (MediaQuery.of(context).size.height) * (45 / 926), + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(4), + color: Color(0xff6D5A8D), + ), + child: Row( + children: [ + Container( + padding: EdgeInsets.all( + (MediaQuery.of(context).size.height) * + (5 / 926)), + height: (MediaQuery.of(context).size.height) * + (30 / 926), + decoration: BoxDecoration( + color: Colors.white, shape: BoxShape.circle), + child: Icon( + Icons.thumb_up_alt_outlined, + color: Color(0xff6D5A8D), + size: (MediaQuery.of(context).size.height) * + (15 / 926), + ), + ), + SizedBox( + width: (MediaQuery.of(context).size.width) * + (10 / 428), + ), + Text( + 'Best Subject', + style: TextStyle( + color: Colors.white, + fontFamily: 'Brandon-bld', + fontSize: (MediaQuery.of(context).size.height) * + (13 / 926), //38, + ), + ) + ], + ), + ), + Container( + alignment: Alignment.centerLeft, + decoration: + BoxDecoration(borderRadius: BorderRadius.circular(4)), + padding: EdgeInsets.symmetric( horizontal: + (MediaQuery.of(context).size.height) * (10 / 926)), + width: (MediaQuery.of(context).size.width) * (181 / 428), + height: (MediaQuery.of(context).size.height) * (45 / 926), + child: Text( + bestSubj, + style: TextStyle( + color: Color(0xff6D5A8D), + fontFamily: 'Brandon-bld', + fontSize: (MediaQuery.of(context).size.height) * + (15 / 926), //38, + ), + ), + ) + ], + ), + ), + SizedBox( + height: (MediaQuery.of(context).size.height) * (25 / 926), + ), + Container( + height: (MediaQuery.of(context).size.height) * (45 / 926), + width: (MediaQuery.of(context).size.width) * (325 / 428), + decoration: BoxDecoration( + color: Color(0xffE4E4E4), + border: Border.all( + color: Color(0xff6D5A8D), + ), + borderRadius: BorderRadius.circular(8)), + child: Row( + children: [ + Container( + padding: EdgeInsets.all( + (MediaQuery.of(context).size.height) * (10 / 926)), + width: (MediaQuery.of(context).size.width) * (141 / 428), + height: (MediaQuery.of(context).size.height) * (45 / 926), + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(4), + color: Color(0xff6D5A8D), + ), + child: Row( + children: [ + Container( + padding: EdgeInsets.all( + (MediaQuery.of(context).size.height) * + (5 / 926)), + height: (MediaQuery.of(context).size.height) * + (30 / 926), + decoration: BoxDecoration( + color: Colors.white, shape: BoxShape.circle), + child: Icon( + Icons.thumb_down_alt_outlined, + color: Color(0xff6D5A8D), + size: (MediaQuery.of(context).size.height) * + (15 / 926), + ), + ), + SizedBox( + width: (MediaQuery.of(context).size.width) * + (10 / 428), + ), + Text( + 'Worst Subject', + style: TextStyle( + color: Colors.white, + fontFamily: 'Brandon-bld', + fontSize: (MediaQuery.of(context).size.height) * + (13 / 926), //38, + ), + ) + ], + ), + ), + Container( + alignment: Alignment.centerLeft, + decoration: + BoxDecoration(borderRadius: BorderRadius.circular(4)), + padding: EdgeInsets.symmetric( horizontal: + (MediaQuery.of(context).size.height) * (10 / 926)), + width: (MediaQuery.of(context).size.width) * (181 / 428), + height: (MediaQuery.of(context).size.height) * (45 / 926), + child: Text( + worstSubj, + style: TextStyle( + color: Color(0xff6D5A8D), + fontFamily: 'Brandon-bld', + fontSize: (MediaQuery.of(context).size.height) * + (15 / 926), //38, + ), + ), + ) + ], + ), + ), + SizedBox( + height: (MediaQuery.of(context).size.height) * (25 / 926), + ), + Container( + height: (MediaQuery.of(context).size.height) * (45 / 926), + width: (MediaQuery.of(context).size.width) * (325 / 428), + decoration: BoxDecoration( + color: Color(0xffE4E4E4), + border: Border.all( + color: Color(0xff6D5A8D), + ), + borderRadius: BorderRadius.circular(8)), + child: Row( + children: [ + Container( + alignment: Alignment.centerLeft, + padding: EdgeInsets.symmetric( + horizontal: + (MediaQuery.of(context).size.height) * (10 / 926)), + width: (MediaQuery.of(context).size.width) * (141 / 428), + height: (MediaQuery.of(context).size.height) * (45 / 926), + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(4), + color: Color(0xff6D5A8D), + ), + child: Row( + children: [ + Container( + padding: EdgeInsets.all( + (MediaQuery.of(context).size.height) * + (5 / 926)), + height: (MediaQuery.of(context).size.height) * + (30 / 926), + decoration: BoxDecoration( + color: Colors.white, shape: BoxShape.circle), + child: Icon( + Icons.timer_outlined, + color: Color(0xff6D5A8D), + size: (MediaQuery.of(context).size.height) * + (15 / 926), + ), + ), + SizedBox( + width: (MediaQuery.of(context).size.width) * + (10 / 428), + ), + Text( + 'Time Taken', + style: TextStyle( + color: Colors.white, + fontFamily: 'Brandon-bld', + fontSize: (MediaQuery.of(context).size.height) * + (13 / 926), //38, + ), + ) + ], + ), + ), + Container( + alignment: Alignment.centerLeft, + decoration: + BoxDecoration(borderRadius: BorderRadius.circular(4)), + padding: EdgeInsets.symmetric( horizontal: + (MediaQuery.of(context).size.height) * (10 / 926)), + width: (MediaQuery.of(context).size.width) * (181 / 428), + height: (MediaQuery.of(context).size.height) * (45 / 926), + child: Text( + // timeTakenFunction(), + timeTaken.toString(), + // int.parse(timeTaken) < 60 ? (int.parse(timeTaken) == 1 ? (timeTaken.toString() + ' second') : (timeTaken.toString() + ' seconds')) : ((int.parse(timeTaken) ~/ 60) == 1 ? (((int.parse(timeTaken) ~/ 60).toString() + ' minute') : ((int.parse(timeTaken) ~/ 60).toString() + ' minutes')) + ((int.parse(timeTaken) % 60) == 1 ? (int.parse(timeTaken) % 60).toString() + ' second')) : ((int.parse(timeTaken) % 60).toString() + ' seconds')), + style: TextStyle( + color: Color(0xff6D5A8D), + fontFamily: 'Brandon-bld', + fontSize: (MediaQuery.of(context).size.height) * + (15 / 926), //38, + ), + ), + ) + ], + ), + ), + ], + ) + ], + ), + )); + } +} diff --git a/lib/screens/Welcome/PreviousQuiz/TestAnalysis/testAnalysis.dart b/lib/screens/Welcome/PreviousQuiz/TestAnalysis/testAnalysis.dart new file mode 100644 index 0000000..fa7a7d1 --- /dev/null +++ b/lib/screens/Welcome/PreviousQuiz/TestAnalysis/testAnalysis.dart @@ -0,0 +1,174 @@ +import 'dart:convert'; + +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_svg/svg.dart'; +import 'package:pie_chart/pie_chart.dart'; +import 'package:percent_indicator/percent_indicator.dart'; +import 'package:shared_preferences/shared_preferences.dart'; +import 'package:http/http.dart' as http; +import 'package:testify/models/GetPreviousQuizzesModel/TestAnalysisModel/test_analysis_model.dart'; +import 'package:testify/screens/Welcome/PreviousQuiz/TestAnalysis/analysisDetails.dart'; +import 'package:testify/screens/Welcome/PreviousQuiz/TestAnalysis/mainTestAnalysisScreen.dart'; + +import '../../../Authentication/login.dart'; +import '../../side_menu_bar.dart'; + +class TestAnalysis extends StatefulWidget { + TestAnalysis({required this.quizId,}); + final int quizId; + @override + _TestAnalysisState createState() => _TestAnalysisState(); +} + +class _TestAnalysisState extends State { + + int _selectedIndex = 0; + late List _widgetOptions; + var _token; + var _userId; + var _getQuizAnalysis; + bool _hasGetQuizAnalysisLoaded = false; + + Future _onItemTapped(int index) async { + if(_hasGetQuizAnalysisLoaded == true) { + setState(() { + _selectedIndex = index; + }); + } + } + + + + @override + void initState() { + super.initState(); + _widgetOptions = [ + MainTestAnalysis(quizId: widget.quizId), + AnalysisDetails() + ]; + getQuizAnalysis(); + } + + Future getQuizAnalysis() async { + SharedPreferences prefs = await SharedPreferences.getInstance(); + final String apiUrlGetQuizAnalysis = "https://demo.pookidevs.com/quiz/analysis/getQuizAnalysis"; + _token = prefs.getString('token')!; + print(_token); + _userId = prefs.getInt("userId")!; + http.post(Uri.parse(apiUrlGetQuizAnalysis), headers: { + 'Content-type': 'application/json; charset=UTF-8', 'Authorization' : _token.toString(), + }, body: json.encode( + { + "quizId": widget.quizId + }) + ).then((response) { + // print(jsonDecode(response.body).toString()); + if((response.statusCode == 200) & (json.decode(response.body).toString().substring(0,14) != "{status: false")) { + final responseString = (response.body); + prefs.setString("getQuizAnalysisAPI", responseString); + var getQuizAnalysis1 = testAnalysisModelFromJson(responseString); + final TestAnalysisModel getQuizAnalysis = getQuizAnalysis1; + setState(() { + _getQuizAnalysis = getQuizAnalysis; + print(_getQuizAnalysis.data.worstSubject.toString()); + _hasGetQuizAnalysisLoaded = true; + // print(_quizId); + }); + // categoriesGenerateQuizData(); + } + else { // Token Invalid + final result = Navigator.pushAndRemoveUntil( + context, + MaterialPageRoute(builder: (BuildContext context) => const Login(fromWhere:"Home")), + ModalRoute.withName('/'), + ); + } + } + ).catchError((error){ + setState(() { + _hasGetQuizAnalysisLoaded = true; + }); + var errorSplit = error.toString().split(":"); + if(errorSplit[0].toLowerCase() == "socketexception") { + ScaffoldMessenger.of(context) + ..removeCurrentSnackBar() + ..showSnackBar(SnackBar(content: Text("No Internet Connection"))); + } + // else if(errorSplit[0].toLowerCase() == "httpexception") { + // ScaffoldMessenger.of(context) + // ..removeCurrentSnackBar() + // ..showSnackBar(SnackBar(content: Text("Couldn't find the said thing."))); + // } + else if(errorSplit[0].toLowerCase() == "formatexception") { + ScaffoldMessenger.of(context) + ..removeCurrentSnackBar() + ..showSnackBar(SnackBar(content: Text("Bad Response Format"))); + } + else { + ScaffoldMessenger.of(context) + ..removeCurrentSnackBar() + ..showSnackBar(SnackBar(content: Text(error.toString()))); + } + }); + } + + @override + Widget build(BuildContext context) { + return Scaffold( + backgroundColor: Color(0xffF8F9FB), + drawer: SideMenuBar(), + appBar: AppBar( + toolbarHeight: (MediaQuery.of(context).size.height) * (73.52 / 926), + backgroundColor: Color(0xff3F2668), + elevation: 2, + centerTitle: true, + flexibleSpace: Container( + decoration: const BoxDecoration( + gradient: LinearGradient( + begin: Alignment.topCenter, + end: Alignment.bottomCenter, + colors: [Color(0xff7F1AF1), Color(0xff482384)])), + ), + title: const Text( + "Test Analysis", + style: TextStyle( + color: Color(0xffFFFEFE), + fontFamily: 'Brandon-bld', + ), + ), + actions: [ + TextButton( + onPressed: () async { + final result = await Navigator.push( + context, + MaterialPageRoute( + builder: (context) => const Login(fromWhere: "Home")), + ); + }, + child: SvgPicture.asset( + "assets/Images/logout.svg", + height: (MediaQuery.of(context).size.height) * (32 / 926), + ), + ), + ], + ), + body: _hasGetQuizAnalysisLoaded == false ? Center(child: CircularProgressIndicator(color: Color(0xff482384),)) : _widgetOptions.elementAt(_selectedIndex), + bottomNavigationBar:BottomNavigationBar( + currentIndex: _selectedIndex, + selectedItemColor:Color(0xff7F1AF1), + onTap: _onItemTapped, + items: const [ + BottomNavigationBarItem( + icon: Icon(Icons.stacked_line_chart_outlined), + label: '', + ), + BottomNavigationBarItem( + icon: Icon(Icons.description_outlined), + label: '', + ),], + ) , + + ); + } +} diff --git a/lib/screens/Welcome/PreviousQuiz/TestResults/mainResultDetailsScreen.dart b/lib/screens/Welcome/PreviousQuiz/TestResults/mainResultDetailsScreen.dart new file mode 100644 index 0000000..660af95 --- /dev/null +++ b/lib/screens/Welcome/PreviousQuiz/TestResults/mainResultDetailsScreen.dart @@ -0,0 +1,362 @@ + +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; + +import 'package:pie_chart/pie_chart.dart'; +import 'package:percent_indicator/percent_indicator.dart'; +import 'package:shared_preferences/shared_preferences.dart'; +import 'package:testify/models/resultDetails/result_details_model.dart'; + +import '../../../Components/styles.dart'; + + +class MainResultDetails extends StatefulWidget { + MainResultDetails({required this.quizId,}); + final int quizId; + + + @override + State createState() => _MainResultDetailsState(); +} + +class _MainResultDetailsState extends State { + + String totalScore = "Loading..."; + String timeTaken = "Loading..."; + int total = 0; // This is the sum of Correct to Correct , Incorrect to Incorrect, Correct to Incorrect and Incorrect to Correct + Map dataMap = {}; + double performance = 0.75; // Just divide the questionsAnswered by totalCorrect + final centerText = 'Performance'; + final correct = 0.3; //percentage b/w 0-1 + final incorrect = 0.6; + var status; + var _timeTaken; + + var _token; + var _userId; + var _getResultDetails; + + String timeTakenFunction() { + // int.parse(timeTaken) < 60 ? (int.parse(timeTaken) == 1 ? (timeTaken.toString() + ' second') : (timeTaken.toString() + ' seconds')) : ((int.parse(timeTaken) ~/ 60) == 1 ? (((int.parse(timeTaken) ~/ 60).toString() + ' minute') : ((int.parse(timeTaken) ~/ 60).toString() + ' minutes')) + ((int.parse(timeTaken) % 60) == 1 ? (int.parse(timeTaken) % 60).toString() + ' second')) : ((int.parse(timeTaken) % 60).toString() + ' seconds')), + setState(() { + if(int.parse(timeTaken) < 60) { + if(int.parse(timeTaken) == 1) { + _timeTaken = timeTaken.toString() + ' sec'; + } + else { + _timeTaken = timeTaken.toString() + ' sec'; + } + } + else { + if((int.parse(timeTaken) ~/ 60) == 1) { + if((int.parse(timeTaken) % 60) == 1) { + _timeTaken = (int.parse(timeTaken) ~/ 60).toString() + ' : ' + (int.parse(timeTaken) % 60).toString() ; + } + else if((int.parse(timeTaken) % 60) != 1) { + _timeTaken = (int.parse(timeTaken) ~/ 60).toString() + ' : ' + (int.parse(timeTaken) % 60).toString() ; + } + } + if((int.parse(timeTaken) ~/ 60) != 1) { + if((int.parse(timeTaken) % 60) == 1) { + _timeTaken = (int.parse(timeTaken) ~/ 60).toString() + ' : ' + (int.parse(timeTaken) % 60).toString() ; + } + else if((int.parse(timeTaken) % 60) != 1) { + _timeTaken = (int.parse(timeTaken) ~/ 60).toString() + ' : ' + (int.parse(timeTaken) % 60).toString() ; + } + } + } + }); + return _timeTaken; + } + + @override + void initState() { + super.initState(); + getQuizResults(); + } + + getQuizResults() async { + SharedPreferences prefs = await SharedPreferences.getInstance(); + String? responseString = prefs.getString("getResultDetailsAPI"); + var getResultDetails1 = resultDetailsModelFromJson(responseString!); + final ResultDetailsModel getResultDetails = getResultDetails1; + setState(() { + _getResultDetails = getResultDetails; + dataMap = { + 'total': _getResultDetails.data.totalQuestions.toDouble(), + 'correct': _getResultDetails.data.totalCorrect.toDouble(), + 'incorrect': _getResultDetails.data.totalIncorrect.toDouble(), + 'omitted': _getResultDetails.data.totalOmitted.toDouble() + }; + timeTaken = _getResultDetails.data.timeTaken; + performance=(_getResultDetails.data.totalCorrect.toDouble()/_getResultDetails.data.totalQuestions.toDouble()); + status=_getResultDetails.data.status; + (status=='completed')?status='Completed':status='Suspended'; + print(_getResultDetails.data.status); + }); + } + + @override + Widget build(BuildContext context) { + var h = MediaQuery.of(context).size.height / 926; + var w = MediaQuery.of(context).size.width / 428; + return _getResultDetails == null ? Center() : Stack( + children: [ + Container( + height: h*420, + padding: EdgeInsets.symmetric( + vertical: MediaQuery.of(context).padding.top+h *10, horizontal: w * 15), + width: double.infinity, + decoration: BoxDecoration( gradient: LinearGradient( + begin: Alignment.topCenter, + end: Alignment.bottomCenter, + colors: [Color(0xff7F1AF1), Color(0xff482384)]) + ), + child: Column( + children: [ + Row( + children: [ + Container( + width: (MediaQuery.of(context).size.width) * (221 / 428), + //height: (MediaQuery.of(context).size.height) *(91/926), + child: Column( + children: [ + Align( + alignment: Alignment.topLeft, + child: Text( + "Test Results", + style: TextStyle( + color: Colors.white, + fontFamily: 'Brandon-bld', + fontSize: (MediaQuery.of(context).size.height) * + (20 / 926), //38, + ), + ), + ), + SizedBox( + height: + (MediaQuery.of(context).size.height) * (2 / 926), + ), + Text( + "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Cras imperdiet finibus elit non luctus. Morbi auctor mattis ante.", + style: TextStyle( + color: Colors.white.withOpacity(0.7), + fontFamily: 'Brandon-reg', + fontSize: (MediaQuery.of(context).size.height) * + (10 / 926), //38, + ), + ), + ], + ), + ), + + ], + ), + SizedBox( + height: (MediaQuery.of(context).size.height) * (73 / 926), + ), + Container(margin:EdgeInsets.all(h*10), + padding: EdgeInsets.all(h*10), + decoration: const BoxDecoration( + color:Colors.transparent, + ), + height: h*153, + width: h*153, + child: Stack(children: [Center(child: SizedBox(height: h*153, + width: h*153,child: CircularProgressIndicator(value: performance,color: Colors.white,backgroundColor:Colors.grey.withOpacity(0.2),strokeWidth: 8,))), + Center(child: Text((performance*100).toStringAsFixed(1).toString()+ ' %',style: TextStyle( + color: Colors.white, + fontFamily: 'Brandon-med', + fontSize:h*25, + ),))],),), + Center( + child: Text(status,textAlign: TextAlign.center,style: TextStyle( + color: Colors.white, + fontFamily: 'Brandon-med', + fontSize:h*25, + ),), + ), + SizedBox(height: h*10,), + + ], + ), + + ), + Container( + height: h*140, + width: w*370, + margin: EdgeInsets.only(top:h*390,left:w*30), + decoration: BoxDecoration( + color:Color(0xffDEDEDE), + border:Border.all(color: Colors.white,width: w*0.4), + borderRadius: BorderRadius.circular(h*12),), + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + children: [ + Column(children: [ + Text( + ' Total Questions ', + style: TextStyle( + color: Styles.darkGrey, + fontFamily: 'Brandon-med', + fontSize: h*14, + ), + ), + Text( + (_getResultDetails.data.totalQuestions).toString(), + style: TextStyle( + color: Styles.lightPurple, + fontFamily: 'Brandon-med', + fontSize: h*16, + ), + ), + ],), + Column(children: [ + Text( + 'Correct Questions' , + style: TextStyle( + color: Styles.darkGrey, + fontFamily: 'Brandon-med', + fontSize: h*14, + ), + ), + Text( + (_getResultDetails.data.totalCorrect).toString(), + style: TextStyle( + color: Styles.lightPurple, + fontFamily: 'Brandon-med', + fontSize: h*16, + ), + ), + ],), + + ],), + SizedBox(height: h*15,), + Row( + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + children: [ + Column(children: [ + Text( + 'Incorrect Questions', + style: TextStyle( + color: Styles.darkGrey, + fontFamily: 'Brandon-med', + fontSize: h*14, + ), + ), + Text( + (_getResultDetails.data.totalIncorrect).toString(), + style: TextStyle( + color: Styles.lightPurple, + fontFamily: 'Brandon-med', + fontSize: h*16, + ), + ), + ],), + Column(children: [ + Text( + 'Omitted Questions' , + style: TextStyle( + color: Styles.darkGrey, + fontFamily: 'Brandon-med', + fontSize: h*14, + ), + ), + Text( + (_getResultDetails.data.totalOmitted).toString(), + style: TextStyle( + color: Styles.lightPurple, + fontFamily: 'Brandon-med', + fontSize: h*16, + ), + ), + ],), + + ],), + + ],), + ), + Container( + height: h*409,width: double.infinity,color: Colors.white,margin: EdgeInsets.only(top: h*560), + child: Column( + children: [ + + Row( + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + children: [ + Container( + height: (MediaQuery.of(context).size.height) * (75 / 926), + width: (MediaQuery.of(context).size.width) * (173 / 428),padding: EdgeInsets.all(h*10), + decoration: BoxDecoration( + gradient: LinearGradient(colors: [Color(0xff7F1AF1),Color(0xff482384)],begin: Alignment.topCenter,end: Alignment.bottomCenter), + borderRadius: BorderRadius.circular(8)), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + children: [Container(height:h*40,width:w*30,decoration:BoxDecoration(borderRadius: BorderRadius.circular(h*5),color:Colors.white),child: Icon(Icons.fact_check_rounded,color: Styles.lightPurple,size: h*20,)), + + Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Text( + 'Total Score', + style: TextStyle( + color: Colors.white.withOpacity(0.7), + fontFamily: 'Brandon-med', + fontSize: h*16, + ), + ), + Text( + (_getResultDetails.data.score).toString(), + style: TextStyle( + color: Colors.white, + fontFamily: 'Brandon-med', + fontSize: h*20, + ), + ), + ],)], + ), + ), + Container( + height: (MediaQuery.of(context).size.height) * (75 / 926), + width: (MediaQuery.of(context).size.width) * (173 / 428),padding: EdgeInsets.all(h*10), + decoration: BoxDecoration( + gradient: LinearGradient(colors: [Color(0xff7F1AF1),Color(0xff482384)],begin: Alignment.topCenter,end: Alignment.bottomCenter), + borderRadius: BorderRadius.circular(8)), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + children: [Container(height:h*40,width:w*30,decoration:BoxDecoration(borderRadius: BorderRadius.circular(h*5),color:Colors.white),child: Icon(Icons.timelapse_rounded,color: Styles.lightPurple,size: h*20,)), + Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Text( + 'Time Taken', + style: TextStyle( + color: Colors.white.withOpacity(0.7), + fontFamily: 'Brandon-med', + fontSize: h*16, + ), + ), + Text( + timeTakenFunction(), + //(_getResultDetails.data.timeTaken).toString()+' secs', + style: TextStyle( + color:Colors.white, + fontFamily: 'Brandon-med', + fontSize: h*20, + ), + ), + ],)], + ), + ), + + ], + ) + ], + ), + ), + ]); + } +} diff --git a/lib/screens/Welcome/PreviousQuiz/TestResults/resultDetails.dart b/lib/screens/Welcome/PreviousQuiz/TestResults/resultDetails.dart new file mode 100644 index 0000000..2ff7dd6 --- /dev/null +++ b/lib/screens/Welcome/PreviousQuiz/TestResults/resultDetails.dart @@ -0,0 +1,402 @@ +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; +import 'package:expandable/expandable.dart'; +import 'package:shared_preferences/shared_preferences.dart'; +import 'package:testify/screens/Components/styles.dart'; + +import '../../../../models/resultDetails/result_details_model.dart'; + + +class DetailsTile extends StatelessWidget { + //same code as quiz details renamed getQuizAnalysis to getResultDetails + final int index; + final int id; + final String subject; + final String system; + final String topic; + final int peerAvg; + final String status; + const DetailsTile({required this.id, required this.subject, required this.system, required this.topic, required this.peerAvg, required this.status, required this.index}); + @override + Widget build(BuildContext context) { + return ExpandableNotifier(child: Column(children: [ + Expandable( + collapsed: ExpandableButton( + child: Container( + height: MediaQuery.of(context).size.height * (55 / 926), + width: MediaQuery.of(context).size.width * (363 / 428), + decoration: BoxDecoration( + color: Colors.white, + border: Border.all(color: Colors.grey,width: 0.2), + borderRadius: BorderRadius.circular( + MediaQuery.of(context).size.height * 7 / 926)), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Padding( + padding: EdgeInsets.symmetric( + vertical: MediaQuery.of(context).size.height * (5 / 926), + horizontal: + (MediaQuery.of(context).size.width) * (15 / 428)), + child: Text( + id.toString(), + textAlign: TextAlign.center, + style: TextStyle( + color: Styles.lightPurple, + fontFamily: 'Brandon-med', + fontSize: (MediaQuery.of(context).size.height) * (16/ 926), + ), + ), + ), + Container( + padding: EdgeInsets.symmetric( + vertical: MediaQuery.of(context).size.height * (10/ 926), + horizontal: + (MediaQuery.of(context).size.width) * (10 / 428)), + child: Text( + index == 0 ? subject : (index == 1 ? system : topic), + textAlign: TextAlign.center, + style: TextStyle( + color: Styles.darkGrey, + fontFamily: 'Brandon-med', + fontSize: + (MediaQuery.of(context).size.height) * (18 / 926), + ), + )), + Container( + padding: EdgeInsets.symmetric( + vertical: MediaQuery.of(context).size.height * (10/ 926), + horizontal: + (MediaQuery.of(context).size.width) * (10/ 428)), + child: Icon( + Icons.arrow_drop_down, + size: MediaQuery.of(context).size.height * (35 / 926), + color:Styles.lightPurple, + ), + ) + ], + ), + ), + ), + expanded: ExpandableButton( + child:Column( + children: [ + Container( + height: MediaQuery.of(context).size.height * (55 / 926), + width: MediaQuery.of(context).size.width * (363 / 428), + decoration: BoxDecoration( + color: Colors.white, + border: Border.all(color: Colors.grey,width: 0.2), + borderRadius: BorderRadius.circular( + MediaQuery.of(context).size.height * 7 / 926)), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Padding( + padding: EdgeInsets.symmetric( + vertical: MediaQuery.of(context).size.height * (5 / 926), + horizontal: + (MediaQuery.of(context).size.width) * (15 / 428)), + child: Text( + id.toString(), + textAlign: TextAlign.center, + style: TextStyle( + color: Styles.lightPurple, + fontFamily: 'Brandon-med', + fontSize: (MediaQuery.of(context).size.height) * (16/ 926), + ), + ), + ), + Container( + padding: EdgeInsets.symmetric( + vertical: MediaQuery.of(context).size.height * (10/ 926), + horizontal: + (MediaQuery.of(context).size.width) * (10 / 428)), + child: Text( + index == 0 ? subject : (index == 1 ? system : topic), + textAlign: TextAlign.center, + style: TextStyle( + color: Styles.darkGrey, + fontFamily: 'Brandon-med', + fontSize: + (MediaQuery.of(context).size.height) * (18 / 926), + ), + )), + Container( + padding: EdgeInsets.symmetric( + vertical: MediaQuery.of(context).size.height * (10/ 926), + horizontal: + (MediaQuery.of(context).size.width) * (10/ 428)), + child: Icon( + Icons.arrow_drop_down, + size: MediaQuery.of(context).size.height * (35 / 926), + color:Styles.lightPurple, + ), + ) + ], + ), + ), + Container( + height: MediaQuery.of(context).size.height * (110 / 926), + width: MediaQuery.of(context).size.width * (363 / 428), + color: Colors.grey.withOpacity(0.1), + padding: EdgeInsets.symmetric( + vertical: MediaQuery.of(context).size.height * (5 / 926), + horizontal: (MediaQuery.of(context).size.width) * (7 / 428)), + + child: GridView( + padding: EdgeInsets.zero, + gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount( + crossAxisCount: 2, + crossAxisSpacing: 0, + mainAxisSpacing: 0, + mainAxisExtent: 45), + children:[ + Column(children: [Text(index == 0 ? 'System:' : (index == 1 ? 'Subject:' : 'Subject:'), + style: TextStyle( + color: Styles.lightPurple , + fontFamily: 'Brandon-med', + fontSize: (MediaQuery.of(context).size.height) * (17 / 926), + ),), + Text(index == 0 ? system : (index == 1 ? subject : subject),style: TextStyle( + color: Colors.grey , + fontFamily: 'Brandon-med', + fontSize: (MediaQuery.of(context).size.height) * (17 / 926), + ),),],), + Column(children: [ Text(index == 0 ? 'Topic:' : (index == 1 ? 'Topic:' : 'System:'), style: TextStyle( + color: Styles.lightPurple , + fontFamily: 'Brandon-med', + fontSize: (MediaQuery.of(context).size.height) * (17 / 926), + ),), + Text(index == 0 ? topic : (index == 1 ? topic : system),style: TextStyle( + color: Colors.grey , + fontFamily: 'Brandon-med', + fontSize: (MediaQuery.of(context).size.height) * (17 / 926), + ),),],) + , Column(children: [ + Text('Peer average:', style: TextStyle( + color:Styles.lightPurple , + fontFamily: 'Brandon-med', + fontSize: (MediaQuery.of(context).size.height) * (17 / 926), + ),), + Text(peerAvg.toString()+' % ',style: TextStyle( + color: Colors.grey , + fontFamily: 'Brandon-med', + fontSize: (MediaQuery.of(context).size.height) * (17 / 926), + ),),],) + ,Column(children: [ Text('Status:', style: TextStyle( + color:Styles.lightPurple , + fontFamily: 'Brandon-med', + fontSize: (MediaQuery.of(context).size.height) * (17 / 926), + ),), + Text(status,style: TextStyle( + color: Colors.grey , + fontFamily: 'Brandon-med', + fontSize: (MediaQuery.of(context).size.height) * (17 / 926), + ),)],) + + ]), + ) + ], + ), + )) + ],)); + } + +} + +class ResultDetails extends StatefulWidget { + @override + _ResultDetailsState createState() => _ResultDetailsState(); +} + +class _ResultDetailsState extends State { + //same code as quiz details renamed getQuizAnalysis to getResultDetails + var _getResultDetails; + + @override + void initState() { + super.initState(); + getResultDetails(); + } + + getResultDetails() async { + SharedPreferences prefs = await SharedPreferences.getInstance(); + String? responseString = prefs.getString("getResultDetailsAPI"); + var getResultDetails1 = resultDetailsModelFromJson(responseString!); + final ResultDetailsModel getResultDetails = getResultDetails1; + setState(() { + _getResultDetails = getResultDetails; + // print(_getResultDetails.data.subjects.length); + }); + } + + + int index = 0; //0=subjects,1=systems,2=topics + @override + Widget build(BuildContext context) { + var h=MediaQuery.of(context).size.height/926; + var w=MediaQuery.of(context).size.width/428; + return SingleChildScrollView( + padding: EdgeInsets.all(h*20), + child: Column( + children: [ + SizedBox(height: MediaQuery.of(context).padding.top,), + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Container( + alignment: Alignment.topLeft, + padding: EdgeInsets.only(left:w*10), + child: Text( + "Result Details", + style: TextStyle( + color: Styles.darkGrey, + fontFamily: 'Brandon-bld', + fontSize: h * 30), + ), + ), + SizedBox(width: w*140,), + Align( + alignment: Alignment.topRight, + child: IconButton( + icon: Icon(Icons.close), + iconSize: 25, + color: Styles.lightPurple, + onPressed: () { + Navigator.of(context).pop(); + }, + ), + ), + SizedBox(height:h*20), + ], + ), + ButtonBar( + alignment: MainAxisAlignment.spaceEvenly, + buttonHeight:h*25, + children: [ + TextButton( + style: const ButtonStyle( + splashFactory: NoSplash.splashFactory, + ), + onPressed: () { + setState(() { + index = 0; + }); + }, + child: Text( + 'Subjects', + style: TextStyle( + color: + index == 0 ? Styles.lightPurple: Styles.darkGrey, + fontFamily: 'Brandon-med', + fontSize: h*22 + ), + ), + ), + TextButton( + style: const ButtonStyle( + splashFactory: NoSplash.splashFactory, + ), + onPressed: () { + setState(() { + index = 1; + }); + }, + child: Text( + 'Systems', + style: TextStyle( + color: + index == 1 ? Styles.lightPurple: Styles.darkGrey, + fontFamily: 'Brandon-med', + fontSize: h*22 + ), + ), + ), + TextButton( + style: const ButtonStyle( + splashFactory: NoSplash.splashFactory, + ), + onPressed: () { + setState(() { + index = 2; + }); + }, + child: Text( + 'Topics', + style: TextStyle( + color: + index == 2 ? Styles.lightPurple: Styles.darkGrey, + fontFamily: 'Brandon-med', + fontSize: h*22 + ), + ), + ), + ], + ), + _getResultDetails == null ? const Center(child: CircularProgressIndicator(color: Color(0xff482384),)) : Column( + children: [ + const Divider(), + if(index == 0) + for(int i = 0; i<_getResultDetails.data.quizResults.length; i++) + if(_getResultDetails.data.quizResults[i].subject != null) + Column( + children: [ + SizedBox( + height: MediaQuery.of(context).size.height * (20 / 926), + ), + DetailsTile( + id: _getResultDetails.data.quizResults[i].questionId, + subject: _getResultDetails.data.quizResults[i].subject ?? "None", + system: _getResultDetails.data.quizResults[i].system ?? "None", + topic: _getResultDetails.data.quizResults[i].topic ?? "None", + peerAvg: _getResultDetails.data.quizResults[i].averageCorrectToOthers, + status: _getResultDetails.data.quizResults[i].status == -1 ? "Omitted" : (_getResultDetails.data.quizResults[i].status == 0 ? "Incorrect" : "Correct"), + index: 0, + ), + ], + ), + if(index == 1) + for(int i = 0; i<_getResultDetails.data.quizResults.length; i++) + if(_getResultDetails.data.quizResults[i].system != null) + Column( + children: [ + SizedBox( + height: MediaQuery.of(context).size.height * (20 / 926), + ), + DetailsTile( + id: _getResultDetails.data.quizResults[i].questionId, + subject: _getResultDetails.data.quizResults[i].subject ?? "None", + system: _getResultDetails.data.quizResults[i].system ?? "None", + topic: _getResultDetails.data.quizResults[i].topic ?? "None", + peerAvg: _getResultDetails.data.quizResults[i].averageCorrectToOthers, + status: _getResultDetails.data.quizResults[i].status == -1 ? "Omitted" : (_getResultDetails.data.quizResults[i].status == 0 ? "Incorrect" : "Correct"), + index: 1, + ), + ], + ), + if(index == 2) + for(int i = 0; i<_getResultDetails.data.quizResults.length; i++) + if(_getResultDetails.data.quizResults[i].topic != null) + Column( + children: [ + SizedBox( + height: MediaQuery.of(context).size.height * (20 / 926), + ), + DetailsTile( + id: _getResultDetails.data.quizResults[i].questionId, + subject: _getResultDetails.data.quizResults[i].subject ?? "None", + system: _getResultDetails.data.quizResults[i].system ?? "None", + topic: _getResultDetails.data.quizResults[i].topic ?? "None", + peerAvg: _getResultDetails.data.quizResults[i].averageCorrectToOthers, + status: _getResultDetails.data.quizResults[i].status == -1 ? "Omitted" : (_getResultDetails.data.quizResults[i].status == 0 ? "Incorrect" : "Correct"), + index: 2, + ), + ], + ), + ], + ) + ], + )); + } +} diff --git a/lib/screens/Welcome/PreviousQuiz/TestResults/testResults.dart b/lib/screens/Welcome/PreviousQuiz/TestResults/testResults.dart new file mode 100644 index 0000000..c3bf03f --- /dev/null +++ b/lib/screens/Welcome/PreviousQuiz/TestResults/testResults.dart @@ -0,0 +1,184 @@ +import 'dart:convert'; + +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_svg/svg.dart'; + +import 'package:shared_preferences/shared_preferences.dart'; +import 'package:http/http.dart' as http; +import 'package:testify/models/resultDetails/result_details_model.dart'; +import 'package:testify/screens/Components/styles.dart'; +import 'package:testify/screens/Welcome/PreviousQuiz/TestAnalysis/analysisDetails.dart'; +import 'package:testify/screens/Welcome/PreviousQuiz/TestAnalysis/mainTestAnalysisScreen.dart'; +import 'package:testify/screens/Welcome/PreviousQuiz/TestResults/mainResultDetailsScreen.dart'; +import 'package:testify/screens/Welcome/PreviousQuiz/TestResults/resultDetails.dart'; + +import '../../../Authentication/login.dart'; +import '../../side_menu_bar.dart'; + + +class TestResults extends StatefulWidget { + const TestResults({required this.quizId, required this.fromWhere,}); + final String fromWhere; + final int quizId; + @override + _TestResultsState createState() => _TestResultsState(); +} + +class _TestResultsState extends State { + + int _selectedIndex = 0; + late List _widgetOptions; + var _token; + var _userId; + var _getResultDetails; + bool _hasGetResultDetailsLoaded = false; + + Future _onItemTapped(int index) async { + if(_hasGetResultDetailsLoaded == true) { + setState(() { + _selectedIndex = index; + }); + } + } + + + + @override + void initState() { + super.initState(); + _widgetOptions = [ + MainResultDetails(quizId: widget.quizId), + ResultDetails() + ]; + getResultDetails(); + } + + Future getResultDetails() async { + SharedPreferences prefs = await SharedPreferences.getInstance(); + final String apiUrlGetResultDetails = "https://demo.pookidevs.com/quiz/result/getQuizResults"; + _token = prefs.getString('token')!; + print(_token); + _userId = prefs.getInt("userId")!; + print(_userId); + http.post(Uri.parse(apiUrlGetResultDetails), headers: { + 'Content-type': 'application/json; charset=UTF-8', 'Authorization' : _token.toString(), + }, body: json.encode( + { + "quizId": widget.quizId + }) + ).then((response) { + print(jsonDecode(response.body).toString()); + if((response.statusCode == 200) & (json.decode(response.body).toString().substring(0,14) != "{status: false")) { + final responseString = (response.body); + prefs.setString("getResultDetailsAPI", responseString); + var getResultDetails1 = resultDetailsModelFromJson(responseString); + final ResultDetailsModel getResultDetails = getResultDetails1; + setState(() { + _getResultDetails = getResultDetails; + // print(_getResultDetails.data.worstSubject.toString()); + _hasGetResultDetailsLoaded = true; + // print(_quizId); + }); + // categoriesGenerateQuizData(); + } + else { // Token Invalid + final result = Navigator.pushAndRemoveUntil( + context, + MaterialPageRoute(builder: (BuildContext context) => const Login(fromWhere:"Home")), + ModalRoute.withName('/'), + ); + } + } + ).catchError((error){ + setState(() { + _hasGetResultDetailsLoaded = true; + }); + var errorSplit = error.toString().split(":"); + if(errorSplit[0].toLowerCase() == "socketexception") { + ScaffoldMessenger.of(context) + ..removeCurrentSnackBar() + ..showSnackBar(SnackBar(content: Text("No Internet Connection"))); + } + // else if(errorSplit[0].toLowerCase() == "httpexception") { + // ScaffoldMessenger.of(context) + // ..removeCurrentSnackBar() + // ..showSnackBar(SnackBar(content: Text("Couldn't find the said thing."))); + // } + else if(errorSplit[0].toLowerCase() == "formatexception") { + ScaffoldMessenger.of(context) + ..removeCurrentSnackBar() + ..showSnackBar(SnackBar(content: Text("Bad Response Format"))); + } + else { + ScaffoldMessenger.of(context) + ..removeCurrentSnackBar() + ..showSnackBar(SnackBar(content: Text(error.toString()))); + } + }); + } + + @override + Widget build(BuildContext context) { + return WillPopScope( + onWillPop: () async { + if(widget.fromWhere == "QuizModule") { + Navigator.of(context) + .popUntil(ModalRoute.withName("/home")); + } + else if(widget.fromWhere == "PrevQuiz") { + Navigator.of(context).pop(); + } + return false; + }, + child: Scaffold( + backgroundColor: Color(0xffF8F9FB), + drawer: SideMenuBar(), + appBar: AppBar( + toolbarHeight: (MediaQuery.of(context).size.height) * (73.52 / 926), + backgroundColor: Color(0xff3F2668), + elevation: 2, + centerTitle: true, + flexibleSpace: Container( + decoration: const BoxDecoration( + gradient: LinearGradient( + begin: Alignment.topCenter, + end: Alignment.bottomCenter, + colors: [Color(0xff7F1AF1), Color(0xff482384)])), + ), + actions: [ + TextButton( + onPressed: () async { + final result = await Navigator.push( + context, + MaterialPageRoute( + builder: (context) => const Login(fromWhere: "Home")), + ); + }, + child: SvgPicture.asset( + "assets/Images/logout.svg", + height: (MediaQuery.of(context).size.height) * (32 / 926), + ), + ), + ], + ), + body: _hasGetResultDetailsLoaded == false ? Center(child: CircularProgressIndicator(color: Color(0xff482384),)) : _widgetOptions.elementAt(_selectedIndex), + bottomNavigationBar:BottomNavigationBar( + currentIndex: _selectedIndex, + selectedItemColor:Color(0xff7F1AF1), + onTap: _onItemTapped, + items: const [ + BottomNavigationBarItem( + icon: Icon(Icons.stacked_line_chart_outlined), + label: 'Results', + ), + BottomNavigationBarItem( + icon: Icon(Icons.description_outlined), + label: 'Details', + ),], + ) , + + ), + ); + } +} diff --git a/lib/screens/Welcome/PreviousQuiz/previous_quiz.dart b/lib/screens/Welcome/PreviousQuiz/previous_quiz.dart index 6523ef5..dc9bbd6 100644 --- a/lib/screens/Welcome/PreviousQuiz/previous_quiz.dart +++ b/lib/screens/Welcome/PreviousQuiz/previous_quiz.dart @@ -109,7 +109,32 @@ class _PreviousQuizState extends State { ); } } - ); + ).catchError((error){ + setState(() { + hasPreviousQuizzesDataLoaded = true; + }); + var errorSplit = error.toString().split(":"); + if(errorSplit[0].toLowerCase() == "socketexception") { + ScaffoldMessenger.of(context) + ..removeCurrentSnackBar() + ..showSnackBar(SnackBar(content: Text("No Internet Connection"))); + } + // else if(errorSplit[0].toLowerCase() == "httpexception") { + // ScaffoldMessenger.of(context) + // ..removeCurrentSnackBar() + // ..showSnackBar(SnackBar(content: Text("Couldn't find the said thing."))); + // } + else if(errorSplit[0].toLowerCase() == "formatexception") { + ScaffoldMessenger.of(context) + ..removeCurrentSnackBar() + ..showSnackBar(SnackBar(content: Text("Bad Response Format"))); + } + else { + ScaffoldMessenger.of(context) + ..removeCurrentSnackBar() + ..showSnackBar(SnackBar(content: Text(error.toString()))); + } + }); } categorizePreviousQuizzesData() { diff --git a/lib/screens/Welcome/PreviousQuiz/test_details.dart b/lib/screens/Welcome/PreviousQuiz/test_details.dart index ac2df98..83c4375 100644 --- a/lib/screens/Welcome/PreviousQuiz/test_details.dart +++ b/lib/screens/Welcome/PreviousQuiz/test_details.dart @@ -5,6 +5,8 @@ import 'package:flutter/material.dart'; import 'package:flutter_svg/svg.dart'; import 'package:shared_preferences/shared_preferences.dart'; import 'package:testify/models/GetPreviousQuizzesModel/ResumeQuiz/resume_quiz_model.dart'; +import 'package:testify/screens/Welcome/PreviousQuiz/TestAnalysis/testAnalysis.dart'; +import 'package:testify/screens/Welcome/PreviousQuiz/TestResults/testResults.dart'; import 'package:testify/screens/Welcome/PreviousQuiz/previous_quiz.dart'; import 'package:http/http.dart' as http; import 'package:testify/screens/Welcome/QuizModule/quiz_module.dart'; @@ -63,15 +65,6 @@ class _TestDetailsState extends State { setState(() { _resumeQuizSuccessful = resumeQuizSuccessful; _isResumeQuizLoading = false; - // print(_resumeQuizSuccessful.data.previousQuizzes[0].quizMeta.quizMode); - // print(_resumeQuizSuccessful.data.previousQuizzes[0].quizMeta.quizTotalQuestions); - // print(_resumeQuizSuccessful.data.previousQuizzes[0].quizMeta.quizQuestions); - // print(_resumeQuizSuccessful.data.previousQuizzes[0].quizMeta.quizStatus); - // print(_resumeQuizSuccessful.data.previousQuizzes[0].quizMeta.isTimed); - // print(_resumeQuizSuccessful.data.previousQuizzes[0].quizMeta.quizId.runtimeType); - // print(_resumeQuizSuccessful.data.previousQuizzes[0].quizMeta.quizScore.runtimeType); - // _quizId = _getGenerateQuizSuccessful.data.quizId; - // print(_quizId); }); // categoriesGenerateQuizData(); } @@ -79,404 +72,467 @@ class _TestDetailsState extends State { } } - ); + ).catchError((error){ + setState(() { + _isResumeQuizLoading = false; + }); + var errorSplit = error.toString().split(":"); + if(errorSplit[0].toLowerCase() == "socketexception") { + ScaffoldMessenger.of(context) + ..removeCurrentSnackBar() + ..showSnackBar(SnackBar(content: Text("No Internet Connection"))); + } + else if(errorSplit[0].toLowerCase() == "formatexception") { + ScaffoldMessenger.of(context) + ..removeCurrentSnackBar() + ..showSnackBar(SnackBar(content: Text("Bad Response Format"))); + } + else { + ScaffoldMessenger.of(context) + ..removeCurrentSnackBar() + ..showSnackBar(SnackBar(content: Text(error.toString()))); + } + }); } @override Widget build(BuildContext context) { - return Scaffold( - backgroundColor: Color(0xffF8F9FB), - drawer: SideMenuBar(), - appBar: AppBar( - toolbarHeight: (MediaQuery.of(context).size.height) * (73.52 / 926), - backgroundColor: Color(0xff3F2668), - elevation: 2, - centerTitle: true, - flexibleSpace: Container( - decoration: const BoxDecoration( - gradient: LinearGradient( - begin: Alignment.topCenter, - end: Alignment.bottomCenter, - colors: [Color(0xff7F1AF1), Color(0xff482384)])), - ), - title: const Text( - "Test Details", - style: TextStyle( - color: Color(0xffFFFEFE), - fontFamily: 'Brandon-bld', + return WillPopScope( + onWillPop: () async { + Navigator.of(context) + .popUntil(ModalRoute.withName("/home")); + final result = await Navigator.push( + context, + MaterialPageRoute(builder: (context) => PreviousQuiz()), + ); + return false; + }, + child: Scaffold( + backgroundColor: Color(0xffF8F9FB), + drawer: SideMenuBar(), + appBar: AppBar( + toolbarHeight: (MediaQuery.of(context).size.height) * (73.52 / 926), + backgroundColor: Color(0xff3F2668), + elevation: 2, + centerTitle: true, + flexibleSpace: Container( + decoration: const BoxDecoration( + gradient: LinearGradient( + begin: Alignment.topCenter, + end: Alignment.bottomCenter, + colors: [Color(0xff7F1AF1), Color(0xff482384)])), ), - ), - actions: [ - TextButton( - onPressed: () async { - final result = await Navigator.push( - context, - MaterialPageRoute( - builder: (context) => const Login(fromWhere: "Home")), - ); - }, - child: SvgPicture.asset( - "assets/Images/logout.svg", - height: (MediaQuery.of(context).size.height) * (32 / 926), + title: const Text( + "Test Details", + style: TextStyle( + color: Color(0xffFFFEFE), + fontFamily: 'Brandon-bld', ), ), - ], - ), - body: SingleChildScrollView( - child: Padding( - padding: const EdgeInsets.symmetric(vertical: 100), - child: Column( - children: [ - Center( - child: Container( - // height: (MediaQuery.of(context).size.height) * (488 / 926), - width: (MediaQuery.of(context).size.width) * (385 / 428), - decoration: BoxDecoration( - borderRadius: BorderRadius.circular(2), - color: Colors.white, - boxShadow: [ - BoxShadow(color: Colors.grey, offset: Offset(0, 4), blurRadius: 6) - ], - ), - child: Column( - children: [ + actions: [ + TextButton( + onPressed: () async { + final result = await Navigator.push( + context, + MaterialPageRoute( + builder: (context) => const Login(fromWhere: "Home")), + ); + }, + child: SvgPicture.asset( + "assets/Images/logout.svg", + height: (MediaQuery.of(context).size.height) * (32 / 926), + ), + ), + ], + ), + body: SingleChildScrollView( + child: Padding( + padding: const EdgeInsets.symmetric(vertical: 100), + child: Column( + children: [ + Center( + child: Container( + // height: (MediaQuery.of(context).size.height) * (488 / 926), + width: (MediaQuery.of(context).size.width) * (385 / 428), + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(2), + color: Colors.white, + boxShadow: [ + BoxShadow(color: Colors.grey, offset: Offset(0, 4), blurRadius: 6) + ], + ), + child: Column( + children: [ - Container( - height: (MediaQuery.of(context).size.height) * (59 / 926), - width: (MediaQuery.of(context).size.width) * (385 / 428), - color: Color(0xff6D5A8D), - child: Center( - child: Text( - 'Test Details', - style: TextStyle( - color: Colors.white, - fontFamily: 'Brandon-bld', - fontSize: (MediaQuery.of(context).size.height) * (20 / 926), + Container( + height: (MediaQuery.of(context).size.height) * (59 / 926), + width: (MediaQuery.of(context).size.width) * (385 / 428), + color: Color(0xff6D5A8D), + child: Center( + child: Text( + 'Test Details', + style: TextStyle( + color: Colors.white, + fontFamily: 'Brandon-bld', + fontSize: (MediaQuery.of(context).size.height) * (20 / 926), + ), ), ), ), - ), - Container( - // height: (MediaQuery.of(context).size.height) * (310 / 926), - width: (MediaQuery.of(context).size.width) * (385 / 428), - padding: EdgeInsets.all(25), - child: Table( - columnWidths: {0:FixedColumnWidth((MediaQuery.of(context).size.width) * (25 / 428)), - 1:FixedColumnWidth((MediaQuery.of(context).size.width) * (200 / 428))}, - border: TableBorder.all(color: Colors.transparent), - children: [ - TableRow(children: [ - Padding( - padding: const EdgeInsets.only(top:8.0), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - 'Quiz ID:', - style: TextStyle( - color: Color(0xff3F2668), - fontFamily: 'Brandon-bld', - fontSize: (MediaQuery.of(context).size.height) * - (16 / 926), + Container( + // height: (MediaQuery.of(context).size.height) * (310 / 926), + width: (MediaQuery.of(context).size.width) * (385 / 428), + padding: EdgeInsets.all(25), + child: Table( + columnWidths: {0:FixedColumnWidth((MediaQuery.of(context).size.width) * (25 / 428)), + 1:FixedColumnWidth((MediaQuery.of(context).size.width) * (200 / 428))}, + border: TableBorder.all(color: Colors.transparent), + children: [ + TableRow(children: [ + Padding( + padding: const EdgeInsets.only(top:8.0), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + 'Quiz ID:', + style: TextStyle( + color: Color(0xff3F2668), + fontFamily: 'Brandon-bld', + fontSize: (MediaQuery.of(context).size.height) * + (16 / 926), + ), ), - ), - ], + ], + ), ), - ), - Padding( - padding: const EdgeInsets.only(top:8.0), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text(widget.quizId.toString(), - textAlign: TextAlign.start, + Padding( + padding: const EdgeInsets.only(top:8.0), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text(widget.quizId.toString(), + textAlign: TextAlign.start, + style: TextStyle( + color: Colors.black, + fontFamily: 'Brandon-med', + fontSize: (MediaQuery.of(context).size.height) * + (16 / 926), + )) + ], + ), + ) + ]), + TableRow(children: [ + Padding( + padding: const EdgeInsets.only(top:8.0), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + 'System:', style: TextStyle( - color: Colors.black, - fontFamily: 'Brandon-med', + color: Color(0xff3F2668), + fontFamily: 'Brandon-bld', fontSize: (MediaQuery.of(context).size.height) * (16 / 926), - )) - ], - ), - ) - ]), - TableRow(children: [ - Padding( - padding: const EdgeInsets.only(top:8.0), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - 'System:', - style: TextStyle( - color: Color(0xff3F2668), - fontFamily: 'Brandon-bld', - fontSize: (MediaQuery.of(context).size.height) * - (16 / 926), + ), ), - ), - ], + ], + ), ), - ), - Padding( - padding: const EdgeInsets.only(top:8.0), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text(widget.system.toString().substring(1, widget.system.toString().length-1) == "" ? "-" : widget.system.toString().substring(1, widget.system.toString().length-1), + Padding( + padding: const EdgeInsets.only(top:8.0), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text(widget.system.toString().substring(1, widget.system.toString().length-1) == "" ? "-" : widget.system.toString().substring(1, widget.system.toString().length-1), + style: TextStyle( + color: Colors.black, + fontFamily: 'Brandon-med', + fontSize: (MediaQuery.of(context).size.height) * + (16 / 926), + )) + ], + ), + ) + ]), + TableRow(children: [ + Padding( + padding: const EdgeInsets.only(top:8.0), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + 'Subject:', style: TextStyle( - color: Colors.black, - fontFamily: 'Brandon-med', + color: Color(0xff3F2668), + fontFamily: 'Brandon-bld', fontSize: (MediaQuery.of(context).size.height) * (16 / 926), - )) - ], - ), - ) - ]), - TableRow(children: [ - Padding( - padding: const EdgeInsets.only(top:8.0), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - 'Subject:', - style: TextStyle( - color: Color(0xff3F2668), - fontFamily: 'Brandon-bld', - fontSize: (MediaQuery.of(context).size.height) * - (16 / 926), + ), ), - ), - ], + ], + ), ), - ), - Padding( - padding: const EdgeInsets.only(top:8.0), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text(widget.subject.toString().substring(1, widget.subject.toString().length-1) == "" ? "-" : widget.subject.toString().substring(1, widget.subject.toString().length-1), + Padding( + padding: const EdgeInsets.only(top:8.0), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text(widget.subject.toString().substring(1, widget.subject.toString().length-1) == "" ? "-" : widget.subject.toString().substring(1, widget.subject.toString().length-1), + style: TextStyle( + color: Colors.black, + fontFamily: 'Brandon-med', + fontSize: (MediaQuery.of(context).size.height) * + (16 / 926), + )) + ], + ), + ) + ]), + TableRow(children: [ + Padding( + padding: const EdgeInsets.only(top:8.0), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + 'Topic:', style: TextStyle( - color: Colors.black, - fontFamily: 'Brandon-med', + color: Color(0xff3F2668), + fontFamily: 'Brandon-bld', fontSize: (MediaQuery.of(context).size.height) * (16 / 926), - )) - ], - ), - ) - ]), - TableRow(children: [ - Padding( - padding: const EdgeInsets.only(top:8.0), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - 'Topic:', - style: TextStyle( - color: Color(0xff3F2668), - fontFamily: 'Brandon-bld', - fontSize: (MediaQuery.of(context).size.height) * - (16 / 926), + ), ), - ), - ], + ], + ), ), - ), - Padding( - padding: const EdgeInsets.only(top:8.0), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text(widget.topic.toString().substring(1, widget.topic.toString().length-1) == "" ? "-" : widget.topic.toString().substring(1, widget.topic.toString().length-1), + Padding( + padding: const EdgeInsets.only(top:8.0), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text(widget.topic.toString().substring(1, widget.topic.toString().length-1) == "" ? "-" : widget.topic.toString().substring(1, widget.topic.toString().length-1), + style: TextStyle( + color: Colors.black, + fontFamily: 'Brandon-med', + fontSize: (MediaQuery.of(context).size.height) * + (16 / 926), + )) + ], + ), + ) + ]), + TableRow(children: [ + Padding( + padding: const EdgeInsets.only(top:8.0), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + 'Score:', style: TextStyle( - color: Colors.black, - fontFamily: 'Brandon-med', + color: Color(0xff3F2668), + fontFamily: 'Brandon-bld', fontSize: (MediaQuery.of(context).size.height) * (16 / 926), - )) - ], - ), - ) - ]), - TableRow(children: [ - Padding( - padding: const EdgeInsets.only(top:8.0), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - 'Score:', - style: TextStyle( - color: Color(0xff3F2668), - fontFamily: 'Brandon-bld', - fontSize: (MediaQuery.of(context).size.height) * - (16 / 926), + ), ), - ), - ], + ], + ), ), - ), - Padding( - padding: const EdgeInsets.only(top:8.0), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text(widget.score, + Padding( + padding: const EdgeInsets.only(top:8.0), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text(widget.score, + style: TextStyle( + color: Colors.black, + fontFamily: 'Brandon-med', + fontSize: (MediaQuery.of(context).size.height) * + (16 / 926), + )) + ], + ), + ) + ]), + TableRow(children: [ + Padding( + padding: const EdgeInsets.only(top:8.0), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + 'Status:', style: TextStyle( - color: Colors.black, - fontFamily: 'Brandon-med', + color: Color(0xff3F2668), + fontFamily: 'Brandon-bld', fontSize: (MediaQuery.of(context).size.height) * (16 / 926), - )) - ], + ), + ), + ], + ), ), - ) - ]), - TableRow(children: [ - Padding( - padding: const EdgeInsets.only(top:8.0), + Padding( + padding: const EdgeInsets.only(top:8.0), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text(widget.status, + style: TextStyle( + color: Colors.black, + fontFamily: 'Brandon-med', + fontSize: (MediaQuery.of(context).size.height) * + (16 / 926), + )) + ], + ), + ) + ]) + ], + ), + ), + + Container( + height: (MediaQuery.of(context).size.height) * (70 / 926), + width: (MediaQuery.of(context).size.width) * (385 / 428), + child: _isResumeQuizLoading ? Center(child: CircularProgressIndicator(color: Color(0xff7F1AF1),)) : Row( + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + children: [ + GestureDetector( + onTap: () { + final result = Navigator.push( + context, + MaterialPageRoute(builder: (context) => TestAnalysis(quizId: widget.quizId)), + ); + }, child: Column( - crossAxisAlignment: CrossAxisAlignment.start, children: [ - Text( - 'Status:', - style: TextStyle( - color: Color(0xff3F2668), - fontFamily: 'Brandon-bld', - fontSize: (MediaQuery.of(context).size.height) * - (16 / 926), - ), - ), + Container(height:40,width:40,decoration: BoxDecoration(color: Color(0xff7F1AF1),borderRadius: BorderRadius.circular(20)), + child: Icon(Icons.show_chart_outlined,size: 20,color:Colors.white)) + ,Text('Test Analysis',style: TextStyle( + color: Color(0xff7F1AF1), + fontFamily: 'Brandon-med', + fontSize: (MediaQuery.of(context).size.height) * (15 / 926), + ),) ], ), ), - Padding( - padding: const EdgeInsets.only(top:8.0), + GestureDetector( + onTap: () { + final result = Navigator.push( + context, + MaterialPageRoute(builder: (context) => TestResults(quizId: widget.quizId, fromWhere: "PrevQuiz",)), + ); + }, child: Column( - crossAxisAlignment: CrossAxisAlignment.start, children: [ - Text(widget.status, - style: TextStyle( - color: Colors.black, - fontFamily: 'Brandon-med', - fontSize: (MediaQuery.of(context).size.height) * - (16 / 926), - )) + Container(height:40,width:40,decoration: BoxDecoration(color: Color(0xff7F1AF1),borderRadius: BorderRadius.circular(20)), + child: Icon(Icons.event_note_outlined,size: 20,color:Colors.white)) + ,Text('Test Results',style: TextStyle( + color: Color(0xff7F1AF1), + fontFamily: 'Brandon-med', + fontSize: (MediaQuery.of(context).size.height) * (15 / 926), + ),) ], ), - ) - ]) - ], - ), - ), + ), + GestureDetector( + onTap: () async { + if(_resumeQuizSuccessful.data.previousQuizzes[0].quizMeta.quizStatus == "suspended") { + SharedPreferences prefs = await SharedPreferences.getInstance(); + prefs.setInt("quizId", widget.quizId); + List _quizQuestions = []; + for(int i = 0; i<_resumeQuizSuccessful.data.questions.length; i++) { + _quizQuestions.add(_resumeQuizSuccessful.data.questions[i].id); + } - Container( - height: (MediaQuery.of(context).size.height) * (70 / 926), - width: (MediaQuery.of(context).size.width) * (385 / 428), - child: _isResumeQuizLoading ? Center(child: CircularProgressIndicator(color: Color(0xff7F1AF1),)) : Row( - mainAxisAlignment: MainAxisAlignment.spaceEvenly, - children: [ - Column( - children: [ - Container(height:40,width:40,decoration: BoxDecoration(color: Color(0xff7F1AF1),borderRadius: BorderRadius.circular(20)), - child: Icon(Icons.show_chart_outlined,size: 20,color:Colors.white)) - ,Text('Test Analysis',style: TextStyle( - color: Color(0xff7F1AF1), - fontFamily: 'Brandon-med', - fontSize: (MediaQuery.of(context).size.height) * (15 / 926), - ),) - ], - ), - Column( - children: [ - Container(height:40,width:40,decoration: BoxDecoration(color: Color(0xff7F1AF1),borderRadius: BorderRadius.circular(20)), - child: Icon(Icons.event_note_outlined,size: 20,color:Colors.white)) - ,Text('Test Results',style: TextStyle( - color: Color(0xff7F1AF1), - fontFamily: 'Brandon-med', - fontSize: (MediaQuery.of(context).size.height) * (15 / 926), - ),) - ], - ), - GestureDetector( - onTap: () async { - if(_resumeQuizSuccessful.data.previousQuizzes[0].quizMeta.quizStatus == "suspended") { - // print(_resumeQuizSuccessful.data.previousQuizzes[0].quizMeta.quizMode); - // print(_resumeQuizSuccessful.data.previousQuizzes[0].quizMeta.quizTotalQuestions); - // print(_resumeQuizSuccessful.data.previousQuizzes[0].quizMeta.quizQuestions); - // print(_resumeQuizSuccessful.data.previousQuizzes[0].quizMeta.isTimed); - SharedPreferences prefs = await SharedPreferences.getInstance(); - prefs.setInt("quizId", widget.quizId); - List _quizQuestions = []; - for(int i = 0; i<_resumeQuizSuccessful.data.questions.length; i++) { - _quizQuestions.add(_resumeQuizSuccessful.data.questions[i].id); + // Navigator.of(context) + // .popUntil(ModalRoute.withName("/home")); + final result = Navigator.push( + context, + MaterialPageRoute(builder: (context) => QuizModule(totalQuestions: _resumeQuizSuccessful.data.previousQuizzes[0].quizMeta.quizTotalQuestions, + questions: _quizQuestions, + timedMode: _resumeQuizSuccessful.data.previousQuizzes[0].quizMeta.isTimed, + mode: _resumeQuizSuccessful.data.previousQuizzes[0].quizMeta.quizMode.toString(), + whatsDone: "resumed",)), + ); } + else if(_resumeQuizSuccessful.data.previousQuizzes[0].quizMeta.quizStatus == "completed") { + print("Reviewed"); + SharedPreferences prefs = await SharedPreferences.getInstance(); + prefs.setInt("quizId", widget.quizId); + List _quizQuestions = []; + for(int i = 0; i<_resumeQuizSuccessful.data.questions.length; i++) { + _quizQuestions.add(_resumeQuizSuccessful.data.questions[i].id); + } - // Navigator.of(context) - // .popUntil(ModalRoute.withName("/home")); - final result = Navigator.push( - context, - MaterialPageRoute(builder: (context) => QuizModule(totalQuestions: _resumeQuizSuccessful.data.previousQuizzes[0].quizMeta.quizTotalQuestions, - questions: _quizQuestions, - timedMode: _resumeQuizSuccessful.data.previousQuizzes[0].quizMeta.isTimed, - mode: _resumeQuizSuccessful.data.previousQuizzes[0].quizMeta.quizMode.toString(), - whatsDone: "resumed",)), - ); - } - }, - child: Column( - children: [ - Container(height:40,width:40,decoration: BoxDecoration(color: Color(0xff7F1AF1),borderRadius: BorderRadius.circular(20)), - child: Icon(Icons.arrow_right,size: 40,color:Colors.white)) - ,Text(_resumeQuizSuccessful.data.previousQuizzes[0].quizMeta.quizStatus == "suspended" ? 'Resume' : 'Review',style: TextStyle( - color: Color(0xff7F1AF1), - fontFamily: 'Brandon-med', - fontSize: (MediaQuery.of(context).size.height) * (15 / 926), - ),) - ], + // Navigator.of(context) + // .popUntil(ModalRoute.withName("/home")); + final result = Navigator.push( + context, + MaterialPageRoute(builder: (context) => QuizModule(totalQuestions: _resumeQuizSuccessful.data.previousQuizzes[0].quizMeta.quizTotalQuestions, + questions: _quizQuestions, + timedMode: _resumeQuizSuccessful.data.previousQuizzes[0].quizMeta.isTimed, + mode: _resumeQuizSuccessful.data.previousQuizzes[0].quizMeta.quizMode.toString(), + whatsDone: "resumed",)), + ); + } + }, + child: Column( + children: [ + Container(height:40,width:40,decoration: BoxDecoration(color: Color(0xff7F1AF1),borderRadius: BorderRadius.circular(20)), + child: Icon(Icons.arrow_right,size: 40,color:Colors.white)) + ,Text(_resumeQuizSuccessful.data.previousQuizzes[0].quizMeta.quizStatus == "suspended" ? 'Resume' : 'Review',style: TextStyle( + color: Color(0xff7F1AF1), + fontFamily: 'Brandon-med', + fontSize: (MediaQuery.of(context).size.height) * (15 / 926), + ),) + ], + ), ), - ), - ], - ), - ) + ], + ), + ) - ], + ], + ), ), ), - ), - Padding( - padding: const EdgeInsets.all(20.0), - child: InkWell( - onTap:() async { - // Navigator.of(context).pop(); - Navigator.of(context) - .popUntil(ModalRoute.withName("/home")); - final result = await Navigator.push( - context, - MaterialPageRoute(builder: (context) => PreviousQuiz()), - ); - }, - child:Container( - child: Row( - children: [Icon(Icons.arrow_back,color: Color(0xff7F1AF1),size: 15,),Text('Back',style: TextStyle( - color: Color(0xff7F1AF1), - fontFamily: 'Brandon-bld', - fontSize: (MediaQuery.of(context).size.height) * - (13 / 926), - ),)], + Padding( + padding: const EdgeInsets.all(20.0), + child: InkWell( + onTap:() async { + // Navigator.of(context).pop(); + Navigator.of(context) + .popUntil(ModalRoute.withName("/home")); + final result = await Navigator.push( + context, + MaterialPageRoute(builder: (context) => PreviousQuiz()), + ); + }, + child:Container( + child: Row( + children: [Icon(Icons.arrow_back,color: Color(0xff7F1AF1),size: 15,),Text('Back',style: TextStyle( + color: Color(0xff7F1AF1), + fontFamily: 'Brandon-bld', + fontSize: (MediaQuery.of(context).size.height) * + (13 / 926), + ),)], - ), - )), - ) - ], + ), + )), + ) + ], + ), ), ), ), - ); + ); } } diff --git a/lib/screens/Welcome/PreviousQuiz/tile.dart b/lib/screens/Welcome/PreviousQuiz/tile.dart index 3b4e78f..a93142d 100644 --- a/lib/screens/Welcome/PreviousQuiz/tile.dart +++ b/lib/screens/Welcome/PreviousQuiz/tile.dart @@ -70,7 +70,7 @@ class Tile extends StatelessWidget { width: (MediaQuery.of(context).size.width) * (12 / 428), ), Text( - (name.length >= 22) ? name.substring(0, 22) : name, + (name.length >= 17) ? name.substring(0, 17) : name, style: TextStyle( color: Colors.black, fontFamily: 'Brandon-med', diff --git a/lib/screens/Welcome/QuizModule/quiz_module.dart b/lib/screens/Welcome/QuizModule/quiz_module.dart index ac94a6f..19d1af7 100644 --- a/lib/screens/Welcome/QuizModule/quiz_module.dart +++ b/lib/screens/Welcome/QuizModule/quiz_module.dart @@ -9,6 +9,7 @@ import 'package:http/http.dart' as http; import 'package:testify/models/GenerateQuizModels/QuizModuleModels/generate_quiz_model.dart'; import 'package:testify/models/GetPreviousQuizzesModel/ResumeQuiz/resume_quiz_model.dart'; import 'package:testify/screens/Authentication/login.dart'; +import 'package:testify/screens/Welcome/PreviousQuiz/previous_quiz.dart'; import 'package:testify/screens/Welcome/QuizModule/question_explanation.dart'; import 'package:testify/screens/Welcome/QuizModule/quiz_final.dart'; import 'package:testify/screens/Welcome/QuizModule/search_bar.dart'; @@ -25,29 +26,30 @@ class QuizModule extends StatefulWidget { final List questions; final bool timedMode; final String mode; // tutor/ exam - final String whatsDone; // new(From Generate Quiz), resumed, reviewed + final String whatsDone; // new(From Generate Quiz), resumed, review @override _QuizModuleState createState() => _QuizModuleState(); } class _QuizModuleState extends State with WidgetsBindingObserver{ - int endTime = DateTime.now().millisecondsSinceEpoch + 1000 * 30; + // int endTime = DateTime.now().millisecondsSinceEpoch + 1000 * 300; + late int endTime; + int selectedIndex = 0; List _questions = ['1', '2', '3', '4']; String _currentQuestion = '1'; - int _currentSelected = 0; - String _labValues="Lorem ipsum dolor sit amet, consectetur adipiscing elit. Cras imperdiet finibus elit non luctus. Morbi auctor mattis ante. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Cras imperdiet finibus elit non luctus. Morbi auctor mattis ante."; - String _note="Lorem ipsum dolor sit amet, consectetur adipiscing elit. Cras imperdiet finibus elit non luctus. Morbi auctor mattis ante. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Cras imperdiet finibus elit non luctus. Morbi auctor mattis ante."; + final String _labValues = + "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Cras imperdiet finibus elit non luctus. Morbi auctor mattis ante. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Cras imperdiet finibus elit non luctus. Morbi auctor mattis ante."; + String _note = + "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Cras imperdiet finibus elit non luctus. Morbi auctor mattis ante. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Cras imperdiet finibus elit non luctus. Morbi auctor mattis ante."; late TextEditingController _textController; double _fontSize = 18; // To change font size bool _showTextZoom = false; // To show ths slider + bool _showMenu=false; int timeElapsed = 0; + /// declare a timer Timer? timer; - // Timer? saveQuiz; // Saves quiz every few seconds. - - //BottomNavBar - int _selectedIndex = 0; // This key is used to open the side drawer final GlobalKey _scaffoldKey = new GlobalKey(); @@ -71,14 +73,6 @@ class _QuizModuleState extends State with WidgetsBindingObserver{ // To void null safety error bool hasDataLoaded = false; bool ranSaveQuizAtTheStart = false; // To auto save the quiz at the start and avoid the quizzes from being suspended - // if(hasDataLoaded = true) { - // if(ranSaveQuizAtTheStart = false) { - // SaveQuizAPI(); - // setState(() { - // ranSaveQuizAtTheStart = true; - // }); - // } - // } //Storing the data required to display quiz questions and store their answers var questionsData = { @@ -88,18 +82,22 @@ class _QuizModuleState extends State with WidgetsBindingObserver{ "correct_msg": [], // This is the explanation "options": [], // A list would be added to this list "statistics": [], // [1, 0, 0] - "answeredCorrectly": [], // Stores string and turns true if answered correctly. Can't be a bool since values are correct/incorrect/notAnswered + "answeredCorrectly": + [], // Stores string and turns true if answered correctly. Can't be a bool since values are correct/incorrect/notAnswered "optionSelectedInt": [], //To change Icon and color "notes": [], "submitData": [], - "SelectedOptionsArray": [] + "SelectedOptionsArray": [], + "eachQuestionTimer": [] // Time user took to solve each question. // "isSelected": [] }; var addToSelectedOptionsArray = { "index": "", "Correctanswerindex": "", // indexOfOptionThatIsActuallyCorrect - "correct": "", // Correct = 1 if answer is correct, -1 if answer is omitted and 0 if answer is incorrect - "optionIndexSelected": "" + "correct": + "", // Correct = 1 if answer is correct, -1 if answer is omitted and 0 if answer is incorrect, always an int + "optionIndexSelected": "", + "time": "" }; @override @@ -107,11 +105,9 @@ class _QuizModuleState extends State with WidgetsBindingObserver{ super.initState(); _textController = TextEditingController(); WidgetsBinding.instance!.addObserver(this); - if(widget.whatsDone == "new") + if (widget.whatsDone == "new") GenerateQuizAPI(); - else if(widget.whatsDone == "resumed") - ResumeQuizAPI(); - + else if (widget.whatsDone == "resumed") ResumeQuizAPI(); timer = Timer.periodic( const Duration(seconds: 1), (timer) { @@ -121,152 +117,214 @@ class _QuizModuleState extends State with WidgetsBindingObserver{ }, ); - // saveQuiz = Timer.periodic( - // const Duration(seconds: 10), - // (timer) { - // SaveQuizAPI(); - // }, - // ); } - @override - void didChangeAppLifecycleState(AppLifecycleState state) async { - super.didChangeAppLifecycleState(state); - final isBackground = state == AppLifecycleState.paused; - final isClosed = state == AppLifecycleState.detached; - if(isBackground) { // As soon as the user closes the app this runs. The application is still in the app switcher(ram) - print("xD in Background"); - SaveQuizAPI("suspended"); - // ScaffoldMessenger.of(context) - // ..removeCurrentSnackBar() - // ..showSnackBar(SnackBar(content: Text("The Quiz has been saved as Suspended!"))); - Navigator.of(context).pop(); - } - if(isClosed) { // When app is closed from the app switcher. Doesn't run for now for some odd reason. - print("xD Closed"); - } - } Future ResumeQuizAPI() async { SharedPreferences prefs = await SharedPreferences.getInstance(); - final String apiUrlGenerateQuiz = "https://demo.pookidevs.com/quiz/solver/resumeQuiz"; + final String apiUrlGenerateQuiz = + "https://demo.pookidevs.com/quiz/solver/resumeQuiz"; var quizID = prefs.getInt("quizId"); _token = prefs.getString('token')!; print(_token); _userId = prefs.getInt("userId")!; - http.post(Uri.parse(apiUrlGenerateQuiz), headers: { - 'Content-type': 'application/json; charset=UTF-8', 'Authorization' : _token.toString(), - }, body: json.encode( - { - "quizId": quizID - }) - ).then((response) { + http + .post(Uri.parse(apiUrlGenerateQuiz), + headers: { + 'Content-type': 'application/json; charset=UTF-8', + 'Authorization': _token.toString(), + }, + body: json.encode({"quizId": quizID})) + .then((response) { // print(jsonDecode(response.body).toString()); - if((response.statusCode == 200) & (json.decode(response.body).toString().substring(0,14) != "{status: false")) { + if ((response.statusCode == 200) & + (json.decode(response.body).toString().substring(0, 14) != + "{status: false")) { + _quizId = quizID; final responseString = (response.body); var resumeQuizSuccessful1 = resumeQuizModelFromJson(responseString); final ResumeQuizModel resumeQuizSuccessful = resumeQuizSuccessful1; setState(() { _resumeQuizSuccessful = resumeQuizSuccessful; - print(_resumeQuizSuccessful.data.previousQuizzes[0].quizMeta.quizMode); - print(_resumeQuizSuccessful.data.previousQuizzes[0].quizMeta.quizTotalQuestions); - print(_resumeQuizSuccessful.data.previousQuizzes[0].quizMeta.quizQuestions); - print(_resumeQuizSuccessful.data.previousQuizzes[0].quizMeta.quizStatus); - print(_resumeQuizSuccessful.data.previousQuizzes[0].quizMeta.isTimed); - // print(_resumeQuizSuccessful.data.previousQuizzes[0].quizMeta.quizId.runtimeType); - // print(_resumeQuizSuccessful.data.previousQuizzes[0].quizMeta.quizScore.runtimeType); - // _quizId = _getGenerateQuizSuccessful.data.quizId; - // print(_quizId); + endTime = endTimeFunction(); + // print( + // _resumeQuizSuccessful.data.previousQuizzes[0].quizMeta.quizMode); + // print(_resumeQuizSuccessful + // .data.previousQuizzes[0].quizMeta.quizTotalQuestions); + // print(_resumeQuizSuccessful + // .data.previousQuizzes[0].quizMeta.quizQuestions); + // print(_resumeQuizSuccessful + // .data.previousQuizzes[0].quizMeta.quizStatus); + // print(_resumeQuizSuccessful.data.previousQuizzes[0].quizMeta.isTimed); + // print(" Time used up is: " + + // _resumeQuizSuccessful.data.previousQuizzes[0].quizMeta.quizTime); }); categoriesGenerateQuizData(); - // categoriesGenerateQuizData(); + } else { + // Token Invalid } - else { // Token Invalid - + }).catchError((error){ + setState(() { + hasDataLoaded = true; + }); + var errorSplit = error.toString().split(":"); + if(errorSplit[0].toLowerCase() == "socketexception") { + ScaffoldMessenger.of(context) + ..removeCurrentSnackBar() + ..showSnackBar(SnackBar(content: Text("No Internet Connection"))); } - } - ); + // else if(errorSplit[0].toLowerCase() == "httpexception") { + // ScaffoldMessenger.of(context) + // ..removeCurrentSnackBar() + // ..showSnackBar(SnackBar(content: Text("Couldn't find the said thing."))); + // } + else if(errorSplit[0].toLowerCase() == "formatexception") { + ScaffoldMessenger.of(context) + ..removeCurrentSnackBar() + ..showSnackBar(SnackBar(content: Text("Bad Response Format"))); + } + else { + ScaffoldMessenger.of(context) + ..removeCurrentSnackBar() + ..showSnackBar(SnackBar(content: Text(error.toString()))); + } + }); } - Future submitAnswerAPI(int? indexOfOptionThatIsActuallyCorrect, int? correct, int? optionIndexSelected) async { // doesn't work properly in exam mode - final String apiUrlGenerateQuiz = "https://demo.pookidevs.com/quiz/solver/submitAnswer"; + Future submitAnswerAPI(int? indexOfOptionThatIsActuallyCorrect, int? correct, int? optionIndexSelected) async { + // doesn't work properly in exam mode + final String apiUrlGenerateQuiz = + "https://demo.pookidevs.com/quiz/solver/submitAnswer"; // print(_token); SharedPreferences prefs = await SharedPreferences.getInstance(); var _quizID = prefs.getInt("quizId"); - print(widget.whatsDone); - print("user id: "+ _userId.toString()); - print("questionId: "+ questionsData["id"]![questionNumber].toString()); - print("quizId" + _quizID.toString()); - print("indexOfOptionThatIsActuallyCorrect: " + indexOfOptionThatIsActuallyCorrect.toString()); - print("correct: " + correct.toString()); - print("optionIndexSelected: " + optionIndexSelected.toString()); - + // print(widget.whatsDone); + // print("user id: " + _userId.toString()); + // print("questionId: " + questionsData["id"]![questionNumber].toString()); + // print("quizId" + _quizID.toString()); + // print("indexOfOptionThatIsActuallyCorrect: " + + // indexOfOptionThatIsActuallyCorrect.toString()); + // print("correct: " + correct.toString()); + // print("optionIndexSelected: " + optionIndexSelected.toString()); + // print("eachQuestionTimer: " + + // questionsData["eachQuestionTimer"]![questionNumber].toString()); - - http.post(Uri.parse(apiUrlGenerateQuiz), headers: { - 'Content-type': 'application/json; charset=UTF-8', 'Authorization' : _token.toString(), - }, body: json.encode( - { - "data":{ + http + .post(Uri.parse(apiUrlGenerateQuiz), + headers: { + 'Content-type': 'application/json; charset=UTF-8', + 'Authorization': _token.toString(), + }, + body: json.encode({ + "data": { "userId": _userId.toString(), "questionId": questionsData["id"]![questionNumber].toString(), // "quizId": widget.whatsDone == "new" ? _getGenerateQuizSuccessful.data.quizId.toString() : _resumeQuizSuccessful.data.previousQuizzes[0].quizId.toString(), "quizId": _quizID.toString(), - "answerMeta":{ + "answerMeta": { "index": questionsData["id"]![questionNumber].toString(), - "Correctanswerindex": indexOfOptionThatIsActuallyCorrect.toString(), // indexOfOptionThatIsActuallyCorrect - "correct": correct.toString(), // Correct = 1 if answer is correct, -1 if answer is omitted and 0 if answer is incorrect - "optionIndexSelected": optionIndexSelected.toString() + "Correctanswerindex": indexOfOptionThatIsActuallyCorrect + .toString(), // indexOfOptionThatIsActuallyCorrect + "correct": correct as int, // Correct = 1 if answer is correct, -1 if answer is omitted and 0 if answer is incorrect + "optionIndexSelected": optionIndexSelected.toString(), + "time": questionsData["eachQuestionTimer"]![questionNumber] + .toString(), } } - }) - ).then((response) { - if((response.statusCode == 200)) { + })) + .then((response) { + if ((response.statusCode == 200)) { print(jsonDecode(response.body).toString()); - if((jsonDecode(response.body).toString()) == "{data: {status: true, message: Answer Submitted}}") { - + if ((jsonDecode(response.body).toString()) == + "{data: {status: true, message: Answer Submitted}}") { } else { ScaffoldMessenger.of(context) ..removeCurrentSnackBar() ..showSnackBar(SnackBar(content: Text("Error! Answer not Saved!"))); } - } - else { // Token Invalid + } else { + // Token Invalid ScaffoldMessenger.of(context) ..removeCurrentSnackBar() ..showSnackBar(SnackBar(content: Text("Token Invalid!"))); final result = Navigator.pushAndRemoveUntil( context, - MaterialPageRoute(builder: (BuildContext context) => const Login(fromWhere:"Home")), + MaterialPageRoute( + builder: (BuildContext context) => + const Login(fromWhere: "Home")), ModalRoute.withName('/'), ); } - } - ); + }).catchError((error){ + setState(() { + hasDataLoaded = true; + }); + var errorSplit = error.toString().split(":"); + if(errorSplit[0].toLowerCase() == "socketexception") { + ScaffoldMessenger.of(context) + ..removeCurrentSnackBar() + ..showSnackBar(SnackBar(content: Text("No Internet Connection"))); + } + // else if(errorSplit[0].toLowerCase() == "httpexception") { + // ScaffoldMessenger.of(context) + // ..removeCurrentSnackBar() + // ..showSnackBar(SnackBar(content: Text("Couldn't find the said thing."))); + // } + else if(errorSplit[0].toLowerCase() == "formatexception") { + ScaffoldMessenger.of(context) + ..removeCurrentSnackBar() + ..showSnackBar(SnackBar(content: Text("Bad Response Format"))); + } + else { + ScaffoldMessenger.of(context) + ..removeCurrentSnackBar() + ..showSnackBar(SnackBar(content: Text(error.toString()))); + } + }); } - Future SaveQuizAPI(String saveAs, [bool? hasUserClicked]) async { + // if(widget.whatsDone == "resumed") { + // if(_resumeQuizSuccessful + // .data + // .previousQuizzes[ + // 0] + // .quizMeta + // .quizStatus + // .toString() == + // "completed") { + // final result = Navigator.of(context) + // .popUntil(ModalRoute.withName("/home")); + // final result1 = Navigator.push( + // context, + // MaterialPageRoute(builder: (context) => PreviousQuiz()), + // ); + // } + // } SharedPreferences prefs = await SharedPreferences.getInstance(); - widget.whatsDone == "new" ? prefs.setInt("quizId", _getGenerateQuizSuccessful.data.quizId) : null; - var _quizID = widget.whatsDone == "new" ? _getGenerateQuizSuccessful.data.quizId.toString() : _resumeQuizSuccessful.data.previousQuizzes[0].quizId.toString(); - final String apiUrlGenerateQuiz = "https://demo.pookidevs.com/quiz/solver/saveQuiz"; - print(widget.totalQuestions); + widget.whatsDone == "new" + ? prefs.setInt("quizId", _getGenerateQuizSuccessful.data.quizId) + : null; + var _quizID = widget.whatsDone == "new" + ? _getGenerateQuizSuccessful.data.quizId.toString() + : _resumeQuizSuccessful.data.previousQuizzes[0].quizId.toString(); + final String apiUrlGenerateQuiz = + "https://demo.pookidevs.com/quiz/solver/saveQuiz"; var date = new DateTime.now().toString().split("."); date = date[0].split(" "); - print(date); int quizScore = 0; var addToOmittedQuestionsArray = []; var finalSelectedOptionsArray = []; var totalQuizTime = timeElapsed.toString(); - for(int i = 0; i with WidgetsBindingObserver{ } } } - if(saveAs == "completed") { - for(int i = 0; i{ - 'Content-type': 'application/json; charset=UTF-8', 'Authorization' : _token.toString(), - }, body: json.encode( - { - "data": - { - "quiz" : { - "quizId": widget.whatsDone == "new" ? _getGenerateQuizSuccessful.data.quizId.toString() : _resumeQuizSuccessful.data.previousQuizzes[0].quizId.toString(), - "quizTitle": "Custom Quiz" + date[0].toString(), // "Custom Quiz" + Date.now() + http + .post(Uri.parse(apiUrlGenerateQuiz), + headers: { + 'Content-type': 'application/json; charset=UTF-8', + 'Authorization': _token.toString(), + }, + body: json.encode({ + "data": { + "quiz": { + "quizId": widget.whatsDone == "new" + ? _getGenerateQuizSuccessful.data.quizId.toString() + : _resumeQuizSuccessful.data.previousQuizzes[0].quizId + .toString(), + "quizTitle": "Custom Quiz" + + date[0].toString(), // "Custom Quiz" + Date.now() "quizDate": date[0].toString(), // "Custom Quiz" "quizScore": quizScore.toString(), // total correct "quizTotalQuestions": widget.totalQuestions.toString(), - "quizStatus": saveAs, // == "completed" ? "completed" : "suspended", // "completed", "suspended" - "quizQuestions": questionsData["id"].toString(), // Question IDs + "quizStatus": + saveAs, // == "completed" ? "completed" : "suspended", // "completed", "suspended" + "quizQuestions": + questionsData["id"].toString(), // Question IDs "quizMode": widget.mode, // "tutor", "exam" - "quizTime": totalQuizTime.toString(), // total quiz time in seconds + "quizTime": + totalQuizTime.toString(), // total quiz time in seconds "isTimed": widget.timedMode, // bool true or false - "omittedQuestions": addToOmittedQuestionsArray, // Don't send anything here - "SelectedOptionsArray": widget.mode == "exam" ? finalSelectedOptionsArray : [] // Don't send anything here + "omittedQuestions": + addToOmittedQuestionsArray, // Don't send anything here + "SelectedOptionsArray": widget.mode == "exam" + ? finalSelectedOptionsArray + : [] // Don't send anything here }, "userId": _userId.toString() } - } + })) + .then((response) async { + //print(jsonDecode(response.body).toString()); + if ((response.statusCode == 200) & + (json.decode(response.body).toString().substring(0, 14) != + "{status: false")) { + if (hasUserClicked == true) { + if (widget.whatsDone == "resumed") { + if (_resumeQuizSuccessful + .data.previousQuizzes[0].quizMeta.quizStatus == + "completed") { + ScaffoldMessenger.of(context) + ..removeCurrentSnackBar() + ..showSnackBar(SnackBar( + content: Text("Review Complete!"))); + Navigator.of(context) + .popUntil(ModalRoute.withName("/home")); + // await Navigator.push( + // context, + // MaterialPageRoute(builder: (context) => PreviousQuiz()), + // ); + } else if (_resumeQuizSuccessful + .data.previousQuizzes[0].quizMeta.quizStatus == + "suspended") { + ScaffoldMessenger.of(context) + ..removeCurrentSnackBar() + ..showSnackBar(SnackBar( + content: Text("The Quiz has been saved as $saveAs!"))); - ) - ).then((response) async { - print(jsonDecode(response.body).toString()); - if((response.statusCode == 200) & (json.decode(response.body).toString().substring(0,14) != "{status: false")) { + Navigator.of(context) + .popUntil(ModalRoute.withName("/home")); + // final result1 = Navigator.push( + // context, + // MaterialPageRoute(builder: (context) => TestResults(quizId: _quizId, fromWhere: 'QuizModule',)), + // ); + } + } else if (widget.whatsDone == "new") { + ScaffoldMessenger.of(context) + ..removeCurrentSnackBar() + ..showSnackBar( + SnackBar(content: Text("The Quiz has been saved as $saveAs!"))); - } - else { // Token Invalid + Navigator.of(context) + .popUntil(ModalRoute.withName("/home")); + // final result1 = Navigator.push( + // context, + // MaterialPageRoute(builder: (context) => TestResults(quizId: _quizId, fromWhere: 'QuizModule',)), + // ); + } + } + } else { + // Token Invalid ScaffoldMessenger.of(context) ..removeCurrentSnackBar() ..showSnackBar(SnackBar(content: Text("Token Invalid!"))); final result = Navigator.pushAndRemoveUntil( context, - MaterialPageRoute(builder: (BuildContext context) => const Login(fromWhere:"Home")), + MaterialPageRoute( + builder: (BuildContext context) => + const Login(fromWhere: "Home")), ModalRoute.withName('/'), ); } - } - ).whenComplete(() { - if(hasUserClicked == true) { + }).catchError((error){ + setState(() { + hasDataLoaded = true; + }); + var errorSplit = error.toString().split(":"); + if(errorSplit[0].toLowerCase() == "socketexception") { ScaffoldMessenger.of(context) ..removeCurrentSnackBar() - ..showSnackBar(SnackBar(content: Text("The Quiz has been saved as $saveAs!"))); - Navigator.of(context) - .popUntil(ModalRoute.withName("/home")); - final result = Navigator.push( - context, - MaterialPageRoute(builder: (context) => QuizFinal()), - ); + ..showSnackBar(SnackBar(content: Text("No Internet Connection"))); + } + // else if(errorSplit[0].toLowerCase() == "httpexception") { + // ScaffoldMessenger.of(context) + // ..removeCurrentSnackBar() + // ..showSnackBar(SnackBar(content: Text("Couldn't find the said thing."))); + // } + else if(errorSplit[0].toLowerCase() == "formatexception") { + ScaffoldMessenger.of(context) + ..removeCurrentSnackBar() + ..showSnackBar(SnackBar(content: Text("Bad Response Format"))); + } + else { + ScaffoldMessenger.of(context) + ..removeCurrentSnackBar() + ..showSnackBar(SnackBar(content: Text(error.toString()))); } }); - } Future GenerateQuizAPI() async { print("Mode: " + widget.mode.toString()); SharedPreferences prefs = await SharedPreferences.getInstance(); - final String apiUrlGenerateQuiz = "https://demo.pookidevs.com/quiz/generator/generateQuiz"; + final String apiUrlGenerateQuiz = + "https://demo.pookidevs.com/quiz/generator/generateQuiz"; _token = prefs.getString('token')!; _userId = prefs.getInt("userId")!; - http.post(Uri.parse(apiUrlGenerateQuiz), headers: { - 'Content-type': 'application/json; charset=UTF-8', 'Authorization' : _token.toString(), - }, body: json.encode( - { - "data": - { + http + .post(Uri.parse(apiUrlGenerateQuiz), + headers: { + 'Content-type': 'application/json; charset=UTF-8', + 'Authorization': _token.toString(), + }, + body: json.encode({ + "data": { "questionIds": widget.questions, "count": widget.totalQuestions } - }) - ).then((response) { + })) + .then((response) { // print("This is: " + jsonDecode(response.body).toString()); - if((response.statusCode == 200) & (json.decode(response.body).toString().substring(0,14) != "{status: false")) { + if ((response.statusCode == 200) & + (json.decode(response.body).toString().substring(0, 14) != + "{status: false")) { final responseString = (response.body); - var generateQuizSuccessful = generateQuizSuccessfulFromJson(responseString); - final GenerateQuizSuccessful getGenerateQuizSuccessful = generateQuizSuccessful; + var generateQuizSuccessful = + generateQuizSuccessfulFromJson(responseString); + final GenerateQuizSuccessful getGenerateQuizSuccessful = + generateQuizSuccessful; setState(() { _getGenerateQuizSuccessful = getGenerateQuizSuccessful; _quizId = _getGenerateQuizSuccessful.data.quizId; + endTime = endTimeFunction(); print(_quizId); }); categoriesGenerateQuizData(); + } else { + // Token Invalid } - else { // Token Invalid - + }).catchError((error){ + setState(() { + hasDataLoaded = true; + }); + var errorSplit = error.toString().split(":"); + if(errorSplit[0].toLowerCase() == "socketexception") { + ScaffoldMessenger.of(context) + ..removeCurrentSnackBar() + ..showSnackBar(SnackBar(content: Text("No Internet Connection"))); } - } - ); + // else if(errorSplit[0].toLowerCase() == "httpexception") { + // ScaffoldMessenger.of(context) + // ..removeCurrentSnackBar() + // ..showSnackBar(SnackBar(content: Text("Couldn't find the said thing."))); + // } + else if(errorSplit[0].toLowerCase() == "formatexception") { + ScaffoldMessenger.of(context) + ..removeCurrentSnackBar() + ..showSnackBar(SnackBar(content: Text("Bad Response Format"))); + } + else { + ScaffoldMessenger.of(context) + ..removeCurrentSnackBar() + ..showSnackBar(SnackBar(content: Text(error.toString()))); + } + }); } Future BookmarkQuestionAPI() async { - final String apiUrlGenerateQuiz = "https://demo.pookidevs.com/quiz/solver/markQuestion"; - http.post(Uri.parse(apiUrlGenerateQuiz), headers: { - 'Content-type': 'application/json; charset=UTF-8', 'Authorization' : _token.toString(), - }, body: json.encode( - { + final String apiUrlGenerateQuiz = + "https://demo.pookidevs.com/quiz/solver/markQuestion"; + http + .post(Uri.parse(apiUrlGenerateQuiz), + headers: { + 'Content-type': 'application/json; charset=UTF-8', + 'Authorization': _token.toString(), + }, + body: json.encode({ "data": { "userId": _userId, "questionId": questionsData["id"]![questionNumber].toString(), "tableName": "marked_questions", "isMarked": true } - }) - ).then((response) { - if((response.statusCode == 200)) { // & (json.decode(response.body).toString().substring(0,14) != "{status: false")) { + })) + .then((response) { + if ((response.statusCode == 200)) { + // & (json.decode(response.body).toString().substring(0,14) != "{status: false")) { print(jsonDecode(response.body).toString()); - } - else { // Token Invalid + } else { + // Token Invalid ScaffoldMessenger.of(context) ..removeCurrentSnackBar() ..showSnackBar(SnackBar(content: Text("Token Invalid!"))); final result = Navigator.pushAndRemoveUntil( context, - MaterialPageRoute(builder: (BuildContext context) => const Login(fromWhere:"Home")), + MaterialPageRoute( + builder: (BuildContext context) => + const Login(fromWhere: "Home")), ModalRoute.withName('/'), ); } - } - ); + }).catchError((error){ + setState(() { + hasDataLoaded = true; + }); + var errorSplit = error.toString().split(":"); + if(errorSplit[0].toLowerCase() == "socketexception") { + ScaffoldMessenger.of(context) + ..removeCurrentSnackBar() + ..showSnackBar(SnackBar(content: Text("No Internet Connection"))); + } + // else if(errorSplit[0].toLowerCase() == "httpexception") { + // ScaffoldMessenger.of(context) + // ..removeCurrentSnackBar() + // ..showSnackBar(SnackBar(content: Text("Couldn't find the said thing."))); + // } + else if(errorSplit[0].toLowerCase() == "formatexception") { + ScaffoldMessenger.of(context) + ..removeCurrentSnackBar() + ..showSnackBar(SnackBar(content: Text("Bad Response Format"))); + } + else { + ScaffoldMessenger.of(context) + ..removeCurrentSnackBar() + ..showSnackBar(SnackBar(content: Text(error.toString()))); + } + }); } Future addNotesAPI() async { - // print(_userId); - // print(questionsData["id"]![questionNumber].toString()); - // print(_quizId); - // print(_note); - final String apiUrlGenerateQuiz = "https://demo.pookidevs.com/quiz/notes/addNotes"; - http.post(Uri.parse(apiUrlGenerateQuiz), headers: { - 'Content-type': 'application/json; charset=UTF-8', 'Authorization' : _token.toString(), - }, body: json.encode( - { + final String apiUrlGenerateQuiz = + "https://demo.pookidevs.com/quiz/notes/addNotes"; + http + .post(Uri.parse(apiUrlGenerateQuiz), + headers: { + 'Content-type': 'application/json; charset=UTF-8', + 'Authorization': _token.toString(), + }, + body: json.encode({ "data": { "userId": _userId, "questionId": questionsData["id"]![questionNumber].toString(), @@ -454,32 +625,61 @@ class _QuizModuleState extends State with WidgetsBindingObserver{ "note": _note, "tableName": "notes" } - } - ) - ).then((response) { - // print(jsonDecode(response.body).toString()); - // print(json.decode(response.body).toString().substring(json.decode(response.body).toString().length-12,json.decode(response.body).toString().length)); - if((response.statusCode == 200) & (json.decode(response.body).toString().substring(json.decode(response.body).toString().length-12,json.decode(response.body).toString().length) == "Note Added}}")) { + })) + .then((response) { + if ((response.statusCode == 200) & + (json.decode(response.body).toString().substring( + json.decode(response.body).toString().length - 12, + json.decode(response.body).toString().length) == + "Note Added}}")) { ScaffoldMessenger.of(context) ..removeCurrentSnackBar() ..showSnackBar(SnackBar(content: Text("Note Added!"))); - } - else if((response.statusCode == 200) & (json.decode(response.body).toString().substring(0,14) == "{status: false")) { // Token Invalid + } else if ((response.statusCode == 200) & + (json.decode(response.body).toString().substring(0, 14) == + "{status: false")) { + // Token Invalid ScaffoldMessenger.of(context) ..removeCurrentSnackBar() ..showSnackBar(SnackBar(content: Text("Token Expired!"))); - final result = Navigator.push( + final result = Navigator.pushAndRemoveUntil( context, - MaterialPageRoute(builder: (context) => const Login(fromWhere:"Home")), + MaterialPageRoute( + builder: (BuildContext context) => + const Login(fromWhere: "Home")), + ModalRoute.withName('/'), ); + } else { + ScaffoldMessenger.of(context) + ..removeCurrentSnackBar() + ..showSnackBar(SnackBar(content: Text("Note not Added!"))); + } + }).catchError((error){ + setState(() { + hasDataLoaded = true; + }); + var errorSplit = error.toString().split(":"); + if(errorSplit[0].toLowerCase() == "socketexception") { + ScaffoldMessenger.of(context) + ..removeCurrentSnackBar() + ..showSnackBar(SnackBar(content: Text("No Internet Connection"))); + } + // else if(errorSplit[0].toLowerCase() == "httpexception") { + // ScaffoldMessenger.of(context) + // ..removeCurrentSnackBar() + // ..showSnackBar(SnackBar(content: Text("Couldn't find the said thing."))); + // } + else if(errorSplit[0].toLowerCase() == "formatexception") { + ScaffoldMessenger.of(context) + ..removeCurrentSnackBar() + ..showSnackBar(SnackBar(content: Text("Bad Response Format"))); } else { ScaffoldMessenger.of(context) ..removeCurrentSnackBar() - ..showSnackBar(SnackBar(content: Text("Note not Added!"))); + ..showSnackBar(SnackBar(content: Text(error.toString()))); } - } - ); + }); } void categoriesGenerateQuizData() async { @@ -493,15 +693,15 @@ class _QuizModuleState extends State with WidgetsBindingObserver{ questionsData["optionSelectedInt"] = []; questionsData["notes"] = []; questionsData["submitData"] = []; - questionsData["SelectedOptionsArray"] = []; + questionsData["SelectedOptionsArray"] = []; //eachQuestionTimer + questionsData["eachQuestionTimer"] = []; _questions = []; }); - if(widget.whatsDone == "new") - { + if (widget.whatsDone == "new") { int c = 0; if (_getGenerateQuizSuccessful != null) { while ((c < _getGenerateQuizSuccessful.data.questions.toList().length) & - (_getGenerateQuizSuccessful.data.questions.toList().length > 0)) { + (_getGenerateQuizSuccessful.data.questions.toList().length > 0)) { // questionsData setState(() { questionsData["id"]! @@ -516,8 +716,10 @@ class _QuizModuleState extends State with WidgetsBindingObserver{ .data.questions[c].correctMsg); //answeredCorrectly questionsData["answeredCorrectly"]!.add("notAnswered"); questionsData["optionSelectedInt"]!.add(0); - questionsData["SelectedOptionsArray"]!.add(addToSelectedOptionsArray); + questionsData["SelectedOptionsArray"]! + .add(addToSelectedOptionsArray); _questions.add((c + 1).toString()); + questionsData["eachQuestionTimer"]!.add(0); }); c++; } @@ -535,8 +737,8 @@ class _QuizModuleState extends State with WidgetsBindingObserver{ } } // print(questionsData); - else if(widget.whatsDone == "resumed") - { // Have to complete Exam Mode + else if (widget.whatsDone == "resumed") { + // Have to complete Exam Mode int c = 0; if (_resumeQuizSuccessful != null) { while ((c < _resumeQuizSuccessful.data.questions.length) & @@ -557,30 +759,45 @@ class _QuizModuleState extends State with WidgetsBindingObserver{ questionsData["optionSelectedInt"]!.add(0); // questionsData["SelectedOptionsArray"]![c] = _resumeQuizSuccessful.data.previousQuizzes[0].quiz_meta.selectedOptionsArray _questions.add((c + 1).toString()); - if(widget.mode == "exam") { - questionsData["SelectedOptionsArray"]!.add(addToSelectedOptionsArray); + questionsData["eachQuestionTimer"]!.add(0); + if (widget.mode == "exam") { + questionsData["SelectedOptionsArray"]! + .add(addToSelectedOptionsArray); // print(_resumeQuizSuccessful.data.previousQuizzes[0].quizMeta.selectedOptionsArray); } - if(_resumeQuizSuccessful.data.questions[c].notes != null) { // notes - questionsData["notes"]!.add(_resumeQuizSuccessful - .data.questions[c].notes); + if (_resumeQuizSuccessful.data.questions[c].notes != null) { + // notes + questionsData["notes"]! + .add(_resumeQuizSuccessful.data.questions[c].notes); } else { questionsData["notes"]!.add(""); } - if(_resumeQuizSuccessful.data.questions[c].submitData != null) { // submitData + if (_resumeQuizSuccessful.data.questions[c].submitData != null) { + // submitData String str = _resumeQuizSuccessful.data.questions[c].submitData; str = str.replaceAll("\\", ""); var strMap = json.decode(str); - // print(strMap); - if(strMap['correct'] == '1') { - questionsData["answeredCorrectly"]![c] = "correct"; + print(strMap); + if(widget.mode == "exam") { + if (strMap['correct'].toString() == "1") { + questionsData["answeredCorrectly"]![c] = "correct"; + } else if (strMap['correct'].toString() == "0") { + questionsData["answeredCorrectly"]![c] = "incorrect"; + } } - else if (strMap['correct'] == '0') { - questionsData["answeredCorrectly"]![c] = "incorrect"; + else if(widget.mode == "tutor") { + if (strMap['correct'] == 1) { + questionsData["answeredCorrectly"]![c] = "correct"; + } else if (strMap['correct'] == 0) { + questionsData["answeredCorrectly"]![c] = "incorrect"; + } } - questionsData["optionSelectedInt"]![c] = int.parse(strMap['optionIndexSelected']); - questionsData["submitData"]!.add(_resumeQuizSuccessful - .data.questions[c].submitData); + questionsData["optionSelectedInt"]![c] = + int.parse(strMap['optionIndexSelected']); + questionsData["eachQuestionTimer"]![c] = + int.parse(strMap['time']); + questionsData["submitData"]! + .add(_resumeQuizSuccessful.data.questions[c].submitData); } else { questionsData["submitData"]!.add(""); } @@ -588,18 +805,56 @@ class _QuizModuleState extends State with WidgetsBindingObserver{ c++; } // Adding data to questionsData["SelectedOptionsArray"] - if(widget.mode == "exam") { - if((_resumeQuizSuccessful.data.previousQuizzes[0].quizMeta.selectedOptionsArray != null) || (_resumeQuizSuccessful.data.previousQuizzes[0].quizMeta.selectedOptionsArray != [])) { - for(int i = 0; i<_resumeQuizSuccessful.data.questions.length; i++) { - for(int j = 0; j<_resumeQuizSuccessful.data.previousQuizzes[0].quizMeta.selectedOptionsArray.length; j++) { - if(_resumeQuizSuccessful.data.questions[i].id.toString() == _resumeQuizSuccessful.data.previousQuizzes[0].quizMeta.selectedOptionsArray[j].index) { - if(_resumeQuizSuccessful.data.questions[i].submitData != null) { + if (widget.mode == "exam") { + if ((_resumeQuizSuccessful + .data.previousQuizzes[0].quizMeta.selectedOptionsArray != + null) || + (_resumeQuizSuccessful + .data.previousQuizzes[0].quizMeta.selectedOptionsArray != + [])) { + for (int i = 0; + i < _resumeQuizSuccessful.data.questions.length; + i++) { + for (int j = 0; + j < + _resumeQuizSuccessful.data.previousQuizzes[0].quizMeta + .selectedOptionsArray.length; + j++) { + if (_resumeQuizSuccessful.data.questions[i].id.toString() == + _resumeQuizSuccessful.data.previousQuizzes[0].quizMeta + .selectedOptionsArray[j].index) { + if (_resumeQuizSuccessful.data.questions[i].submitData != + null) { setState(() { + print("Correct runtype: " + _resumeQuizSuccessful + .data + .previousQuizzes[0] + .quizMeta + .selectedOptionsArray[j] + .correct.runtimeType.toString()); questionsData["SelectedOptionsArray"]![i] = { - "index": _resumeQuizSuccessful.data.previousQuizzes[0].quizMeta.selectedOptionsArray[j].index, - "Correctanswerindex": _resumeQuizSuccessful.data.previousQuizzes[0].quizMeta.selectedOptionsArray[j].correctanswerindex, // indexOfOptionThatIsActuallyCorrect - "correct": _resumeQuizSuccessful.data.previousQuizzes[0].quizMeta.selectedOptionsArray[j].correct, // Correct = 1 if answer is correct, -1 if answer is omitted and 0 if answer is incorrect - "optionIndexSelected": _resumeQuizSuccessful.data.previousQuizzes[0].quizMeta.selectedOptionsArray[j].optionIndexSelected + "index": _resumeQuizSuccessful.data.previousQuizzes[0] + .quizMeta.selectedOptionsArray[j].index, + "Correctanswerindex": _resumeQuizSuccessful + .data + .previousQuizzes[0] + .quizMeta + .selectedOptionsArray[j] + .correctanswerindex, // indexOfOptionThatIsActuallyCorrect + "correct": _resumeQuizSuccessful + .data + .previousQuizzes[0] + .quizMeta + .selectedOptionsArray[j] + .correct.toString(), // Correct = 1 if answer is correct, -1 if answer is omitted and 0 if answer is incorrect + "optionIndexSelected": _resumeQuizSuccessful + .data + .previousQuizzes[0] + .quizMeta + .selectedOptionsArray[j] + .optionIndexSelected, + "time": _resumeQuizSuccessful.data.previousQuizzes[0] + .quizMeta.selectedOptionsArray[j].time }; }); } @@ -608,14 +863,20 @@ class _QuizModuleState extends State with WidgetsBindingObserver{ } } } - print(questionsData["SelectedOptionsArray"]); - print(questionsData["answeredCorrectly"]); + //print(questionsData["SelectedOptionsArray"]![0]["correct"].runtimeType); + //print(questionsData["answeredCorrectly"]); setState(() { hasDataLoaded = true; }); if (hasDataLoaded == true) { if (ranSaveQuizAtTheStart == false) { - SaveQuizAPI("suspended"); + if(_resumeQuizSuccessful.data.previousQuizzes[0].quizMeta.quizStatus.toString() == "completed") { + // Do Nothing + } + else { + SaveQuizAPI("suspended"); + } + //SaveQuizAPI("suspended"); setState(() { ranSaveQuizAtTheStart = true; }); @@ -623,29 +884,22 @@ class _QuizModuleState extends State with WidgetsBindingObserver{ } } } - // print(_resumeQuizSuccessful.data.previousQuizzes[0].quizMeta.quizMode); } // To change text size - text zoom Widget _textZoom(BuildContext context) { return GestureDetector( - onTap: () { - }, + onTap: () {}, child: Container( height: ((MediaQuery.of(context).size.height) * (51 / 926)), - decoration: const BoxDecoration( - gradient: LinearGradient( - begin: Alignment.topCenter, - end: Alignment.bottomCenter, - colors: [Color(0xff7F1AF1), Color(0xff482384)])), + color: Colors.white, child: new Slider( value: _fontSize, - activeColor: Colors.white, - inactiveColor: Colors.red, + activeColor: Color(0xff482384), + inactiveColor: Colors.grey, onChanged: (double value) { setState(() { _fontSize = value; - print(_fontSize); }); }, divisions: 4, @@ -656,110 +910,46 @@ class _QuizModuleState extends State with WidgetsBindingObserver{ ); } - - void onEnd() { + void onEnd() async { print('onEnd'); + // Uncomment this when testing is complete. + // await SaveQuizAPI("completed", true); } - Widget bookmarkQuestion(BuildContext context) { - return SizedBox( - child: AlertDialog( - contentPadding: EdgeInsets.all(MediaQuery.of(context).size.width*(15/428)), - content: Column( - mainAxisSize: MainAxisSize.min, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Text( - 'Bookmark', - style: TextStyle( - color: Color(0xffB0A6C2), - fontFamily: 'Brandon-bld', - fontSize: (MediaQuery.of(context).size.height) * (18 / 926), - ), - ), - IconButton(icon:Icon(Icons.cancel),iconSize:23,color: Color(0xFF3F2668),onPressed: () { - Navigator.of(context).pop(); - },), - ], - ), - Divider(), - Text("Are you sure you want to bookmark this question", - ), - ], - ), - actions: [ - Divider(), - Row( - mainAxisAlignment: MainAxisAlignment.end, - children: [ - TextButton( - onPressed: () { - Navigator.of(context).pop(); - }, - child: Text('No', - style: TextStyle( - color: Color(0xff3F2668), - fontFamily: 'Brandon-bld', - fontSize: - (MediaQuery.of(context).size.height) * (21 / 926), - )), - ), - Divider(), - TextButton( - onPressed: () { - Navigator.of(context).pop(); - print(questionsData["id"]![questionNumber].toString()); - BookmarkQuestionAPI(); - }, - child: Text('Yes', - style: TextStyle( - color: Color(0xff3F2668), - fontFamily: 'Brandon-bld', - fontSize: - (MediaQuery.of(context).size.height) * (21 / 926), - )), - ), - ], - ), - ], - ), - ); + int endTimeFunction() { + // widget.whatsDone == "new" ? (widget.totalQuestions * 120) : widget.whatsDone == "resumed" ? _resumeQuizSuccessful.data.previousQuizzes[0].quizMeta.quizTime + if (widget.whatsDone == "new") { + print("New: " + (widget.totalQuestions * 120).toString()); + return ((DateTime.now().millisecondsSinceEpoch) + + (1000 * widget.totalQuestions * 120)); + } else if (widget.whatsDone == "resumed") { + if (int.parse(_resumeQuizSuccessful + .data.previousQuizzes[0].quizMeta.quizTime) <= + (widget.totalQuestions * 120)) { + print("Resumed: " + + ((widget.totalQuestions * 120) - + (int.parse(_resumeQuizSuccessful + .data.previousQuizzes[0].quizMeta.quizTime))) + .toString()); + return ((DateTime.now().millisecondsSinceEpoch) + + 1000 * + ((widget.totalQuestions * 120) - + (int.parse(_resumeQuizSuccessful + .data.previousQuizzes[0].quizMeta.quizTime)))); + } else { + ScaffoldMessenger.of(context) + ..removeCurrentSnackBar() + ..showSnackBar(SnackBar( + content: + Text("You have already consumed all of the quiz time."))); + return ((DateTime.now().millisecondsSinceEpoch) + 1000 * 1); + } + } else { + print("else"); + return ((DateTime.now().millisecondsSinceEpoch) + 1000 * 1); + } } - Widget labValues(BuildContext context) { - return SizedBox( - child: AlertDialog( - contentPadding: EdgeInsets.all(MediaQuery.of(context).size.width*(15/428)), - content: Column( - mainAxisSize: MainAxisSize.min, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Text( - 'Lab Values', - style: TextStyle( - color: Color(0xffB0A6C2), - fontFamily: 'Brandon-bld', - fontSize: (MediaQuery.of(context).size.height) * (18 / 926), - ), - ), - IconButton(icon:Icon(Icons.cancel),iconSize:23,color: Color(0xFF3F2668),onPressed: () { - Navigator.of(context).pop(); - },), - ], - ), - Divider(), - Text(_labValues), - ], - ), - ), - ); - } Widget moreMenu() { return Container( width: (MediaQuery.of(context).size.width) * 0.3, @@ -771,12 +961,12 @@ class _QuizModuleState extends State with WidgetsBindingObserver{ end: Alignment.bottomLeft, colors: [Color(0xff3F2668), Color(0xff482384)])), child: ListView( - // Remove padding + // Remove padding padding: EdgeInsets.zero, children: [ Container( - padding: EdgeInsets.only( - top: MediaQuery.of(context).padding.top), + padding: + EdgeInsets.only(top: MediaQuery.of(context).padding.top), height: (MediaQuery.of(context).size.height), color: Colors.transparent, child: Column( @@ -790,7 +980,7 @@ class _QuizModuleState extends State with WidgetsBindingObserver{ ), SizedBox( height: - (MediaQuery.of(context).size.height) * (47 / 926), + (MediaQuery.of(context).size.height) * (47 / 926), ), InkWell( onTap: () { @@ -802,95 +992,95 @@ class _QuizModuleState extends State with WidgetsBindingObserver{ // ); final result = Navigator.push( context, - MaterialPageRoute(builder: (context) => SearchListExample()), + MaterialPageRoute( + builder: (context) => SearchListExample()), ); }, child: Container( - alignment: Alignment.center, - child: Column( - children: [ - SvgPicture.asset( - 'assets/Images/lab.svg', - height: (MediaQuery.of(context).size.height) * - (37 / 926), - color: Colors.white, - ), - SizedBox( - height: (MediaQuery.of(context).size.height) * - (10 / 926), - ), - Text( - 'Lab Values', - style: TextStyle( - color: Colors.white, - fontFamily: 'Brandon-bld', - fontSize: + alignment: Alignment.center, + child: Column( + children: [ + SvgPicture.asset( + 'assets/Images/lab.svg', + height: (MediaQuery.of(context).size.height) * + (37 / 926), + color: Colors.white, + ), + SizedBox( + height: (MediaQuery.of(context).size.height) * + (10 / 926), + ), + Text( + 'Lab Values', + style: TextStyle( + color: Colors.white, + fontFamily: 'Brandon-bld', + fontSize: (MediaQuery.of(context).size.height) * (15 / 926), - ), - ) - ], - ), - ) + ), + ) + ], + ), + ) - //Divider(), - ), + //Divider(), + ), SizedBox( height: - (MediaQuery.of(context).size.height) * (47 / 926), + (MediaQuery.of(context).size.height) * (47 / 926), ), InkWell( - onTap: () { - Navigator.of(context).pop(); - // bookmarkQuestion - showDialog( - context: context, - builder: (BuildContext context) => - bookmarkQuestion(context), - ); - }, + onTap: () { + Navigator.of(context).pop(); + // bookmarkQuestion + showDialog( + context: context, + builder: (BuildContext context) => + bookmarkQuestion(context), + ); + }, child: Container( - alignment: Alignment.center, - child: Column( - children: [ - Icon( - Icons.bookmark, - size: 37, - color: Colors.white, - ), - SizedBox( - height: (MediaQuery.of(context).size.height) * - (10 / 926), - ), - Text( - 'Bookmarks', - style: TextStyle( - color: Colors.white, - fontFamily: 'Brandon-bld', - fontSize: + alignment: Alignment.center, + child: Column( + children: [ + Icon( + Icons.bookmark, + size: 37, + color: Colors.white, + ), + SizedBox( + height: (MediaQuery.of(context).size.height) * + (10 / 926), + ), + Text( + 'Bookmarks', + style: TextStyle( + color: Colors.white, + fontFamily: 'Brandon-bld', + fontSize: (MediaQuery.of(context).size.height) * (15 / 926), - ), - ) - ], - ), - ) + ), + ) + ], + ), + ) - //Divider(), - ), + //Divider(), + ), SizedBox( height: - (MediaQuery.of(context).size.height) * (47 / 926), + (MediaQuery.of(context).size.height) * (47 / 926), ), InkWell( onTap: () { Navigator.of(context).pop(); - showDialog( - context: context, - builder: (BuildContext context) => - notes(context), - ); - }, + showDialog( + context: context, + builder: (BuildContext context) => notes(context), + ); + }, child: Container( alignment: Alignment.center, child: Column( @@ -901,9 +1091,8 @@ class _QuizModuleState extends State with WidgetsBindingObserver{ color: Colors.white, ), SizedBox( - height: - (MediaQuery.of(context).size.height) * - (10 / 926), + height: (MediaQuery.of(context).size.height) * + (10 / 926), ), Text( 'Notes', @@ -911,96 +1100,219 @@ class _QuizModuleState extends State with WidgetsBindingObserver{ color: Colors.white, fontFamily: 'Brandon-bld', fontSize: - (MediaQuery.of(context).size.height) * - (15 / 926), + (MediaQuery.of(context).size.height) * + (15 / 926), ), ) ], ), ) - //Divider(), - ), - SizedBox( - height: - (MediaQuery.of(context).size.height) * (47 / 926), - ), - InkWell( - onTap:() {Navigator.of(context).pop(); - showDialog( - context: context, - builder: (BuildContext context) => - Calculator(), - );}, - child: Container( - alignment: Alignment.center, - child: Column( - children: [ - SvgPicture.asset('assets/Images/calculator.svg', - height: (MediaQuery.of(context).size.height) * - (37 / 926)), - SizedBox( - height: (MediaQuery.of(context).size.height) * - (10 / 926), - ), - Text( - 'Calculator', - style: TextStyle( - color: Colors.white, - fontFamily: 'Brandon-bld', - fontSize: - (MediaQuery.of(context).size.height) * - (15 / 926), - ), - ) - ], - ), - )), - SizedBox( - height: - (MediaQuery.of(context).size.height) * (47 / 926), - ), - InkWell( - onTap: () { - Navigator.of(context).pop(); - setState(() { - _showTextZoom = true; - }); - }, - child: Container( - alignment: Alignment.center, - child: Column( - children: [ - SvgPicture.asset('assets/Images/zoom.svg', - height: (MediaQuery.of(context).size.height) * - (37 / 926)), - SizedBox( - height: (MediaQuery.of(context).size.height) * - (10 / 926), - ), - Text( - 'Text Zoom', - style: TextStyle( - color: Colors.white, - fontFamily: 'Brandon-bld', - fontSize: - (MediaQuery.of(context).size.height) * - (15 / 926), - ), - ) - ], - ), - )) - ], - ), - ), - ]), - ))); + //Divider(), + ), + SizedBox( + height: + (MediaQuery.of(context).size.height) * (47 / 926), + ), + InkWell( + onTap: () { + Navigator.of(context).pop(); + showDialog( + context: context, + builder: (BuildContext context) => Calculator(), + ); + }, + child: Container( + alignment: Alignment.center, + child: Column( + children: [ + SvgPicture.asset('assets/Images/calculator.svg', + height: + (MediaQuery.of(context).size.height) * + (37 / 926)), + SizedBox( + height: (MediaQuery.of(context).size.height) * + (10 / 926), + ), + Text( + 'Calculator', + style: TextStyle( + color: Colors.white, + fontFamily: 'Brandon-bld', + fontSize: + (MediaQuery.of(context).size.height) * + (15 / 926), + ), + ) + ], + ), + )), + SizedBox( + height: + (MediaQuery.of(context).size.height) * (47 / 926), + ), + InkWell( + onTap: () { + Navigator.of(context).pop(); + setState(() { + _showTextZoom = true; + }); + }, + child: Container( + alignment: Alignment.center, + child: Column( + children: [ + SvgPicture.asset('assets/Images/zoom.svg', + height: + (MediaQuery.of(context).size.height) * + (37 / 926)), + SizedBox( + height: (MediaQuery.of(context).size.height) * + (10 / 926), + ), + Text( + 'Text Zoom', + style: TextStyle( + color: Colors.white, + fontFamily: 'Brandon-bld', + fontSize: + (MediaQuery.of(context).size.height) * + (15 / 926), + ), + ) + ], + ), + )) + ], + ), + ), + ]), + ))); + } + + Widget bookmarkQuestion(BuildContext context) { + return SizedBox( + child: AlertDialog( + contentPadding: + EdgeInsets.all(MediaQuery.of(context).size.width * (15 / 428)), + content: Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + 'Bookmark', + style: TextStyle( + color: Colors.grey, + fontFamily: 'Brandon-bld', + fontSize: (MediaQuery.of(context).size.height) * (20 / 926), + ), + ), + IconButton( + icon: Icon(Icons.close), + iconSize: 20, + color: Colors.grey, + onPressed: () { + Navigator.of(context).pop(); + }, + ), + ], + ), + Divider(), + Text( + "Are you sure you want to bookmark this question?", + style: TextStyle( + color: Colors.grey, + fontFamily: 'Brandon-med', + fontSize: (MediaQuery.of(context).size.height) * (20 / 926), + ), + ), + ], + ), + actions: [ + Divider(), + Row( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + TextButton( + onPressed: () { + Navigator.of(context).pop(); + }, + child: Text('No', + style: TextStyle( + color: Color(0xff482384), + fontFamily: 'Brandon-bld', + fontSize: + (MediaQuery.of(context).size.height) * (21 / 926), + )), + ), + Divider(), + TextButton( + onPressed: () { + Navigator.of(context).pop(); + print(questionsData["id"]![questionNumber].toString()); + BookmarkQuestionAPI(); + }, + child: Text('Yes', + style: TextStyle( + color: Color(0xff482384), + fontFamily: 'Brandon-bld', + fontSize: + (MediaQuery.of(context).size.height) * (21 / 926), + )), + ), + ], + ), + ], + ), + ); + } + + Widget labValues(BuildContext context) { + return SizedBox( + child: AlertDialog( + contentPadding: + EdgeInsets.all(MediaQuery.of(context).size.width * (15 / 428)), + content: Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + 'Lab Values', + style: TextStyle( + color: Color(0xffB0A6C2), + fontFamily: 'Brandon-bld', + fontSize: (MediaQuery.of(context).size.height) * (18 / 926), + ), + ), + IconButton( + icon: Icon(Icons.cancel), + iconSize: 23, + color: Color(0xFF3F2668), + onPressed: () { + Navigator.of(context).pop(); + }, + ), + ], + ), + Divider(), + Text(_labValues), + ], + ), + ), + ); } + Widget notes(BuildContext context) { return SizedBox( child: AlertDialog( - contentPadding: EdgeInsets.all(MediaQuery.of(context).size.width*(15/428)), + contentPadding: + EdgeInsets.all(MediaQuery.of(context).size.width * (15 / 428)), content: Column( mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.start, @@ -1011,27 +1323,34 @@ class _QuizModuleState extends State with WidgetsBindingObserver{ Text( 'Take Notes', style: TextStyle( - color: Color(0xffB0A6C2), + color: Colors.grey, fontFamily: 'Brandon-bld', - fontSize: (MediaQuery.of(context).size.height) * (18 / 926), + fontSize: (MediaQuery.of(context).size.height) * (20 / 926), ), ), - IconButton(icon:Icon(Icons.cancel),iconSize:23,color: Color(0xFF3F2668),onPressed: () { - Navigator.of(context).pop(); - },), + IconButton( + icon: Icon(Icons.close), + iconSize: 25, + color: Colors.grey, + onPressed: () { + Navigator.of(context).pop(); + }, + ), ], ), Divider(), TextField( controller: _textController, keyboardType: TextInputType.multiline, - minLines: 1,//Normal textInputField will be displayed - maxLines: 5,// when user presses enter it will adapt to it + //minLines: 2,//Normal textInputField will be displayed + maxLines: 5, // when user presses enter it will adapt to it decoration: InputDecoration( hintText: "Add notes here...", - hintStyle: TextStyle(color: Color(0xffAEAEAE), - fontSize: (MediaQuery.of(context).size.height)*(15/926), - fontFamily: 'Brandon-med',), + hintStyle: TextStyle( + color: Colors.grey, + fontSize: (MediaQuery.of(context).size.height) * (16 / 926), + fontFamily: 'Brandon-med', + ), contentPadding: EdgeInsets.fromLTRB(2.0, 1, 2.0, 1), focusedBorder: OutlineInputBorder( borderSide: BorderSide( @@ -1041,8 +1360,8 @@ class _QuizModuleState extends State with WidgetsBindingObserver{ ), ), style: TextStyle( - color: Colors.black, - fontSize: (MediaQuery.of(context).size.height)*(15/926), + color: Colors.grey, + fontSize: (MediaQuery.of(context).size.height) * (16 / 926), fontFamily: 'Brandon-med', ), onChanged: (String value) { @@ -1051,98 +1370,175 @@ class _QuizModuleState extends State with WidgetsBindingObserver{ }); }, ), + SizedBox( + height: MediaQuery.of(context).size.height * 15 / 926, + ), Row( mainAxisAlignment: MainAxisAlignment.end, children: [ - IconButton(onPressed:(){ - setState((){ - _note=''; - _textController.clear(); - } - ); - } , iconSize: 21 ,icon: Icon(Icons.refresh,color: Color(0xFF3F2668))), - TextButton( - onPressed: () { - addNotesAPI(); - _textController.clear(); - Navigator.of(context).pop(); - }, - style: TextButton.styleFrom( - padding: EdgeInsets.zero,), + InkWell( child: Container( - height: (MediaQuery.of(context).size.height) * (31 / 926), - width:(MediaQuery.of(context).size.width) * (97 / 428), - decoration: BoxDecoration(borderRadius:BorderRadius.circular(4),color: Color(0xFFDDDAE2),), - child:Row( - mainAxisAlignment: MainAxisAlignment.center, - children:[ - Icon(Icons.save,color: Color(0xFF3F2668),), - SizedBox( - height: (MediaQuery.of(context).size.width) * - (14 / 428), + margin: EdgeInsets.symmetric( + horizontal: + (MediaQuery.of(context).size.width) * (25 / 428)), + height: (MediaQuery.of(context).size.height) * (35 / 926), + width: (MediaQuery.of(context).size.width) * (100 / 428), + decoration: BoxDecoration( + borderRadius: BorderRadius.circular( + (MediaQuery.of(context).size.height) * (8 / 926)), + ), + child: TextButton( + style: TextButton.styleFrom(padding: EdgeInsets.zero,), + onPressed: () { + setState(() { + _note = ''; + _textController.clear(); + }); + }, + child: Center( + child: Text( + "Refresh", + style: TextStyle( + color: Color(0xff482384), + fontFamily: 'Brandon-med', + fontSize: (MediaQuery.of(context).size.height) * + (20 / 926), + ), + ), ), - Text( - 'Save', - style: TextStyle( - color: Color(0xff3F2668), - fontFamily: 'Brandon-bld', - fontSize: (MediaQuery.of(context).size.height) * (19 / 926), + ), + ), + ), + InkWell( + child: Container( + margin: EdgeInsets.symmetric( + horizontal: + (MediaQuery.of(context).size.width) * (25 / 428)), + height: (MediaQuery.of(context).size.height) * (35 / 926), + width: (MediaQuery.of(context).size.width) * (100 / 428), + decoration: BoxDecoration( + + borderRadius: BorderRadius.circular( + (MediaQuery.of(context).size.height) * (8 / 926)), + ), + child: TextButton( + style: TextButton.styleFrom(padding: EdgeInsets.zero,), + onPressed: () { + addNotesAPI(); + _textController.clear(); + Navigator.of(context).pop(); + }, + child: Center( + child: Text( + "Save", + style: TextStyle( + color: Color(0xff482384), + fontFamily: 'Brandon-med', + fontSize: (MediaQuery.of(context).size.height) * + (20 / 926), + ), ), ), - ]) - ),) + ), + ), + ), ], - ) + ), ], ), - ),);} + ), + ); + } + + _onQuitReviewed() async { + return (await showDialog( + context: context, + builder: (context) => AlertDialog( + content: Text( + 'Are you sure you want to go back?', + style: TextStyle( + color: Colors.grey, + fontFamily: 'Brandon-med', + fontSize: (MediaQuery.of(context).size.height) * (18 / 926), + ), + ), + actions: [ + TextButton( + onPressed: () async { + Navigator.of(context).pop(); + }, + child: Text('No', + style: TextStyle( + color: Color(0xff482384), + fontFamily: 'Brandon-bld', + fontSize: + (MediaQuery.of(context).size.height) * (21 / 926), + )), + ), + TextButton( + onPressed: () async { + // await SaveQuizAPI("completed", true); + Navigator.of(context) + .popUntil(ModalRoute.withName("/home")); + // final result1 = Navigator.push( + // context, + // MaterialPageRoute(builder: (context) => PreviousQuiz()), + // ); + }, + child: Text('Yes', + style: TextStyle( + color: Color(0xff482384), + fontFamily: 'Brandon-bld', + fontSize: + (MediaQuery.of(context).size.height) * (21 / 926), + )), + ), + ], + ), + )) ?? + false; + } + Future _onQuit() async { return (await showDialog( - context: context, - builder: (context) => AlertDialog( - content: Text( - 'Mark Quiz as', - style: TextStyle( - color: Color(0xffA1A1A1), - fontFamily: 'Brandon-bld', - fontSize: (MediaQuery.of(context).size.height) * (21 / 926), - ), - ), - actions: [ - TextButton( - onPressed: () async { - await SaveQuizAPI("suspended", true); - // ScaffoldMessenger.of(context) - // ..removeCurrentSnackBar() - // ..showSnackBar(SnackBar(content: Text("The Quiz has been saved as Suspended!"))); - // Navigator.of(context).pop(); - // Navigator.of(context).pop(); - }, - child: Text('Suspended', - style: TextStyle( - color: Color(0xff3F2668), - fontFamily: 'Brandon-bld', - fontSize: - (MediaQuery.of(context).size.height) * (21 / 926), - )), - ), - TextButton( - onPressed: () async { - await SaveQuizAPI("completed", true); - // Navigator.of(context).pop(); - // Navigator.of(context).pop(); // Uncomment when "completed" and omittedQuestionsArray work again. - }, - child: Text('Completed', - style: TextStyle( - color: Color(0xff3F2668), - fontFamily: 'Brandon-bld', - fontSize: - (MediaQuery.of(context).size.height) * (21 / 926), - )), - ), - ], + context: context, + builder: (context) => AlertDialog( + content: Text( + 'Mark Quiz as', + style: TextStyle( + color: Colors.grey, + fontFamily: 'Brandon-med', + fontSize: (MediaQuery.of(context).size.height) * (18 / 926), + ), + ), + actions: [ + TextButton( + onPressed: () async { + await SaveQuizAPI("suspended", true); + }, + child: Text('Suspended', + style: TextStyle( + color: Color(0xff482384), + fontFamily: 'Brandon-bld', + fontSize: + (MediaQuery.of(context).size.height) * (21 / 926), + )), + ), + TextButton( + onPressed: () async { + await SaveQuizAPI("completed", true); + }, + child: Text('Completed', + style: TextStyle( + color: Color(0xff482384), + fontFamily: 'Brandon-bld', + fontSize: + (MediaQuery.of(context).size.height) * (21 / 926), + )), ), - )) ?? + ], + ), + )) ?? false; } @@ -1155,14 +1551,36 @@ class _QuizModuleState extends State with WidgetsBindingObserver{ super.dispose(); } + @override Widget build(BuildContext context) { + Future.delayed(Duration(seconds: 1), () { + if (questionsData['eachQuestionTimer']!.length > 0) { + if ((questionsData['eachQuestionTimer'] != null) & + (questionsData['eachQuestionTimer'] != [])) { + questionsData['eachQuestionTimer']![questionNumber] = + questionsData['eachQuestionTimer']![questionNumber] + 1; + // print("eachQuestionTimer " + questionsData['eachQuestionTimer'].toString()); + } + } + }); return WillPopScope( onWillPop: () async { // ScaffoldMessenger.of(context) // ..removeCurrentSnackBar() // ..showSnackBar(SnackBar(content: Text("Click on Quit Quiz!"))); - return true; + if(widget.whatsDone == "resumed") { + if(_resumeQuizSuccessful.data.previousQuizzes[0].quizMeta.quizStatus == "completed") { + _onQuitReviewed(); + } + else if(_resumeQuizSuccessful.data.previousQuizzes[0].quizMeta.quizStatus == "suspended") { + _onQuit(); + } + } + else if(widget.whatsDone == "new") { + _onQuit(); + } + return false; }, child: Scaffold( resizeToAvoidBottomInset: false, @@ -1297,7 +1715,7 @@ class _QuizModuleState extends State with WidgetsBindingObserver{ width: (MediaQuery.of(context).size.width) * (39 / 428), ), // for timer - Container( + hasDataLoaded == false ? Container() : Container( height: (MediaQuery.of(context).size.height) * (25 / 926), width: (MediaQuery.of(context).size.width) * (87 / 428), color: Color(0xFF3F2668), @@ -1318,6 +1736,7 @@ class _QuizModuleState extends State with WidgetsBindingObserver{ fontSize: (MediaQuery.of(context).size.height) * (13 / 926), ), + // widget.whatsDone == "new" ? (widget.totalQuestions * 120) : widget.whatsDone == "resumed" ? ((int.parse(_resumeQuizSuccessful.data.previousQuizzes[0].quizMeta.quizTime) <= (widget.totalQuestions * 120)) ? ((widget.totalQuestions * 120) - (int.parse(_resumeQuizSuccessful.data.previousQuizzes[0].quizMeta.quizTime))) : 1) : 1, // endTime, endTime: endTime, onEnd: onEnd, endWidget: Text( @@ -1332,7 +1751,7 @@ class _QuizModuleState extends State with WidgetsBindingObserver{ ), ], ), - ) + ), ], ), SizedBox( @@ -1357,42 +1776,172 @@ class _QuizModuleState extends State with WidgetsBindingObserver{ TextButton( onPressed: () { // print("i: " + i.toString()); - if(questionsData["answeredCorrectly"]![questionNumber] == "notAnswered") { - int? indexOfOptionThatIsActuallyCorrect; - int? correct; - // whichOption = i; optionSelectedInt - setState(() { - questionsData["optionSelectedInt"]![questionNumber] = i; - }); - int j = 0; - for(j = 0; j<10; j++) { - if(questionsData["options"]![questionNumber][i].toString() == questionsData["options"]![questionNumber][j].toString()) { - break; - } - } - if(questionsData["statistics"]![questionNumber][j] == 1) { - setState(() { - questionsData["answeredCorrectly"]![questionNumber] = "correct"; - }); - correct = 1; - // print("correct: " + correct.toString()); - // print(questionsData["answeredCorrectly"]); - } - else if(questionsData["statistics"]![questionNumber][j] == 0) { + + if(widget.whatsDone == + "new") { + if (questionsData[ + "answeredCorrectly"]![ + questionNumber] == + "notAnswered") { + int? + indexOfOptionThatIsActuallyCorrect; + int? correct; + // whichOption = i; optionSelectedInt setState(() { - questionsData["answeredCorrectly"]![questionNumber] = "incorrect"; + questionsData[ + "optionSelectedInt"]![ + questionNumber] = i; }); - correct = 0; - // print(questionsData["answeredCorrectly"]); + int j = 0; + for (j = 0; + j < 10; + j++) { + if (questionsData["options"]![ + questionNumber] + [i] + .toString() == + questionsData[ + "options"]![ + questionNumber][j] + .toString()) { + break; + } + } + if (questionsData[ + "statistics"]![ + questionNumber][j] == + 1) { + setState(() { + questionsData[ + "answeredCorrectly"]![ + questionNumber] = + "correct"; + }); + correct = 1; + // print("correct: " + correct.toString()); + // print(questionsData["answeredCorrectly"]); + } else if (questionsData[ + "statistics"]![ + questionNumber][j] == + 0) { + setState(() { + questionsData[ + "answeredCorrectly"]![ + questionNumber] = + "incorrect"; + }); + correct = 0; + // print(questionsData["answeredCorrectly"]); + } + for (int c = 0; + c < + questionsData[ + "statistics"]![ + questionNumber] + .length; + c++) { + if (questionsData[ + "statistics"]![ + questionNumber][c] == + 1) { + indexOfOptionThatIsActuallyCorrect = + c; + // print("indexOfOptionThatIsActuallyCorrect: " + indexOfOptionThatIsActuallyCorrect.toString()); + break; + } + } + submitAnswerAPI( + indexOfOptionThatIsActuallyCorrect, + correct, + i); } - for(int c = 0; c with WidgetsBindingObserver{ children: [ TextButton( onPressed: () { - // print("i: " + i.toString()); - // if(questionsData["answeredCorrectly"]![questionNumber] == "notAnswered") { - if((questionsData["answeredCorrectly"]![questionNumber] == "notAnswered") || (questionsData["answeredCorrectly"]![questionNumber] != "notAnswered")) { - int? indexOfOptionThatIsActuallyCorrect; - int? correct; - // whichOption = i; optionSelectedInt - setState(() { - questionsData["optionSelectedInt"]![questionNumber] = i; - }); - int j = 0; - for(j = 0; j<10; j++) { - if(questionsData["options"]![questionNumber][i].toString() == questionsData["options"]![questionNumber][j].toString()) { - break; - } - } - if(questionsData["statistics"]![questionNumber][j] == 1) { + if (widget.whatsDone == + "new") { + // print("i: " + i.toString()); + // if(questionsData["answeredCorrectly"]![questionNumber] == "notAnswered") { + if ((questionsData[ + "answeredCorrectly"]![ + questionNumber] == + "notAnswered") || + (questionsData[ + "answeredCorrectly"]![ + questionNumber] != + "notAnswered")) { + int? + indexOfOptionThatIsActuallyCorrect; + int? correct; + // whichOption = i; optionSelectedInt setState(() { - questionsData["answeredCorrectly"]![questionNumber] = "correct"; + questionsData[ + "optionSelectedInt"]![ + questionNumber] = i; }); - correct = 1; - // print("correct: " + correct.toString()); - // print(questionsData["answeredCorrectly"]); - } - else if(questionsData["statistics"]![questionNumber][j] == 0) { + int j = 0; + for (j = 0; + j < 10; + j++) { + if (questionsData["options"]![ + questionNumber] + [i] + .toString() == + questionsData[ + "options"]![ + questionNumber][j] + .toString()) { + break; + } + } + if (questionsData[ + "statistics"]![ + questionNumber][j] == + 1) { + setState(() { + questionsData[ + "answeredCorrectly"]![ + questionNumber] = + "correct"; + }); + correct = 1; + // print("correct: " + correct.toString()); + // print(questionsData["answeredCorrectly"]); + } else if (questionsData[ + "statistics"]![ + questionNumber][j] == + 0) { + setState(() { + questionsData[ + "answeredCorrectly"]![ + questionNumber] = + "incorrect"; + }); + correct = 0; + // print(questionsData["answeredCorrectly"]); + } + for (int c = 0; + c < + questionsData["statistics"]![ + questionNumber] + .length; + c++) { + if (questionsData[ + "statistics"]![ + questionNumber][c] == + 1) { + indexOfOptionThatIsActuallyCorrect = + c; + // print("indexOfOptionThatIsActuallyCorrect: " + indexOfOptionThatIsActuallyCorrect.toString()); + break; + } + } + print(questionsData[ + "answeredCorrectly"]); + var addToSelectedOptionsArrayExam = + { + "index": questionsData[ + "id"]![ + questionNumber] + .toString(), + "Correctanswerindex": + indexOfOptionThatIsActuallyCorrect + .toString(), // indexOfOptionThatIsActuallyCorrect + "correct": correct, // Correct = 1 if answer is correct, -1 if answer is omitted and 0 if answer is incorrect + "optionIndexSelected": + i.toString(), + "time": questionsData[ + "eachQuestionTimer"]![ + questionNumber] + .toString() + }; setState(() { - questionsData["answeredCorrectly"]![questionNumber] = "incorrect"; + questionsData["SelectedOptionsArray"]![questionNumber] = + addToSelectedOptionsArrayExam; }); - correct = 0; - // print(questionsData["answeredCorrectly"]); + // submitAnswerAPI(indexOfOptionThatIsActuallyCorrect, correct, i); } - for(int c = 0; c with WidgetsBindingObserver{ (13 / 926), //38, ), ), - onTap: () => _onQuit())), + onTap: () { + if(widget.whatsDone == "resumed") { // + if(_resumeQuizSuccessful.data.previousQuizzes[0].quizMeta.quizStatus == "completed") { + _onQuitReviewed(); + } + else if(_resumeQuizSuccessful.data.previousQuizzes[0].quizMeta.quizStatus == "suspended") { + _onQuit(); + } + } + else if(widget.whatsDone == "new") { + _onQuit(); + } + })), ], ), SizedBox( diff --git a/lib/screens/home.dart b/lib/screens/home.dart index 503f884..37cae26 100644 --- a/lib/screens/home.dart +++ b/lib/screens/home.dart @@ -1,167 +1,471 @@ -import 'dart:async'; import 'dart:convert'; +import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; -import 'package:flutter_svg/svg.dart'; +import 'package:http/http.dart' as http; import 'package:shared_preferences/shared_preferences.dart'; -import 'package:testify/auth_storage.dart'; +import 'package:testify/models/DashboardStatsModel/dashboard_stats_model.dart'; import 'package:testify/screens/Authentication/login.dart'; -import 'package:testify/screens/Welcome/side_menu_bar.dart'; -import 'package:testify/screens/Welcome/QuizModule/search_bar.dart'; -import 'package:http/http.dart' as http; +import 'package:testify/screens/Welcome/GenerateQuiz/generate_quiz.dart'; +import 'package:testify/screens/Welcome/Notes/notes.dart'; +import 'package:testify/screens/Welcome/PreviousQuiz/previous_quiz.dart'; +import 'dart:math'; +import 'package:fl_chart/fl_chart.dart'; class Home extends StatefulWidget { - const Home({Key? key}) : super(key: key); - @override _HomeState createState() => _HomeState(); } -class _HomeState extends State with WidgetsBindingObserver{ +class _HomeState extends State { + var performance=0.75; + var scaffoldKey = GlobalKey(); + + int selectedIndex=0; AppLifecycleState? _lastLifecycleState; + var _token; + var _userId; + var _getDashboardStatsSuccessful; + bool _hasDataLoaded = false; + int _allQuizScoreLength = 0; + + final _duration = const Duration(milliseconds: 450); + @override void initState() { super.initState(); - WidgetsBinding.instance!.addObserver(this); + getDashboardStatsAPI(); + } + + Future getDashboardStatsAPI() async { + SharedPreferences prefs = await SharedPreferences.getInstance(); + const String apiUrlGetDashboardStats = + "https://demo.pookidevs.com/user/getDashboardStats"; + _token = prefs.getString('token')!; + _userId = prefs.getInt("userId")!; + http.get( + Uri.parse(apiUrlGetDashboardStats), + headers: { + 'Content-type': 'application/json; charset=UTF-8', + 'Authorization': _token.toString(), + }, + ).then((response) { + // print(jsonDecode(response.body).toString()); + if (response.statusCode == 200) { + if (json.decode(response.body).toString().substring(0, 20) == + "{data: {status: true") { + final responseString = (response.body); + var DashboardStatsSuccessful = dashboardStatsModelFromJson(responseString); + final DashboardStatsModel getDashboardStatsSuccessful = DashboardStatsSuccessful; + setState(() { + _getDashboardStatsSuccessful = getDashboardStatsSuccessful; + //print(_getDashboardStatsSuccessful.data.allQuizScores.length); + _allQuizScoreLength = _getDashboardStatsSuccessful.data.allQuizScores.length; + print(_getDashboardStatsSuccessful.data.allQuizScores); + _hasDataLoaded = true; + }); + // print(_questions); + } else {} + } else { + //Token is Invalid + if (json.decode(response.body).toString().substring(0, 14) == + "{status: false") { + ScaffoldMessenger.of(context) + ..removeCurrentSnackBar() + ..showSnackBar(const SnackBar(content: Text("Token Expired!"))); + final result = Navigator.pushAndRemoveUntil( + context, + MaterialPageRoute( + builder: (BuildContext context) => + const Login(fromWhere: "Home")), + ModalRoute.withName('/'), + ); + } else {} + } + }); } @override void dispose() { - WidgetsBinding.instance!.removeObserver(this); super.dispose(); } - @override - void didChangeAppLifecycleState(AppLifecycleState state) async { - super.didChangeAppLifecycleState(state); - - // if(state == AppLifecycleState.detached){ - // - // } - - final isBackground = state == AppLifecycleState.paused; - final isClosed = state == AppLifecycleState.detached; - if(isBackground) { - print("xD in Background"); - - - - } - if(isClosed) { - print("xD Closed"); - - - } + _logoutAlertDialog() async { + return (await showDialog( + context: context, + builder: (context) => AlertDialog( + content: Text( + 'Are you sure you want to go Logout?', + style: TextStyle( + color: Colors.grey, + fontFamily: 'Brandon-med', + fontSize: (MediaQuery.of(context).size.height) * (18 / 926), + ), + ), + actions: [ + TextButton( + onPressed: () async { + Navigator.of(context).pop(); + }, + child: Text('No', + style: TextStyle( + color: Color(0xff3F2668), + fontFamily: 'Brandon-bld', + fontSize: + (MediaQuery.of(context).size.height) * (21 / 926), + )), + ), + TextButton( + onPressed: () async { + final result = Navigator.pushAndRemoveUntil( + context, + MaterialPageRoute( + builder: (BuildContext context) => + const Login(fromWhere: "Home")), + ModalRoute.withName('/'), + ); + }, + child: Text('Yes', + style: TextStyle( + color: Color(0xff3F2668), + fontFamily: 'Brandon-bld', + fontSize: + (MediaQuery.of(context).size.height) * (21 / 926), + )), + ), + ], + ), + )) ?? + false; } + @override Widget build(BuildContext context) { + var h=MediaQuery.of(context).size.height/926; + var w=MediaQuery.of(context).size.width/428; return WillPopScope( onWillPop: () async { - ScaffoldMessenger.of(context) - ..removeCurrentSnackBar() - ..showSnackBar(SnackBar(content: Text("Press Logout Button"))); + _logoutAlertDialog(); return false; }, child: Scaffold( - backgroundColor: Colors.white, - drawer: SideMenuBar(), - appBar: AppBar( - backgroundColor: Color(0xff3F2668), - elevation: 2, - centerTitle: true, - flexibleSpace: Container( - decoration: BoxDecoration( - gradient: LinearGradient( - begin: Alignment.topCenter, - end: Alignment.bottomCenter, - colors: [ - Color(0xff7F1AF1), - Color(0xff482384) - ]) - ), - ), - title: const Text("Home", - style: TextStyle( - color: Color(0xffFFFEFE), - fontFamily: 'Brandon-bld', - ), - ), - actions: [ - TextButton( - onPressed: () async { - // Use this where ever Navigated to Login - final result = Navigator.pushAndRemoveUntil( - context, - MaterialPageRoute(builder: (BuildContext context) => const Login(fromWhere:"Home")), - ModalRoute.withName('/'), - ); - - }, - child: SvgPicture.asset( - "assets/Images/logout.svg", - height: (MediaQuery.of(context).size.height) *(32/926), + backgroundColor: Color(0xff3F2668), + body: SingleChildScrollView( + child: Column( + children: [ + Stack( + children:[ + Container(height: h*130,alignment: Alignment.topCenter,decoration: BoxDecoration(gradient: LinearGradient(colors: [Color(0xff7F1AF1),Color(0xff482384)]),borderRadius: BorderRadius.only( + bottomLeft: Radius.elliptical(30,8), + bottomRight: Radius.elliptical(30,8), + ),)), + Container(padding:EdgeInsets.only(top: h*60,left:w*19 ),decoration: BoxDecoration(shape: BoxShape.circle),child: Icon(Icons.circle,size:w*88,color: Colors.white,),), + Padding( + padding: EdgeInsets.only(top:h*87,left: w*117), + child: Text('Welcome Alen!',style: TextStyle( color: Colors.white.withOpacity(0.9), + fontFamily: 'Brandon-med', + fontSize: h * 22),), + ) + ]), + SizedBox(height: h*16,), + Container( + alignment: Alignment.centerLeft, + padding: EdgeInsets.all(h*12), + child: Text('Actions',textAlign:TextAlign.start,style: TextStyle( color: Colors.white.withOpacity(0.9), + fontFamily: 'Brandon-med', + fontSize: h * 15),), + ), + Container(height: h*86,color: Color(0xff482384), + padding: EdgeInsets.all(h*15), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + children: [ + IconButton(onPressed: () async { // Generate Quiz + final result = await Navigator.push( + context, + MaterialPageRoute( + builder: (context) => GenerateQuiz())); + }, icon: Icon(Icons.edit,color: Colors.white,)), + VerticalDivider(color: Colors.white,), + IconButton(onPressed: () async { // Previous Quiz + final result = await Navigator.push( + context, + MaterialPageRoute( + builder: (context) => PreviousQuiz())); + }, icon: Icon(Icons.quiz_outlined,color: Colors.white,)), + VerticalDivider(color: Colors.white,), + IconButton(onPressed: () async { // Notes + final result = await Navigator.push( + context, + MaterialPageRoute( + builder: (context) => Notes())); + }, icon: Icon(Icons.event_note_rounded,color: Colors.white,)), + ], + ),), + SizedBox(height: h*38,), + Container( + height: h*353, + width: w*329, + padding: EdgeInsets.all(h*10), + child: Stack( + alignment: Alignment.topLeft, + children: [ + Container( + height: h*343, + width: w*319, + margin: EdgeInsets.only(top:h*20,right: w*20), + decoration:BoxDecoration( + boxShadow:[ BoxShadow(color: Color(0xff482384)..withOpacity(0.5),offset:Offset(13,-13),blurRadius: h*2,spreadRadius: h*2),], + color: Color(0xff7F1AF1).withOpacity(0.2), + borderRadius: BorderRadius.circular(h*20) + ) + + + ), + Container( + height: h*343, + width: w*319, + margin: EdgeInsets.only(top:h*30,right: w*30), + decoration:BoxDecoration( + boxShadow:[ BoxShadow(color: Color(0xff482384).withOpacity(0.7),offset:Offset(10,-10),blurRadius: h*2,spreadRadius: h*2),], + color: Color(0xff482384).withOpacity(0.7), + borderRadius: BorderRadius.circular(h*20) + ), + child: AnimatedCrossFade( + sizeCurve: ElasticOutCurve(), + firstCurve: Curves.bounceInOut, + secondCurve: Curves.easeInBack, + crossFadeState: _hasDataLoaded ? CrossFadeState.showFirst : CrossFadeState.showSecond, + duration: _duration, + secondChild: Container(alignment: Alignment.center,height: 270,child: CircularProgressIndicator(color: Colors.white, strokeWidth: 1,)), + firstChild: Container( + color: Colors.transparent, + padding: EdgeInsets.only(top:10,left:15,right: 20,bottom: 0), + margin: EdgeInsets.only(top:10,left:10,right: 10,bottom: 0), + width: double.infinity, + height: 250, + child: LineChart( + LineChartData( + minY: 0, + maxY: 100, + gridData: FlGridData( + show: true, + getDrawingHorizontalLine: (value) { + return FlLine( + color: Color(0xff482384), + strokeWidth: 1, + ); + }, + drawVerticalLine: true, + drawHorizontalLine: true, + getDrawingVerticalLine: (value) { + return FlLine( + color: Color(0xff482384), + strokeWidth: 1, + ); + }, + ), + borderData: FlBorderData ( + show: true, + border: Border.all(color: Color(0xff482384), width: 1), + ), + titlesData: FlTitlesData( + show: true, + bottomTitles: AxisTitles( + axisNameWidget: Text(' Most Recent Quizes',style: TextStyle(color: Colors.grey,fontSize: h*12) ,), + axisNameSize: 20, + sideTitles: SideTitles( + showTitles: true, + interval: 1, + reservedSize: 20, + ), + ), + leftTitles:AxisTitles( + axisNameWidget: Text(' % Performance',style: TextStyle(color: Colors.grey,fontSize: h*12),), + axisNameSize: 20, + sideTitles: SideTitles( + showTitles: true, + interval: 20, + reservedSize:30, + ), + ), + topTitles: AxisTitles( + sideTitles: SideTitles(showTitles: false), + ), + rightTitles: AxisTitles( + sideTitles: SideTitles(showTitles: false), + ), + ), + lineBarsData: [ + LineChartBarData( + spots: [ + if(_allQuizScoreLength > 7) + for(int i = 0; i<7; i++) + FlSpot(i+1.toDouble(), double.parse(_getDashboardStatsSuccessful.data.allQuizScores[_allQuizScoreLength - 1 - i].score.toStringAsFixed(2))), + if(_allQuizScoreLength <= 7) + for(int i = 0; i<_allQuizScoreLength; i++) + FlSpot(i+1.toDouble(), double.parse(_getDashboardStatsSuccessful.data.allQuizScores[_allQuizScoreLength - 1 - i].score.toStringAsFixed(2))), + ], + isCurved: true, + color: Color(0xff482384), + barWidth: 4, + // dotData: FlDotData(show: false), + belowBarData: BarAreaData( + show: true, + gradient: LinearGradient( + begin: Alignment.topCenter, + end: Alignment.bottomCenter, + colors: [ + Colors.white.withOpacity(0.7), + Colors.white.withOpacity(0.1), + ]), + ), + ) + ]), + ), + ), + ), + ), + ], + ), + ), + SizedBox(height: h*28,), + Container( + alignment: Alignment.centerLeft, + padding: EdgeInsets.all(h*19), + child: Text('Recent Top 3 Quizzes',style: TextStyle( color: Color(0xFFFAFAFA).withOpacity(0.8), + fontFamily: 'Brandon-bld', + fontSize: h * 20),) + ), - ), - ], + Container( + height: h*60, + width:w*382, + padding: EdgeInsets.all(h*5), + decoration: BoxDecoration(borderRadius:BorderRadius.circular(h*5),gradient: LinearGradient(colors: [Color(0xff7F1AF1),Color(0xff482384)],begin: Alignment.topCenter,end: Alignment.bottomCenter ),), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Padding( + padding: EdgeInsets.all(h*10), + child: Icon(Icons.event_note_rounded,color: Colors.white,size: h*25,), + ), + Column( + crossAxisAlignment:CrossAxisAlignment.start, + children: [ + Text('Microbiology',style: TextStyle( color: Color(0xFFFAFAFA).withOpacity(0.6), + fontFamily: 'Brandon-med', + fontSize: h * 16),), + Text('You have successfully completed this quiz',style: TextStyle( color: Color(0xFFFAFAFA).withOpacity(0.8), + fontFamily: 'Brandon-med', + fontSize: h * 13),) + ],), + Container(margin:EdgeInsets.all(h*5), + decoration: const BoxDecoration( + color:Colors.transparent, + ), + height: h*50, + width: h*50, + + child: Stack(children: [Center(child: SizedBox(height: h*40,width: h*40, + child: CircularProgressIndicator(value: performance,color: Colors.white,backgroundColor:Colors.grey.withOpacity(0.2),strokeWidth: 2,))), + Center(child: Text((performance*100).toStringAsFixed(1).toString()+ ' %',style: TextStyle( + color: Colors.white, + fontFamily: 'Brandon-med', + fontSize:h*10, + ),))],),), + ],), + ), + SizedBox(height: h*20,), + Container( + height: h*60, + width:w*382, + padding: EdgeInsets.all(h*5), + decoration: BoxDecoration(borderRadius:BorderRadius.circular(h*5),gradient: LinearGradient(colors: [Color(0xff7F1AF1),Color(0xff482384)],begin: Alignment.topCenter,end: Alignment.bottomCenter ),), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Padding( + padding: EdgeInsets.all(h*10), + child: Icon(Icons.event_note_rounded,color: Colors.white,size: h*25,), + ), + Column( + crossAxisAlignment:CrossAxisAlignment.start, + children: [ + Text('Microbiology',style: TextStyle( color: Color(0xFFFAFAFA).withOpacity(0.6), + fontFamily: 'Brandon-med', + fontSize: h * 16),), + Text('You have successfully completed this quiz',style: TextStyle( color: Color(0xFFFAFAFA).withOpacity(0.8), + fontFamily: 'Brandon-med', + fontSize: h * 13),) + ],), + Container(margin:EdgeInsets.all(h*5), + decoration: const BoxDecoration( + color:Colors.transparent, + ), + height: h*50, + width: h*50, + + child: Stack(children: [Center(child: SizedBox(height: h*40,width: h*40, + child: CircularProgressIndicator(value: performance,color: Colors.white,backgroundColor:Colors.grey.withOpacity(0.2),strokeWidth: 2,))), + Center(child: Text((performance*100).toStringAsFixed(1).toString()+ ' %',style: TextStyle( + color: Colors.white, + fontFamily: 'Brandon-med', + fontSize:h*10, + ),))],),), + ],), + ), + SizedBox(height: h*20,), + Container( + height: h*60, + width:w*382, + padding: EdgeInsets.all(h*5), + decoration: BoxDecoration(borderRadius:BorderRadius.circular(h*5),gradient: LinearGradient(colors: [Color(0xff7F1AF1),Color(0xff482384)],begin: Alignment.topCenter,end: Alignment.bottomCenter ),), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Padding( + padding: EdgeInsets.all(h*10), + child: Icon(Icons.event_note_rounded,color: Colors.white,size: h*25,), + ), + Column( + crossAxisAlignment:CrossAxisAlignment.start, + children: [ + Text('Microbiology',style: TextStyle( color: Color(0xFFFAFAFA).withOpacity(0.6), + fontFamily: 'Brandon-med', + fontSize: h * 16),), + Text('You have successfully completed this quiz',style: TextStyle( color: Color(0xFFFAFAFA).withOpacity(0.8), + fontFamily: 'Brandon-med', + fontSize: h * 13),) + ],), + Container(margin:EdgeInsets.all(h*5), + decoration: const BoxDecoration( + color:Colors.transparent, + ), + height: h*50, + width: h*50, + + child: Stack(children: [Center(child: SizedBox(height: h*40,width: h*40, + child: CircularProgressIndicator(value: performance,color: Colors.white,backgroundColor:Colors.grey.withOpacity(0.2),strokeWidth: 2,))), + Center(child: Text((performance*100).toStringAsFixed(1).toString()+ ' %',style: TextStyle( + color: Colors.white, + fontFamily: 'Brandon-med', + fontSize:h*10, + ),))],),), + ],), + ), + SizedBox(height: h*80,), + ], + + ), ), - // body: TextButton( - // onPressed: () async { - // // final result = Navigator.push( - // // context, - // // MaterialPageRoute(builder: (context) => SearchListExample()), - // // ); - // - // - // SharedPreferences prefs = await SharedPreferences.getInstance(); - // var quizID = prefs.getInt("quizId"); - // var _token = prefs.getString('token')!; - // // print(quizID); - // final String apiUrlGenerateQuiz = "https://demo.pookidevs.com/quiz/solver/saveQuiz"; - // await http.post(Uri.parse(apiUrlGenerateQuiz), headers: { - // 'Content-type': 'application/json; charset=UTF-8', 'Authorization' : _token.toString(), - // }, body: json.encode( - // { - // "data": - // { - // "quiz" : { - // "quizId": 387155.toString(), - // "quizTitle": "First quiz", - // "quizDate": DateTime.now().toString(), - // "quizScore": "2", - // "quizTotalQuestions": "5", - // "quizStatus": "Completed", - // "quizQuestions": "[15, 18, 91, 20, 22]", - // "quizMode": "tutor", - // "quizTime": "900", - // "isTimed": false, - // "omittedQuestions": [], - // "SelectedOptionsArray": [] - // }, - // "userId": 7.toString() - // } - // }) - // ).then((response) { - // print(jsonDecode(response.body).toString()); - // if((response.statusCode == 200) & (json.decode(response.body).toString().substring(0,14) != "{status: false")) { - // - // } - // else { // Token Invalid - // final result = Navigator.pushAndRemoveUntil( - // context, - // MaterialPageRoute(builder: (BuildContext context) => const Login(fromWhere:"Home")), - // ModalRoute.withName('/'), - // ); - // } - // } - // ); - // - // - // }, - // child: Text("Search Bar"), - // ), + ), ); } diff --git a/pubspec.lock b/pubspec.lock index a6a45fc..75c7307 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -15,6 +15,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "2.1.0" + bottom_drawer: + dependency: "direct main" + description: + name: bottom_drawer + url: "https://pub.dartlang.org" + source: hosted + version: "0.0.5" characters: dependency: transitive description: @@ -42,7 +49,7 @@ packages: name: collection url: "https://pub.dartlang.org" source: hosted - version: "1.15.0" + version: "1.16.0" cupertino_icons: dependency: "direct main" description: @@ -50,13 +57,27 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "1.0.4" + equatable: + dependency: transitive + description: + name: equatable + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.3" + expandable: + dependency: "direct main" + description: + name: expandable + url: "https://pub.dartlang.org" + source: hosted + version: "5.0.1" fake_async: dependency: transitive description: name: fake_async url: "https://pub.dartlang.org" source: hosted - version: "1.2.0" + version: "1.3.0" ffi: dependency: transitive description: @@ -71,11 +92,25 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "6.1.2" + fl_chart: + dependency: "direct main" + description: + name: fl_chart + url: "https://pub.dartlang.org" + source: hosted + version: "0.50.6" flutter: dependency: "direct main" description: flutter source: sdk version: "0.0.0" + flutter_countdown_timer: + dependency: "direct main" + description: + name: flutter_countdown_timer + url: "https://pub.dartlang.org" + source: hosted + version: "4.1.0" flutter_lints: dependency: "direct dev" description: @@ -95,6 +130,11 @@ packages: description: flutter source: sdk version: "0.0.0" + flutter_web_plugins: + dependency: transitive + description: flutter + source: sdk + version: "0.0.0" http: dependency: "direct main" description: @@ -109,6 +149,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "4.0.0" + js: + dependency: transitive + description: + name: js + url: "https://pub.dartlang.org" + source: hosted + version: "0.6.4" lints: dependency: transitive description: @@ -123,6 +170,20 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "0.12.11" + material_color_utilities: + dependency: transitive + description: + name: material_color_utilities + url: "https://pub.dartlang.org" + source: hosted + version: "0.1.4" + math_expressions: + dependency: "direct main" + description: + name: math_expressions + url: "https://pub.dartlang.org" + source: hosted + version: "2.3.1" meta: dependency: transitive description: @@ -130,13 +191,20 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "1.7.0" + nested: + dependency: transitive + description: + name: nested + url: "https://pub.dartlang.org" + source: hosted + version: "1.0.0" path: dependency: transitive description: name: path url: "https://pub.dartlang.org" source: hosted - version: "1.8.0" + version: "1.8.1" path_drawing: dependency: transitive description: @@ -200,6 +268,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "2.0.5" + percent_indicator: + dependency: "direct main" + description: + name: percent_indicator + url: "https://pub.dartlang.org" + source: hosted + version: "3.4.0" petitparser: dependency: transitive description: @@ -207,6 +282,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "4.4.0" + pie_chart: + dependency: "direct main" + description: + name: pie_chart + url: "https://pub.dartlang.org" + source: hosted + version: "5.3.1" platform: dependency: transitive description: @@ -228,6 +310,69 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "4.2.4" + provider: + dependency: "direct main" + description: + name: provider + url: "https://pub.dartlang.org" + source: hosted + version: "6.0.3" + shared_preferences: + dependency: "direct main" + description: + name: shared_preferences + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.15" + shared_preferences_android: + dependency: transitive + description: + name: shared_preferences_android + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.12" + shared_preferences_ios: + dependency: transitive + description: + name: shared_preferences_ios + url: "https://pub.dartlang.org" + source: hosted + version: "2.1.1" + shared_preferences_linux: + dependency: transitive + description: + name: shared_preferences_linux + url: "https://pub.dartlang.org" + source: hosted + version: "2.1.1" + shared_preferences_macos: + dependency: transitive + description: + name: shared_preferences_macos + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.4" + shared_preferences_platform_interface: + dependency: transitive + description: + name: shared_preferences_platform_interface + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.0" + shared_preferences_web: + dependency: transitive + description: + name: shared_preferences_web + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.4" + shared_preferences_windows: + dependency: transitive + description: + name: shared_preferences_windows + url: "https://pub.dartlang.org" + source: hosted + version: "2.1.1" sky_engine: dependency: transitive description: flutter @@ -239,7 +384,7 @@ packages: name: source_span url: "https://pub.dartlang.org" source: hosted - version: "1.8.1" + version: "1.8.2" stack_trace: dependency: transitive description: @@ -274,7 +419,7 @@ packages: name: test_api url: "https://pub.dartlang.org" source: hosted - version: "0.4.3" + version: "0.4.9" typed_data: dependency: transitive description: @@ -288,7 +433,7 @@ packages: name: vector_math url: "https://pub.dartlang.org" source: hosted - version: "2.1.1" + version: "2.1.2" win32: dependency: transitive description: @@ -311,5 +456,5 @@ packages: source: hosted version: "5.3.1" sdks: - dart: ">=2.15.1 <3.0.0" - flutter: ">=2.5.0" + dart: ">=2.17.0-0 <3.0.0" + flutter: ">=2.8.0" diff --git a/pubspec.yaml b/pubspec.yaml index b7130cf..571ccd5 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -41,6 +41,11 @@ dependencies: flutter_countdown_timer: ^4.1.0 math_expressions: ^2.0.0 provider: ^6.0.2 + pie_chart: ^5.3.0 + percent_indicator: ^3.4.0 + expandable: ^5.0.1 + bottom_drawer: ^0.0.5 + fl_chart: ^0.50.6 dev_dependencies: