From 0be2a7712404ce1979772a6d8d0b2591277e7094 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carl=20Sch=C3=B6nfelder?= <carsc272@student.liu.se> Date: Thu, 8 Apr 2021 13:22:44 +0000 Subject: [PATCH] Resolve "Improve admin style" --- client/public/favicon.ico | Bin 3870 -> 411372 bytes client/public/index.html | 7 +- client/src/pages/admin/AdminPage.tsx | 34 ++++-- .../pages/admin/components/AddCompetition.tsx | 15 ++- .../src/pages/admin/components/AddRegion.tsx | 115 ++++++++++++++++++ client/src/pages/admin/components/AddUser.tsx | 16 +-- .../admin/components/CompetitionManager.tsx | 4 +- client/src/pages/admin/components/Regions.tsx | 18 +-- .../pages/admin/components/UserManager.tsx | 4 +- client/src/pages/admin/components/styled.tsx | 8 +- 10 files changed, 170 insertions(+), 51 deletions(-) create mode 100644 client/src/pages/admin/components/AddRegion.tsx diff --git a/client/public/favicon.ico b/client/public/favicon.ico index a11777cc471a4344702741ab1c8a588998b1311a..47e3c3fa2717eb81cf538764dce8bc4776ed61c1 100644 GIT binary patch literal 411372 zcmeI5hkF!9mcUu>?xo#3dmX@l0?Gj)k#kN4X*3$;1c(d*OfX<D@sGM)-=6op{yt-` zH+=WE+`n*D_391H$TOPhG&9oAZmL^7U7>%~UG@6at5<8*{KEXd=KsF?c8%F@vIp1S zTeEh}nl;_#pZ%%V{IkEf|0dpB^WksSxPNlOMKzJwAOHafKmY;|fB*y_009U<00Izz z00bZa0SG_<0uX=z1Rwwb2tWV=5P$##AOHafKmY;|fB*y_009U<00Izz00bZa0SG_< z0uX=z1Rwwb2tWV=5P$##AOHafKmY;|fB*y_009U<00Izz00bZa0SG_<0uX=z1Rwwb z2tWV=5P$##AOHafKmY;|fB*y_009U<00Izz00bZa0SG_<0uX=z1Rwwb2tWV=5P$## zAOHafKmY;|fB*y_009U<00Izz00bZa0SG_<0uX=z1Rwwb2tWV=5P$##AOHafKmY;| zfB*y_009U<00Izz00bZa0SG_<0uX=z1Rwwb2tWV=5P$##AOHafKmY;|fB*y_009U< z00PSr`2M?PFW~|R)GvX*e^b9@r{vWo@Hd{FZ>w7a<PHG{KmY<!2wdE^%|y?(t}|h# z>0=WPHGbs6;IW)}8_Ja<EuWezAB_%~kPQN55?H)yE_^t0#)MZ6>@?v_Uxx`t+Z#-n z-Bj#JEcHC<GyC=lt=}`5274FT27AAmz`H2#obVA=Q=8k&H5d16HQ~Lp$4zMeoR_@` zpXZM_fB*y_009UjN8t4O_f6sx-OVPP9k6}++(75saBG)6me8MfXWa3u3+D&y8R@%k zojh!g*;YJ(yEn}(E}lGS!l~XC6Am}8HQ`XBm4H;<*=UaC$(q{SYK~{N*yn4u-#%aR z?991m$3I{GDSP{T`Co(2V;vtay)QZQHWVhpM_5hwS!r>yXOjs>JDjZTzTbqiNS9;o z{3Z8I`1-=ExsnY65P$##AW#m0D+hO(%f`E`3@Fl{^gH3gbK84NI%hY2SWeblQ?mpf zX05hw!bx|c(;9C6#GD!LY&4-f8!E-UmFQ;rt&BIbr9FR5xTlC%!ccgMOc?w!lV3%; z9%)%`Xb&~oH*U1U*3O;Jj+&4S0uX=z1R#)W+h8C_ZxX$4m41JClhyf{?amDV*A#)r zqZw14u}&+|i>_$2-PXU<yy(@W4ug88=+6ZyL?IwDotLS%TA5nTjCESgpUB{2olWNW z#r%{B-~7P@Y!H9|1R$^?31phA&Lz55PWq);r=1af!Sk8%6-lg?Z|a39+_{~7CY0Vh zCsLWymPsAQC80-=Lx>xWfXLD!U5n&4(rT@3Wo-OG=5#GTnv@L!5P$##Dk3oC=3mG+ zd$?XB7)#`{T&uO5dO9&uQAxPCQUbI6cBFdHS?y2tS{o~|M3Y(w)(gigi9pZ-am-2J zVoCRC%xX>9AOHafK%l+|B%vwGwc1g$CrDxuy2Zc#NuHw{hxeL;!G_<NQ04=8ttPf& z&dPr!Nm%9F%S^wu5tJ{dT${CElef(ryn1E=HV8lf0uZQ80*T05Ey!EpJHD6ZK^b<w zIL5oI#n61fhNzq#nQK-90k8dXmH>m!Z^_*=-VaG_HZ+t90uX?}DkOl6RozN|d2ZSi zU~r?=S$TVT*Ke){Ie~kOLSSxNw|QnnuQl6meSEM%00IzzKy?WqQ>D-UVRq1DDl-x1 zx7waDO5aM{)k#1s>nEMB!m+MK^A!D!<!+EGApijgq)Gr8DjgZ>shgvjX|!`d=bc8O zMtgo|!zFXxd?<dvR%j?Q1iY^^xyL00YO|(9iz$A?CVH&rUN#6o00Iz5hXAruqMTnm zHOUV;@3XZaF?pZ&0l)Qr9MQ=OVh1n1@wn4yh&T7qb~^(!*S0c4xx3L0dv{~bo9sll z^=dWg=3t84Bodae^8U))x&b0xR!g>$@<<(BKeEr1nGFIEfB*!NBY?ydFWaBKk@T`| z%^vB~((h4&J^XZ^oeL(iK-PJcm9awcoFpFS=iT~1m-gGWPj8+$V8XkDCrv1;Qa;Yv z5yr<kyRPX<3LoXpnmc-sIc35-r|s%mR}bwr;li#hCY<WE>ne>n-@fveh+na6i(Qd( zyvs^eA~8uVr|;Q9WN@iXQ<%s1O~3{L2tWV=@e)8zikGLXq9R}WY4)7KzFPeD%j%l4 zLet_YD+QSC^TmSO{o(6^6Z{E*<Op1vH)&rxw8w<9>X1C8V)HKF6G307Nq=F;yvD4P zg_FB!QicEoAh0?KAYsN^@1hqGucJx#kGhhe)wE@st$t|4jW5btLGj)fsX?H22t1w2 znZk^_c>{xPl}s6Fj%!toVsEabpLHHtOaZQ3s2wDf1OgC%KwT3+8jW6kUyfU!=b~jy zTE{7J?wGUtk{nIeH?Ks$2~vQ-3M25^+|PNpQkbkTB6g$+uGZ@8Q760YDi~}KfB*y_ z5S;)rYIKI8xhbY)iR-+Kx=VfCJ&Q+F!~h6HBJk4A#2R(u@smBx<~WJ9ZRML%{1``X zX-EMA5P$##kXxfa1AcVh&Har_N)4tX{i)QHDeaRlq8FJIAOL{^0=k0Ttn*wcbJb<_ zvf$eo<yb~ua;<h1v=`?l3i9Vq2tWV=5GbDj@@x653a-3=+nkV@*GbF`pB?Bh>1UeO z7G%qx5P(4X1SWgiOs3PDttWwLX9W;Nl9jmPb3nAdm-cN>|E9<h0uX?}iXnhJ8?Gv! zObnZdN!Ygr?FCF0ZnQI88Hoh}2qZy3MqrZoik;}eQZ|xxND|denh=0M9T7mP4Odx< z$F2WMSpzLDkJvf}xxu9TbRrwBV8ns|1X3Wdu+#c~6+Z@Xw*b}(feiu>fB*!-5kRsH z$L-32ohG8Jh!a=8CU&y9Rx8=EK>z}^PvEQBF;mEF>!&7+%P)!OfyJ`v4Zf0T3n2gj z2vke}**0ANd3pa16EQZ~)~_IG*KnS7YlDX?6|o=yfs_ecyJ#|$Rl4G`P6$f3-~S=y z`yo3BKmY<OfB@2MxJry!a~qUy-O8WgN<}OPKp<rTR~Jl%NVkkOK>z{}s3ihOx8eH2 zD+hO(h>7TKk#1}01qt_f5Nq`i5b4&f>J_i<Hrs4{qM*B_Ie-8JAW%60q}y=a@YO@R zO+@e6GP(~Sbhnj1y5TC0SP+PpKyuQplbGN9G2Y^m8U!E!fz?0&={8&~Uq8CnL>%vG zGGPpJ%8+i6ZXr;g1d@<$`>j9gY>S<#_S65EfDHl=fB*z4B7k&T5w85jw@w{0$77w1 zCPcc;W8nY-tBpVc(yjNM;#TopZ8*7K2tWV=aS=em4M+0c;7Jp4w4=d<F{~jU(BI1H z@!?8EEC@g#Wdcb^xUM}I>#*O?Y!H9|1RxNO01|FEZcoNyU8O7_;m*4?>%*0bSP+0f z$^^tSSgf<lrnlG?ekZzFu?ztp0uX>ecmhbc;rhc@=ci4?5oaYAmp}LEKDTClUwgPB z5eotkNSVOPbFLj|wQG#U&<^-7UE2=K_IIXyFJuP+2tZ&Z5kS5TU7NSAnW))K)`w5L zeu1P;LYIq(5P(2x1jMFjs@Hv+I{9?E&+1>pg<{b^*<*FLm-cQ=?Jmd&0uX?}$|Hb; z8@f(kJ~dG@O&^<ZZoq0=!u4svSYppBv)68%I1svMM1%kY5+ZQvoJrV^-Ng0YZ?Rqz z<h{Rr`ba_rCs_zU00OIl0CH{gTFx|zY};j$3QDO_j%8d@R<eIQk&RwRQh)#iLJ)X; z!P*{V<F&1Ix?Qnk7;#n&FXpF0l#M75fB*y_AOw(R!#xQ<eIxOtmz#4oaZ#k#rEx{` zn{$2L!k%s6ib*U8K%h(l^V@sPmGQ2p8+@<l2JH9lko)$PBE2rNWLyRT2tWV=O9>#s zE@e{bne#igm?&cX7K3lwC3bjXr#sQpY;qC1hQ;IiD=j3~LtvE<c=P-Gjow={ha#DZ z<T%;eV$Q^6`5u%{<yb6*M%%3yKsE?K00Iz*P5?PIIzyAfgU?Mc-1LbF6YK-sd=k;u zjJp*dGL0Xa9Od})Gv1Ew(Oq+n4FdH@;IDoJBUtvAZcP3B&OUQ;xOtrm?L5oL&30bY z+*WIgp2YW|NS-p{AtNd#BWDe3_G}P<00bZqkpL2CM1Td+#h3X^zx9i?RF4wx8R>Or z-3X!_%bbqkW-AGcW@w_zYKCqe^Rv4G{pZVqlE3-7-~@j{pn$*+MW2xua;1B|Zk;@A z{t}(xi1W#jY5d5X8ELiav`+R~xlz8;Buq|v^zU216To;Eo>-BdApijg#7_We(sXU{ zZcd*#*x=?yZH;qoR5`M!N|;v1BXXw18t-f}XJl5g%-fQ1*v;>dal$D#CON;Y+g!P@ zyWfOY_H8%ewS&7%c>Ty86W%zoH-9W=>MT68+uqTEohH2KJOs(8?9^uKfk-$EH(PC) zNaI3D)~gp;U9J>4NOa3GpCxgbXo)?BtX46&@pq=QY!H9|1R#(c0c54**j{!$@<gY# zSDGEL-cHJqc9Ofs%TaDdkc?<a==C1~ZJ|g_Vs$y$Wo;uTx~!}<{!ZBF&eT_E??Ucn zs@vX|+@svDkQc3~%0eP@z716(N<*_+`bn5`GVPGlX_*_jamfU15P$##AdnmZB&Oup z22&QzgdeBrufFtDx;OT}x-lM+5mrMu9T?Lpi_a2$Pnxkrw<P1z561?B4;#l2fB*y_ zkSGCUr$q7Q6aV4A<S^H^(Hu-VO^1x@q}kt+*UBIuqo*=E`itDz{8PpO1Rwwb2&72> z87fWMlGi`Jlf8O*wHCxPF|C8JGGqkqqBH@qLmz6eb9JAeo07+g5CRZ@00gQ?0C}p4 z@C&lOpE+gDjJ0ntVLG!HOZVFRTFV4vgf-V@rE#-8yd!%;2tWV=5U3FXNLV#e5lf44 z{jxcibMltxwraV*r)=pH@EXsS_4#M#dH#q42tWV=5U4c*NL)2lBTpWh;w<d4zAI&> zefs@4Io1IIXH7425ijjyT{WgNLI45~s9gfcS?SAJKmJkjT-as3ISn>gpN_KfOda&_ zRh|C^9~m*6aPuJsH(FaPvt3(|Js|`j009V8kpL1^`tXOGr}pt~>l<k<b?=@?CG}1~ zq$+uGhMKI8*xRQMr~ep}BLpA-0SFiZ$WiG$24^>XU^4RFvg^f56<VkoCNQ_v`l=sk zwH8;G4p=YsY!H9|1R#(O0c5A-I1jqjs>ScP=nbl+{gB)x6!}ejeg{2&i_ff}m-OH@ ztKnGv#M?E0-r?Z9$ctBl>egfM`4JtI$WDtV4<+{)lQIM#009UX0?148J_a+cZxuUW z>0yI?Tyn==7IJ>AM7EjPV*Rd*&AP0%mus_niD6k!*NyeaYI3p;iC<r?$*%k?E6&MU zd@D9=UT5x9o`1RbLAM@@_{to19Q-<a9d;EUS#2iBIVe-5FGqRLo{e_Q&TKcY$es`a z5P$##VkCf+6bsCIw@flau4hf$R>{rBk{(**u<@=&le?@SGUP1Jv(Cf%tQ)hrar}V! z_32bjZuHhQ**||G`_SR{zn7>#d@cLG{I~3XTBZBK`&V!G-~VT5#1HS9sIM-}nDFk| z<0f3#Jz&D|?oB2X`#6zsvu<r^SqD)(l*v<=j_fw?tn)<1GzDXW00bZaffxxOr$vW3 z+0$wgnMv5nMkF)QlZp04*1K6eVdXHh-MbzAR!9K?RVVPHm;4I~vS{^n*N^Qp;b^;E z=}Epx#yjm-O7OcS37xTg5y@KGH(VJ^rfd*^00bZqkpNO?M1Ur`Xl#<u5{kA*dO#WF zo8Pus3jF-b=mjSQ2&^gscTU*(qM4?(CX{vG#r_}(xmDT&`CeRAkhxh1KmY;>5kO)M z2ln;Ctcf_%Vpp-5b(Vi|^?EucX?3w;6K@Wl+&2Lm1R#(cf!imoJezfXb>;@F4Q*WS zw4@{Rm2$1N&3G|CncR(#G6Wz1ffY{x=`~yx-#TW;+QlwX<;^y8Ca(T&w8M^NvOxd> zRVVQ5u_;2f*-D-9&P$V)V{)^#ww>SZM^dVOyA%Kd5P(2E5<s2}S8L*ZP1ci$OP-an zOqsJ3u2jT=00dGX;O6Ry=Yn`G5L9EkA%&YD3kW~}0xOjOvTeAU9q(*55#y3-B^_By z>&hYg6r-euKz$Inc4)V02PV4WYz<_#nfSd5*E$gk0uX=z1dwmbe+K^dJGpkGWxY9w zYgAHnKjQ1hBzyg0`32%i2tc5^1Rhx%cbS(Nmlju60+1P{)x9}#hX4d1P`?C_Z^PAH z#?2>*t4EV`WUSMa=kCpLg(4ONAW#(oFHNrE$3V2N(QWQU%FVbn461TVWC{TYKwt$B zK*|kQiGyx68tI9m_h?AD%$|cl-4b~H+%zJ{xZzq-VnF}`5J-*yGHy7w+N0T3wUKe_ zRyqk+`NV=i0Rg1k`mmfXs5btD00dS%0i@h;RXo`Ep^1nl7x@+f5cuv}q+Fz22tWV= zwMYOd7bzDh1p*L=MgS?d7JIjFZ9B0b0D+Z604X<IZ4NelWFpRO?KB}43(+Kma5X?I z2-FS%q+Fz22tWV=wMYOdH(XDNl#65w0SG98pp+Yrtv-Il!nMrAf&c^{5F~(<8>CVG z@u2hXGaIWeH}5O=>V@(P!j%w!Ky?W`x@YnqZu;1Sad{R*#;tCZk~;(-urdfB<A$rp zcs(r0T4&>3O{Or{kM0duBw|4T0x1*tB74^4INH9^gz>HpBQkT!w?lRifB*zm3<2cZ za8;RUj#FbJ7QF?&a>EsjSP+0fY6QGwyQRbA7~L*E*bc~u&R@Ps?N-PL0uX?}iXnh( z8?GwHIvPww(YeOer_Hz?a=hDWaIYTR8LnW&f&c^(BJgnJj7d4yw!wsPX=;P5$7D}S zLM10z2tWV=tAPMAZMa&#ymz~aIMLH=!gwWH(b|r<e)I0&$#BIZ76c#=oxtVuCXMW- zwI+<qnpR|3X)`9o0_g}ANVPcYI{M>73J`!mIs}kpLvy}-&O{w)S!cr8{&+ls1vNF& zbB;QR_QI}#(8VMo1RzijfjgfaHJ6RFSh;m(AWmBXd9US-&NkZ?!)&)M%bpMd5P$## zLJ&w&e$9p`Pd!G-Y_wi&=Lh1KVT1kNq|^G!e36GEc0LLl1RzkFz~BFz|NWZvDUxel zZ^BV$8x*f@HTdm0=h}k7#!vE@a{vJdKmY<!2n;z7Gt#;S+uLx*v;9^_k!!KGVoxSV zq7<x-;$GO*Z%RAay~%{}+7JY5K~kP|S|FKSB6W9R*A`*5i1r2neiadT{=_`@i^mU| zaAcF!U}pWuhi!wBuvC?|(U17MZ^w&!x0<}zAOHafKp;8+(VoVoNAU7!tCdF|j}1pJ zULB?I%9M4uIev?`piCM(7S{45G1+TnVd<4Kjn*T=SZAXNFCExr!lyH%CN$gQ`?CMp z@E>pWOh5ZOCm|4m!0Trc>C$<#zkTws38(w4#F%Zix<&EdG2x!pc{evPuC^%nt}H#C z+iKS_7;+w<%>f$(AW&Tb&%ZSJKOP-2;o=GVm3iaXej6UG@9?@S|4nyC7x&rOFO$7? z2IkT>DbktEttQR6t=*Q`u>&qlmYdv{<aO<^wZxxtWr%baeQhS4N>lKfI%k0?KDWKj zpxe$e%C*_?vf(D%+lV(*k$Fd2KQ(7WPMUK0p5NYU&RpDWwTqYc?=Yd<m%r0Ge-7n6 zx^`rry*notF6_28rRR5UHlgTm#vL)4LzQv;vl6p1Wwyl<8+U!R)V1{05(@K5>n_~& z!O~trCxrY0fhrNmwOb!08D}RTqa@OzuDo!<wT<E0t8!vVi&_P4UAC7jr-W%<qkX#l zQk4EhG#$RjapRuB9%stQRFgec4<a=sUdqQio6MOiP<6dzy!px<O}P4+aCbW8e0j)| zQ;eAB=A<L>{*z`sF3n5Ili|y|N-ef|9oSYmfn1yIwWl`Q?@-Z%i9{`J$Vv^Dwng!t zsTQ|*@1hE+ZD}{p;j{~@#W4MR<$iq_O7D?oP0ekynx#QEPrw{JePjYQ2tXh;0?!_s ztVDM?@ASNBzW?L}0SMF=0pDjg*tvZ#FU+LYP>~S?AP^+*Xk^g*Df)4-+p4dYgwjF) z0!b4P9mMQ_wM;v+@dFdSUYH9uBOF5j0#zZfc+%QbiS3KLr%AU4qz?fI)C&O_MUzqa zOoO$SGutz?<O~u(ptcCyJZWvq>B;M*Wu=@DNSZ*<f<5Crv@AFuBhrl%LI47_OyJ(& z2~#}3UZ%4RPP)Y)eF#9Hb_j@NyXelPRKsrm+L&7@$TSX59@KIJM%f?$fuAMtd~V8| zA8}r989T3?7MGGhAZ`M79zf8qksOPzF5~RjCY`0cx$NGppKUET2>}SyDS;Q(15CW@ zdBoj9h4D{986dDa33!V(r;!WJ;-BiXGf#8v8%-!4W=5RP$UCQx)M?X2u^|9~a0Gt* zTH>8;{Lmbn+umcs={`3nxaQ}@uFiIyyIw^Emd?vx(w_%?^GKgBYrW;%+Ql-WE^_^} z^AY%9_;kLhc%47u00IzzfDrg{%C2X0dfk7RaB7SF?iOvJ_W<VBr{fp`5Qv$8^AsoV zTF@($NIc?eZpy8_HPO*%-pX9N^RK&UtvQx&dGV?~?9NPdTmO5P_H8qvywT?1#aAX^ zg8&2|5F>%RH%(&F8p<lU(gukqYq19+ga8Dh5XibUj<SIj0L3;(zV*f9?NqN_jX<pN zF72^v_T6&pA3SoaJD5MOT{MB&Uf4ASgWC^(2>!(}1Rwx`nj-K$3#Gl&WY<*XP#6e6 z00IyY0&jjV`yc!m`%iy@3<Mwm0SG_<0uX=z1Rwwb2tWV=5P$##AOHafKmY;|fB*y_ z009U<00Izz00bZa0SG_<0uX=z1Rwwb2tWV=5P$##AOL~-BCvQ~%6oJ`_Rni*xuC~> zse^?HDci!h>?gbv#mpi3`_wMk*GT9cJ09tm@?4v#Zn>V_m;AFwWq*24`Q<sYPp<vU z@5_%_-75$ElW}r)xN;odA@ODg%a4C%zg$~Otj=3kf@b^7*ZEEVwwHfbrLVj)Ex!-@ zXY1?%`TMM0YS?V~zx8~<{!GE&nZpuq+H-$o9UCRIUG}ZYA>Z;Pl+Ciq-n%T99I@_V z%%-j0vJum{;H6}9VN~|RzJ><1h70!vHM-;p@YfF?ll0EzWdHmN*~b+g+b${1566{a zI_aG9Z|Wcm0wnd~r&E#SQg;MC{k0Ui@i(&HW*6&7dFyYK3^)F(?3;e;|Na-*uk&SG z_p5iW`_&rx`@uEYS1Ua1d$INZ{BHS@E{}e<Y~CO_X&r8QU;h53=VSizJzB6t7suqU zwZD}8N52UETKmTz`n&tsm;2Sj(q-P)Ex$MTr%dm=bS(K*^ZLZII`4b%a^gn0X2i>w z&Hn9d@iqI2zvt$EFF*C$=jGZqyYPnDl*6b0B!3saW%<AL?JIZh-%?Gt!Ixd%j@&WH zFG{%9=ds?GJ?ka3C}~z2x8dI;MuTsy^ewD3ohaAOXC=12@!EoFtFA3(eqU}K>UEy8 zJ_{Rs3#a$K(YMf-r^>&JQ~vu@pASu={1no^a`dF+sn6R-Z(G*%3qy_&ScL>SK9Za6 zTr2y7ed$2ZwzKOK$*<SCz&D#psXII5@6&r_uR6z>jQl-2B>P$jRWs4<Wq|H=@s{eV z`;uO-mq?p@-{0}EoL5<3XM6ei-nt;ywtOIa<z9XY)xA<>v_QF^l`hdquiNkRPn_O) z=~(is64yA_XUmCI{xvF*HhQV2^>-4tO>4(4;bOL_&&p48%=fOJyeDzG{8Op-aA=F1 zANOM*b6)BRyPrBM>7Cpu`!?UQ^fk!eD&=4BUr2Jcbol1a^1HrS%4O<I>3B)}+ViQT zsvLLw7AlFnf@vQ1^`w%%zV)rXwK?H=EB~<dH|y(P(>c^HrD*fdqSm8+wLSN(Qn0MS z<E;N8(J!M;-&zH)skLL3{I$%1)}_{pN_il#A_-`FqwU<j-sEoc=vGNv-*;`}b)Q_$ z>8Jdem!w<0Ordg6r6qac+x^~+5>xe~T3@Qg2<W_DRhoxfuQF=0mwq(maH*vqtI_MS zHu}9O!PC;EP-}s9FFQ3=povt?W3$(0UYRVNSFvC9OG`Cy`abG&)8NZA?&Zs3>6CL` zWtuHsM%>a^PORFwMr9iPdhPLFvE`KTdn?eJO|{ReZB(12a?*(F8f^>o9o}gdi%elt z4XA2)b<8J)tfOS{Tq1As?NXQ5oh;W=W&B9Ie$}Z2AEhWs$DQ^17X50hw>CIwKBNzU zqzPybtgZ8M?M#&NXj`_~OLsc<6(!ADj$0@dE8}8ies))W(H=`RgW7|tG(6ChPvK?$ zD3$}YvqmZ|2d7HKjb3WKd9HM<jJFNYdTsIAFV#G%hIaIL>2#v}s?U&0hI7MFQcFMX z*a^u~pHOX6$|*@rO2vM}AYrN4OO^VB)pN_+@4x5tJ9fKW%(BFWWLyFcKS2NjKT9B0 z$=HvdcKdNaZQFjfU@PFHT3)CWqWa#;({ghv;eP6^*R(FQ-x_GlLs({HK7U=r10>^0 z^u=m*s9!Ex-_w2^Uv;x8#i?FdrBl@tN367pqN_$-b)^@^D~ewAi}kCaP;*#L!B(+k z?7yJ($<uGTa;VkXHEN@!-;+C#j7xnO)LQjX9thM00hPv7pP7cvSnXcbdP3Vc?d@XU z`;l(71=aLFSY{r9TFm7oTeUs*IzrV~>8NhNCi+EnD<28B5(!u5m8j*ST9N8=qW08% zeyl@%1yr|=C3m$M(PvR-q1Qs$$|-~TiO_Llwev40?kbja^LTWeU9E1e&*y)ti-TQ$ zE`s&}Xn;#9!0Vz;DI^4HjX*W!T$OiKCQ<!FY<oW&Nc#fSIB#v1TG-&{37fyXh9p=! zc`4W1`>Ir~J+azaD#5##gR!f7jGU{_R5|sKmvg-wt8+Qk8ddiJi|lfeP3;=hK<l@v z%De~q@<sSEe^gTkIyXz_59pngQ%I!T@4nTsqCP*fRc9j)9w>)kb+6H{Ms1b1x0Egq zHV&ov@GAr$u#|wxXWBa^smWD|R(oL8oGmR??VM4sxT<N`;5|_lE1}B8I)<$6xO%eE zK1tJ4{wj5wbe|VXJGt}Bg{w#+_BJW1!QbJvQCin(+n|!NYAHv(<!W;ESboZ?t=8vJ zM>#fl?_4?xu9nJ?zdH46(|Z@`_OqJwyHRDca_#`x_FZkCeyOW%ukQ6Z)GvJXH=w`g z_r6ZT*0Hwh`h8Nitg6=U-q%DqbziM(mdsRJrXQ$QIms6SE0uuCN-C@FPtbQmzD@If zWolKsRjjVnL*qu@wimnZg!fye)(R?{7rXx8fc&EJfy%jRJGsqkkIhvHYSrppgR4EV z_PB=DGFHrS_-;@c_xjw@+Ex9$_Tl>6sD17xZ@n^hYH8dw&pfy(xgFgmdmU#`SzFr% z-K!4;-K*TIZAr1cj*RzudwiAkJH4I0rdR2`>$iZuH{(^{sde0u&djrA5nY{<OAc(7 zz0MBS^66fg7w(s<)533Uon5PSs?SQfa;w&%`k-6(2CI0%{D@?(W!9FbibW!82&^gs z+LyF@S#rN`=aPV+I#r!Vrfp>sdBv6H!l<OAeX&|67E51cR^_Vgcd_e>o!6C&RCd+b z_$rmD->7HziltEg`P<$juFi9+lXlo!Br72$WA6K_()S*RysEP26)zu@&QX5-{HpBr zJ4SU}nwHAIBQdOKP)>R3@tS_`T|~cubzkYd=r^TWMC;tYO4EsQeO}h}ZSSs>{OU$2 zbFIZ~_umQnjkO#@U1d+(bFF{%w_I!Ym-U|0^gE(X+U8orNO>SoDS^ilK_xitwYM%~ z?Nn(t!RvKIUp>a_JRKc@zfpy`5D#uh3Ds-9wnW+!FSqWMu0Eg=vG#hw`;Ky~-rBWg z)O>V}E7hnx^xC;f^ZMvLiP7i1I_!AsA@oV5X~lcJu8uLV>D?0Qx(DUtc4CKIrM7%3 zi<T2t_3TaF8|YQ<AETVO#jd$~Nq$kinvM&rPEuuL?H7xsvr^9w9g;iKr&_;yDzO{Y z^$XOlLF@jg_X(Z?JOAybZK_IdTi*H(Ora2Um&Ge7v97kPera??p<Cxm-_c{=0_tjR z+Pj?CUOHZyzv{|wy4Hx=EvYR~nq?s`2&@JIzx7@Nw2xK0H`T3ZE3NOK+H~n&b)p~p zbar)>rl!7tbj3#Xx4+)c>Qegv?b}oaD7M#Cz*GX%^61~{ZCrJzD$(hx@x@B3exX#N zj9YRomaoqK(fd$|TkliLQ!IY)e9qf-e(a@KmG5-sl;)vwRoJ~g8*105dKFzwS8ddS zWh-`k*xPaFmzO>V#jX#YPeLXQrXM_B^m=n0J5hEzo~bJ!KVA&Rs-5FKJyMpnzm~mn z*7r}>DEROf^1HsT>;3i1*&Ti5$0q*6w+pTBOFBCKqwS2=v%dejFKk~los5@(B{d1( z_j%~^t!<a?3)`?_dFYq7e%%K1sD)#d+1Gm;Pi+(Qesm>cefIP^l@W(R&M(t(!NO-n zp9y_-^c@Jh*EtN@o@hIw_oLsuwNMw70Rk(DfXW#?-i}P$&Lw+4KSJlzYul>rxyos} zreLLvCO?xHYV)La0{JmJZ||q`LW=FxE>QPsYo*_mIxn@-@)fR}kd|Cnteh$@YCWmu zv)J|JoIkT)uG;D~G97*%gt9Egyx4h-r_Y%B&^>dooYIuOX8er&u5!NG=#`EozoscK z7Auc>I8yr<o!7LGD;A@==XZL~o!a+nAFXn)+NJL8mU3ne=gYgyDscJh3Jx>}ZDI6D zFWhTORJhl8DplOOA{qSfo$U2`o%vOmuKumpEou3Di>c+*RgDX7qw0UQ`qlN+@<hKR zRjTawV;nlxqbuSjQSjG~BvrM>QHv(^D4{HiwJ62TYdme0b-bn;tIH+9jWi)p?*w$j zN#D^uo%Mc4(aZn+pQEP{Orh4K)L_{-j!r<ok}6H979`$E%gpuR2&gQjU%o>zd~H=) z5|x?NqC@Sc;%@IMEf?39Ch*388<oC_Um*a2)j&Y|5*@8O_|`||YPkK>?ol<b+GlJ3 znOXtJC>8=g`u=l^_wcD&>2~i~sGLl6Zkx``yEa=+EUqa=;Kn)mMQ8OFyDrW1`kt%x zRW;V)Q2n;b=)2L!e4FMoKwc1l00iP9pd-jCv+LT6aivc>Lg1*MIiX{YI-Uxj`X%ri zZ%L|SRQmV*>!t5Wt!34kePOKh_58Y&fO@@J`iq>=F^@Y7#jZ&1eEwU^Tc1_K#zQUO z^x0G^s^spPlpz2C2tXhS0*Cu0Rh|DlJDfx=q^Ul6)slRFg5H^-oj!pnKV#tO=jG?E z_NHosW@5f7KlW<A^8U5_-B)1GU5#~|_xks|&3jn;!uztxmp_FA^{~?6XU$-T{O$@N zDO3SjKmY;|fB*y_009V;Cg4|joU1?^alD3nh?TxMeuV%8AOHafKmY;|fB*!71kQRN zaq}5D`|_de_jrFU!D~5&00bZa0SG_<0uX=z1Rwwb2tWV=5P$##AOHafKmY;|fB*y_ z009U<00Izz00bZa0SG_<0uX=z1Rwwb2tWV=5P$##AOHafKmY;|fB*y_009U<00Izz z00bZa0SG_<0uX=z1Rwwb2tWV=5P$##AOHafKmY;|fB*y_009U<00Izz00bZa0SG_< z0uX=z1Rwwb2tWV=5P$##AOHafKmY;|fB*y_009U<00Izz00bZa0SG_<0uX=z1Rwwb z2tWV=5P$##AOHafKmY;|fB*y_009U<00Izz00bZa0SG_<0uX=z1Rwwb2tWV=5P$## zAOHafKmY;|fB*y_009U<00Izz00bZa0SG_<0uX=z1Rwwb2tWV=5P$##AOHafKmY;| nfB*#2A+U!3AOHafKmY;|fB*y_009U<00Izz00baVMFRg1^a5O} literal 3870 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 baj7?x%VD!5Cxk2YbYLNVeiXvvpMCWYo=by@ diff --git a/client/public/index.html b/client/public/index.html index aa069f27..c3e215c0 100644 --- a/client/public/index.html +++ b/client/public/index.html @@ -5,10 +5,7 @@ <link rel="icon" href="%PUBLIC_URL%/favicon.ico" /> <meta name="viewport" content="width=device-width, initial-scale=1" /> <meta name="theme-color" content="#000000" /> - <meta - name="description" - content="Web site created using create-react-app" - /> + <meta name="description" content="Web site created using create-react-app" /> <link rel="apple-touch-icon" href="%PUBLIC_URL%/logo192.png" /> <!-- manifest.json provides metadata used when your web app is installed on a @@ -24,7 +21,7 @@ work correctly both with client-side routing and a non-root public URL. Learn how to configure a non-root public URL by running `npm run build`. --> - <title>React App</title> + <title>Teknikåttan</title> </head> <body> <noscript>You need to enable JavaScript to run this app.</noscript> diff --git a/client/src/pages/admin/AdminPage.tsx b/client/src/pages/admin/AdminPage.tsx index 270e2dd0..10e38f65 100644 --- a/client/src/pages/admin/AdminPage.tsx +++ b/client/src/pages/admin/AdminPage.tsx @@ -12,7 +12,10 @@ import { } from '@material-ui/core' import { createStyles, makeStyles, Theme } from '@material-ui/core/styles' import DashboardIcon from '@material-ui/icons/Dashboard' -import MailIcon from '@material-ui/icons/Mail' +import ExitToAppIcon from '@material-ui/icons/ExitToApp' +import LocationCityIcon from '@material-ui/icons/LocationCity' +import PeopleIcon from '@material-ui/icons/People' +import SettingsOverscanIcon from '@material-ui/icons/SettingsOverscan' import React from 'react' import { Link, Route, Switch, useRouteMatch } from 'react-router-dom' import { logoutUser } from '../../actions/user' @@ -21,9 +24,13 @@ import CompetitionManager from './components/CompetitionManager' import Regions from './components/Regions' import UserManager from './components/UserManager' import { LeftDrawer } from './styled' - const drawerWidth = 250 -const menuItems = ['Startsida', 'Regioner', 'Användare', 'Tävlingshanterare'] +const menuItems = [ + { text: 'Startsida', icon: DashboardIcon }, + { text: 'Regioner', icon: LocationCityIcon }, + { text: 'Användare', icon: PeopleIcon }, + { text: 'Tävlingshanterare', icon: SettingsOverscanIcon }, +] const useStyles = makeStyles((theme: Theme) => createStyles({ @@ -61,7 +68,7 @@ const AdminView: React.FC = () => { <AppBar position="fixed" className={classes.appBar}> <Toolbar> <Typography variant="h5" noWrap> - {menuItems[openIndex]} + {menuItems[openIndex].text} </Typography> </Toolbar> </AppBar> @@ -77,24 +84,31 @@ const AdminView: React.FC = () => { <div className={classes.toolbar} /> <Divider /> <List> - {menuItems.map((text, index) => ( + {menuItems.map((value, index) => ( <ListItem button component={Link} - key={text} - to={`${url}/${text.toLowerCase()}`} + key={value.text} + to={`${url}/${value.text.toLowerCase()}`} selected={index === openIndex} onClick={() => setOpenIndex(index)} > - <ListItemIcon>{index === 0 ? <DashboardIcon /> : <MailIcon />}</ListItemIcon> - <ListItemText primary={text} /> + <ListItemIcon>{React.createElement(value.icon)}</ListItemIcon> + <ListItemText primary={value.text} /> </ListItem> ))} </List> <Divider /> <List> <ListItem> - <Button onClick={handleLogout} type="submit" fullWidth variant="contained" color="primary"> + <Button + onClick={handleLogout} + type="submit" + fullWidth + variant="contained" + color="primary" + endIcon={<ExitToAppIcon></ExitToAppIcon>} + > Logga ut </Button> </ListItem> diff --git a/client/src/pages/admin/components/AddCompetition.tsx b/client/src/pages/admin/components/AddCompetition.tsx index b67714ba..7bc82f00 100644 --- a/client/src/pages/admin/components/AddCompetition.tsx +++ b/client/src/pages/admin/components/AddCompetition.tsx @@ -8,8 +8,7 @@ import { getCompetitions } from '../../../actions/competitions' import { useAppDispatch, useAppSelector } from '../../../hooks' import { City } from '../../../interfaces/City' import { AddCompetitionModel } from '../../../interfaces/models' -import { AddCompetitionButton, AddCompetitionContent, AddCompetitionForm } from './styled' - +import { AddButton, AddContent, AddForm } from './styled' interface ServerResponse { code: number message: string @@ -84,9 +83,9 @@ const AddCompetition: React.FC = (props: any) => { } return ( <div> - <AddCompetitionButton color="secondary" variant="contained" onClick={handleClick}> + <AddButton color="default" variant="contained" onClick={handleClick}> Ny Tävling - </AddCompetitionButton> + </AddButton> <Popover id={id} open={open} @@ -101,14 +100,14 @@ const AddCompetition: React.FC = (props: any) => { horizontal: 'center', }} > - <AddCompetitionContent> + <AddContent> <Formik initialValues={competitionInitialValues} validationSchema={competitionSchema} onSubmit={handleCompetitionSubmit} > {(formik) => ( - <AddCompetitionForm onSubmit={formik.handleSubmit}> + <AddForm onSubmit={formik.handleSubmit}> <TextField label="Namn" name="model.name" @@ -170,10 +169,10 @@ const AddCompetition: React.FC = (props: any) => { {formik.errors.error} </Alert> )} - </AddCompetitionForm> + </AddForm> )} </Formik> - </AddCompetitionContent> + </AddContent> </Popover> </div> ) diff --git a/client/src/pages/admin/components/AddRegion.tsx b/client/src/pages/admin/components/AddRegion.tsx new file mode 100644 index 00000000..658fe63f --- /dev/null +++ b/client/src/pages/admin/components/AddRegion.tsx @@ -0,0 +1,115 @@ +import { Button, Grid, TextField } from '@material-ui/core' +import FormControl from '@material-ui/core/FormControl' +import { createStyles, makeStyles, Theme } from '@material-ui/core/styles' +import AddIcon from '@material-ui/icons/Add' +import { Alert, AlertTitle } from '@material-ui/lab' +import axios from 'axios' +import { Formik, FormikHelpers } from 'formik' +import React from 'react' +import * as Yup from 'yup' +import { getCities } from '../../../actions/cities' +import { useAppDispatch } from '../../../hooks' +import { AddForm } from './styled' + +interface AddRegionModel { + city: '' +} +interface ServerResponse { + code: number + message: string +} +interface AddRegionFormModel { + model: AddRegionModel + error?: string +} + +const useStyles = makeStyles((theme: Theme) => + createStyles({ + table: { + width: '100%', + }, + margin: { + margin: theme.spacing(1), + }, + button: { + width: '40px', + height: '40px', + marginTop: '20px', + }, + }) +) + +const schema: Yup.SchemaOf<AddRegionFormModel> = Yup.object({ + model: Yup.object() + .shape({ + city: Yup.string() + .required('Minst två bokstäver krävs') + .min(2) + .matches(/[a-zA-Z]/, 'Namnet får enbart innehålla a-z, A-Z.'), + }) + .required(), + error: Yup.string().optional(), +}) + +const AddRegion: React.FC = (props: any) => { + const classes = useStyles() + const dispatch = useAppDispatch() + + const handleSubmit = async (values: AddRegionFormModel, actions: FormikHelpers<AddRegionFormModel>) => { + const params = { + name: values.model.city, + } + await axios + .post<ServerResponse>('/misc/cities', params) + .then(() => { + actions.resetForm() + dispatch(getCities()) + }) + .catch(({ response }) => { + console.warn(response.data) + if (response.data && response.data.message) + actions.setFieldError('error', response.data && response.data.message) + else actions.setFieldError('error', 'Something went wrong, please try again') + }) + .finally(() => { + actions.setSubmitting(false) + }) + } + + const initValues: AddRegionFormModel = { + model: { city: '' }, + } + + return ( + <Formik initialValues={initValues} validationSchema={schema} onSubmit={handleSubmit}> + {(formik) => ( + <AddForm onSubmit={formik.handleSubmit}> + <FormControl className={classes.margin}> + <Grid container={true}> + <TextField + className={classes.margin} + helperText={formik.touched.model?.city ? formik.errors.model?.city : ''} + error={Boolean(formik.touched.model?.city && formik.errors.model?.city)} + onChange={formik.handleChange} + onBlur={formik.handleBlur} + name="model.city" + label="Region" + ></TextField> + <Button className={classes.button} color="default" variant="contained" type="submit"> + <AddIcon></AddIcon> + </Button> + </Grid> + </FormControl> + {formik.errors.error && ( + <Alert severity="error"> + <AlertTitle>Error</AlertTitle> + {formik.errors.error} + </Alert> + )} + </AddForm> + )} + </Formik> + ) +} + +export default AddRegion diff --git a/client/src/pages/admin/components/AddUser.tsx b/client/src/pages/admin/components/AddUser.tsx index 81c6adc9..f55caa3a 100644 --- a/client/src/pages/admin/components/AddUser.tsx +++ b/client/src/pages/admin/components/AddUser.tsx @@ -1,4 +1,5 @@ import { Button, FormControl, InputLabel, MenuItem, Popover, TextField } from '@material-ui/core' +import PersonAddIcon from '@material-ui/icons/PersonAdd' import { Alert, AlertTitle } from '@material-ui/lab' import axios from 'axios' import { Formik, FormikHelpers } from 'formik' @@ -9,8 +10,7 @@ import { useAppDispatch, useAppSelector } from '../../../hooks' import { City } from '../../../interfaces/City' import { AddUserModel } from '../../../interfaces/models' import { Role } from '../../../interfaces/Role' -import { AddCompetitionButton, AddCompetitionContent, AddCompetitionForm } from './styled' - +import { AddButton, AddContent, AddForm } from './styled' interface ServerResponse { code: number message: string @@ -91,9 +91,9 @@ const AddUser: React.FC = (props: any) => { } return ( <div> - <AddCompetitionButton color="secondary" variant="contained" onClick={handleClick}> + <AddButton color="default" variant="contained" onClick={handleClick} endIcon={<PersonAddIcon></PersonAddIcon>}> Ny Användare - </AddCompetitionButton> + </AddButton> <Popover id={id} open={open} @@ -108,10 +108,10 @@ const AddUser: React.FC = (props: any) => { horizontal: 'center', }} > - <AddCompetitionContent> + <AddContent> <Formik initialValues={userInitialValues} validationSchema={userSchema} onSubmit={handleCompetitionSubmit}> {(formik) => ( - <AddCompetitionForm onSubmit={formik.handleSubmit}> + <AddForm onSubmit={formik.handleSubmit}> <TextField label="Email" name="model.email" @@ -208,10 +208,10 @@ const AddUser: React.FC = (props: any) => { {formik.errors.error} </Alert> )} - </AddCompetitionForm> + </AddForm> )} </Formik> - </AddCompetitionContent> + </AddContent> </Popover> </div> ) diff --git a/client/src/pages/admin/components/CompetitionManager.tsx b/client/src/pages/admin/components/CompetitionManager.tsx index 2acce64b..f41c1705 100644 --- a/client/src/pages/admin/components/CompetitionManager.tsx +++ b/client/src/pages/admin/components/CompetitionManager.tsx @@ -20,7 +20,7 @@ import { getCompetitions, setFilterParams } from '../../../actions/competitions' import { useAppDispatch, useAppSelector } from '../../../hooks' import { CompetitionFilterParams } from '../../../interfaces/CompetitionFilterParams' import AddCompetition from './AddCompetition' -import { FilterContainer, RemoveCompetition, TopBar, YearFilterTextField } from './styled' +import { FilterContainer, RemoveMenuItem, TopBar, YearFilterTextField } from './styled' const useStyles = makeStyles((theme: Theme) => createStyles({ @@ -178,7 +178,7 @@ const CompetitionManager: React.FC = (props: any) => { <Menu id="simple-menu" anchorEl={anchorEl} keepMounted open={Boolean(anchorEl)} onClose={handleClose}> <MenuItem onClick={handleClose}>Starta</MenuItem> <MenuItem onClick={handleClose}>Duplicera</MenuItem> - <RemoveCompetition onClick={handleDeleteCompetition}>Ta bort</RemoveCompetition> + <RemoveMenuItem onClick={handleDeleteCompetition}>Ta bort</RemoveMenuItem> </Menu> </div> ) diff --git a/client/src/pages/admin/components/Regions.tsx b/client/src/pages/admin/components/Regions.tsx index 103c2b1d..7f4ece95 100644 --- a/client/src/pages/admin/components/Regions.tsx +++ b/client/src/pages/admin/components/Regions.tsx @@ -1,5 +1,4 @@ -import { Button, Menu, TextField, Typography } from '@material-ui/core' -import FormControl from '@material-ui/core/FormControl' +import { Button, Menu, Typography } from '@material-ui/core' import Paper from '@material-ui/core/Paper' import { createStyles, makeStyles, Theme } from '@material-ui/core/styles' import Table from '@material-ui/core/Table' @@ -13,8 +12,8 @@ import axios from 'axios' import React, { useEffect } from 'react' import { getCities } from '../../../actions/cities' import { useAppDispatch, useAppSelector } from '../../../hooks' -import { RemoveCompetition, TopBar } from './styled' - +import AddRegion from './AddRegion' +import { RemoveMenuItem, TopBar } from './styled' const useStyles = makeStyles((theme: Theme) => createStyles({ table: { @@ -31,7 +30,7 @@ const UserManager: React.FC = (props: any) => { const [activeId, setActiveId] = React.useState<number | undefined>(undefined) const citiesTotal = useAppSelector((state) => state.cities.total) const cities = useAppSelector((state) => state.cities.cities) - const [newCity, setNewCity] = React.useState() + const [newCity, setNewCity] = React.useState<string>() const classes = useStyles() const dispatch = useAppDispatch() const handleClose = () => { @@ -81,12 +80,7 @@ const UserManager: React.FC = (props: any) => { return ( <div> <TopBar> - <FormControl className={classes.margin}> - <TextField className={classes.margin} value={newCity} onChange={handleChange} label="Region"></TextField> - <Button color="primary" variant="contained" onClick={handleAddCity}> - Lägg till - </Button> - </FormControl> + <AddRegion></AddRegion> </TopBar> <TableContainer component={Paper}> <Table className={classes.table} aria-label="simple table"> @@ -113,7 +107,7 @@ const UserManager: React.FC = (props: any) => { {(!cities || cities.length === 0) && <Typography>Inga regioner hittades</Typography>} </TableContainer> <Menu id="simple-menu" anchorEl={anchorEl} keepMounted open={Boolean(anchorEl)} onClose={handleClose}> - <RemoveCompetition onClick={handleDeleteCity}>Ta bort</RemoveCompetition> + <RemoveMenuItem onClick={handleDeleteCity}>Ta bort</RemoveMenuItem> </Menu> </div> ) diff --git a/client/src/pages/admin/components/UserManager.tsx b/client/src/pages/admin/components/UserManager.tsx index 7bea8713..d85290b2 100644 --- a/client/src/pages/admin/components/UserManager.tsx +++ b/client/src/pages/admin/components/UserManager.tsx @@ -20,7 +20,7 @@ import { getSearchUsers, setFilterParams } from '../../../actions/searchUser' import { useAppDispatch, useAppSelector } from '../../../hooks' import { UserFilterParams } from '../../../interfaces/UserData' import AddUser from './AddUser' -import { FilterContainer, RemoveCompetition, TopBar } from './styled' +import { FilterContainer, RemoveMenuItem, TopBar } from './styled' const useStyles = makeStyles((theme: Theme) => createStyles({ @@ -192,7 +192,7 @@ const UserManager: React.FC = (props: any) => { <Menu id="simple-menu" anchorEl={anchorEl} keepMounted open={Boolean(anchorEl)} onClose={handleClose}> <MenuItem>Redigera</MenuItem> <MenuItem>Byt lösenord</MenuItem> - <RemoveCompetition onClick={handleDeleteUsers}>Ta bort</RemoveCompetition> + <RemoveMenuItem onClick={handleDeleteUsers}>Ta bort</RemoveMenuItem> </Menu> </div> ) diff --git a/client/src/pages/admin/components/styled.tsx b/client/src/pages/admin/components/styled.tsx index 69040178..985ed510 100644 --- a/client/src/pages/admin/components/styled.tsx +++ b/client/src/pages/admin/components/styled.tsx @@ -7,20 +7,20 @@ export const TopBar = styled.div` align-items: flex-end; ` -export const AddCompetitionButton = styled(Button)` +export const AddButton = styled(Button)` margin-bottom: 8px; ` -export const AddCompetitionForm = styled.form` +export const AddForm = styled.form` display: flex; flex-direction: column; ` -export const AddCompetitionContent = styled.div` +export const AddContent = styled.div` padding: 15px; ` -export const RemoveCompetition = styled(MenuItem)` +export const RemoveMenuItem = styled(MenuItem)` color: red; ` -- GitLab