From ff0d24bbb6f3d6b272bf42659cac2111111d87e8 Mon Sep 17 00:00:00 2001 From: SrJuggernaut Date: Fri, 16 Feb 2024 13:06:56 -0600 Subject: [PATCH] feat: static applications dashboard --- bun.lockb | Bin 280907 -> 292632 bytes package.json | 5 +- src/app/SessionConsumer.tsx | 23 +- .../_components/ApplicationsList.tsx | 326 ++++++++++++++++++ .../dashboard/_components/DashboardTabs.tsx | 73 ++++ .../_components/TeamApplications.tsx | 14 + src/app/dashboard/page.tsx | 15 + src/components/layout/Header.tsx | 78 +---- .../layout/Header/SessionButtons.tsx | 102 ++++++ src/components/ui/Skeleton.tsx | 18 + src/components/ui/Table.tsx | 112 ++++++ src/components/ui/form/DebouncedInput.tsx | 34 ++ src/hooks/useSession.ts | 13 +- src/state/sessionSlice.ts | 10 +- src/types/teamApply.ts | 13 - src/utilities/date.ts | 10 + src/utilities/teamApplication.ts | 4 +- 17 files changed, 753 insertions(+), 97 deletions(-) create mode 100644 src/app/dashboard/_components/ApplicationsList.tsx create mode 100644 src/app/dashboard/_components/DashboardTabs.tsx create mode 100644 src/app/dashboard/_components/TeamApplications.tsx create mode 100644 src/app/dashboard/page.tsx create mode 100644 src/components/layout/Header/SessionButtons.tsx create mode 100644 src/components/ui/Skeleton.tsx create mode 100644 src/components/ui/Table.tsx create mode 100644 src/components/ui/form/DebouncedInput.tsx delete mode 100644 src/types/teamApply.ts create mode 100644 src/utilities/date.ts diff --git a/bun.lockb b/bun.lockb index 62fb89626cd17fb1c4462c2f2c7d0dfd23e16ff8..6ae294cb5dc4bb05fa0808e682881b53ba5e2a7f 100755 GIT binary patch delta 61363 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 Pw&sg<%;}eQ+C~2Z)=}_S delta 55361 zcmeFadzek-|Np=Dn%T_82qng$P|9hXiaD`|oW}Wl${~Ych8e?*VTPDNPN8C@<(N~> zsU%^9BtjG&M5R(GDoLeK^nE z;nHw9xFmdkVUOn)cywlJ%0SW?=w)U5Jf2GMIk;Rdfi489!0*8-s3BYd-VNUlmxb?u z*SYpJnlJlFY^DDMTj}@072%ceo$wr34H^TNfisiR#w2BUJXy3}9m`2fP0dZo9PJrS zf}#k6(o@rk_Y5!Y@f5?}3-d4UR=T11Z5T!1{;)i73D-%_NJ<YLu@smEUbo~BcI}vOL=PBfsYVW;Kfo-MAKWHiqcZjk|GBW^wh_eD}82VqfG8` zI<02yg()#_L{heD_iV*ka_|y30-g+)gNM0#S6I!6arH{D(iMX#D(@GZMKJFItmd7B z)jfkkRNoiabU!!mZ3IOyFGdf_%=F}xcbcCL%ReI$N2I3=_IQqvL4F*Vl{qjy$K%<{ zD9PU9>KkBH^d{X`N8V=i6u%!q`x&;%J?Aoa* zsgXlQdU8F(QqIlZm0=PAB}hxk7@AbyZzUx9as5NA`d8q_4a z8h!-UYP30*fD&4;3eJPez`<2IIX!)N;=t6TIc^2p+c>V>1gj^-xC>PA?6yuhztJGw zhR?KfI(Lazsn0LKrR~uYfhZ&;CNtk=AiTuLk0~WnUOSl zbV^c2s@wCi$ti=9BS)r9=;T!NDlCt7GQDB<`k(3I%$&hyy|6OI=B{R&uzM5R z8JU_sC~zA(@eE1sRE@%rjwS zyp_zWVeId{oywcK-2FkPbBQBz(h^4xN*1eIz$V`oLix&m43)iRv`rbJ=AxhGt^)f5^#@Q!jc1rl*T* zHy+?rG{xn6U=4S9SQR%VokpWRtUG8>YD!j$hsF$aDjEnY-KG9cM=!c|$_S;(^?1$_ zA+Nm$tDvOpq(O;9jU4O@YZ9yi(nlnXX212Y>81>d95SLey7G-o9Gx6FJSnHWYd440 z!zfrcL?kRvRe@EGJ^YlPl1WX}@2NS|Y55IU8TPpi8I+uuI-L03_*U~HIWaSGNNVEH zEyQbh)96AP=aWTrL_Hs!oROY2G`ao&+$?)5tbBzjL=~ruNKVQ~8J(FqGBss1YgSrP z`dHO})AhjA%J>c=XFi%1lokljO-C<&TtSf=OCV;v9N zL%}NOYc%yNSaDFlhlZ$O!&62Kj!YloIgsPjmza^EUBFW|mjo)<538WG#F6%WQfRzW z@o$Ws;@`&Bqzc9#aP9AiSH8jST{M-spq{RB=g9XH9M2tx)xZO=hU~^fr@Vf{G9z;m z(^5U;ADNhune-zO@<{NmxQK@|))Vub3>%p*D&QKn(hW-)O_d(cMhY&EePWW+ZEH6Ygvtfwf>Hu=EM(&<9UsE$$V zIzR2$EPkU$vm7U7W{pmvkfh8}SxFf=o=WqbRwQMz)h2m7FH@*y&a=y$N;hB^!?u0Qxq(@%y`HpOZA4s&!|ZxJ!6|!jg>%#}DX0tuWx;a%gRmz3hE>iw z(+OLSZvv}Vv!8Jqaxb>r>4%l?F&Zp8eT~zwov_@Ndlvysow~66*J-WO;v1_SF1pSs zFb~$fGc;Yhl*f~bt*O_ad?n%h^^To@eLHqxSAS)LQ*Io#>M0AWo_?F`e7Si$2xy>r zQi|lMHM!xlPJ$g9oq{^J@ztMq)|q_R9#_(dH(;yh3t=_n2{--@SQRxQzwV)tq*srt zV#}k&ZRTG2od_lP9MjsJlTmSL^SJ3~MT9^B@%@NH~0=xJDEJq=ca{=Q|5W=vJ_ zP?x*I%GU~3Ph(v@E8iKKQ?MrKu_vAQaN=_%e7V!f_`oYp%b$hqf_6DQSP$EGx661U zGikKW6Orr=9#4Jr(v(vkmTQZ^^3YMrl^vY*m#J7C`2?1}!pm-~jE{Sr3McJ#W@qqr z8ig$v+I}B7k|Vm~sT;3374+Wc*gs+yBi;AdO8*(QIxz2br^kBO9Gx;Evp4x~Lw|q2 z;Jp&JpQNeI)dMAIFGLnaeLkC^yKeff&{F=IL5VeCS~y9%zjSZ(!I=}5c6QUYQ0X)Xx^>bjqPIwta>prc|!WN z@Wb2R$Q?d!cXZrGwHFld8fCT|P|Pe*t89r+ zFR#1PU%YJo!qZQ_+2K2d9X+2=mq`CaAATIC))HS3nEtDZHCTfTq4$7`P)FthKfRCaEi2j|?g zwQ-C;z0rYhIxpHebIFOGp*@PdY9>Ths&;R9-hsX~ADvb`FmPs6abLea<==QYyTOfb zPR+RIMxf6Of5gGL{?k)m*l1=)Za1SVC7TB;%`gX49$+2=(N(IM$yEk~UGDf~@g^U) zX=>KJE5TfFSKTcq?|Q*&F0Xpb%)V!&`NKU6wmflf39tD=wN7SO^=jso>P^hLwG)ir z4Rc)WfVZ`|qjtRa5%Vgaub44);*DQI%yD%B-e_}2op@ijLVVw2?y3{#TTZBh9r~V7 zONG46%pG;(y_3zWb>n?674~?#+3{gvJnfi`?~n5hC)CT<_7NItYc>4A62}ngV{69= zb+Xe{=7xO8*768B+OeBjoua|K;|bY$jT1%9*!u&%`&fe#?Tk+navJ(Mp)Phqo0>5V z;{6l3$zr+B3YksskMeKFYKRqTdKX29Vg$_Vwd1_C%$SDp-mzv*!+7KE;%0usfcFmb zDpFrFCMw>$z|4t?H$J?@%#R9qdz)8nDJDAJf2o91c&G~Z)nv1%Z(h%76h@#2wRlZ$ zbd>)XRzEC{*|biSFOp>~&b%HK=N)D4h>7<;YhI0s_g_I(EA4{3ZOxq6c<&5z2cLV) ztFiIETUqX#tEc{+grc3&qNBWzn>*s-{hun(5eZvtP8mnKB2f<4x-zmU?HH zO=)upGbTRX+tJM7(=>O)$NR69V<3q4n3JNSn1nG+;{DUupB_NNhj{HERwMP_TgtrJ zB;MQ7jA|tYuTx}Nboo2=~k2lWTX^v|i;A@~A&EtJL zDp9-HxK5n^Dj{Vz$;9D&9NN%;EDzb4ROq|F3s(k2&q=7!}_3ZjUEM7FT(uS50$d?Xd7V zRXv`@|3ytj)lmL5?IG0ozpLIbb4Tm=@a7x>G>CuA@i=PJ|Dqm4jr)sQ*Yp=-6Z$WO zhnKDPPpXO9`Y#2jDhgJ7@?kB0&+}k|L-w~@m7B_K1RQM#U|I&B=VN_>i zC)JMf7pmb*KqgaEl+mPyd97c-c%+6I+dtsnNnA9gg_wKeqkKPMC72V;MqxE?&RN!t z$FMYqyqX%unVROfT>;;W^5dHwNuw*LQc9j2{|n(fnyx4HzB9IHH4fT z7YMbr%Zt7*m~IjwC*4~?ExZiQZb5hdG7tR8sG57X+IP!qSeh%v?At25ftlYn;2+Fw z*Yc*Hb~P|#+XakE4a{-v0{&PQUd3^LL`R2VG`ACSd;8zP(gI=M9R7w;&e(;Tds{~t zDqm;BQDb zs8Y)2#qykI|ckv6r_YqJeGtsEV+e*2~qytSWWCWt@7dA z3r^3QHjMIj#nOF1Ut34{=V7@iyGMsnm72$5$a1u#kvXnQz<9rrncpSgzm16;AdYsm ziVE+7_18O0H%Lzsv?oo0vDxYO2F(1f0l%L*|MY54EXQTq`etDbAYUPS3jYyr=6Ayp zG^>+cq53clOWExt{=-_#Yx( zWzm(6QO2qV%xgUYMzv;UY|nr(t(ln*9cpG?>lyHuCs`M}Xzne48dl$+WgKd5=JyKt z|3IWQ6y~iL<&S3!v>q`iF;V_ec)j;c>oC?sH?8WeIF;PAW@Dw?v@T;M-n4pfclWtz zZN~buloG9-4cw_O4XbA`rSBwGK+C^zdmHmwpMbxA8^<+8%t=X6{x`5RE7(LjGDo;y zoZdw@_>#czMlxin7fkVe6<+u?sjMrp;ihR zr`wycLjy)c2jw#Q+Z4Wv0s8A*Teq!03{lf9%)T2MvMFo4nZdD9{`pwk9-4}@?z=xN z7TLQ=CYLj)#Ld8RQ!kH7vD^slnN& zzIin@-k;pf*&yiUJJDenD#=NH3`?1v<6v>lFUsu1wZu|NmKds;j-`}zD>lm5-`$L@ z6Yv-9;grl&h>!9%He=G`eQ9X5&0YN(d3%`o=>h)-*pBD+ei$9fR7tQ8ZVwT1R+*;b zqQfwpX6SZ0g{6hHsJ#W<(Tn`%gs3=we?n?rA-h3OVJTG++j<*Ie)gJ8pN|gX22es; z-Z#qM&$SFwd*A$ zz+Z;@!`^7ky>U_g30O=6XBqP!#Zu?+3+tVq8#oG!^IYvHqe)+L-2Q-nKjOoPh3y5r zeLu%Z_A2Oq3QO(xncg&}7uNk)cAU@XPe<)TeoI1e=7jxm{yzxaM~afBcYTz97`Lj{ zgVJ)JepW%Yp{Sxn=rcIbKoe zYq4}gI}7^-EVfiqYU!#r&>0eE<4MC(DNM|?DBngb=Kz1r)jevh5k1I^Jsj{4VU^OH zaVFv#ELF)t^u;LO4_NihUGZ`LDTAFw*m2r%ELFh4#ftLXlEmaS8+VNJw;&{EI)gd^ zOC>u?^)5HgKJ54}yK#=A8w`=7HShR&i@m%%C2Yph*mBEEj1I$4rSy?wdAFfz8q1Y` znnHG^+H1CBwY+H+O?Ha2=bW!SR=homvk57Wy+!zsU^TZ()-qCpg<72;jwh=Gtj5aY zTQA+b-Z9QNlVV;w8t_*e7EGu+DIH4{b0e@(?88!#9Q&A7rG`6AXUJPd`8#1bUeeA! z14~m5zp#71f~6@GX6{Xn4oh`r*KKCgX;H@NRP)-~0sm)+4>;-B8`FZB)%SEPIo#>( z4y;Dzgn5mWNIC2d`J+Yz-KdF^g{6C$`(=ET|9LF;X221}({ILc`zBy%ESTKUQO3S> zGyk1{FMOoOGtk`Co`EBztoAwAzZOelMX@cTjI$%n{C5NXm{B(eDm}`dizN@?lOFgB zOWB>p;Ww;Kc44}w+h#b0F(>ifOf2<=Q`N*M|C?B96>CweD5G$ung4#k7@lcfdq3cR zC)0U+VKJfxey7I6y(T}?@6WNi*p|G|HH#yuZ8gn`@-4w?X%DjG{QRoEsrt%vTgQvhr^q>pYK)Vd4v+>eI zbKL2Gzi@7_QqA$ESn9Il0R1dn(}r$shz`SWM~i#zch_=eeWSdf+xH%c4#QAW?cLVc zn`e&O9xw_`GV`|w{9PtFUtZwEZBf1{SY6HQpEe33;QGB@l&|(=or|<6Od(Xq+?5^Y zKSxOZ#y337RhUA1YVm)`$()RERma{01 zn8B|V&;w^D_#DgWkLJPcGaa`Svp2d{Sn{;98$5-j*@Q*PkFgqIF}IlfH6L|`i@3ww zgIIDrakO|b)?h4Wa{PhC<0GC(nC14+m^sUg%?cPl&N9bk1$+%=vksUOvf_Lf3Gt{* zC~6KR+M!W|Y^~ZCgt#&Cd>)UdFz^ChJJ4&O*IT%${-KRK=bHm+m-Y93%sJYG+xzHC zSXy}Ojv1kko8!g?{DH@V>yI}fn(w`?jScv=qp`Tsf}aWDKlZLsPdJm&+1S@(X$f?W zbYElX*igj2Q_IbD4)QFI95FFCc5sVL8XM)mj+GR&jDhpaapMF2XXgc1aE<2oSbt_{ zYdQ}MPWBC0T086`h;hR-^B)fQJ3i^$g={J_qrFd>u@eHud-Kh469WEbmNQ!R3EIfD z%yAO~zAK2hl5b&~EMPk_CvX55Nl3%W;{=2JtZT7ku)d#LVCLrr{Ph<)V@;B%C|@!b zb38iE{~RIbcGHq~ZlRf<$7Zl7Sf0HNVP#M{6Ju?37)Emp_5#*~nu{Gj+NJtaurw>_ zA9Hsp76-KGIOBuG=C#QIWLDNrSsRZ_cCDCC^o$Z#B zVgD#!D_M4v#}ZN^Rsou@5i8oZSfqSkVDa3=7owG)c5<`CG>G!|#c~Fm9vO?CHe;s+ z{KpWrTrr_2sL(RU!fotGjj+@%yDvueGIQMYfU$L%nLj)ytS=e5M zm%DM!y89uPrmVBh)mY&))!9b}V%4|f_VPsdBvvgf+QK-zy26Z|9q{>AYEjY%_a@ZW zj@I_E6{{l_9>8g#tDG-f?JdISy~?~cC*V7P*jY2*DD#Xxnc6*bb6KF#%dk37f_>mK zE<9t#KEYG}YG>c2wG_Jws}D)AhDZ6wuW_<73CMm3tA*VFZKB23-dw*qCH2OVt4aA> zbQp%F7e{~&1q_`W?pWtEfppwA3$S|G2{q+@z^WUxe3jPQZs^}Alt3H%c798eQ!Z8B zvB9~q@W9w8e+E_?Co_$E1Iuj=)%Z3Bo62l4T5UAP%?}tOHktYJ1HOZs?3;qQQ~Wt+ zpqvMlmd}~vo(lLMLF{H1tJa^y(z@zQ!oc&6=NxMvmeXl`Wn6#W%(nu*s26nK>I9NY z$Z4M*p$}o*OzaQY9Bi%Tc2lf&PL&iiXR{f*FyMO!v4_1=ReLcQnn@e zvDLXHoKCjG>UPrs%drx$*y|sO4#SXdxTm=#Yrjl3J;VEk5$a~&oVyA2uroJp7v;Zg zThNy*SpH-ztuV}s)=|D^vD(=?^c6z=&FdQ)g>F~RbdNtr=zfxN0ODBl`F3;MvVi~2 z9l;@H+3+Xcv^azMS7FJaJf>Mu{)<>nOHhu>OSg*C?bw~c z^-rZw#By%LyNV|HV?ah!#F?lNO{#fR>aXY{SkMLWdZ>Z`e% zF4@{cH$x_&u4d!masICeIey!_DmrYBGjjHR=$nRRPYeIYgtQ_$$I07X4c=I4R4SHJ zfV%b?Ru{*A9EOnJhQ^0rjklpZ2alVwp z_H-t+ixBq}p^!HNs~QR={qZ zzGd2X#I8Exs9TLO@u->qLcqU60;$+~x<>i_z~TtIDbC;VEoVpIdk}VuXRz9n%K4FB z{@WhUgIFAed2sA-%$cOzLA|1kUyhmMUJMwWj+^-}2K?)fJ8kf5WAlBD#Zfsn&fnmj z;4PrrH3v)gptFf?!cs3-F`7mB&$=l&!0^>j^>+(ysY&me`7Z_hFC*#>;%kp#EYI(G zJj1YX!gQWOv07s>`WyIJ9~M6|zd7OM zIOBm6=Czjte&Yj=ea2%|85ZShfYnXWzL|tt+M%}z^{}&4J!!`B(2;!7ytbXw7`oc0oI07MeWF7#;wAfDCDhgq75z}hWHh7Qhh~0Ez&9PiNp#?5$oG+M zIA!cYsD&M}2s!Ca5Nd5}cYf^F>+4I1bkpN}D+uvDFrg1`YImNtzXwJeLMYmt&?CoFUjZN+E%-^=7GMLWd+W~I&C@b*=Z4HOn(kGKm^dWPA)3bOQWpb%hQ+v)na+!xkW zfFHCI^mBBb)IA|!08l}RKot%G(uV-)LxC=_>|_~S1v$i=^HrJL(x`cg;>xo>|L<6> zne3KRkflH3>SDEay8Y|-PQZ>r_%E#H&v13I?3u1DR>8AeTP%By%a6NyK@LSTfy#MO zzy7c5N#F-dWpMo`R>r68RDWevyd0=!tAMV5V#TikMZspbeh+6PJL5~Ru7a!zw*pnL z4crM%fFj^Cpn|>yO7|U5y6=Im|A}*zKp8J8HCI7aL6?Bye+0V3x~ak>{@-)%|Eq%j zSLLWfMQFIVnB4*VuYe{+3AaZDSyD+p#HHMLu@9SN!Y(Mn)x`>ybGf|B6(n*MWJ&rR zL9fRD4mW{VEvuvmxU#E@rQhZ1ce{E)R)ea$@ipA|e`4M4@ov00R|Pk9g@P=-8MXj~fp=^Iw9rzApE36BK04_Mxu+|BmmY zRJY*5@Cdhpf-EWB)x|}&T=@2Due~oE!BosqKIE9UUHh0su7a%ge~7MX&baXfS&sSA z&41R7{}1dqP6?FpoXg+31$^i71(&~vb^Q}--TT#zFUXRvxVl)utFC?3p16MzF#cw% zVZXZ>ue%w=3f^#Sv4Vf_ArE@_kZs6tSyQKwYl}7IifZC2VKG=0-QwCMU|j`S=}Mw& zp{(G>{}U_f4nCCrPB&daRy|c*Jy!v>>>gJT%dX+t1z82wbak`>{Qn-$lgL`~vcAibJ5+09pwbvm5k>i>bARX_>k zxLL3Ye%#GikkyYTTwSc-Jl8JBN@u$9^If)JmAe>L{1Vq*Zcx936$rY-YREILEmm+1 zA4<0tR{RFn-U##0v&pregVpnwB)Y78TU}eM{M%vaJM8UC0XO0mH=$SwcDcOU)&Gf0 zlJ0Hd?}0D7>BMTtZ>}v?@H!tV_lB!?4+j2;mGBQYqgT!5`d_g%$M1C>JVMB(oQ3#M zafM;EE8MkgG;PnN0+;}x>&*PeB28^4C_{%1gpHsE>D4V6=XGVx|@D>h&Uf{vU{$;rR>8|){&`lqyxQe;E^l=CIauYtApa}lORz4n z?Cr36vcu(kH(spZE?3_TtDsk5<$E3GpXUuel>eY>zX|JT^A4=^@4>oq6;SvCmp_D+ z;A7YR)aB1%Rq&O|-@vNiTUZ|W0WJ>TaP1Hh>sIi?#o*Gg@<;HY^2^K6KIsPj!Ya4| z3B(m$zQg4^U9JSH;;JzJJk?#j2CSaebM5+yePI519&+^oGPuMF4tDhQV6IgBj7MtfA1z7o&w8- zGhw-G7OYFGbSA8ZJn8a$Sm_tTy2OfK;@V=B^E9mdYhcxH2ZF4IY$Sqzp6B_{#+?tV zpq;Rm<0Gzp6xQ`mtn_cW@&Ck%e>>E@|Btx|#adWS!D{J8u3nIp@ndu~^bD-AKIf+Y z#!W9){_k8{Ec<&{`7gTq#ZdY$SO4w`Voj1iTwAORs!atLaAo)|Se~iv>UCjVVx_C^ z#y5tQKj6lT)xlP--71%WGPH)Jb#NoZ(mTPrefq+3y{>95)W%v8xc(FWr!Uz`HzTuJ z*j%M>iU0kU4JYIQU3vEB|2NjiO?LAYWa*E%x>!?fx_c8UU|;{l8lf3(yjb>3*A}bb zS*|UX{qMJI|I@c?!T5i_W&8JAwtv56v%kL6Zd&l$HLWSKwcz~wEt}(qf4^nZmutHI z{g&$zh(RPTeg3{W&8JAw*UXXWvk_W zoA$r@mTlY8Qr^6~ntWTbYv-wX*D97=Sohq*C9jvN@yTyDQl1?5RWGC0;^F@9GV^i< z4qN}m^RdR+HI1t*uXtO9BJJ=0aKg*O2Q(@+w?j;Pf2&_ZZ`s@)-lZj06+IHV=V;C& zd$t-CD^|W%yiD5_MVs`@?mXxA`l|y2r*^vSn<1x$-Tvvr4Lgm>d~EmOZ|=Pk+qhk9 zl}5{&d^~{-#p}6oi+&ED;%qMVXXwu*AM(DQaJA3ucgL4CA~Jt|D#<^3(eIPXkN+jN zM~_;cK4#wb#?wC)Iv?@Jn>jDtb*^d|bub&^a4!mWBN71}l*NuAd5^4-mE-S^#l+nav+#~A;hc@_POe^~l) z)$of;zwy64?5$mSPaS`~K=XzdY~G;5EqgYv6OpiXcZnB=r_G)F?)VCEcP(r8=%b?# z?EJJ%`zBGZzq9YxedQxouFw9h*~Bx)>xDo4%1>R2PIsAwt8mJQy-*#QRbr;9^CoOh7RAKEc%s|7EQOG>HG6Hr`|m~vQ69Pn$0{s?EHO& z9@}=~zBUbKRfrAwc3$J~4;#&yQn<_~&vie#G`;YQ)ZWXUIGVWTrBfMu%ID4Au;lTA zqmo{*btzq6-rCZ;^PO?4pNg$kW9#o1*N%$GsC0j#!X= zxY*Q~BYR7w-|<-eA)RU$%RJ_JGWvnAHCDwKn%B5--q0q$RlhTT%)#3$jt)$%U8mNW z_xBd=dwuPRscTxlU9$0}jhAloXT7{^=$KWdtA6?FnV6mzbNx}(w=7=!<(7Hgp9_r2 zsDjOlS~Q@;%xCwS+1J9~n6UoLyVJ(rdo^pyiB!_O7qt3yz<2DRUd*S@#9b2=!abH%Adur}a z3mZq3`(jD`5z!C#y7iuCUk@q%O7U{L;%ddZx?_0hp*Or zzNOc-sqHTId~vN&rQ(!6Z%!IJE2mt$vqiGn-Ln1U%C)~Ps5x}rcbiV_D>3`UK|dD% zeSDX0O;>%^Xm^EuNBRBQoA=;Y>v%JYJx8&YuN(E`Se?5eENFzVRl;~Hu`NPEV}$M> zAWX1&cSpD)VOMu=TYe~St^B~-!^rbk*Tj=NR+p3TWRJB$JjG)fr{G6C)`Q}y9_vN% zG>=u}LwLH!8YrIOvGT<;JyxlY;72{yF!3yp^_qCL$13+RJjY{Yh#&Je2>k*GtE}|_gs`><;qeHot={nn+a>Ihu-5W7K}c?gkk$lY zy|qI^+4cw(n<8wqQko(hlyFqSCM)6rZ%^-Y)+o{Q)*;agR%Pafce9lvdeN%h9NJ<{ z61`-d5^c5WwVdsqKGC%bs9$Gh&l(6-Xp zBBcsVzA&vr(HT*d1r?J4m}m*~>-b2_&6Jp63C0-n@wod&PaIe~`Xe7U&N zhIx-(j-Ijna;N9cd|9-2+rdvCEd5aN(^b>LKd5}^>n0s*M)+=9J#W#dejjw7zogpY zP6JD~$^Pl}4&`ble`}rY%w5!?CH>rC&23407j&WHmnH19nzlkn=!&qq6~Zp-l7uS~ zx+fs)u~sA?tm}s0YmKni>f9QkS9gT1682f%HV9!o5R%#;?6)=}cn?^9?i}wM)(+7@ zt7JRqkd-1jZ0!}jX+^Y$j##5aN3BDmx2(z?ptr3Y(J|||=(ttABbA(dkV@usq>^{7 zQwZMota_cG_pO4XNe$tu?8K*o}o6o&HydPRkyP$q#ErhIu{-o~r zkhiV1ygwb^s?fTJ(832$!Wpag021{YfUrx#7nVN}AuJIgEfL|YwL`*ogmxbvpBOoB z{*mu0?jQ8_1F7e{6)^~*>>z{*gAl&84oNsDA#yOn z1uJJTLiS*U(-JOP)sqmaB_Yg7Lbzm|l5kQ&;~@w?Su=+q%ou`jLBeG#W++1RP=uvJ z5q`DKOE@Q?eKNvTYhg0Nf@Fm25`MEXSaX)7iJAvyzLX$C?W>%4?>653}XL|6+m5f)@3Tt_gcJjzKabIzmO=e0hRGUH*C#^0bc@LG?4gAzRf<${zbuNC_($~h@Z zzeS1hTHi=nFj2YYp~QKu2fjl|$VFNG9ZF-b^`n$4Qo3KDTk%%T6Lf1`9>VD-5Sm)m z=OXl)gfM3=LNn`>gs{m7o0O%6HFF-qb_o}#$J@$^F%godAo#vVXl(LKC6w+Af|TePC{=$%>B%7ch;mNK`%-!{2tT1Ln29p=CzL*3>m4ZxkD@gA8Ks}s zn*1}$6)9(>Jmj_NUq)Fs3uXRglti!fxs+bBQCj?hGRSMq`voOz4$5UINx1x1lB4j;}FxJXhjBrlE>BSV1gG+y> zkOfaF$?quRajBGq`6yMdqfEf1*HNxWd0$E{F1>-W?kSY1H&7sGOu?mp zpoA?zIV)wVcYb{X-yqDNZ?rY0d*^?SoxG3)ExZUb@uwH1>>`xQQfA>#1LdHU)dtEO z{3#`SF-rFkl*jRB2uigjDEnWhmvgPkQ|aYN2~(#cn3jKm9J3T5Z2`i3YlnpBrx7YH zq-_?xK1OTLNvV1qWg!)vKv}R1#TQCNiy5X+DoR+6vQ^4bhRKI=MN0c8DR`N+@JR|@ zw*n!_N0Jqco09Zei4s1Wf>(L1B85=GR-vR7BF$>Al`mzxl!}E>)_SdBg;A29K{+aA zz1J!ihEjGl%7ieKjb7`pl!HL26Yfw&0d7j0k2uiiJD07OSY-Vwha#Bj; zq9|KfT#BO1Sch^!%2pPaVkpt;QI-}%*~a1`<(!oE;V3)2)}nBugZ0D)R_^Yj>H1D< z#b~;ou#qIbEQDQF=PZOP5_rnd$;LZI&UqFgX$-<%YqNx2n-EHmMc8L0jztK24q?B9 z{Z`3rgzXZtvJu{}a>gMfKaX&F9Ks>1`gnx0FCferkMO2-O2R=2jUPrhYR!BYA$v2z z1qp9kF%uA~y@;@M0>W|Yyo8ey+D}Ay*IGCcVa67O>k{6#TIV7}zl5+U7vTfzs)TbA z!Y3h|vU*QKSg;jgmxPZj|73)Oml4t?Bb>H&NVp=Q;uM5Wt&}MU>$V{rm2k$2cm$!> zc7zF!AbepRk`T57;k0J*S*!XqgzXaMOhfqEIwc`FAEEJdg!9(S=?G90eC2Pf_q&O+THw)n>tMe>`8M_g-O1NzG zo{bQ_2VobpnzM_44#GJJX>$;+T00~xcom`IV+g-lDUTr}>_s>#;kp&^IKmYP6COwS z!#X5k-D?PuY(|FHu)Z<1s_a9#&i!SC7*?D4T2)?0*)$);XIR&yY?spSDU`y7wc#n0 zq%3$7 zrTsFL@`kl&8A`$tlNm;rcB?kXUS#ScS{RWgc{IdZi;RBTGQX1o*jXYcj3~Qx09`A^o7*>~O;imXT z{D5JxF!nH-;Tdsr!+KHN0>3;5w=}GQ;#P+B+VgM%J%0giZCDxNHuPJ}9#Lg8+>Tz0 z+Z)z9;turrMYyA3O%`{e$KuY0ReuZIh5m}W8rJ8qHRDry(BdU}(A}`+y@V3|8OmiT zJq_!DttjWDtlo;!+pvC=vfvC#_m@%n(BGF)5Q_<5;teV1q;%hll7lz)qAd6h#rGP@c)al%O2P${ttfndIgr$cOOzXUa8J7{-zlkv4TKFbH^e+h4C0JJLBM9dtY&wFl(7GyN!LJDYjv_3! z)*nSkxPlP=7Q#}i_ge^8B>#tQ``1T|=mN3}Ka(attBtH-rhC zj`$Af&~b$A5+dJ0SZn3HgOL0?!f6TXt?KV0l)a8H=Us%2)+q@GB{Y5yVUsoUJ%sEV z2rb@6c;1@(K0>uW5H3sDY&AWBa8knR69`+ZnV))l&Yxl6uurkKS}~uIAli$t^fQEQ z)_Do%B(y(+u)|t-24R7LaQ%$8*|u&Kjk*SZj62k-P{IiF-On#Chg+kn7@tb>&fXSY zlIH_oD({hoZ$s|smF^Gzhn}I^j^Anw3bAgBFqYeeybwzvCu;J`%-b$Kz!GhX?aCl- zXyEbODzT3v9*IC~AJ6-hs_soCj0pZ0gZ!6nwTJOlu6`@16u(e>`?iuLjgH}NN*SEL_zfJvT!+nkV)4Xka%klWLZ9qjM)b4zE>`+vGf44d8 z)T*L<_W#QEXX5R4V%w_`RmM0u)R5r+I5q&yc2XSDrYpc~H zrA1zA7ix5!VbyMF3@j4-kF09fv0klaOtgDc_ioDhlHb`au8w@+G&wmdb9fGwx8TM1 zB38W$MtSRndr0@je0N-(g12q2W_;}3R-%EC5NgrkBX)_J7!mfwpws`@g}XwOu*k4X z=f895e_-494;Zl_D&mK2y<&`7UImwIyRDV6b83+VTT}?YOuxgr`i{{tCKFS`7G|p+ zPtaB>y+x~Qw3|l1;H+O?*Og^Wde^u$cMMUI`H`IdA0PYDD|sqXZ!ZLY%YB@iPQQ^@ z(N5*Ok{7IcER##uL^rQ~tv=h;^xm1$sW~~WCRgy!{txXu<6Kei^eLg*sFw;9p5khH zFF^k_v93p4O>ek-MOfEVS5qf8lTPw9KEx%!i*8=M{-<))u@QRVK)s*oCe#Zg?MbM# zdOuJJZv~y)%(GqXHnf_qHpkWUvUu=SzQ{8zec43D}j6EDz25TR+;cr(#hqkT&)V>A!u^ByrH~z0i~16%|gXdc{(iBf%5&M6T59mC|avnmqZktJQI} z%J4Q1y}OCaf#?3Mboy=U!I} zzRuYY?N(RY?dFX_D??cId-f1ed^A|D7I5u#6UGpJ%GF+TwOF)pG5wuDuQ8t{p$wIi%b zq(}Cy=JFPM4JYiM6SIljK_EwOaK!>F31C?fi?pTxCU4Qs_}adXv|K44}iu> zV!3qU)} z7O)j;19~H|4QLD60c|3kK^M>+^Z-3UZ_p4#foKp10=4+iyOY{wUZoPEK2W3D6(DqsZ+~H%c z+(}>=L$w^}EpOeoUlP_fs%^6dxD(t#qwWM12v?L1^w&JJD(FRqYv4DaH_1zZTY&-A zqOAiJf&MVVZ{T-u1N@T9$FJZT&>uz7`t??1HXaa!FBK@$S1>2Wg>h( zXaE*tn{<2@m<}ER)4*hq2a>@sFbE6=NkD)3ODmmLwg-TYZS47N?LQ7N5ksCx2ZKQp zCtk?3x2>3x!Pz-!XVZ5(vztejJjz`mL`JI7Y!|wrlf(Jn#&<{KWlE4r! z6eNQbFdU?UG>`!@!Dx^L#(=SUEjpV(4j2c<1N#+yD&9i44Ol{Jb7ThJcFgC;=l7RQ5TpgCv(S^~YkHH=Q^?^EdyPi%m1f%k(0awK>J zOaoy!xI6JZKu-{0CfR5!`!5q@-xi1Tp1LZ+DWjCd4{Y`)Z$o0e$F&ms9V=WTa03E=c zpfb?uRj1VwK!2&M9~cQnfebJj=#Ux-YJ)mpCE8tZRX4l@dmI=K3Z|=Pa4xP(qGyO` z2uHhN9So({2djw_6h67153boC+2=#%p!4U}G}Nn!dIng82cfSbtd&jcfsTq=qGy1y zAPppe0pKB^J#jbK`^iKD7_k}bjqW$9tPt< z4)uGo3CMRUTnREju(!e9Wuc7*9$AcopmcyTMMd z9cbv}(QQCpmHUSQc{CsF0J|iqpthh5XbqHET98%wYp%W5jZ?hzcHnie&kY}h-v9@I z##d!3ozlO;@8lRYbA#DFLi!LW3GJ|xoQA&upM$gDOK=8!20jHJ0~Mua2Ge~;I2b1_ zXe*7vDo3m`&uQ|=d0zt+BqwQ({*#k50KbFF-~#v#eD8*v!tZ{#2erb;IS@!$5)uz%5@)x0?iiHQH-z-Y=UeZ<}|z3f?EkIT`9OE z&>Fh}TN{Bih0DQmu#N&{3xq2W))~AKaL@9&o*fukOSPaUfac(Sa381->VPVs7SQ0< zglmAR;BKI!fEM{`K*x%Ef#MX71hos;Rmoo$yB^R{BcLNeV*-sp9Ebr?pdn}gqJefB z;Q^qtNmI}av;Zo+C1?d^0X4o2Xbm0({i(1s+zGS=?LbGMvyN_s4!N#46P^ktgGpcl z(ALu%=n&HlbOl{NFAzM`Xt?`eKM2NwRG{syFBk|0fQNw2ABkWX7zBobAs}}!A4wn? zq=4Z-393_Y4x9-xKpGeYbOIX*(%rCl49Ehb!B~(D9tP4YP>%9eg!5o^cp`WNO!4xZ zJcGb=Fb!zpFM(HqML_P9n;!>{fjQs^X>{XjZY%`aI~A`R$AsqsdEg0Gn`e#sfqAZC zRh*J62EnN%Z7Em@R)FO|r>tdQJ9rMP21>UMtOaXaThmnfCh#oS2sVKAK>9ZDJa|b* z-xmpN1}}gu;AOBCR0K*aM~T(n17I(xgSHcX1-uG&gFRrE8xCr+Uk9&&eV_sP?gRC} ze(Y}Ay|lcmu*0AR5r^P|K>9t{(%!;80`4Vz6s`up4G(Z_X*y~32mL@_pyTte=sGfg z2J86T8tB;E3aHGMxdd8(aBu>l7+e(iK^Q0md|(3=>48PhcJf3#_ygPk*THY#D!2lE z0hfV>?i--lgcXs>lm-+ zf%~kczZzw7^+<6yxDy21pvMZ;R|&`wDqn4@>DpCcJ%&^V)qtwglep37jfixG$B-_#dDv++RWvt)l@u(XU|8!=JD^e2 zI#V#NJ+>N9P*dd^mOg(=tLYV-)0$Sfnv=mfrTNqeXo{#oDnzd83^a%TUV#ee0yJ0U zg$IGWqc3iI0S$$wpj@vx(-mm^dx9RIyMC&pZ+um-DpMf}i&e3fgMyW+r%LyCO?Ubr z^hBWL;4_d3vnXjbU|q} zJY#@{NZUmw=nJwy2GH=RT&>P3TU*8`&`RU4R*nEFY$TixS`*f(S6r~S>b(jd?Xn70 zPYb3AdMSrAGe9;_*=cYRcnIhKp^oHE;bS^@1dIb(S%dqDwhQ%c0=f!QAxb|UJPd;A zrAyPID-P=FoO(PF4wj>emx9S?lQjOzFf?X*vdcr%Q6^Z3+&v9U1qCY(4vQM0hO5zP zq#E+~o-RgT1k?cyhXv$`S>Sygi614PRs}Q9$9@uMOf{A!m*6U`4O{?gE~vwrb7RofQUA>r>*-@55!z8#!Yja1pv)>%_Hx$_x>lZe z8f_U+CzM9R5KKD=tqk_`wzA1d7zf%gB?IEd=5Md z3N~&FwkrDADa0-#m|y9YFWC4j(kN~4+lGe;>(Oc<4YI!*k=ugq*i6QtCxSiK6Yr-$ zmAwM=)cZ2&wu7zUB^T0^b{nkpN*9b%x^viSNbuoUo=DaBtG5MP9UKCEEg`qcovQdS zI0Rk=d%$k66Kn?>u3#q$dg|4WD4gpZeTC0eq*0&x4f|z92P)NXSSd4QoVDP0L*FfX zwypi$*kf1&YKD~aK4rcAhY?Xm<=oCqxxd2i>2)6(KgRIZtzEBned~`ujEdgf^DBl# zc;B2K6>^{Pkug6tq`q;^n7=%vtZ~VhpC8h$ync=qPVN)CC$-ts{{1fvZ~ywW>(=J9 z9%WVbhTP|EVs#e{w`PjQSi8I-5#{HEa!exEYgcMrdH&#qm7&ym-+i??+pn}Pk$~Ub zFKUEDRM3xfE0FGul{b#{`ReR5q278FUYCws3$>aUA!T_JGBT6`8~U7t@4uM*#O}rC z1Aiv$V$Go>?`Z4O5a>y3udH>}M=E|dxzzP*vzp#D@!f@4e>USipH(6xq-=w8q$o#< zi@i?IFWzQrnLkq)h1e~LsZjpvth4vsa^laJa#la8DqoWX>f^{Yf$fvWf4l6@1Wl~D zYRmoB#t>ZMw#;egf9QzQQ^W0e`TyQEj_u5HDcBed;! zuMNjq|GexhqvkqxuT{@Sx?8Qb&_AS`SdYnZKV7$Sm9C++&`0U*t)sq>_TJf6`9dKP z4bGKdv7q#G>mI%3#EC*94ev=5{^eyPB@WWf@x<3BKZ$ta^(RYsx0JM>qw}1s-ehY^ zAsXm6{)^~+M>U-;3-pG*KL!&u-Smh%_BCIZjnZ!OTtuQ0G_co`3@>N2X zbzXkI)1i6|m?}>8vc~b-tXB$$lr6u3F;U~5TldrSE{irFGQ9QfXHLxNqK|aeJ38pJ4FTy)(y8mbL<6A@wVKfi3SDYkoL9Bzb#H!`lF-=)v?tX=`>E zmHa{qO{}MT#hx(s4Z4Hr=vGq9+7pJ0DiIq&g6DH{&z16DT<~Xt7-BTz5~g|D)LPri z{4=Jj74BzDhLJ!M?};DQ9cek{$X$OXm~1sAfp>}3N9ne@=}!Ij>wzK{zL@%Fx}(

