From 746a017737477699e4dd040271fcde363e850cea Mon Sep 17 00:00:00 2001 From: leoho2fi Date: Wed, 24 Apr 2024 17:32:34 +0800 Subject: [PATCH] add report ar06 --- ...port with Outstanding Un-billed Hours.xlsx | Bin 0 -> 12670 bytes .../ProjectCompletionReportWO/page.tsx | 10 +- src/app/api/report6/index.ts | 42 +++ .../ProjectCompletionReportWO.tsx | 17 + .../Report/ProjectCompletionReportWO/index.ts | 2 + .../ProjectCompletionReportWOGen.tsx | 44 +++ .../ProjectCompletionReportWOGenLoading.tsx | 41 +++ .../ProjectCompletionReportWOGenWrapper.tsx | 19 ++ .../ProjectCompletionReportWOGen/index.ts | 2 + .../ReportSearchBox6/SearchBox6.tsx | 302 ++++++++++++++++++ src/components/ReportSearchBox6/index.ts | 3 + 11 files changed, 477 insertions(+), 5 deletions(-) create mode 100644 public/temp/AR06_Project Completion Report with Outstanding Un-billed Hours.xlsx create mode 100644 src/app/api/report6/index.ts create mode 100644 src/components/Report/ProjectCompletionReportWO/ProjectCompletionReportWO.tsx create mode 100644 src/components/Report/ProjectCompletionReportWO/index.ts create mode 100644 src/components/Report/ProjectCompletionReportWOGen/ProjectCompletionReportWOGen.tsx create mode 100644 src/components/Report/ProjectCompletionReportWOGen/ProjectCompletionReportWOGenLoading.tsx create mode 100644 src/components/Report/ProjectCompletionReportWOGen/ProjectCompletionReportWOGenWrapper.tsx create mode 100644 src/components/Report/ProjectCompletionReportWOGen/index.ts create mode 100644 src/components/ReportSearchBox6/SearchBox6.tsx create mode 100644 src/components/ReportSearchBox6/index.ts diff --git a/public/temp/AR06_Project Completion Report with Outstanding Un-billed Hours.xlsx b/public/temp/AR06_Project Completion Report with Outstanding Un-billed Hours.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..419bd2e45ac75ed8a2d1048027ae33e96fb3c124 GIT binary patch literal 12670 zcmeIYg;yMF);-*~ySrn41a}D#+}+*Xe%w1V-<`?a z?=N_#YORv4I(v0JbrwB*eRGY|p|0B^pnvqD`>du}3Ex4ZW;Loudm)HlI!~)BF1lgGa<8jG{Q)UIs?_03 z=t(wH%Kv+bR#bIN1Q!?|<>Ul*q83iEVcwXw+_55%kgWr_CQC8<< z_$c5%789unR+*}DX|&ksFuM5?V7ciC{5#d?-cJL9yNNBm-kEBJRr%%2rssb{|Xt} z5BX5S!EE+AlK8H80d*-oTa0Wq@eGyd`8Cd7UZ4P~{}HCOnygfpufC`FdKKw4Obs1O ztQ>(Xe{BC3p8tnq^4}i4Bu+`CixoNeMD{VH|7L0_23=giMNIYwg@(7U+#*_SR1P)K zQX3sHx&~nYl#EY{_v7Hgl3>(+KgIPrXGsJmwg6R~OKEV@y}c70BdtTCw0+51H-_`n z)zo#ejJzAYbITXT;)a4Og@F|+>4`JRO7u|{Z9)XBT;gC{p=7^zy-K>v#n`W=l;=gK_$tthVU2sPiD@tIc`XE^Xvx*2}5 zYQK<7ZNqx7xN(`Mj&)JR3@P>*hh|D(*iW@Q)xXSboh|{~aWi z+r4hLuK_X+3jmz{X2Oo=E?62%uO0Q4G>Z%c>z>u{8Gl{FON zOMLs~`_s&H25U>@2V}F=dqEj<85@Dl%C3Gc@Ufmq!8)b9CLhI$({SA3D0QVde`zxS zH3JeS>f5&@mo;;xqzoXt<4oU+OoH*ZI8#cICoA2WJoVvV%iS;ol}QsE z8G|t2EJ2!i$lO!=%v9>%NFmhabGZ`5*(x}XMg_xZv3t@LpZemEcD&!|GGoyxzLtmX z@t}KWx4OOdJQr?y=x(YnIe1Pt5T#BaO`zr;XEz*&@A83x`>+8*cc6$^OE92d=Bx#< z@Dz}~gNX}%BA-yim8_1X=hU%QdCI9Ps+1`NVC5iP=dZ_g%t0WD@v~wQ#^$DArDw~3 zW+RnCavaf+qt`P_D3;P?=1|5<+1gr9h8iebdg%xVOu?LuxsIMces)6e&59(<9IlnL z6Cui!DD{c;C=lFDJw)3^mOrSoMPj77xn?^}+iNEX((*u8X7(Y3)^gzmm9WCQk5tSM zI0r0aQB!q=BC79!fJJ`Mm1u|=f!;CJSoY}!>jSa9In`}U9BqUtvtQ+AYsxK0xcBMX zbhD38fS8qGm0NBttnIs5bEogg5>xp-yRg#z1JY0n>Q^2{ZuwzGY!B>wQyh#I9%w9S=)<|U!v)e*yL!x*TSdMj30^_c*6ziHLY#C2 z$#6ru>(lexI`N-CEV0QJvEt=Bb;H0}t;{$2qpL!wX%sE5e3dOL=q_|%Kt|a;uQ!(_Xb1W3ANZi&s3&U;q zK7Sh|e!}rd7q7w5^cpCH0CPiaTuXPX7a|o+T zsxuD890*8xsCj?}KTyN4Kuf{leYrx!*rcyBtpJ3w4R$*j?sLB3LS2W#y6SjS5RM7$ zj%9Ts0Ao9RF$@K7d{j#6F9U;xdANU2e1wFW;)vBK9M{j3fz7*pOHV@(l9NX%dD%D~ z%xN*g>cnp0_={xll~{*rHhu2{-yW9w*VNaOr!aipdTEqcxQ5O2cOx6SAV824L~#R* z?M_m>x$Tg;hCgq9{H)|QV%d>%kGw@(tUy}CCFB_lA`j`8A@gB~bKJ^K{-JrY1`>Z5 zWN2GBXBxUZ`Mf#MH?{KmrvIB)LASEo_s{@ZZzuxgrUUf7xF#$OO|J{oSf1xu|xjEXolQ*FJ47Pc;AOh9s35R2+zoxf$4f;<)VS z`E%15hMOXJfDOUe@mMruNojS#rP`$GKDXe-k%p4&JWy7Ez_x^-x=dJLhwD# z8YX@lUQJas;Q1;=yD1C789`aKc20|gRw^iz2H3#IOMeDUBvK+@xLeiUbffl#-M0J` zYomVQyZxxhC(Ja4LK7QLYB-ruvLP~<9N((M%gW~nRyCmN>EID;hU%G9Vz&2CxJt!w zLWLMo^^y7p^C;%I0IF#`EK?wUT`{s^wi&Bd;FJj-*;Uia`oPKq*P zlRq6Ra4P5A!6sviO1NE@rUQgoQ_LO>Wt6(g(2vC)(QBAproXQBxLPrBax5f~q@oJo z@XerHZ;@ljz-L}fC7FfH406Rji~;5@>fAxGAeRE^s>A3x9&xr+SI-+8-c;E2K_U&3=Pz{rG&%cf`Z+x&maNBXT=0d(#n7*O8W!d138HRnWQ|wgJD7kJ zP_y}iF`21CxY^x*At3TX;fCcnda>0fK*t)@ImO;_PK$_P|9e?dDgFvSTkkt!nN}{% zVhnHTD37B_d?Ke&vQ~xYa~iYi)w+V}0)wbdot*4bpGg9`-C4el+5XD!5#jC10t~&< z{HH%&aP4U?l$iTm_d7J1+uK$)q*0r?-V*Iom@8CXY}2j+|8&qlH}Q#UHvX*WeTG4o z5R%Ypxa1fLUZ|b2kDIt`HXaZ9d|Jn4fnk|HM-3NV^i|kS%Jpx44d*aiJoIVX0X4q+ zKUX(iogN>7{SR_fe;m<{%qqaFsEyayo`^IZEF8mP@)rHn`_VIS3~_M7=!@pwKFU7S zWttpvRG^`ZAmeZydM$f|u@Q?zLxH`;xNtUz`=-Js%M3zB4M14vaEBo}^nQ3Ov3$%y ziP?|B*W`=#r+SuAZ}hn_@;MBq&q2}P z2}6)uc6xl_~4R^@#EcovZF^*#Ase&=N^{#(B z@7txrHmX*p>Iz|w6MVs!zn!zpP{t6Z-JO%&os0WsKec*VJtL@3`It;L(yQOOr_%jz zZ&31!zD=hna$tGYIRqjDB=n%PxF7&6A!Zk*F6?Uw{Pm#ayM&1u3=ywK>5XK2H?cjt zh^`p@VQqCZ7>z9jC;!qArOIU-*22Mowid>>qk)76ISq+&Xi*_ByiZEIey&58QE^lg zuHVE%$i$jt=TK(f4PPF4p(-2Cw2AUX-H%@awYG-7x+9|u%5qe&Ow$R*sT9m?s>{;n zyH?*P%w>C@lak%7>QKhP){2n^iz<~3+agVm1rKF4irjWNj0k0G`TQ+kIteG6e|@b% zBMJY|RQ}{kkeP|K3GmPDpHz9Ms~52#jqMG*6oGFMXqBsK=_az8Q=UJhr8xM$X>awV zbRe2jnqxT%!7onmDpyrj!4T2wK!O2<^VhGW=WjuQ+)o%n9C4+|SG=i1c{MbaI^V}! zMm!xy#(41bn?b<55e#KMBe{iAgMtQBuoR2xDj25X4t9%>G&j{c+HWx2$r*8 z_f6n|YB!9a*$%q!3+-sI z6p~}F$H6zuZ03{VfBYPb#(f$kpTEO}+zcrdPaQ(E8%{RaHDxvv!;qt0a+-L8LRh=# z=I3vrqn&hUJcwCYI&BO}%7p^Rl1uqhN9&B7VMk?!OGpmT(~OWNOR2g##M}hoA3|txjzAMOZP5^CT8l9(Z4~q|#AbES4eS;e39&H_&CMLMp`XcI&uY z?_e^kFE*f9?{U|q?c;URc(DUqY4dz^n!Yj@oH+w}->>)BwzUlkMK-|qT-atbyWVf! z)f+yaZG4QlQ4W{p_mnmMnQnPI+c;p14-OI`&9(i^7KzTrqzc{2T=qc8?mLqhI&Y_M z6@2Q9$oLV;z+jQ9fmCu&99>~lJ7*Sf%pv`QsTOv%=ujcz)GqetVR}9ii3?U1mEH=4 zd?fS@o@0!*u_J->EZ8j|TM|s5Tw%A#;T&3N0&;<8TW?b7W!SJ{OcUtdqclbth>468 zXN)Y1!9TC6!3fkKs+?;(0uj_kHHCapq;AFyeb_K` z+dr?w8bsjhAKLJatxwMHhMcl~kuUeW(=T1zC`Gzq$hs6|Vp!g=I2tiBNI?dxSu;+K zIJCs3%Gf2_Vj(XwNe%YOCErGd?vjf;>a1!{af5mtXE=_35`;LlS!fX%dk)sm3o)&G zaSvPq~COKah(<&YRqrxCgy_VcYXb;V$r;z;9X zcRkiZ1Bi-n9Zk{Ly~NEXCszlMZefdb9t!5W#$@Um_Q+q*J5z;ZX=$cqdQ$Qz?(Epb z^;zICv(_)~6)^a6Q8>pE{Aow*7f|+v)1sornvax?R?w2ph%G{fV1U^iyn;j#oE~c{ z(z@FWctYJdOsn!BcCOH{_Cg7{Mdz*4nJH1MT#9hLT3G+na+(=P-MjkOfbXety%P+i zNJ2;NA|gS~NQjx{L05(BJ{}b{pO9p4#5nn!r9rXFlB&kuIgC)e6vWX!MY^1H&?6i( z;#!j{g<%Xy`cI;2Q>xR^yMp3(k=YS$u-cSOc{#_^Y`>1r*(5}HBzRK>5U$frm#XtE z2>6sZBlsp%ari9fdoG`p&IyZ+F}ZY1#!Kr^ntwG-%O8MMORKvHs*f!d;R$QAIRa8X zH8XUnS6^s-o#$hLuaSk;Td&KYDv5PnNG3Z})-FvW*E*2byxs2#d4Bc2V}IAnRcu!= z812G9AR2?el%aEU+5l`b<&9*kbl@A)*tj~6wsn{0itUhG`H7RH<|b_ht|#S|$+IW- z+7srTy%pT%NyIj&0*cH8kY~RHGku40z>&n4s!&# zS(!NgQRq+V{FS|!+slTr@z=A4zKVbWvE8;s|x z-;>RU2wr9ZpLpcvpCdAoE18aZezbl<@T%m>Np@_#NFO3rdLUQ9Izp~Qemg#PJHDe){OvNI5Ka%_iw0<9_2dwk?pP^=FtumP4*c6y91O+_y+SqdvY zcuqK-64KUqa6G0fCTiGfP?dMEJCBo%WT+_BJT$C~x@O#rgu=W(V>nM*a>Bg-44v-V zXfBh!Le6v-TNV>BEr6?jiFMrJ#|SaAX%Hr#hm=YK9L(7qogL{z3`#9-y!*R0N;C0qqj%xW z_*-ro>u!3MGiq&h^KZyP*CsrAy5Dl0&0P>|p&?(n*pVlBxw#wi{IGV+s$Pg@V9@08 zrRnfFAjsOGMlZ)Ett?s?F)%YVg5;=+!59l!cO9?X{OXNPx#Y1Ml91yHsNXFp=&pJ~lA zmt`ShYGf;}LxF*UNv@x-ue`mIDhI`#pK>*q)=7-Jf6c6`>%xmH!+Xy~kW6&1Hyr;Uf~9DKN& z8X)j9*OWCK{q_gJu8pwU9S~xh#2_DbvyDe!7aNTcC419sWv?taNGz z3>pg;P_YDQ87O0xLhXse?y)=23&Z33lDdn;i`q*Pi-RW2+3{dh#kHu~^`qU#O}B0< z+SQbWjN)@bhdAcr(zNE(7d6eQ5A@FRw$4hS`QISCKZK=a#Erl*du#AUcv&ZPT;J%F z(ig$x7N$YGL2EOhHLqBN^*a&dB@43w^u;!JMD*IdhThtxfJ4Ah;$9oK+85J3^h(jX ztn44NT!JTn?j@O0avLhNV=Yu$Csd{eRhr3yg214!(}Nqs+4mdnCjqA9thwRWTMf&8 zznGCWiYP0&yVI4!(`#*G0$z}SWzdD`)pqXw4tHMk^DS?pl(uRvgblWMq#~e{lyW(m zf8ntRkSkqYkUSk_uDo3A-%ygZ2d^R15q~vNaD0MAkso6Za+ppr+GTFD~o>i2Mc!HxO;UuesO>DUe$|sx~y^-t?FWqXvX#TUU1gag>+%FGCG8OwC9@{djkby z$lVY45x(TIk6U3$AU0fuQcubq^|@u6z|U0RscC`8)la+Q*xHTgV{%>Tu@kgwdC!`M zaL4yk&9$t3CSHVK9(*I*4Avom`s2T^^x^0d$k|^7GS*iy4f~%gX=dbL^64$e!Q965 zPqGBXEhu-2q6eQSd4>$Qqv$n|2iMSi@9hebg%@m}M+FT#=N&6+E-&M}p#>)itPsEW zOw7q_tfF{TC?*r4V8O`JXeT-+&zIQ3%^>>Y7e#*TR6JrU(DinU4JJpoWcXBsYo7lu zq^h?!kfL5T)@qJNdVS&qWG0ltI2k(5E2JD3W)n#RL*qhif2<=Wb6wk&jTWhq0h^j1 zhqqXRN^=ayBh5M$mw%7swZRo(Uy)^cK&*9YRK|kLhgA7b_30nlu0)pp5V5 zVHc8OZm^#`s)1xq znqX;7fl^kM59^E3!9l7FQloyt@AB@RtBgh{j1k_RlM8cW9k`1i`c+b7VSR20R|8b8 zJz?7P(hlGkQrCSxjP@cEw8?23kv$&`l;ex}Ae=4B*DrN+?rSV|;BuW|>4gfNXZ>^N z;u_)a^fxgVO391Y>3U*r0D$fvBVhOHULX^Pw?VOFp*xcsu-BJY6435YT zcbBBYDT~= zU-^ISi_umfj;@~|KVg#&)d?UvRjq&GD0ldg=kpe_rqm4Qr39XPPWxCO4Zqkp-r4)Q;daTy znQZv|T1p)0G8)v~DdV@moobvSLhjH|cL{K^L}B&Dp^aYN0_%PDmilOgXDqsJhEq}P zV%mmN(9YYI8L0Aawe+iy+ci{Jw*IT+JJ5a{n`vSpV0V<{YpDq_XJfB7P`xIp1AP@t z#npz2g+?wYU5UKep^Bu^vvROHgG9=cd!g43+37@k{wAAOF z9;yhC2PJ;W%7ObUU}>MW7`GnVD;_%Y(@YpqyFiYg+de?UYD;R+_qk&ek$CQQCM`&J zTqc(vyEe17HFJQ}d=(SkV@qgw(S;54KEl1%5e_dc0rT#snaq03i-v+-e_^o99P@8U zqD@8$h(GY*5?wHFVrnj~M1LIp`b4zmK(=5VSxx9t>uErc@`nHODE1Po^0Smyx{y9G zbpJdqs8BQdTCGu_uEzL>pHlAJ^kBJ>V`yD{b3n?%wW?1=+z0jefYFa}?6yaVq5~nw zbfFs!kwHO9QwvlCKP9!H*btYs7`~8c><88u6C*C)6-I-ZHtf_1X)|g|sJDWthP=Fp zIgW+(omDqbVy-wBKlhR#L*sr2`j?noTXV$#FYh)t@Inoim^3!3yKOTJ@Af%9Y?k(g zwthJfS$V$fO(pYgbO$MydtM%z+xtHIq*J;Bstynxtwz1jho14vA=~_HBin+mQxRFf zPYN(DW6xZz`2OCw1Iy~0GG;z7BgQ^HPzEreSDDfe1TZ_lo?HCknEJ%{>Rxb$a2_d6 zl~!k0R{U1fPT!jOV0G$vlirf}&Kf3dkyG~a_+~;yU%kLTX8XTDJZAXMfN$3W!dg&Y z4}Fjxh3yVcusEZ!JqcU6Rp`!{S99PURUepq=wnwtMOGUTpJeJ9cBpjTFt55c)1Ja1 zKJ%Rhg<#z=C(3+F_wGHH5$D_B>ULNg`_vo}*%rS#;|FBCwO;l2e*wIQ+;+V++E;1E zk$NWhh;5WM>b5zrdg}CngttxvvNgM3#N^S{_yybHiGuY&B+M4#Rt95ROmJ0ntZm>n ztos>j6$<8s=#~!g8MUDa_2)B342tiH>L!oxm)5*ns8*Pt_cLc+$cx_KRZ~BpAjzP8 z7V;3)&odi{7n)8yiWQ^BD^(wq2BhY2ln;2L?WE7h{E{b@uF=kBp;}PdWGXX{X-XP7 zxQ(v3F1}4wC+x{)Fr42QOGW$go)z81guBpAnacOAhjv_vwA>B#7_O>e(E?Cu|sDQIyPV!I8X_UJ{3#Z>c=W?zw=iit(mPYJ|6z zd_|Z&J^f_B%4YQO({vx7&QI^SC^v4pom^SC0vC!q_R5sAL4Z|I$(j)4Y4aJQ4p;Mo zqQ$v~uz^ws!mZ)Y&$urUx})1Ztxurm{JEbyJ}Euxk1Ey5w=-;}86{UA_UAKz+HUFP zZVxOy7e60_SEN`5(m7l4&b+{1yrG;}#jRW$$jYT#ZG*U+bqDW`x#9^{G2mt>Y81|o zxfP1V5*G`DCb!-dZwTqAXjzI{2v^IboP1=Tm@@#mX>U8N4P3+7~K#g^*h-~6cl30Ch4ozxpdMcNi0d|$zF4e4BCH3 zoye}k3AXlskh)CWzzU33yY-y-`Y>xHJya!rXH$iu_Zj599M&5AjhDOfgT8WgT1hWS zce8*21NDuSfyCLo5$vES1(vYIg$0PVThBBt_0|)goKg6Wnj7YWcCVYSP>3_$y>wYfL%j_smf=hzpI;q?Pn#GU#mvF*XkVO zb*lT5?MGDyTRTVKM_UJzKXi=O)~Wx^aK9Fmo^fglU98waD=;q-10JcI3!uO{sD!ny zV1JyR`j|!Q9&QG?&-FgG^ER~-XKXiV4@-_fIoyyUBNjGaueVaGz3}Bp1A`aV-0cuU8omzR)iakH<5w zv3Qq1x1JKA(h8%9(Aa^)%hI^f026#ADoOVp8>(tKwF*ksFDno+zM41M_;JJO1LK3K zM1EwN=2~>^${x1M&%|szxSI~#fJ*a}f@Bbz=QDm=xi)aA$S7-G4?$Fy5(W#lVS;u+ zj}?IwXMQ7Lv8lH0A`jr^@>2^O(3cPWq9s^}w7ek-D~xy$keN_F@FdYHNkDVPM9o8y zymgk=Qy&@k#ragqho}^&k$?7rxyMO85i_3lb1uG$fCOXIw`9ocj-=}Eg|wT(Z@9&; zPDld<0HFW76B^ms{m%zqo$sGZT3m+>7TfD*vaA=}5FIb)GB&nm?2Kjt?iGO2B5qm# z#LD<|{*6bIyelpXam+oe&>6SJI@`A;%?XsPZtKs_XD6c^iKYvKm9WND9Xpiw#P%xOOrE!I~JOgx8f@D8KB`8zH2{D+2 zCP>R~ybG+Vfo1V;EN;)?9jFTPW%dVxdCP8sn_belZ`<;uSeXr*bdN0{wa%N%(zyut z683Yr*uJY${#YcmQ%9DP10k`xjIAr1s3X5^WS#GbjMOaDhh)e=I!6Qv)HK$yG0d&j zKm<@!eQFz@Rp$LMh43ydjfel;QEbJ0o$#KqHeKZY*;-$D=8CsZTay1}>vT}pw2{?H zq5X_#htWsNUyd<$vJEx67jN7u>Vbp4XAX$D(8tX zJU=5z{DH#e-mtv)tJ*bpjy{@&y5NiL72LmA76Ov_Rqy!w9`b*^(0}d!rlVX{;XeWX zv%B?QhJWnyU!&&VdR>1v{JrDvFVml|^RK`4|NU pzsiH(&Ht0i|J~f^&A*xdlh{=iU|xL?06>0SX { +const ProjectCompletionReportWO: React.FC = () => { return ( @@ -17,8 +17,8 @@ const ProjectLateReport: React.FC = () => { {/* }> */} - + ); }; -export default ProjectLateReport; +export default ProjectCompletionReportWO; diff --git a/src/app/api/report6/index.ts b/src/app/api/report6/index.ts new file mode 100644 index 0000000..e1f2925 --- /dev/null +++ b/src/app/api/report6/index.ts @@ -0,0 +1,42 @@ +//src\app\api\report\index.ts +import { cache } from "react"; + +export interface ProjectClaims { + id: number; + projectCode: string; + projectName: string; + team: string; + teamLeader: string; + startDate: string; + startDateFrom: string; + startDateTo: string; + targetEndDate: string; + client: string; + subsidiary: string; + completeDate: string; +} + +export const preloadProjects = () => { + fetchProjectsProjectClaims(); +}; + +export const fetchProjectsProjectClaims = cache(async () => { + return mockProjects; +}); + +const mockProjects: ProjectClaims[] = [ + { + id: 1, + projectCode: "CUST-001", + projectName: "Client A", + team: "N/A", + teamLeader: "N/A", + startDate: "1/2/2024", + startDateFrom: "1/2/2024", + startDateTo: "1/2/2024", + targetEndDate: "30/3/2024", + client: "ss", + subsidiary: "sus", + completeDate:"30/2/2024", + }, +]; diff --git a/src/components/Report/ProjectCompletionReportWO/ProjectCompletionReportWO.tsx b/src/components/Report/ProjectCompletionReportWO/ProjectCompletionReportWO.tsx new file mode 100644 index 0000000..c0165f2 --- /dev/null +++ b/src/components/Report/ProjectCompletionReportWO/ProjectCompletionReportWO.tsx @@ -0,0 +1,17 @@ +//src\components\LateStartReport\LateStartReport.tsx +"use client"; +import * as React from "react"; +import "../../../app/global.css"; +import { Suspense } from "react"; +import ProjectCompletionReportWOGen from "@/components/Report/ProjectCompletionReportWOGen"; + +const ProjectCompletionReportWO: React.FC = () => { + + return ( + }> + + + ); +}; + +export default ProjectCompletionReportWO; \ No newline at end of file diff --git a/src/components/Report/ProjectCompletionReportWO/index.ts b/src/components/Report/ProjectCompletionReportWO/index.ts new file mode 100644 index 0000000..0382210 --- /dev/null +++ b/src/components/Report/ProjectCompletionReportWO/index.ts @@ -0,0 +1,2 @@ +//src\components\LateStartReport\index.ts +export { default } from "./ProjectCompletionReportWO"; diff --git a/src/components/Report/ProjectCompletionReportWOGen/ProjectCompletionReportWOGen.tsx b/src/components/Report/ProjectCompletionReportWOGen/ProjectCompletionReportWOGen.tsx new file mode 100644 index 0000000..2942e38 --- /dev/null +++ b/src/components/Report/ProjectCompletionReportWOGen/ProjectCompletionReportWOGen.tsx @@ -0,0 +1,44 @@ +//src\components\LateStartReportGen\LateStartReportGen.tsx +"use client"; +import React, { useMemo, useState } from "react"; +import SearchBox, { Criterion } from "../../ReportSearchBox6"; +import { useTranslation } from "react-i18next"; +import { ProjectCompletionWO } from "@/app/api/report6"; +//import { DownloadReportButton } from './DownloadReportButton'; +interface Props { + projects: ProjectCompletionWO[]; +} +type SearchQuery = Partial>; +type SearchParamNames = keyof SearchQuery; + +const ProgressByClientSearch: React.FC = ({ projects }) => { + const { t } = useTranslation("projects"); + + const searchCriteria: Criterion[] = useMemo( + () => [ + // { label: "Team", paramName: "team", type: "text" }, + // { label: "Client", paramName: "client", type: "text" }, + { + label: "Report Period From", + label2: "Report Period To", + paramName: "targetEndDate", + type: "dateRange", + }, + ], + [t], + ); + + return ( + <> + { + console.log(query); + }} + /> + {/* */} + + ); +}; + +export default ProgressByClientSearch; diff --git a/src/components/Report/ProjectCompletionReportWOGen/ProjectCompletionReportWOGenLoading.tsx b/src/components/Report/ProjectCompletionReportWOGen/ProjectCompletionReportWOGenLoading.tsx new file mode 100644 index 0000000..466b74d --- /dev/null +++ b/src/components/Report/ProjectCompletionReportWOGen/ProjectCompletionReportWOGenLoading.tsx @@ -0,0 +1,41 @@ +//src\components\LateStartReportGen\LateStartReportGenLoading.tsx +import Card from "@mui/material/Card"; +import CardContent from "@mui/material/CardContent"; +import Skeleton from "@mui/material/Skeleton"; +import Stack from "@mui/material/Stack"; +import React from "react"; + +// Can make this nicer +export const ProjectCompletionReportGenLoading: React.FC = () => { + return ( + <> + + + + + + + + + + + + + + + + + + + + + + ); +}; + +export default ProjectCompletionReportGenLoading; diff --git a/src/components/Report/ProjectCompletionReportWOGen/ProjectCompletionReportWOGenWrapper.tsx b/src/components/Report/ProjectCompletionReportWOGen/ProjectCompletionReportWOGenWrapper.tsx new file mode 100644 index 0000000..c294e0c --- /dev/null +++ b/src/components/Report/ProjectCompletionReportWOGen/ProjectCompletionReportWOGenWrapper.tsx @@ -0,0 +1,19 @@ +//src\components\LateStartReportGen\LateStartReportGenWrapper.tsx +import { fetchProjectsProjectCompletionWO } from "@/app/api/report6"; +import React from "react"; +import ProjectCompletionReportWOGen from "./ProjectCompletionReportWOGen"; +import ProjectCompletionReportWOGenLoading from "./ProjectCompletionReportWOGenLoading"; + +interface SubComponents { + Loading: typeof ProjectCompletionReportWOGenLoading; +} + +const ProjectCompletionReportWOGenWrapper: React.FC & SubComponents = async () => { + const clentprojects = await fetchProjectsProjectCompletionWO(); + + return ; +}; + +ProjectCompletionReportWOGenWrapper.Loading = ProjectCompletionReportWOGenLoading; + +export default ProjectCompletionReportWOGenWrapper; \ No newline at end of file diff --git a/src/components/Report/ProjectCompletionReportWOGen/index.ts b/src/components/Report/ProjectCompletionReportWOGen/index.ts new file mode 100644 index 0000000..20bd632 --- /dev/null +++ b/src/components/Report/ProjectCompletionReportWOGen/index.ts @@ -0,0 +1,2 @@ +//src\components\LateStartReportGen\index.ts +export { default } from "./ProjectCompletionReportWOGenWrapper"; diff --git a/src/components/ReportSearchBox6/SearchBox6.tsx b/src/components/ReportSearchBox6/SearchBox6.tsx new file mode 100644 index 0000000..1f201b1 --- /dev/null +++ b/src/components/ReportSearchBox6/SearchBox6.tsx @@ -0,0 +1,302 @@ +//src\components\ReportSearchBox\SearchBox.tsx +"use client"; + +import Grid from "@mui/material/Grid"; +import Card from "@mui/material/Card"; +import CardContent from "@mui/material/CardContent"; +import Typography from "@mui/material/Typography"; +import React, { useCallback, useMemo, useState } from "react"; +import { useTranslation } from "react-i18next"; +import TextField from "@mui/material/TextField"; +import FormControl from "@mui/material/FormControl"; +import InputLabel from "@mui/material/InputLabel"; +import Select, { SelectChangeEvent } from "@mui/material/Select"; +import MenuItem from "@mui/material/MenuItem"; +import CardActions from "@mui/material/CardActions"; +import Button from "@mui/material/Button"; +import RestartAlt from "@mui/icons-material/RestartAlt"; +import Search from "@mui/icons-material/Search"; +import dayjs from "dayjs"; +import "dayjs/locale/zh-hk"; +import { DatePicker } from "@mui/x-date-pickers/DatePicker"; +import { LocalizationProvider } from "@mui/x-date-pickers/LocalizationProvider"; +import { AdapterDayjs } from "@mui/x-date-pickers/AdapterDayjs"; +import { Box } from "@mui/material"; +import * as XLSX from 'xlsx-js-style'; +//import { DownloadReportButton } from '../LateStartReportGen/DownloadReportButton'; + +interface BaseCriterion { + label: string; + label2?: string; + paramName: T; + paramName2?: T; +} + +interface TextCriterion extends BaseCriterion { + type: "text"; +} + +interface SelectCriterion extends BaseCriterion { + type: "select"; + options: string[]; +} + +interface DateRangeCriterion extends BaseCriterion { + type: "dateRange"; +} + +export type Criterion = + | TextCriterion + | SelectCriterion + | DateRangeCriterion; + +interface Props { + criteria: Criterion[]; + onSearch: (inputs: Record) => void; + onReset?: () => void; +} + +function SearchBox({ + criteria, + onSearch, + onReset, +}: Props) { + const { t } = useTranslation("common"); + const defaultInputs = useMemo( + () => + criteria.reduce>( + (acc, c) => { + return { ...acc, [c.paramName]: c.type === "select" ? "All" : "" }; + }, + {} as Record, + ), + [criteria], + ); + const [inputs, setInputs] = useState(defaultInputs); + + const makeInputChangeHandler = useCallback( + (paramName: T): React.ChangeEventHandler => { + return (e) => { + setInputs((i) => ({ ...i, [paramName]: e.target.value })); + }; + }, + [], + ); + + const makeSelectChangeHandler = useCallback((paramName: T) => { + return (e: SelectChangeEvent) => { + setInputs((i) => ({ ...i, [paramName]: e.target.value })); + }; + }, []); + + const makeDateChangeHandler = useCallback((paramName: T) => { + return (e: any) => { + setInputs((i) => ({ ...i, [paramName]: dayjs(e).format("YYYY-MM-DD") })); + }; + }, []); + + const makeDateToChangeHandler = useCallback((paramName: T) => { + return (e: any) => { + setInputs((i) => ({ + ...i, + [paramName + "To"]: dayjs(e).format("YYYY-MM-DD"), + })); + }; + }, []); + + const handleReset = () => { + setInputs(defaultInputs); + onReset?.(); + }; + + const handleSearch = () => { + onSearch(inputs); + + }; + + const handleDownload = async () => { + //setIsLoading(true); + + try { + const response = await fetch('/temp/AR06_Project Completion Report with Outstanding Un-billed Hours.xlsx', { + headers: { + 'Content-Type': 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', + }, + }); + if (!response.ok) throw new Error('Network response was not ok.'); + + const data = await response.blob(); + const reader = new FileReader(); + reader.onload = (e) => { + if (e.target && e.target.result) { + const ab = e.target.result as ArrayBuffer; + const workbook = XLSX.read(ab, { type: 'array' }); + const firstSheetName = workbook.SheetNames[0]; + const worksheet = workbook.Sheets[firstSheetName]; + + // Add the current date to cell C2 + const cellAddress = 'C2'; + const date = new Date().toISOString().split('T')[0]; // Format YYYY-MM-DD + const formattedDate = date.replace(/-/g, '/'); // Change format to YYYY/MM/DD + XLSX.utils.sheet_add_aoa(worksheet, [[formattedDate]], { origin: cellAddress }); + + // Calculate the maximum length of content in each column and set column width + const colWidths: number[] = []; + + const jsonData = XLSX.utils.sheet_to_json(worksheet, { header: 1, defval: "", blankrows: true }) as (string | number)[][]; + jsonData.forEach((row: (string | number)[]) => { + row.forEach((cell: string | number, index: number) => { + const valueLength = cell.toString().length; + colWidths[index] = Math.max(colWidths[index] || 0, valueLength); + }); + }); + + // Apply calculated widths to each column, skipping column A + worksheet['!cols'] = colWidths.map((width, index) => { + if (index === 0) { + return { wch: 8 }; // Set default or specific width for column A if needed + } + return { wch: width + 2 }; // Add padding to width + }); + + // Style for cell A1: Font size 16 and bold + if (worksheet['A1']) { + worksheet['A1'].s = { + font: { + bold: true, + sz: 16, // Font size 16 + //name: 'Times New Roman' // Specify font + } + }; + } + + // Apply styles from A2 to A3 (bold) + ['A2', 'A3'].forEach(cell => { + if (worksheet[cell]) { + worksheet[cell].s = { font: { bold: true } }; + } + }); + + // Formatting from A5 to G5 + // Apply styles from A5 to G5 (bold, bottom border, center alignment) + for (let col = 0; col < 7; col++) { // Columns A to G + const cellRef = XLSX.utils.encode_col(col) + '5'; + if (worksheet[cellRef]) { + worksheet[cellRef].s = { + font: { bold: true }, + alignment: { horizontal: 'center' }, + border: { + bottom: { style: 'thin', color: { auto: 1 } } + } + }; + } + } + + // Format filename with date + const today = new Date().toISOString().split('T')[0].replace(/-/g, '_'); // Get current date and format as YYYY_MM_DD + const filename = `AR06_Project_Completion_Report_with_Outstanding_Un-billed_Hours_${today}.xlsx`; // Append formatted date to the filename + + // Convert workbook back to XLSX file + XLSX.writeFile(workbook, filename); + } else { + throw new Error('Failed to load file'); + } + }; + reader.readAsArrayBuffer(data); + } catch (error) { + console.error('Error downloading the file: ', error); + } + + //setIsLoading(false); + }; + return ( + + + {t("Search Criteria")} + + {criteria.map((c) => { + return ( + + {c.type === "text" && ( + + )} + {c.type === "select" && ( + + {c.label} + + + )} + {c.type === "dateRange" && ( + + + + + + + {"-"} + + + + + + + )} + + ); + })} + + + + + + + + ); +} + +export default SearchBox; diff --git a/src/components/ReportSearchBox6/index.ts b/src/components/ReportSearchBox6/index.ts new file mode 100644 index 0000000..9ead696 --- /dev/null +++ b/src/components/ReportSearchBox6/index.ts @@ -0,0 +1,3 @@ +//src\components\SearchBox\index.ts +export { default } from "./SearchBox6"; +export type { Criterion } from "./SearchBox6";