X;9C@mEIH%rAUl29p7Qs6Qv^Mp0s-+Z_JB{^D}k#Gu!%&jWNh zt5%Va8et!jw-PC=yoiu8p$$3JSaY>v6af)C;%Y3YXt2PsB=#=G?kXA^u@^9w#1f;% zB=+`IV{CapbLXyWVg0_(`#is2{>Zp@&N*}D^f`BSaS}>h=#2$@wkLJ+76YiACG@wL z5-kCdL4<*^bjlL)J6nURbKb)6Wt)yyJ;Y*C5Yv%KH~QBSo6E$aOpC29mMpln-*J;1 zc4QrlC6`JtjtDEUy7L?bYJEkuji--mDd#`P$KP)eO|Sxg8)=c1H~~Kjz;K+MYM~wl z(I4`jwXuIR`iP+N#ER@cPwHGr4CvGg|Fi+XrjP~uZXW*Q1nBuShNuGMcMjlL+j-x7 zSGOILcN=D=0*3|2Ej62+t?%Hmj%~#sETE*JgM-9?MssTOy80LwAM zmK)*Z5o=v1VwVAR3vF=}tGIKpg8*at>sHTgLdw$D9}p;|*@H#-7&>5V}|A;vqhJLWd*^V`p+`VxKTo?Xm2J{-cJdYAwA<{ zJ_P3f7J*3lwMDhFapo;)rVT8k8XdHOrrhX?4I)f^@*9F7kowx#@ z$TvHOcOv$iEzXPv64cFg7R_~51UMEDk0e};y7Zr<`UVQd#rWT}VJ>UqbzRch ziH?p|^>`R7+}UA8g`gk*W-A0BG1F!{QO(8T)adig!}Vnjjc<`_&`n;8}g|{=YcF=N7CAA~PG&mBNRL)#;6^=d$-}lDcZ6^Q#5&B_ zVJ2mF$l5@&A%7ZX_IS}L;Hpa%>dV*V40>3h&QAu2n_h)kApQ~n)j;CxGFz7)>)q*O z0I>1q%X-??3sBAYeVJjVmN!K*+$IV{zp8I4+SIUrVSwm}8OGROg;`IRHG8qgFcarZ z-vU>iso>5HzF%w5%!RoIh$-Gw#;DI%AdbDz*2rENjpV5pY7u6b$SPD0Yp_c-@04L? zzc;xKhhq8!QXiP2dKuCTbIo}Z9rwIF;TJ&vHEueq#(_=+?7 z&)c&1^6}pkqe0A22hm>OBJ5qTM|$)MqB0NBfoeF2E<$Dyg*kxk9bhw83H{H3EhlUn zB?CK%uk4FjiLEI0^zU}sZ2e)(pdw;CO=wJc4sg5FCUgKageOhtvV$0*`J5A_m^azl zl!ue4=JgkMT!CNdVch%qG(j7?DfOue?fewXiv`^}kJ~fP9y$dGRxH3}e+{O5KnS;k zX?<1EQ~d;x-NDzVPHwAe8$yq(if+#OZ=$^L-mH!K^Vg9m(&Un)k%^oYoTybbRE7&e zDZUz{!?OX+sU`*rt3s)06u8+R%AM!d4708e=IufS5v$>jcs`V_Gl;(c!Rn~nMUSR+ zd}*`K0P$}qHFN~OmBPqpG{*X2ROTdB6$4Cos%vCC28D-l*ZB3a@3O?%o4bIh5>R<` z3g!XPc-;JNK|WZHyNSbwB@IhNtF7Ior&3O%1z0A4@9s4iU^-tOa4~Yps(*qo!|V{Y zbgvm{$B5okLoJ%Ja;>`RqgqYbrN1&dkW+Qh1;51ccC=W{HP9rZIoIy0KcwukwdP|C zD{|>Ln8E?ZHm51oaVXS(@hE+MsZCC91Ob?pzlegT=s|VSX;6h0oXf-cmftk%e%o3G zkPFMIm|-Pn_C?z*Z z%5a7T?OM`wXPhDUj_p6?&sH_ACEaxvo2my(eEH;mvb9pP9c^V&NSvVFn!?p^H)_pm zqVZCfS}$kko<&*h;}78@!DGf5fZyeqwCKBh=^(?*sn#@$;r;;#cAWj*H?ibG?hq3L zgsKg%qn*5e>bkagQL$mhy$xLjt~v}5jQY5<|DGE;v^3cO(W?#Fy1)%&T{&q!m($X( zxSTd(WU_60AeP2DG{}@?3kOGU;VX(50}@<50yhuRIDa4Nc1DlZBv<5tPG;@{luc&RJBR@qG!mBgtx{=t!}( z;VnvCsf2*fD<{RzP5z&U0F)lFb;PO_PIuyIgR}uS>-3M}CrXze?4OY~ zq%)4T)DZ)m4*-BghDBf9h+L-~SPU(KWu|=@z)8UIwz`KHp^Bmhy>WuldWeDQm0fsp zncIDhs@*EpUL->$obX%}A#CYNu61ELoCrnL6(iZRr5``5LVwg1-PPIA+yZ^qgdO;E zazC7{!2<}Q`x#9&>xo(v@hj?y9T_iA>%n2|s9Aj&2_M+gnEHq>^-(=DLtZ>(Ps_D$ ztyhC9b^=F`YfcC2qxkPc&+CgFoimXd*(otP{{FwO@)LM92BF}c1oidAF`S*~m`t+G z`YsC1Ta^ZWlsH;0s@x{%MjL>t51w)K8$LOw^yVRG=;~ihM$~me682>0M*OD)Sq`UO z)JJ|PtsSzv!;RZn7w5>XB!}nbed!EbP?*`5ZjTWo)DvQPIn?Tz&5jMn_vZjoK5GV= z%#Ed}v4|!s0AUN}qmG8mTm5t)OZ*DNHf83w=WA>P0Kq?w(y|eRn#XaBTfcTbn)1LU78npG z6KIz>TAqzMC>9V_pcy)_tbg{@LA4nKD-`@poa5;+qu~+HQ)E%P-}cmpiHnt0VFRJ@ zbYPt5UQDJO5KR&wnAPs;9MQV{*8N2QF(%oP1!~v$@B9jj|8O;{ISd z1zh!O;4-&Ll}axD_WfSwRvLsF_-Dn`!U-Vmn92cq>PFvtTIHcH02Fb0V8#}xA*)T! zZvLyyY(b@{&P0<+k-!xqQYm=?l-47azQt#CI6BbG$q(8EKaY!;a}u-=QyN1zv2j$! zR_i{53sL7SuCggDc?t-n97)6sQ`&%QCDXQUU9a~5Y-Q6Ba-E1^7*2yHqQCf88gElR z&E6Qkzq2q!W*9{97B!WYPQ)ToI=7wVMscfsy&e<*f)(3?_kRw`)a9CDYdVE|jZId8z?tp5NGqIZZ?U=-AXxB*JJcUa8DE1&Kez>h zi1aXvy`~pZAzvU!s>GK{ivjAA5N&8_GJ_#g0@8jy_=8;9S zCW);q8f9^9wa%jJlfmXed}i_-6W-uvfOj`bnF(14r?bcw5SqZ@+<45JrA{w)+t**- zs_aNDF=Go{kCU}`@4tRK`!ig%afsz3$hrr%xOoJ9+Yw{&2-?{ZHu7vFd4+*55AelI zHm2@D&4m1JKY=#00EiEmMUw%k>;OM%g?70U*-gRu;>c+7nSwd9vDA-^N5)bi8%xL1 z2{w)#NAIR!Pjkodlf-w2J=S1Lc)cKWHDXzr*E5L--jkq*mS7* zmq|SNO}KV1snfY8YDS%_`HnKPc-B9oPc%Hh>Wq)otZp)yXY<|L|4Oy_@fC|73Pgv= zbO6-Vv4CJ24z-B8{^w=WdIktR?<{BQ#iS0N!i90FI|j~7D}NTS?sjuA|RB+ z=s2C`<%yma?$deb)R#c|4Zq4WY?wRB#TnGD0nGP`K-p~c$fL~-z~72IUQ;yrzGX{W zA@3VOH4IN63~ez+mbe3ZH=p3)T{n)st3j6yQSN9Sy#uarC6BaTFl*zG{}<{CRZYPx z9+oEroBvX*SrW-kLw-y=CQC8H6kg$W*g?Cin=c3|MJ()<)fq4S8!spPXd-*v<$M^C z!2;NSuI)YM08r4GyI$AKpTUw@PByMnoQx39HV z^~k4%KBAj2bT(aU2nRpU(0-XsdA=}-JX`L4!p}ps)Z8DhwxCWq&n=llVZIQ#0;wO> zW%IbtIXHgjRaH101`M`CM5b%==m2O6&*#x)hFPhAtg)cRt$=T2aOk|;q35n11qSQw zLR(ES!<5zS%9wf$)QtzAipCSLq(z&p4{+6O@tJw}-)s9tOuAG7F|I3jQT)@ z#{IuqRIJs0%vuEkQ6fv3X;3X=ZlA8B9~yAEC_IG;1!Um|(ab6!FFzRO8eq6#wTgul z?+4m-3%O8lcK;~ z>C9TTHTvziQnV<+haBhD7t$$zVC*cUKmAd-Z=Fby0r-5pkdgynQu6x~C)$n^qj0H^ z%J59MSx8bK#s`Jen2oOsDHS8yYAmw|is%J5BA+;r@+Ep0i1CAxya{oQMqj$oz^+CI z)*MofmV1c0H$t8{38+3Yj4 zQrKAZtR1?P_mBu9D_s)~xgTyj--$^@3F5$fr%=Ec@r9K2Xcl6()O-DJBv!8)_*F+}{+s%zj6- zoF4%MzuvQ&^09!v*b}1GP;6%dYxE)%#;#O?@A4N&e)vnurTq&d$AGG9y(4yIrP81WtOPgwQ;5;=8kVK_J~UPn32 zz>M)#K2d|(xG*`%FOb^1p7OuKqMStsN(>iW)W%gXWdnT+9@UFCaD#ZPJsIWc@y|j< z0@(KM4OGT0FN;pCM!B+zJ;=eC9=z z3Shydh^910%rGvE@-+Mf3#?m2AuYg#rikZ4%S+D+dhWCwDs$n_QfTuc%4mTlI|HIB z_;j3nY{9;s>wY(Ea$phd0}Uagh!(dMtGfD|0JNBIjPh=9FWa;FZG{$QRu|DMhPwk04uDwu zbkx+I3*1?2g7x?ChUWxkm}zE&XKy$#KG<5p#jb7^(N*B8-vGi65a;fW{N?xRo!Dgw zr7X7INVcs&z0O9ip9w2V>@G_)S#nY!LNLQ{P3^LFEnU<`uXgxmyOOXET0MB6llNo-AL-T5Xc9f#W3DSHg1Hnz>GbYgSHZd6r+7F;Ln1& zp7&3K{C|56`Yhnl)b@BEsR#a4AbKVg-I2#v2*(^)erbe7uYVA(-+PUo-lwBJVnCI8 zIe>&$2ZI5z&<4JY?^hph%MA!})fS_pH=tn56kv+_ZR*)EJfiFf>`;lD@5S<|Z1rN% z2Pfm9M-hO!F6_ky_A+GQUiaAv``9Z@b~1)VebW9=7mq-j6p(KY1pRX|sWWS`DDJEm z=BM0z`q>zqk>_7H1q?4PjNv_9B@C*K*WpH}3zv#%UnkhVv3b2Ll_0G?y@!XhT#t$- zn-6lLaMs8hl=0~YU2q3nvyx!?^$sxp~YVE=>kk6l>v`CUn=Fku(KlEOJ+&n zSgZY|x^Kd8h?S*+JwM(+@35*qs;e!2;9+;{-%q^{#;wK)PG97~qawP3KW9L&Qov`v zd;Po3Yx*eigZudZK-#X*a!wI#$EYzL>uTo{#8(LkJG3 zX{=#)wFm0e>xa0;{KI2?ZXC@n1eqX|8i<)s50PC@fWJFL@jaoB<%kt53#}M5V)*EH zy+8YwfDxk)_0e|5zrS`@#|94RK z1m!MAXlZZ#3($ZsMVpL1*oG2y>2aU;3GMT9(kI41d40t)p>83?#)6Sf$7wT;)avx( zToAK$B_$~}{c;5rnhJQSg>Ri4ry>Tq@;JSV1Izr(?rVzri=W5+g_7fxmk7O&i4*OF z(&ID>6fN}Tq^ux#pCD~K=(IjTk6|PVy;kqxlzH{eLVh~@>-*8Od)yrQH-wBA<1GH^ zDJY!Ksd%)FU?M^S*wXV5nE+8J7oG&$Q#1*a%5^C^nILu*l&rf)729}aVlIU-`4l|YI)h+DH(EkF^@-m7~f=z73XBNTQtxEg; zml|f~*sszhQ`|@I9qi~-Tt>%0PdHXaZy54LAXfqM9kVm{s#VEm?>m^6;j0R_`uWZzbwTu}WTug}tLfZm5#n2V6qSpgNhxcu= z#%HPeK!lbR=O}p~xJf@x-wwoW?(Og|#*O9nPA<+1Qip>qPF?JL&oB3?pCVdW0l>k! zeN1BV&rJak$fFf}OiG5Y;mv<)GWsB$;3=#lm*)DP{TF_z-GsGsHE1Kq_8F4GE&O3J zUQLB6Jr>xl{2Z3nJw-fXG5VtX+a+54bEWISEK(1bH3(KK-_Gu+zgs+q?%{5+u)H?8 zrQ@;#zsyA$gGICQZ!pX4%u;s!+DW)xo8ocfQ+QFEHsd;(%8Y(v*OlcvrB2FC-1n2p zQ+Wu${ds)lrrbNw1C?8E>TukJV0IE@^4;4ygP-9Pp}a{o;df~xzH~2I#rLHy_qMOR z2W7|Q+!RLdMTRK%%CkK4fs};sFglO{6D#-PvkYCXcm!N$w#a}wx^1)%%!@fE0v z!{1+lQbkbk2=x5RyGw-*p$WdS$gW(myHxHU3>*u8b}4!UtVW^!{%>DmyH?us=z1RFlELym+-@3zpZiA@H zOtBTspDAVt`|6X$EYa1yLKhz8k4@kDrX;HKYDau#ZuWcD#1z~9?XT3N_OrxJ7EyyZ zjcx68%V&vu1>HBZ#m(+?>x}3|n_Eg2l(J2<68wW`jr#+rEF6vqS9v{)0@#W~XTX@sp^XqBVOGzf*k3#weZGj(W6_s({#{Hd1Bw)d8QZfn#Xjeld|cmWey4^--}gMYff^$@i>y zp`v^>oq_0Fe-fXmbdTCf9%dB3O{_@wcH)1|Z6sS&kZ!9^w5mX}7mI3L%>$yj3XAF* z926bcKlq0Cm5AoLL5IXE5*=73n(8JV6`z|?Xq03})6R&y>EspBgAQI6opq}(i*-~w ztEW3SN!6rbS(zy`D_U}=$bZC%Iy}o!RY*u1mf}4uYcy@~l3b~exfDh}cuMBF z$I()>$}%xCeb_MXVHpV{({!zSNce+Dea)oC^th+=lA<1oW;)SSicv8xtms)UDS*}{ zNY)kED^|{_&P-axX9HrSXbNv6nbHYg$&t)MBxhZ2jFhe_7$h~;{oPwSW=ei9MSJp_ z3%OlMkPb_9#tmzgdP)|$s_s$~{DCBE$*IzS;c1CkDd}n6{Zi8U)01VQnrhfcEp&Sa zNOR3>Q-)-uXJ&a1z)#{QXC!1L)0sMw8+mJ_rsQ=)w4<-yihZe@rQ}ClmWVF2-xCaN z=q@?XF-vJZ^*I2LU%T-pMGZBjR4h*UvkGazADmUsW8qzvz* zp~DkWsdBnxPdRCl5B+T}rBYFvw3v>nq&9r(Zw3RgU%KRKPF6A4_M&^@U`aRQiMYs& zTEB#oWW5yA>A_1eL09&Vm@JYuS(0??--?HX9V?|;DqST(dW^r$Vh;K>gC%Erl_q)V zzNsLE2=udslugA}lAZ2rD@h|%Oimc)ospTImCoeotc$mi(kfHC3P6HZ?a0hsvZbH5 zV5U<|DXl`G7c~9aQ`#h%r>6At#otJf_p38+C<$iN{+Q@Y|JIO9b*UPum89F#R9a?E zH(N*pDYZ2y!gDOC*>=%JH?yVmO2s|N?U3lE`=hmFry}pxlA3 { - const session = useAppSelector((state) => state.session) + const { status, session, user, clanes } = useAppSelector((state) => state.session) const dispatch = useAppDispatch() const ensureSession = useCallback(async () => { try { - if (session.status !== 'initializing' || session.session !== undefined) return + if (status !== 'initializing' || session !== undefined) return dispatch(setStatus('loading')) const currentSession = await getSession('current') const currentUser = await getCurrentUser() @@ -36,6 +37,22 @@ const SessionConsumer: FC = () => { }) }, []) + useEffect(() => { + if (user !== undefined && clanes === undefined) { + getClanes() + .then((clanes) => { + dispatch(setClanes(clanes)) + }) + .catch((error) => { + if (error instanceof AppwriteException) { + console.error(error) + } + }) + } else if (user === undefined && clanes !== undefined) { + dispatch(setClanes()) + } + }, [user]) + return ( <> diff --git a/src/app/dashboard/_components/ApplicationsList.tsx b/src/app/dashboard/_components/ApplicationsList.tsx new file mode 100644 index 0000000..5840046 --- /dev/null +++ b/src/app/dashboard/_components/ApplicationsList.tsx @@ -0,0 +1,326 @@ +import IconButton from '@/components/ui/IconButton' +import { Table, TableBody, TableCell, TableContainer, TableHead, TableHeadCell, TableRow } from '@/components/ui/Table' +import DebouncedInput from '@/components/ui/form/DebouncedInput' +import useManageError from '@/hooks/useManageError' +import { css } from '@/styled-system/css' +import { formatDate } from '@/utilities/date' +import { type TeamApplication, type TeamApplicationList } from '@/utilities/teamApplication' +import { faChevronLeft, faChevronRight, faSort, faSortAsc, faSortDesc } from '@fortawesome/free-solid-svg-icons' +import { FontAwesomeIcon } from '@fortawesome/react-fontawesome' +import { rankItem } from '@tanstack/match-sorter-utils' +import { createColumnHelper, flexRender, getCoreRowModel, getFilteredRowModel, getPaginationRowModel, getSortedRowModel, useReactTable, type Column, type FilterFn, type Table as TableType } from '@tanstack/react-table' +import { useCallback, useEffect, useMemo, useState, type FC, type ReactNode } from 'react' + +const fuzzyFilter: FilterFn = (row, columnId, value, addMeta) => { + // Rank the item + const itemRank = rankItem(row.getValue(columnId), value as string) + + // Store the itemRank info + addMeta({ + itemRank + }) + + // Return if the item should be filtered in/out + return itemRank.passed +} + +function Filter ({ + column, + table +}: { + column: Column + table: TableType +}): ReactNode { + const firstValue = table + .getPreFilteredRowModel() + .flatRows[0]?.getValue(column.id) + + const columnFilterValue = column.getFilterValue() + + const sortedUniqueValues = useMemo(() => typeof firstValue === 'number' + ? [] + // eslint-disable-next-line @typescript-eslint/require-array-sort-compare + : Array.from(column.getFacetedUniqueValues().keys()).sort() + , [column.getFacetedUniqueValues()]) + + return typeof firstValue === 'number' + ? ( +

+
+ { column.setFilterValue((old: [number, number]) => [value, old?.[1]]) } + } + placeholder={`Min ${ + ((column.getFacetedMinMaxValues()?.[0]) != null) + ? `(${column.getFacetedMinMaxValues()?.[0]})` + : '' + }`} + className="w-24 border shadow rounded" + /> + { column.setFilterValue((old: [number, number]) => [old?.[0], value]) } + } + placeholder={`Max ${ + ((column.getFacetedMinMaxValues()?.[1]) != null) + ? `(${column.getFacetedMinMaxValues()?.[1]})` + : '' + }`} + className="w-24 border shadow rounded" + /> +
+
+
+ ) + : ( + <> + + {sortedUniqueValues.slice(0, 5000).map((value: any) => ( + + { column.setFilterValue(value) }} + placeholder={`Search... (${column.getFacetedUniqueValues().size})`} + className="w-36 border shadow rounded" + list={column.id + 'list'} + /> +
+ + ) +} + +const columnHelper = createColumnHelper() + +const columns = [ + columnHelper.accessor('id', { + header: 'ID' + }), + columnHelper.accessor('status', { + header: 'Estado', + enableSorting: false + }), + columnHelper.accessor('role', { + header: 'Rol', + enableSorting: false + }), + columnHelper.accessor('name', { + header: 'Nombre' + }), + columnHelper.accessor('message', { + header: 'Mensaje', + minSize: 450 + }), + columnHelper.accessor('email', { + header: 'Correo' + }), + columnHelper.accessor('discord', { + header: 'Discord' + }), + columnHelper.accessor('createdAt', { + header: 'Creado', + cell: (info) => { + return formatDate(new Date(info.getValue())) + } + }), + columnHelper.accessor('updatedAt', { + header: 'Actualizado', + cell: (info) => { + return formatDate(new Date(info.getValue())) + } + }) +] + +const ApplicationsList: FC = () => { + const { manageError } = useManageError() + const [applications, setApplications] = useState([]) + + const table = useReactTable({ + data: applications, + columns, + filterFns: { + fuzzy: fuzzyFilter + }, + initialState: { + columnVisibility: { + id: false + }, + sorting: [{ id: 'createdAt', desc: true }] + }, + getCoreRowModel: getCoreRowModel(), + getPaginationRowModel: getPaginationRowModel(), + getSortedRowModel: getSortedRowModel(), + getFilteredRowModel: getFilteredRowModel() + }) + + const getTeamApplications = useCallback(async (controller?: AbortController) => { + const callController = controller ?? new AbortController() + const response = await fetch('/api/team-applications', { signal: callController.signal }) + if (response.ok) { + const teamApplicationList: TeamApplicationList = await response.json() + setApplications(teamApplicationList.teamApplications) + } + }, []) + + useEffect(() => { + const controller = new AbortController() + getTeamApplications(controller) + .catch((error) => { + if (error instanceof Error && error.name === 'AbortError') return + manageError(error, 'Error al obtener las aplicaciones', 'Error desconocido al obtener las aplicaciones', 'error') + }) + return () => { + controller.abort() + } + }, []) + + // TODO: Better UI Controls for: column visibility. Quantity selector. + return ( + <> +
+ {table.getAllLeafColumns().map((column) => ( +
+ +
+ ))} +
+ + + + {table.getHeaderGroups().map((headerGroup) => ( + + {headerGroup.headers.map((header) => ( + [data-is-resizing]': { + backgroundColor: 'border' + } + })} + style={{ minWidth: header.getSize() }} + > +
+ {header.isPlaceholder ? null : flexRender(header.column.columnDef.header, header.getContext()) } + {header.column.getCanSort() && ( + + + + )} +
+
+ {header.column.getCanFilter() + ? ( +
+ +
+ ) + : null + } +
+
+ + ))} + + ))} + + + {table.getRowModel().rows.map((row) => ( + + {row.getVisibleCells().map((cell) => ( + + {flexRender(cell.column.columnDef.cell, cell.getContext())} + + ))} + + ))} + +
+
+
+ { table.previousPage() }} + disabled={!table.getCanPreviousPage()} + > + + + Pagina {table.getState().pagination.pageIndex + 1} de {table.getPageCount()} + { table.nextPage() }} + disabled={!table.getCanNextPage()} + > + + +
+ + ) +} + +export default ApplicationsList diff --git a/src/app/dashboard/_components/DashboardTabs.tsx b/src/app/dashboard/_components/DashboardTabs.tsx new file mode 100644 index 0000000..00903b0 --- /dev/null +++ b/src/app/dashboard/_components/DashboardTabs.tsx @@ -0,0 +1,73 @@ +'use client' +import TeamApplications from '@/app/dashboard/_components/TeamApplications' +import Button from '@/components/ui/Button' +import ButtonGroup from '@/components/ui/ButtonGroup' +import Typography from '@/components/ui/Typography' +import useSession from '@/hooks/useSession' +import { css } from '@/styled-system/css' +import { ADMIN_CLAN_ID } from 'entgamers-database/frontend/clanes/administrative' +import { AnimatePresence, motion } from 'framer-motion' +import { useState, type FC } from 'react' + +type Tab = undefined | 'teamApplications' + +const DashboardTabs: FC = () => { + const { clanes, belongToClan } = useSession('/login') + + const [currentTab, setCurrentTab] = useState(undefined) + + return ( + <> + {clanes !== undefined && ( + + + {belongToClan(ADMIN_CLAN_ID) && ( + + )} + + )} +
+ + {currentTab === undefined && ( + + Selecciona una de las opciones de arriba para comenzar. + + )} + {currentTab === 'teamApplications' && ( + + + + )} + +
+ + ) +} + +export default DashboardTabs diff --git a/src/app/dashboard/_components/TeamApplications.tsx b/src/app/dashboard/_components/TeamApplications.tsx new file mode 100644 index 0000000..2a0d547 --- /dev/null +++ b/src/app/dashboard/_components/TeamApplications.tsx @@ -0,0 +1,14 @@ +import ApplicationsList from '@/app/dashboard/_components/ApplicationsList' +import Typography from '@/components/ui/Typography' +import { type FC } from 'react' + +const TeamApplications: FC = () => { + return ( + <> + Aplicaciones + + + ) +} + +export default TeamApplications diff --git a/src/app/dashboard/page.tsx b/src/app/dashboard/page.tsx new file mode 100644 index 0000000..6b7f0c4 --- /dev/null +++ b/src/app/dashboard/page.tsx @@ -0,0 +1,15 @@ +import Typography from '@/components/ui/Typography' +import { Container } from '@/styled-system/jsx' +import { type FC } from 'react' +import DashboardTabs from './_components/DashboardTabs' + +const page: FC = () => { + return ( + + Panel de control + + + ) +} + +export default page diff --git a/src/components/layout/Header.tsx b/src/components/layout/Header.tsx index 52d82fd..2c32dd1 100644 --- a/src/components/layout/Header.tsx +++ b/src/components/layout/Header.tsx @@ -1,32 +1,20 @@ 'use client' import EntGamers from '@/assets/logos/EntGamers' import Menu from '@/components/layout/Menu' -import IconButton from '@/components/ui/IconButton' -import Tooltip from '@/components/ui/Tooltip' -import { useAppDispatch } from '@/hooks/useAppDispatch' -import { useAppSelector } from '@/hooks/useAppSelector' -import { addAlert } from '@/state/feedbackSlice' -import { setSession } from '@/state/sessionSlice' import { css } from '@/styled-system/css' import { Container } from '@/styled-system/jsx' -import { iconButton } from '@/styled-system/recipes' -import { faRightFromBracket, faUser } from '@fortawesome/free-solid-svg-icons' -import { FontAwesomeIcon } from '@fortawesome/react-fontawesome' -import { nanoid } from '@reduxjs/toolkit' -import { AppwriteException } from 'appwrite' -import { logout } from 'entgamers-database/frontend/session' import NextLink from 'next/link' import { useCallback, useEffect, useState, type FC } from 'react' +import SessionButtons from './Header/SessionButtons' const Header: FC = () => { - const session = useAppSelector(state => state.session) - const dispatch = useAppDispatch() - const [isScrolled, setIsScrolled] = useState(typeof window !== 'undefined' ? window.scrollY > 0 : false) + const handleScroll = useCallback(() => { if (typeof window === 'undefined') return setIsScrolled(window.scrollY > 0) }, []) + useEffect(() => { if (typeof window === 'undefined') return window.addEventListener('scroll', handleScroll) @@ -79,65 +67,7 @@ const Header: FC = () => {
- {session.status === 'idle' && typeof session.session !== 'undefined' - ? ( - <> - - - - - - - { - logout('current') - .then(() => { - dispatch(setSession(undefined)) - }) - .catch((error) => { - if (error instanceof AppwriteException) { - dispatch(addAlert({ - id: nanoid(), - message: error.message, - title: 'Error mientras se cerraba sesión', - severity: 'error' - })) - } - }) - }} - > - - - - - ) - : ( - - - - - - ) - } +
diff --git a/src/components/layout/Header/SessionButtons.tsx b/src/components/layout/Header/SessionButtons.tsx new file mode 100644 index 0000000..6a26ab0 --- /dev/null +++ b/src/components/layout/Header/SessionButtons.tsx @@ -0,0 +1,102 @@ +import IconButton from '@/components/ui/IconButton' +import Tooltip from '@/components/ui/Tooltip' +import { useAppDispatch } from '@/hooks/useAppDispatch' +import { useAppSelector } from '@/hooks/useAppSelector' +import useManageError from '@/hooks/useManageError' +import { setCurrentUser, setSession, setStatus } from '@/state/sessionSlice' +import { iconButton } from '@/styled-system/recipes' +import { faCogs, faRightFromBracket } from '@fortawesome/free-solid-svg-icons' +import { faUser } from '@fortawesome/free-solid-svg-icons/faUser' +import { FontAwesomeIcon } from '@fortawesome/react-fontawesome' +import { ADMIN_CLAN_ID, MODERATOR_CLAN_ID } from 'entgamers-database/frontend/clanes/administrative' +import { logout } from 'entgamers-database/frontend/session' +import NextLink from 'next/link' +import { type FC } from 'react' + +const SessionButtons: FC = () => { + const { session, status, clanes } = useAppSelector(state => state.session) + const { manageError } = useManageError() + const dispatch = useAppDispatch() + + if (status !== 'idle') return null + + if (status === 'idle' && session === undefined) { + return ( + <> + + + + + + + ) + } + + if (status === 'idle' && session !== undefined) { + return ( + <> + + + + + + {clanes !== undefined && clanes?.teams.some(team => team.$id === ADMIN_CLAN_ID || team.$id === MODERATOR_CLAN_ID) && ( + + + + + + )} + + { + dispatch(setStatus('loading')) + logout('current') + .then(() => { + dispatch(setSession(undefined)) + dispatch(setCurrentUser(undefined)) + }) + .catch((error) => { + manageError(error, 'Error al cerrar sesión', 'Error desconocido al cerrar sesión') + }) + .finally(() => { + dispatch(setStatus('idle')) + }) + }} + > + + + + + ) + } +} + +export default SessionButtons diff --git a/src/components/ui/Skeleton.tsx b/src/components/ui/Skeleton.tsx new file mode 100644 index 0000000..8eb24fc --- /dev/null +++ b/src/components/ui/Skeleton.tsx @@ -0,0 +1,18 @@ +import { cx } from '@/styled-system/css' +import { skeleton, type SkeletonVariantProps } from '@/styled-system/recipes/skeleton' +import { type MergeOmitting } from '@/types/utilities' +import { type DetailedHTMLProps, type FC, type HTMLAttributes } from 'react' + +export type SkeletonProps = MergeOmitting, HTMLDivElement>, SkeletonVariantProps & { children?: never }> + +const Skeleton: FC = ({ children: _, className, ...props }) => { + const [skeletonRecipeArgs, allOtherSkeletonProps] = skeleton.splitVariantProps(props) + return ( +
+ ) +} + +export default Skeleton diff --git a/src/components/ui/Table.tsx b/src/components/ui/Table.tsx new file mode 100644 index 0000000..c1dd3c8 --- /dev/null +++ b/src/components/ui/Table.tsx @@ -0,0 +1,112 @@ +import { cx } from '@/styled-system/css' +import { table, type TableVariantProps } from '@/styled-system/recipes/table' +import { type MergeOmitting } from '@/types/utilities' +import { type DetailedHTMLProps, type FC, type HTMLAttributes } from 'react' + +type TableContainerProps = MergeOmitting, HTMLDivElement>, TableVariantProps> + +export const TableContainer: FC = ({ children, className, ...props }) => { + const [tableRecipeArgs, allOtherTableProps] = table.splitVariantProps(props) + return ( +
+ {children} +
+ ) +} + +type TableProps = MergeOmitting, HTMLTableElement>, TableVariantProps> + +export const Table: FC = ({ children, className, ...props }) => { + const [tableRecipeArgs, allOtherTableProps] = table.splitVariantProps(props) + return ( + + {children} +
+ ) +} + +type TableHeadProps = MergeOmitting, HTMLTableSectionElement>, TableVariantProps> + +export const TableHead: FC = ({ children, className, ...props }) => { + const [tableRecipeArgs, allOtherTableProps] = table.splitVariantProps(props) + return ( + + {children} + + ) +} + +type TableBodyProps = MergeOmitting, HTMLTableSectionElement>, TableVariantProps> + +export const TableBody: FC = ({ children, className, ...props }) => { + const [tableRecipeArgs, allOtherTableProps] = table.splitVariantProps(props) + return ( + + {children} + + ) +} + +type TableFootProps = MergeOmitting, HTMLTableSectionElement>, TableVariantProps> + +export const TableFoot: FC = ({ children, className, ...props }) => { + const [tableRecipeArgs, allOtherTableProps] = table.splitVariantProps(props) + return ( + + {children} + + ) +} + +type TableRowProps = MergeOmitting, HTMLTableRowElement>, TableVariantProps> + +export const TableRow: FC = ({ children, className, ...props }) => { + const [tableRecipeArgs, allOtherTableProps] = table.splitVariantProps(props) + return ( + + {children} + + ) +} + +type TableCellProps = DetailedHTMLProps, HTMLTableCellElement> + +export const TableCell: FC = ({ children, ...props }) => { + return ( + + {children} + + ) +} + +type TableHeadCellProps = DetailedHTMLProps, HTMLTableCellElement> + +export const TableHeadCell: FC = ({ children, ...props }) => { + return ( + + {children} + + ) +} diff --git a/src/components/ui/form/DebouncedInput.tsx b/src/components/ui/form/DebouncedInput.tsx new file mode 100644 index 0000000..d706709 --- /dev/null +++ b/src/components/ui/form/DebouncedInput.tsx @@ -0,0 +1,34 @@ +import Input, { type InputProps } from '@/components/ui/form/Input' +import { useEffect, useState, type FC } from 'react' + +interface DebouncedInputProps extends Omit { + value: string | number + onChange: (value: string | number) => void + debounce?: number +} + +const DebouncedInput: FC = ({ value: initialValue, onChange, debounce = 500, ...props }) => { + const [value, setValue] = useState(initialValue) + + useEffect(() => { + setValue(initialValue) + }, [initialValue]) + + useEffect(() => { + const timeout = setTimeout(() => { + onChange(value) + }, debounce) + + return () => { clearTimeout(timeout) } + }, [value]) + + return ( + { setValue(e.target.value) }} + /> + ) +} + +export default DebouncedInput diff --git a/src/hooks/useSession.ts b/src/hooks/useSession.ts index 2d8bd59..c54a5db 100644 --- a/src/hooks/useSession.ts +++ b/src/hooks/useSession.ts @@ -1,21 +1,26 @@ import { type SessionState } from '@/state/sessionSlice' import { useRouter } from 'next/navigation' -import { useEffect } from 'react' +import { useCallback, useEffect } from 'react' import { useAppSelector } from './useAppSelector' -type UseSession = (redirect?: string) => SessionState +type UseSession = (redirect?: string) => SessionState & { belongToClan: (clanId: string) => boolean } const useSession: UseSession = (redirect?: string) => { - const { status, session, user } = useAppSelector((state) => state.session) + const { status, session, user, clanes } = useAppSelector((state) => state.session) const router = useRouter() + const belongToClan = useCallback((clanId: string): boolean => { + if (session === undefined || clanes === undefined || clanes.total === 0) return false + return clanes.teams.some((team) => team.$id === clanId) ?? false + }, [clanes]) + useEffect(() => { if (status === 'idle' && session === undefined) { router.push(redirect ?? '/') } }, [status, session]) - return { status, session, user } + return { status, session, user, clanes, belongToClan } } export default useSession diff --git a/src/state/sessionSlice.ts b/src/state/sessionSlice.ts index 5f63ba8..9540946 100644 --- a/src/state/sessionSlice.ts +++ b/src/state/sessionSlice.ts @@ -1,5 +1,6 @@ import { createSlice, type PayloadAction } from '@reduxjs/toolkit' import { type Models } from 'appwrite' +import { type ClanList } from 'entgamers-database/frontend/clanes' import { type UserWithPreferences } from 'entgamers-database/frontend/session' export type SessionState = @@ -7,6 +8,7 @@ export type SessionState = status: 'idle' | 'loading' | 'initializing' session?: Models.Session user?: UserWithPreferences + clanes?: ClanList } const initialState: SessionState = { @@ -34,10 +36,16 @@ const sessionSlice = createSlice({ ...state, user: action.payload } + }, + setClanes: (state, action: PayloadAction) => { + return { + ...state, + clanes: action.payload + } } } }) -export const { setStatus, setSession, setCurrentUser } = sessionSlice.actions +export const { setStatus, setSession, setCurrentUser, setClanes } = sessionSlice.actions export default sessionSlice diff --git a/src/types/teamApply.ts b/src/types/teamApply.ts deleted file mode 100644 index bb50058..0000000 --- a/src/types/teamApply.ts +++ /dev/null @@ -1,13 +0,0 @@ -import { type Models } from 'appwrite' - -export interface TeamApplyData { - name: string - email: string - discordName: string - message: string - role: 'moderator' | 'administrator' | 'collaborator' -} - -export type TeamApplyDocument = Models.Document & TeamApplyData - -export type TeamApplyList = Models.DocumentList diff --git a/src/utilities/date.ts b/src/utilities/date.ts new file mode 100644 index 0000000..59ada01 --- /dev/null +++ b/src/utilities/date.ts @@ -0,0 +1,10 @@ +import { format, formatDistance, setDefaultOptions } from 'date-fns' +import { es } from 'date-fns/locale' + +setDefaultOptions({ locale: es }) + +const DATE_FORMAT = 'yyyy-MM-dd HH:mm' + +export const formatDate = (date: Date): string => format(date, DATE_FORMAT) + +export const formatDistanceDate = (date: Date): string => formatDistance(date, new Date(), { locale: es }) diff --git a/src/utilities/teamApplication.ts b/src/utilities/teamApplication.ts index e052992..69fc684 100644 --- a/src/utilities/teamApplication.ts +++ b/src/utilities/teamApplication.ts @@ -1,5 +1,5 @@ import { type PaginationOptions } from '@/types/api' -import { type TeamApplication } from 'entgamers-database/backend/teamApplication' +import { type TeamApplication, type TeamApplicationList } from 'entgamers-database/backend/teamApplication' import { number, object, string, type ObjectSchema } from 'yup' export interface TeamApplicationDynamicParams { @@ -19,6 +19,8 @@ export interface TeamApplicationSearchParams extends PaginationOptions { export type TeamApplicationData = Omit +export { type TeamApplication, type TeamApplicationList } + export const teamApplicationDataSchema: ObjectSchema = object({ name: string().required('El nombre es obligatorio'), email: string().email('Invalid email').required('El email es obligatorio'),