From b88ee376cb032b4b40c097daef6c106dd5a0c9da Mon Sep 17 00:00:00 2001
From: Taeeun Kim
u$- zJrpnslG43z`0PTMZk-yefW$*8BCos8za*!nwt|Pnu{WG*iCmy+i6P@#y>OrtvH?)~ zk^R4t**ntM=)busG%UN312JV1caCJfmqb0Mp`$CSMC9!4nNhZ5q0D*k9o@<*UhxB2 zDq{da1$jxY94qU5LZbh3diSIK^UK_?^xQ~!6~#iF%F(DD$On{z@y zVl`Ao(mzM}3*+h!moMp~Ixo%5C4*K1QwwAze>8?&x7-gDhvcNr5)LK2%oNlb#sqzy z{&Vwm-aKKPJ8QTZ=M`gTjo9DHp=|m@u0%dvZm~^PJ?H4gg(ZnnDH0_A1s+zr-ka0C zu1 zt!DKlznFHY3zrQx7?70}t)F#5e`o28yz7P(H3lp2Er4t|93!;2HQ6$LOZ;xMn|>_; zUmA=>q aBZJYbGzo?Nm7k=fqBsPQ`h~qtnEiPnYCI$wSoWzAr3~d zbnsd$ zgRWeceKv0t@?k$Y7LEz%UqKTdF0`Lqk0^joZ{;?hIS8+wk~$9Ca#E3 zK#UaIb2@6j`AUiUwv4RJU6&m9$^7G`KHM!Op|z!en2l?w;Z3>R_Vv% @D$W_p@H1e(ID|F(v8`8^OoUmrEZP?9dbegX#@r)?>G8?zCez z YDpwA2lS!b>BRLe49V76WwCIU7^00gek-&v zcFj?HBIgqyLu>-65OUC@-n|kkx`q5)B#opDCuaFOf2A&pb8JwwVYtllEXAA=82u75 z;{>hg _m^lalfZ184^G;;Cm}{fBxD`CR z8B{*m8>K1pMPUE#qO%U2y;mv7rCz`@2v`p=MX#!#_T>@?Zn`(o#52R;Qkhyuy(=@0 zwa#J0Zvy*^tTq||@GZ!Y2Fer3ym)L@Bgpstqq-*EpYU9tg0#xa B|rn-+vv(SwE#a@U#F(btSa zhz!_*g_(9Gt(Y?uo8#W58@=1GV>d%Igam*@FoIhr3{v4n*#j2uq!31jGFRW^NB=z1 zr70R7^yOEU^EEk|+L+|(wmu2$wqKj=U1`X)Go*u 60?|?1S`dy|th6LJKVzmxkuo$CLnmrdV~Dg?&lukl{fRIx~sNi(bT$R^ZVW zHp{AJ`f09^O1od_Ga#1-uRq>#xVE0W*E!K2$Z}$40yTenhY9~}S9CGm%X!sEObX+s zUl_cULyb1XM!%@)=Alufg=T_;gMRtt)Ku`=SAG?fu{ob9r~nwi(L1TrHlbVuRXmz| zHSBBnrQfi<5`sJHU0qXSdz!({XVsn@J18aG-O!L>FQQ5vo1Bs=A|j`4y+VWi@88bu z?$%hfL2_#9Diy9u<~hi%d1kor@U fuA#T`0?TpSqWe{cGyy&!P}{CW5iSCFzw7`s+HLQ#5j zv)|KdsU>YmF(jWgj!1ZNMGsh9ygXDJ4k1O>`(fGMY@wVppR5te()Ds(s>{T-oL-`` zk*4iOJC5Cls^|^2t*+@?=m-mEhNfBWm(`-X g%8{d1stXnkc+FHt}600@WLBnMJ2BiI|5tEHH zXl!uV-}66NQ@`mK41VX=wcUw&KR$t0E8{BMsv*i4C^$Uae!0KFvKJMFdQrAqa2Ngx zL;dnkthHfMB(WF+Cci4UjE6`gC#iXN=iE^ySy3lwIRnz6XE6S-*SzmPWN^HG%2`}q z9WaHSI3gq`H|E!U34eUtM}FPTE{6Qr-mah?A7?p!-j?oq^mG+ &2%sD+Rj^_%*D$2DP zXYl)q0)V|eRW0A%CnO|fP&8*jb~TLeY;OuA99GR%1d~Ha@VW7`sd1^t!fxH4{QK^# zPq^av+5b2#WSl)i`ZDqi 5x5gaCW~?FO~+de0$EtJM^SA;*DZroeA?7AsKl7F$QiA-k7JuZKUE>#0&^L zy)!p+XSq;kx$|I+$Dmp+O0#@gcYT7_eRe$G3e(abkc%OX%wgB^{|7BzCF?#(Y7(&4 zCC}ape20Ls%MFF1LtlM#`PN+9a~Bcl2D%CSew PVV(wvkmU0iLdS5^L2GkSnCfbWobQ}&>31L6pH->>` z6Uf*(Uk^dJXA#S0fJjGn`tDwj8|+oh9&Bu>W4F0}7I(~|&avZn#D?fgJy;A#Q=EVE z6D0AMt=MCIFX-Mr!;XkTzDd2Oc6xsQDPf_Wk2}WSyVv*44^p1BisnIIdB&i19EJM? zy_}}Jsvq_ua;KZJ!#ei2Ns12!|L!K3wKRT%z<=AWVhfHH3-Edc$L?KYu|nzR00o;J zLRep^ZvZFs7IuY}tK&U8o5upHHIYT+BK>+}Wj%uE<`H6^-Xv(It5PR=J+noJ^wNXn zf?@`X=zuaOeN~auau?I=3cJD-VUwJJPNI$oqR q+Aaim!3!kyqi@=+_v()>3J@zft)= zKaqTKwEi%$buh4*8phyH{PF!_H33^f;ca2h7xXZEIf>ibvFGR*QaP7jx91ir$On#L z;~(I^9Eu)qI89d&^>cAvOTTBPPalaw-^MN9H?|h}b#+ pzmArk6$Vr-Nvw%3syHViCUmgY~b^o|O9|-PmUS;M#=+Iyj18$YFI*NDY*K z_^V3VH8al{KYq6~=0>dcY(L@&5KRBEkeUhVsmxjjTRN7$Dg=XrC>Qeml7;`%y1#I} zlgbvkSXgeq?UK-Ygxdy&URWNAY0A#Y&JkIYxe_oR;a`y8R|b^CUp6@p&Q1`k^A({p za=1MVB|O;2`}#7~|D8aS?-2^OJiWlW`}X;RqsjJVrtHV|iE|U&dy$jJ_N^Qrzm oaER2gfVN8cK7N9csMGpBSD=hjBZ!E(q4tXyr=#%dmUW< zW)bfY1fBvNFzHp`y4WeLJPVFDafzL)Vl2L&;91wTqgy5O!&Vn;>HcKugmu93M%pcU zprP7=#0-VOmoK}n>)}Ha88{m_J&=Z< z&9y<{uVB@(;fJDKq{P<)3Lw`P?DZe;GK;6tj)AGJFX&D8H$@mgt?eJ)hs#FLF^!Yi zE#1uBa2mrG&xD5{NvPT4H?=ZP;TC^dcS_JvclTVJ_b+G5`V7C$;|DPb@!aI>91uXu z)Ww`?woB8cGqcq|QnhH#qbuKJj@bOLu|G1Dwf?WJUZ@0GLF_1}g*D3#&5;_fr>I9? zKL+=|^y&AA&H*hp(F%` +f^h|W)z&bRtdYA1dj@S7Puef}FkUA zyN&KRpyyMKJ9&kWbkqNu61PK|>RLlAQj# eqeK6MpH4AZS?dQqCSKP^WW&J xX)s?`!tj6ssyy52fx8plO~% zv51V1+I3lMvQ{?7MFP5ojB3@NXvyhJMq}In{Znt>*fHHTSU7*8=r8Pj?=6B*hVJte zsASlgI#rOn`|sFFxGx2on{RVR6aNRvhL*1|hgH0e=sIYIqF0@QnBoX8h42_GCZheG zajpi34h>lBPH@Cy%t`KRYZ%Yk$qpp^p@EwGZpcIBl=!)Ou_)=EWV0aQ?tcQDX=%<@ z*`9=Cbajzj9mx;R`4{b52sWd2fET$tSd2-VRvkE==sYsHv)~5F&dCt)^2w_5=Y_8& z *{jR i9T9r zBnyj4NS^;FOUuw*=}_B#_1)L 7vqfX&PGoGW&)igMC?SJ_D*5ibz?Y8^#^JfE zBS+YLzsdPf{*gL4HeVAFJb7*6+nai~hu91nd2@|u;wC=J5ey=E3({?O?t#^LPpgpT z_x1IQu6>D);qFOuVC!sN92umz_T6O$9bKW7Mo5X!;7b(oi^`*|`uD(LdNH*e!hO_r z97@^T)bA2OMfS{=xISz}GcXW2KA4soUwiIHVB9j{0aHp7lBV?*owR)sHY*&th>5rR zW{1lz#GH;!(*3)qo2zOo#Hq3>acPkY0)ACzHh?Jf%Tf7jpv9f)N9b{2qG;={(^5uv zV-83~?pb^}c{E*Tgt Zy zvcY${IUk08_il!!PR=6( ?# v;1@Ru=NiwyU zL;#0;=O+>A*`H?r!- )NvG;ua|? a#$CaWb zJTF4yz6SEc!w?@vCYymoY*x&tU(}D;{)yI%b3_LmMMdJg`}nye7n!^~RU$_d#Cnhp zyt!c3=lt1rU$5C16hn#@Zvb`?JfSpD4K`BO`L3v%y?6VMAuIX63KV=3xe~wfC2=M0 z$Si9r ^LOt z^D+0EUoB(pXYG4~65_|Gtlr{Uf59Ob(rM83a64R3ILTv}9T1VqB4ZU;w9NW^D&3(( zCR(3-s>z9DUlNh7ZT0lkT^UN2l*^~etxAlE0*xa^pFBHb%!f1p-_MMAt841i)Je=- zUcYuRZFV>$aR1f7_o~in{EUKkvRw*m7+K65U9#2l=%!oDD8nY__$Al#q0Q|ov95pi z>7*q9Dfl#mCM9t@^Lm{=&9oZAqxv+g8+vgmIJFSU^*DvzMkkZl>OH$8chxWZv8JZI zHy58Ho;jIW#728D5};IB8fhq#V$JnZ-*kBCdU@zh@kR^ UT{ozbP9vPlE(!Ww`{p%uS zmaurF`SZ F#>aop%<#9O zq1e-#ovP3xb;b}Bv#6EB&zi4cd-g1_BYfhPS`ocW2@nkh%F*R}rQ_T+V3(s}Rlal* zZ>vAr1iOB2b&F${4tXv0FG}(L71H`~Jnbwr^r-n?-TZVRa8D4Oq32tC)d1fHu0WDu zVxznzeZZ;oVBACr P-y@XBV&`#V4D0;+Rih#fW z%lqo* I2TSwiKf`TmjryTO)W0`#rmW8 z5ET-E2usUM&GCSs*$RZF?KLUY `b}aK;Zf&cOTaY!c6SVb24&X2w? zh~yxG&mRve%D&t`4y|}E>hGPZD_&?Gg`PdsGwlcPtu$n|ABRL8^*yI#>k>Aqa?{ts zqoBy$LN#g7ty;~9ZPJu!BQCGH`58Rsgx*kwGAgg)gZm7R(IB<%yKTkLz!xnNPHB zgXTWh7E-RzwN~8joqdt@`O}E~UfOX$0zXk_j6F=;%;lYNEo}IoPQj5YCvKf|n(G8L z)Wb6OU+f@n?0&RM89kn9MO7Icn#Qx&UKO*Zj1H@J7gtwrk$+J^IgZR>3%@YnNyr2t zzDG?<+;R~k!fhqhulZy(EBor;#`gENIaPV`(q|XB i0MB 12g>%e8EaErdnocej $VkWfQB2)RHkmlmUPO~8yRxAj7pe83yg)#-vMgQ* zA4RdOl>pV$)qglN&gJO9L*%jFj=U?J&PDf(qDY7#=c-5)*yPU2;^Lk$9RUX-#Le=Q zpJ2KzhMG9o#^Cy&84$wj!qWX7Ml;F7yd!*pmDZHXY!~XIZs*}3W5=4}Mzm|Nh9=C& zh`#YE1ou{sm9;M!KTSwR0u0RM#NWs=g=+_QMl Ep(y#LG;)S1O>i)0A0RlL=zfNTy8Nd-7DL8CAX#U;wh z;ztG@a@^Z8$)3N-q+>As@G;KxE1xD169Gp>UQy~WQp0mWD&GlmC6C3ljh~_&Mbz{0 zB2xR;bflq|^VO*b!Nz$%Glv|&DpMdp7P)UfOmwTs@TLHBNiv5*bEvMl+=3%UMV+K7 zt=YTgfq7ad3GHRhKn>il{@D5{f4P3D?ZE97mD+y1g@8JF>>QqjzF~YTclYAh+xb=! zJPKc~&GP~}dbX2?3{Tl;V$JnHA&7Qbkd>ljFxJ3rH%|pQg(sJxkch{-%;(o@+v}5= z`3Lj@@C6amT NXtY}}0v=tZHl4moAFvQ$i#2>ZJBH);79 z$@_(2CZ1=_kRM|G3NTxi(c!*3X}>LUP_@+ATkZO-i6Bkm@h2WPGZ$1aY4u>f@x1Gc zd3Kkm ~A*LQ1Nqt0C+0RDjGny`&PF_(2!0x zIf!i_*}vdzMtVf3F5|L#XfQsIUCo7OkIuC5oN>|K%WAt>lbdE|e`8=ftlwrHYz `#WyE+ID;sZy#uq=HE z+>!OnGGK_Cv_;D-?E44fH9 LQLb$J;2l28=hqnwG)08!^H!0*- }3gsIO?7^e+kZ~Dh}(iXQ30F8jK#yYb4oey9jZ+ z5vCaYpfnGz^Mc=bEq@Z9$YWjw1BW}$J2 wW{3T~fQAj49-pZ g{My_M*8DsO5E)!#Xe2%=;l`R?*FznZg+8R^>3Xe4O-G-1U4RF~ytPQ3 zC}W^M+ odh?KX0SCVI*kRJ%?7 z?wvQXCxZvheVZ4QFAhkVQn7upKX_;;*`nQj%m%@~EG)g7?84gpiUS1ny)}@Rr=M%d zts^UxN>zqiGSr!i@QyE$mvXI}s6YQN+;>_b7+mxpsU9p~++Y{m%05hWza7ODDB-*? z-%DR(IIcN4jg!Xw6U-g(#bv=oK(mG V$Q7YIhX5CRw*&Zf#Qdj^h~9`DSG%fi{kk1_*QOb zB>&@O&Gs`WMPCrBactj(6< (X@oH5Qq{5eK1=>A80G5>@opO`< z0M3NOkzFMU$@KM$de(y71Cz<0Xdpl-m%Y7zUfJQ{{pOJ3*5Bd|4Zm5<-pL_PdDqeQ z)jY7yra^wN5;011hO`8`dS<)sVUK&LFtcCRrH*cqRD?B`cCmZ40U$CRMEuysr20G` zI_IYQZ0)5B2 9^?pb g)@FdEw7*8^Da&vQV-uFUz!zeddM-|4N zV4vZ`6LTn|L6T&lyCs8MjC+f&Bqti=(C}qSMwj@VYx709N3$?We^K@qwfG3Nqz$ce zX^DQ{Y1`hIYKilk)WV9MKrtsSs{=Nc8wF60B$mXMymR%r?aEQ+k~d>vUgigaw_j0l z(5q;$Jd@g#!<|T3xD5X8;vMM%Q;6)cPc6O@Oj*?Bs68z+?pp9>?Br8PnN*cb?FY z?9iipP&&kBUZQS)ot=~|Q}gF8ezUKy;p}f4bBSS}#JxRQ*M&i1bMWk?21jOVU6MHT zwFxoiCI<&KGL`H`f%!*jnyAka{cUjS_ePA1>q}t;3AH!D1r`cSVeZfHtR^I}xuVy0 znSZXN39)W*WbqZ9Q~LmuCxu8=ru^`fZpz`NxqQz#%gc{VWF1o(OAs(_h}kdEK4bX8 z0PoY;3eACh+p4&nL!UM; JmKwlw&6N!J7NXnj(2i~}Bb8XXtHddK z` y$Q+WM_Poh)7O092Xq#o9b$rb;vxzxhZA>0}D)uoc@S<_) z= @EFv&B&wC-UwvH!7j wKhH> 2S =r6~$%%ZeJR7l;OhA}bdjU^oQj2lzI&qaKe){ZEE&8aF>b7L4MAwre!WC`XLe9b- z R E)0KH_du=rH&RVntmNewXkPWE^}r$}$IaS1cVB8TkG8d%IA zXui9U%$(>WVeK#c{yOX%u_{tjPgHJ8ReU4#1@SI)zT@d`K6q_EhMBsUrcfs2LR^ `gR@Us8$BHgv* z J5!_*j&^S$Ml?=B` F?yf>p zaeBmKhF%b#H;ki aEGX~5W z=fAX+wF=!YYu}O%X$g5WWTFs_yP5E*2%c7Xa}n2# Ff?t(LR2sWH1OoxOS{1ajM{`Ezrn5FW?3)@e+j+uH zhB)d2>F*XJpzQpxu}vNeZ0+UipdpSk>tU?#?lHC(7;x%Yyv6U 6|}tQOcUcc&1r)0+%f^ON|` zEh4?kw1VHnl&r6sJ@5b%9n?02)EnIwnO7J_mnle_F}jF 2_~DsM zY8qr|k{s KC{lE0YBIEv3e97=AY}mh6y0c-=@H{eoYzzXIoGXpfX+S zQ&+PXieA7Jq*ney^CV!k)u$>uQHm4j6=N3O*h3T^SDC8rqSH{CVI+G@v+`7Sd__>W zH#~>1 VqX8-FK$M+Le%%D@^d$Ab1H=(O|i@Obf&iU_jJYg@R_XwVL2l5 z&XM3LO!+9!bqeQi;n}~AY5QV>mZg@%YOb}c9}b`7USqAj8fus^2MfFc&u9V}xCc7E zsGkM)Q7e}d{BcrDymZYN hwl_ep-(weHg|#it+LdR3hRW-b@EF|35oo|}eC zoi}sU&~osL_1LZYg o$zW2^O|Y!@L%wV8apgI ztGDRgN3)rm1K~k!0Tz4h@=Fc!-L9AFLs48Zq|sB1iU4bZlwF~%yEd+s2S$e2F#F`{ zE+^3^qLYOl>6Ud?Rr%u5m4BN0K|OKdE38&h4jhUkp! WTSPru5-s-0L&H$kn<5lbH7$C#OjgLD)A~t4t9e=OP8Laxs{RIzWp)O94}k?^A@+ zJ}-B4Vo ouC2W z{t1bXj?Y~n7L5`3dz+uZVs*8jao%Q{HZUN(xSPM`&@OR(3lhtFLDyjRUKpzVica3% z=7-a-Pbt!6DKwL6*Ks8Z6uVAbKOIc^goM5ysGVl?AkjVv1}eVmaO^}IKuo+uk1YDm ze1d)=@Zq);i9jPlS5I*7ZH^Du$0&=Czzhrw?7)%=XT{>y8ZmUOhk e8*q#}O%PLPcc4K3&P m$Y(acEW9I&LSjI%xOP{C=V6H3E*l+?(X jaDc=_(g@2!=<^CCs zQa?JnW>z?HZfVXZA4!Pz =Bqgpg4YyeOT6t!e9vM*ylc z+#Wa&fgc9gU=rJ(@P=_aXj{Ig7;QyjaBRPzNrZ|y94v6?;!FCCPL*k|D=%Y*Tvxcv zdk*KG cOwD*hjAJze?x zCR&fdr<(1CU6I)|y@Ra>Ru94Yo-q7iEGgrIsBiQz1LLhk?bstW&mV5Qo@@?+^>`*; zGj0Eedu0Cqch+ SAAr+8xC1qiW(~Z|eh-fqKDE2Q(2O5mA02DSlxI zLm@F4Q4!RaS4c=kNa*ue*UA4Y1Ki!-*&*QnJHt{swl*pQ^M5sXyF2*!*?PgyoP2yd zyk!Iho#D2QFjR7ex(K*?Id&i!{%Z~Of3k*7zHmDk85MV^FC6CPBO~(?CF+ePT=n!# z@PCuh{I3)l84Z}TqmvJsu(ZevOHU(|4AuWA=l_;5cDDC%`cLH7XCMG2Li0aFbe!QZ zp8yXS+W%^mpog2IV#6!l|E(MyLzEPnu!OXTu!NAPxQO+=zadJ5=zo-B;2a1;69R#< zN)--Jw_g2^TSgE~GzVu_80ygl;ch;z?v8>Ewr`xF?rz?K|4)|-ibL%sgeC24rA38N tXCg4Dh>)llYHt!u3T7uPD()bF${~PiUzv8?M^p`HnyR`gbs(F_{|nI*t&;!% diff --git a/frontend/public/assets/favicon-16x16.png b/frontend/public/assets/favicon-16x16.png deleted file mode 100644 index a277e1839cdc36cd6ab222050a38b0217cac24a2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1448 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!63?wyl`GbKJOS+@4BLl<6e(pbstU$g(vPY0F z14ES>14Ba#1H&(%P{RubhEf9thF1v;3|2E37{m+a> pEST@^=?*kOUQ}2?Ot`nB?c1{#ug_mP zck*OQV}lq!FHlfPLe$I2fsKIys0PSZmJkIBva>MD3JWTUivW>=xbXk~|A8h0ow4D; z7c&!6YeUuVALjo0JRc|mL?Lm>Hb$zqE_eO^xoE?~FALAy%}aF!Y6*%>k`ocqR#OEU zD8R@NlU=ARDGKyp|JEa=y)%@hBox8s14%eTMM|uu*sq}?5NOe+C*PYEZxH3-lo1k; z5f%g^0TFKQ9h*x3|6Kh4&q|=%j5Jgyw6~qxw|~dxO+c3`iU})-3h5}xYb(h5xjN68 zK6UoAss3&*N@Bu+9&Y#V-UYhq;e-1jKAs99f?D#j+c$6e^XJdMfB$xG-=?h~=jP=j zC(Qr)@w4ZTpZxs! JYKd+f;JlgEx0 A1J+G z2aGbFfjX@0saJpgc`-qPt@hh$;kYmVnweCty)b8FG^v@sB2~Zk@2}sFJ#Ef+ur<`> zXUgy2E~UL=&B+`09^5{&c9RCH4L6^Jth}@UuPduVqQz05J&Z}-?k=YHw%yDIaySb- zB8wRqbi6^BajEUJl|VuE5>H=O_U9Y|EDGuqs+U{@3O)36aSV~ToSblgO+t0)lGK!^ zGZJdjDp_4sQ$<5f#lj5c`^GvO+bSDtM|;nfT{F+w-CW&V-+aG=|NVx^jg8&6FKDRm z-LPWE5|iUMj$G+Ec;}Fj?e;Z$7A@MOWq$Y6t+s>L&h6W^Y}>j;`_?TqyngUv=fRsx zSMJ=fbnCjcdlwt8KYg{g@%Y}|%eSvzv~T~S_2&A=o2NIPFFtg{bMkVZxnb6|Zhn2@ z_RS63&!35`-2D8^TyyQ(ee35dG*8%2?~o8s;E@qg;gT|?LxZ_FqQoaBrp75LsK_g8 zmc=G 3h!0&IPKK0I3bhD9uf>vU15!F3nBNE3vW)04gnJFkJqBw?3L0 zPmn2ARvxLD=@}&qhL%PSv4x>PHR4F-K-Gk2rj%rWlw4k;$N^L$iKN6gGdH!QvLKZK z>?-|&ymb3bVSZ@l_=W&gF&LUz8X1}y7@Hc!|EUN8D&a>mCpfbzmBGNtY04tIH$bT{ zB&pCKPlmM2oK&FK^>gz|a`Myl(-O-vlk@Y6^$|g?Z91S9|e diff --git a/frontend/public/assets/favicon-32x32.png b/frontend/public/assets/favicon-32x32.png deleted file mode 100644 index 89b5dff577d1adf1fead02e8b0f701c8a5325c6a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2349 zcmZ{ldpOhY8^=GB@O2!KLpfFo*~VtEL}oIIa*Wl!bJ*C3Im{uxgjggYhjc*SVk(&= z9hOlk=ge`6kfb@Q$Wm#)kKgsXu3x|Jb^WgAxu5&F?)&w=pZj_Kc`}YT+sjF7NCN;M z=YYq#f?j9cq$I#KGA?czbmD WEA;{eh6xW=u>10#Qg;k_dPVE4gwgOu+pyafg&84gZ% zk^(8HxX#X;__7{Q_|ySs gmR*hi!VUoMY1ZLbloG z>1(wgLopb^+=wJ;ZwdZd!jx@o*-}{7pYc^9k&qCq{jL31i+*Ucg~sy4qjrC3!^Cf& znp6gY7vRp@l@d$G#u^q$W=_>1Z@%=5CX`+kTh3}m(O($6tHB3^j0l zPsrp6HijLa>`;(MT&U?Bb1;yBq(aLsIGoq6EWb%srpOq6R#DMAe(_zaUUOk#A^Pf_ z>iR~`cWPUD3agShGWaT-7@M1v-9;YSm0_>FRMbpQgEl;~ax}pHjfjE$l8-bpYRi7v z%IfPM;NMG_-Ao|Bv|C?y5js%LsJaJZ=0GXU)$=&sJ|^gKi)m>d_5(@bCSRjm+12q- z2i72M)?7*#ihcKJf!{@*(Y0;I1^eApYSOZCNi1^bmw+9=V&?mwS#oh4=fDWTW%+o6 z9>-*ULR(~uSsUtH=I5}{ 0Py1_WI0m>|&0=zfhI9d|+iwmg5H*1%LjkhtFA4VSN|g+Rn1Ol{ ztz~6U9;+Oy8OM35=xTMzsRDx`!1giN3)C7 wlh;nWL+5_}7-wqIwc>0HibLzWncg0ob+x3?4|j0( zR1+J0r;BLF% *`;aM> iFs>UCm9;==h+V^tGT)w(tS#OcMbU1)l+|oZinHujc10m$Kk*Vh1ycV-~ znq~Y7rxqJ54?YN7aFT0b7vYJ~bJoAYt?(hY$qZy$t0ycL1X9hHO &m5$s#0x8lIP`0Vw)TJLRC5G3eknp@hxm^r?$LL@0R2E zH#<*>>_0Xr_?_cR%T 0gi}4X@Oi$f!EAmzf(X z>*iTyf>FpSbIpiP*qQv$F|gCHvA1}XGhM#tVdzcHhHPIitB&PM%<%%(*i>kMd=j59 z%&zQJZ*kaB8y(lj8u;E)`B5?5{@1kvD{9ORw~}s-?qjC$z+08#!#ukI@gp9a9~-P9 zi+RFkk~j*;8vVq%a`tn<+Nsx#kiKsN1nO4Z4)A;1!LajUkbM~xjDG|Lbbu+s6lshw zH#R}LBTyKmDL9P~2n+&or?cVH{|G|pWLm(<|1TKHl{f?nbk 2#7`kCKaM5@P9B4 z>s2rqJcSlWWdJ4?ru&KE9w4LoTb=(fM`>gRbsg!uqbmg>>c1gQv=9p8WEchbcUSPR z&_L^Zp3eWM 5S~?cB~87%cmG`X-@ipAOVpQyLS1cDOwE^|EDI|U`lF(U78D~Ts0=D2 zGBtZhQd75DDabIh1W_ocD6}<2CBdH*ZEbg_xpy_{!IvI7m+zc8Gw1v6oVjxW1oSWr z(5#0eegJX+FcHW_9 @ z;D(LzV1`vI#jILG(2}hR43siwY)^xloM>)#p|I7BJm1$Z01)56tH)PjZ(cs#rBH>p zNEL>Dslxb?))9h(?9YS&xhkSH_ms6G|7=Bc@zq-(6a@goYN$Yr?nK$1?o4wkN@NCt z9u=xc)aYYSYluZ `lHI5`#-K`L!o#J< zv9+xeU-rJnzP^6!wArz=>?9wPDZ`NiE7zBj7Svrk2M6{Rl<&&RLWb3$C8rQ)XXcR` z9*+mzZZ~hw&d#AFyO7U~<4dGkt1`^Q)h%Uspm8Y2l7S%-Ev9AU;>6fAj*m^E%jH6+ z(}`b4C-B?k45nx1dGDr ;1a9 v;dcPx=kIop!=T3eP)xFZ!*WV|YQU2~f&Il2!ASgsGqPUeb zmiRnP33#EZ2D_gRqRrNY+fuV00Ek%1^)K$)hI#^mnNWYqql9$cS5;qHnVMK~y&amK z>hB+{DX%!MXl`x+A0PS=*BRVhXb5CVy}G`kDXXWax1gc1AuiLBDco1Qe;wApyODk) goCJ8`>qR+LbPa#1Zl{fd&N%!5=0X5|=!i$$Um=WXfB*mh diff --git a/frontend/public/assets/og-image.png b/frontend/public/assets/og-image.png deleted file mode 100644 index 3d4b525e2bc61113de6df4efa9ffd2e175c5c5b1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 20533 zcmeIahf`DU6FwSjpfnK!DosU2>4@}Z15~6FN{}wnq)V3~MWoy4y+aau5=!V*X`zJ@ zO6W)+bV4Wh@cGT1x&Okw_v?(qgb91z^PYX5-F^1i6Q-f2On>Fp6%YtS|N7NSEfDBJ zDF}4Vo#qno8}+9??|>hdon9HZf p^lo@S;$ iw@Nbl?S}-0w6`a~o*QCmR9etyk(p z#U2j=5hrAVP*19iL>+NDXs`*@b&47{cKdVZGAQGhn|<+X5a?~EQ3Pwg%zCZpBm^V- zj<#4gQp*h74l9SA4*jy3>&rumDs%ek2=qzc t9c?v=`zVv=JLuZn1$Bt zC=75jDx?fMj#f=}a8dG@2e{Imo=X!8vXQsXf$Y`KF2JB^ 6Tk&k`nL( LLd~3^4e5~Ha4mvzWVCMlJz8Pr0>l9H)R4)P3iOdX5Z)zJ_vB erFDBUyhOoZ-o~B=e^i&9hpC%3t4&iq_5rz$SI5uFEr22y* z87)3V$Z*H$4CS?+iJKb~^})#5Fj&t~Zr6VK#ZqcK2n0LZtWU@ry_`)D-*()~Aovfz z!|rX>oAdHFEiM|+VgX+w4QVrjp2mLS0R=Ez7YMX!*sHTST`@KZ))Set-8(f{zK_{e z=dHaWny0Qx@m$V*MD4R)p?>&pf#P^bKH1Bs9KyT`EA#UU1ZCz(`S}g F7B!oInt)ke>jq(x9V05JzMBNO;qwA )#0cSUlHH^X4(j|^<;5-t*DD2oi|tt0`Pc_+puDm z(-T5IWwX*h{*tYuGG?07^=PnrSzCKV@T*>CK1PO~uK2C?;o-m!WiGiN>Z&XLhZV@# zXvh4Xl@Z5kx}wi_iYNy{19*z(<09| #TyqIaFBX z7>MTOD@B;Cv5C8>R$Z|htl3>o#QGIhamLi^9Yd2g#~U;;$MH`zcWn{(V@@(W6<}o! z4Ra=|Iy9j7U37p&l9AtX?%5;J10D%2(bA{e{*5Qt+;6y@eq|sOtKk1UofQl@DUtg) z!DUi1dU#+}{~OrL4x77bvIoCE4GL7|jc}YC8Gf+fIFu<7^aGB()WCBZ5VFX-Yg%#1 z gkKRy3*U`kxOx(|G^BiO)6hnv+3mY$#GK`P)`p1+P*8* zZ+k=FD;uy0s$R<~9h1;e1uM0~E^T!cQQ)*3t(~gfdUx>raM8XJyvHHdL{ A~t zVr~I%cwCb;M Z%< z6Sux#c_HW(0;RrUKwF)H@TBZZq<$~1CBk0QXHkQ!F9Aob&t0h(6V6gyP(xfHy|y$g zbAcSD5@h&&w+%gV{(j@QY+= D8gh0FFyME3898n6{aj=c+NIxl( zrsVFQa49|J%jFN)%u~1W<_0NV`~7!YA5U+TFNzIdNxeUBq(=uTqS=xa!M4KOACWYNJ@V1J>>F_m#2iRgy@5w ziUY;ZQ^Tr_ `*+XWeIS6Cf>EimS!vHBb`xLV>oF9di zOCMG^`i!r20MKM)sL-a}@uWQ%UV?UOYG%yyuiC$M2iS0zbAYu0rLTIJJ?tA%04Jp) zn$~=3=Plbz_a<60ZUj oLd7O&z4pi4Lm3b?J{h)}xkgOeGqT0!4Myq$J$ zujkRS&BF9k?`4M*o6g@;cl(lnzhxZ(fh@JYw6TaF-TDP8b2>PEp3pPU<;0#3YO_x* zXz*7{lFL`%@SJ|OoG=%y0zi@@EbvD|%YwQ*?mK~Ce6;$DJmr)AgfcoeK()P?%RcF` zH@Qq6cX-5E*_H0iOM>m6tfSWDm&HQ4enc1g5=i$rnI-%-BW%XDEPtJPwOQP4ottgM zTg>)xM?duY0J#>E*by(QbzBtu_mur`srwNp59IhJGRWH#H#wPVtVOGT= ({Ate3 wLxV2fM z3jpPUetg@uJ!IHY%6f6GFm*)5V$A*IscRc_yOi755X1iCHcjcncc0dpKlQ}w-Ba=y z_?w@@XzXM*OkL2G=Kc6&;kCck$1hX-jtX<#c TT4lN3W M@u4ru2=5U(9xPi|*G~RvBxTCRL4GAEP}# z`_97bD&!K?yu44XRI{=#m$ NV>>2+ZJjkH_f8>Xa>J~}DvTSUEl z_LQS9d->yzb@#=zQwme0-JneGAqEwc-nq#4YB5p$t+U(M(|=LRtPT5$wn$0Isue?z z_Y_fU)^Rj_Z$g~^_;mDJQu0snV#DNmmpQ!w9OV-v2{S(NY2!|4j&7CR=Ip0qXUDgc z%{i{T>g-kHQ5+5u9AY 5KmP)_l2Ti#QBww4`KH)l* z?0S ZgO;_`C|jQT;3l)?J(Q&22^EI@q9r99|b5j^K`whW#FHE~t@S zs#{kz+3&U*ba4Fu&csK5WXJ#ZJ3W4iN7`ujpYCUF_o}=#PQ(t9vWO);J=cpG)=TOZ zQJo_W4cSG!mYwgcDl9Zf^&5e-%&A>h_ZU3pc6;O!>?A~9+*W3K8FwF68)qpTligim z+7H{`|4B@9 jSY8m>H=RhinckOiw z(bZ}3mEJbnsot&?afbNYJLDDA+vY~}9% @(j zOWy6sQTHcyKFKbT*~KPlB59)aE*O<%n@i@i@XG@^L)hQy^(mig%$3K5Jj{j>Bh$Ji zdKPLrG9mIYK1SH~>41ZP)MAPLe)D|kgo2ri7FMK7*D_nf3X?jGr%gVsg@#YcxY}m( zZCjakl(t7~*#4Kp2~}9VwL99d%}GmJdtz}oG } hl@-~GTs>$!-he9v>FP)?3}QWfZ$R(oec 16Ry2LHZW<_{V3wu z(bEH$q+D^??6)f%efsD4GkzW(9cd@R*xQkJrxAK)O~wC(?3rn%$lCXnr&;0OWTV)L zerPZKzH1VnAH|THYS=!qTzrxcdt2l6iK|X(lpZC;rKMgPqQ4qmFdsHaYF;}L4bcN% z#hHpQ^R>z%tSJ{dnMgs^q)uxO)r@|`C93u&HD%`fD-nNz+^T}G2b}v+=TiCYu;aGK z@<-a<5d^c I?uOHM#SN^|zy(f@bq9^EHUCwGYp_q`qbU+L(f? zq-UhjWz@B`cVi_s$oLd@t_j^$C7Qm6=lBDhH58wC!AftGVBfit;;Qw&qV){Bo0Enm za)IQj^<2`@Y2^40lIdL3drO+PqviQ&Z-kA@JnN2sMli3w(lIjfY;y7hyOsp&;VKO& zh^$y)JPqpF^X&;IUt mz4|PNPE=fBp*VjRX8&sVny!1@G6#HjE76&VX>Jodf z9_#zTi(S>erD|tiKF4o;{-olFd46px#`ve{lXw$vn;N^#)J0=d=8vLa_xr)^|Bvqm zh{tz1O|#irnL^CUiU8a^s$1uqiniq_3L@oCy}5z8rlfKCiP{<|$PG{PMXB`71>Qn` zwF8J%7wYO-`B`YYtn_~p8X!v&5JaZa+_%EsIGs$}t>1f)Ap+}@*Uyi-YJGu9H?+cD z6oMlVyj&ab&-jrjCJm37gC$n5e!ujMpm7_MiVtsv{ICGBX!Jk664kf7GRli&9EMa! zl`>oPJTJbWFHA+v`AH+oRbb?F_-efGP;@X|C4=!NKi`pOz+#Ira6ZzMf-HgGZ~an@ zV-MBV{LY>SnXV6ZW(5`HR8qI6Hb2uCw0K`S8F%+>qa)VG@-7#w6!sd-a>t#64oWT4 zF;xHPQcX djwQbr{nY&rd7DpCC;PQ?;A2xJ$90&(Qm z^VzFX`awZKVeJ|rxG{Ox9+aUw$B^`>fq90Ha9^qs3J4 r^Y4dmoEQuK zuoou4of>QPSQeI3 !LPv3emo_#BC5K`t_Du}0n>&vn7AQfDeEtic@%=j3EntO8f z?_Za3M#IV p*}uKU zPw>X~)1w|9wR!WGeK!IMmqPxoxY#{^F|FbX2oa*spd{VV!YH2r6r`xO@zg%)8`QEs zB#b(#wWn5qcGEk99h~aC!HnhWvcp=mP`^mkT)26D(h8f9bjes>TgPnDZ-*nyg~NTH zY1jg++XeuVH=7y6 (7`5VR?u>7a~IZ zIZp{JQ(Fz8!Es6bQ&k +xn0xJE))hNV#U(Rg5s@l6D7A%?kMAWd%(pl2(SLJC z3dfZ@)ok@Y)nv9ge%X2yq~l`5W83!pOA@vRi$(RauJC=x2(jk7*q+}BoW=-;6D4z( z4_J}mV8DgW@xoV!s}|HD6(PbNtf?5`{wXxa#FU_U!j8h{<8r9e?womcj1pEQ@=C~z z@X8nD#xZRKr6jeL4oUN5Zd21y;G#R?%&expEqDCiFy;q+e}P&Gsl)%?qJWRIvZW#< z@I1WGR~v8c _HApZzz4Jbw7XR`#{*sAl^*Nqu`ogCF^m7+m#kUXN2d2} z6gIE{X#jd7a}kNZ&&iX%Jk84w0Y@r#bJv{2k*ymro8COd0b$IhRIw29TEr9e;PH5) zyREj$y9Y`wBy*gR`^(1CjlhTjp5l7+Oi>^+_?a$}Md`>~<^tC)dceEya-^WRr!^~p zXMX`U>U)S?ac#4Mg#Cy4kJ+PMr7&~yP*23#tNc{w51p@(LhU1v-7$S`c b!>*Y=W3zS>dzxQhOZySRi@RHU7W=P}=2rLWN~+T2ETER~k}OLn z$$OpK>ksRT6WU@8tHd=$^XRck$=%Vx$)UP=JuB&IkpzGo%z}1) 7Sl>Ey7D)xL8n845dj$9001B*RHJOSO5D-uR;|K<;uUCJSxn#IvC$8uvsepBl zsx|^=-Xs+u3e9&R!Ov)gs)Ql0={!qZzKPkjBWDkrX?wZ$mgtJSa|#-X#KhE$)L5Ln z=RmT$Ae4st4{wlobFJG}Qo8Kr(tyh=^H;6 rYnNFueb(795#D+eeRvVT7}mw5#)i!H$?#K~jO?sCZc2t3lu6 &56?O7#}l>!x*a(aOQAyB%(eEFL58zHU*?jr+bi*9QW%OW=>&8 zW7yA|Lb_|dWW0Jlm=EpW%VFRPuJJ|}XTd62++#F-#U4)+*Cs`u^*S`{vgM|LqL-Rl zqDQ^gaK{#egwBkpt2czGSTqdERMf^`qnE}N@{iNCxmyEI&XO7HXx3o{aMO^dqMI%f ztn^PT4m)%%R3kT)dd_RULgI67kztj*GY-|(WCPjRCFj_nKu?;_Snp4mqe@u)6{7}Q zNKqw&gU=B<-Q>c%W 4V* zTHYY+ZfEul-6T*^k++&AjVrf=8NsrU f%PRYz9WrAC}Wn!=GZ51}# z)_%dgVCL+V*9z8GFB$drsEp|4O7jKJKp?OZHR*%joju=@fCRQ+VDFYdfk?MpV869W z(KvE#8R<2ideMXqX8zFU!aKKdGz&{n5MP7B?4a?F+g6q+Mx|JsNJrF^pd{2%SJayO zLi-CK?TrJWMPGu4eLZAE$6sOVg{z71AD4#d> fEe8seM%-b3~4su&a zHV{}n)M GGWX?|)V;}i$ZPF_>D4Q1MBcB}B}NUI zHx^I#*5z$~GZM$;Q@k}tA~07S#@w9d^W8i>!7F9#e1;Yy6JxH6`ti9s$9|nqSN57; z0lbSAZ7WU{Z4@SgE1&o>73>*s-m~Hr1f{|&R2(TQqU|YEPt(kQ*nN0z^^F&S<=BjE zEe;DWR0_8(CMYa6 eCLbD>0$ww zDAdqwrtJzs6JGI{ZMt6XFXrW9EhjD0`<{}bjwy)F8(k~v9;KSiLl^gjh~4$xb1nL8 zCZDE4wQf4puGK^*s!HDUar;L&KV)+!n6=Fyy+P^(`6eYc&utbVR-{?dY`!&YZ~g9Q z`jz9sN`s0|-SI-<6={^4Q%-@y{`5uG9Nq#(*BF*&O#R6TNx^jRuuMS;R&i y5Edk>Mmbgvf;kq4z%jVtNu-d;9GBKgSps9pU}Ph z2%`#E6Hd>q!tTqTXVhFNF08Tasd(wCqJxh5GGw(l1}5KqvOPi&{h_XsEKy&2V!Frb zraH#0Nzdhp#c1V+^%WzCTP+M+CU&RC62C>e>!y@wgl_>E{N2v@!mkOjnh!8#$T(i$ zIv*xAY~w~K{pq Z$6jW(ATO=bg0a-SjK;rXJ;zFLso;_B&6x!ycmp8pwjH4c9R z9!3_noFAhc42KRB6BE(?S 3di@FJ|aS64`nrqW)q&A3x~cL;BdCbgO8VaQ49nB;v8^7%!M zoT$
BTvF$pfBgeKcn*1)n8o?3AKx%mRM+~d6 zexl1Zxj~-0%oS45ob))?LxpYTm%3d1173Ho)ioc*PR%j4pWpKVM*uozsqd`i5~uCT zkxUNiqpJBpqRJdMIF_I`^~Jds>Sl@rsOfNln&jnj6+w4*rxfoRt-&H_;>h}4PX7*e zy{YavUOv~*vcKWt&C5azu9S)R2UAL;a@(<&U339_D@olU9EIh-{kU;d+^19}XC{%V z2EgevJ{fC?93#{;qC#6#(bKI53@dHV#$fnVZCt{4e{spjxeTm!m|$$&aqqdiQ^eU# zeUH|-RObh^^stB_Q8_I68I2{HF>Pn@@A?Bt+2gvDI1BsWM)U=J4z=AYZzrZRzQoPB z&Hl}Q;+x54AIwrUCt6hLMKvs{U=*iY)V<<3*LS7ct@Cwvao6PgaT=cw6o f&&; z03q*U7SMs!F^j@ZEceisuAK~%9`W$hdyOn2Tjw6R*8s?)mtUE(!?WDJ(g}~g5u=C- zs`02lLC)IQ&40KAxv^;M$jy#*2sYAoSC^|WP6a|Ino&IKF^cKVs3%b2hK+cb(gH0x z)%+`bj3U%_YQLT%d{_u^E=(=s+>(=EF3-I{^Irjy1(BWK_8P37Ie$+Kq8U70B<1Iw zvEG{~BcQ#pGlS1%Vo31NAioGyMl&(c6$?775Q*bNi`kR3u@W_3pHmwmF)iu8i}xy^ zMR34zG*koY*47KvD1upp0mYyWln>3U`$fzdR=QQTwE9SqO_y7s=Ag@ ^91P|P9w!?P!E&zAuY84MP%QeX zzYmQMmkQTM)KuztOA5XL{>;X-HqxVjuH`UxteRryH%$Q179dYgs|!B{x!*~-4$=4e zmP%vt7$YGzz*@Yo-}$!~%@}<@J^(o;li9vVTb(TK_L9xa!$f3`m$#@UZ}mrw_XnPW zaGLHeTdt2fo)Ai9Cv12~X%uQHCvPST9A )wh^;1e5Z*?=HoECRx(2b#7zPv^6_6Bs^#M%G7 zv+Ny7rhK)~=I$9$qWOKcad=|^{T(60#kWK6eStDjOSJ9o-j<4>+Ui8tlA6t{Z?T5E zkZfK$d4NPgUnx_Qnd2DKd64S9m}rPvZymX5;+Xx?(+%jEKeFmqk}Pt3bL+;tUz{hK zc^4q4f*d3A?D}EC+^uo)$e-}yRNxzL0SK`B$Ve4C_uA=Gb-GvYv){}<$HJPMK$;mT znk=pI@B>vU^hiMoo?&LkWUjhQdV?*V`2JvSJN;N+7pG@t1-`^)_oX8bw=$3iS@CzX zaP%N1_Q!i4TIH-2wy0!#A_VIxK5ec>loTn{NXXU_DeAs)w)`0(RCZq_e2;PB!AE?p zvo?Oei*+E+jcsrdf4{z=IBji6&cc>RN>8it_V7D>>=$j>vyg}=^sPG+kpP7zMMavp z>;K!@WK&`^y3?NP<1u@uMYN1y?p}`8&^S#|e`ZBtW1!}5FQr1w+KhOsg@8M2GUYC& zZ4B!sPGl)n|61eIewAx;6-$UI=y#l6cYD$|E88aAlET5}@8lOIGKbHg!MboRleFO> z!Id;maeGhq4ZZmEqE~kQTW_Je(*v{8=Q3(&%3ZFMD1}ekzV`%wfqae;lHK? }wDsjVY-s527w<|_<+W3r_-e;+TIs-`~9tvbc4O7P&vsi+r>m?RBy(TtqqqvWQm zB?~=M8My#YdKKUk!z~^YzSulDaov(_v_+rBtv 4~emannIG z>`Az8jdQqdQOe63m EuOL=tpr?}XLk-qQo #CPr2vRr=pPrv +KXgbCmsB7=x<)W0k8 f=ZI8!ilBx|&feaeIbEg>&^rw>odM&@n $&$lP#V;fis-z}S`@KVTHok`@BNJ6P-x8@qdV`)Oyd8DW(Ght{ zZnr+C;f6!~<^jZJ@Q_}yO-rP&mgRJ(H| 2j4>`u}kC%Z%?P*Pxx4A5jUS92I z2jZBoE|jtp{sigLqZ|8vQ_fADi*r_fVPr9S#Rt(my;?t&HhX9S=+s0+DC8Z{u;J d_epwa}0Fm)RS>`I5?PswqwKdIIfkx@Jn!k53IUN}gXPX}XXu8RXje{iwG 5ef9FM?L4yDK{Lo*&qYN)pP@&<# z5uq-FJhk{~l!;O_y2 L6ldn SW-QauDeO~>9lu%CZf~vH~mQ|`NQ*DF^!A2NRrw|dkwhLiD_8b0Vvbj-} zjt#qUv(r07b)&M}=GjK*H`K_~5zCjpDIW@P 2$LG&ZSHfoNxc zcaiO$(1-V?PNuU0!kW%oEO)fs(K@EPr?%BjgG-c0Cv7rQ7+i-UL>GP@!OptPB&!(P zSgd;`#oA+n14gZX{ycvDLG!E7VPL~cjn3{O7Ar2(DER1zUkB3LtxexTeNdu0zc51` zdLB{FYDm+<&G=EFRF1biE4CDu^1}g9zzz@eZaj3-F@3g(WE59I+MQ2T2I8>s7 _zn<23!lm(G(Tm=oj|WzH%q%s8=S!f<)YXYKV9 zHOPk!HxEYOp7@{@hTM_y tbbi%+}y_H}Y? z--31JFX ^q%0=%a=~e49S}E1ez2zMiH; z$82GJTkrG7p>adGZn@_}4RR+>Fu&C_*xv(UfMy-BWN}Bq;-%iy g0T8ARl?L z{QeyOoBa26Qe=lF(@nU7o26~8?nP@KlHDcUn?P6PEks`cNjN E zrMQ-f77LZQoCeut^ od3wEZn=K|HX^s@RdUg7ME<_(rP5r^QEf**Z)YSHQZ%i zmy_LiyKu|nZ}`*P@XR;hC3k?hE0S{c;47AJ#LF&ry!1o?K!{%>vwy7)r74S6Saic* z_LwcZA9H;M!p93`GaFo-0og@g;eVXtTYB(+TbEkh7|AO)a#gfLLu1+?w^MCB;_*V;tl^7)dW$2(s%j>~7`b`SDnTi@B+6V*6<)R8; zYgk1?% uIu3QMKBi6o|#adPO!|iHG5MV zmDN4-+ZrWKH@j5RDfya?j=REp_LF`q5(E9Arw)gWKGGiX%{1Gy7oH+@(Op!88hW dyugypX8EJ2P9*ha;(57Kplzvaegt@ wk?Uv29dk6_HzJs`1!1VhSQ zGB$DSw7t?Yn)QG*sJv>b)On6U!2u!O3_O{b#jp4;Y8MO~rIyvD7c=rX-*KGyl&HlU zxj2u1EVu>^T#=wtkdKi)EVv-mFR#yOAKYVcUeM(XDIjSTKQPvn(yQOLmP|w7CAC@0 z_P)E%T8dnzpKU|S$1QMAEJ`UrEE_2AaOZ*RArZ!vexY2f7$zmY8MMpIMftdb$Zx~V zgo7f&Ls&V>q_>J833`K|a^Vxx&`Gc3Nj&;WF>$zvtGND}@egiN(82&PfEIM#efvHa z&>0d9RQ@d z7vadZOMdsYdi_ I(~Dch)q=Tt;SPBBb=SkJ^pJ`2mC(ylItQIZ4_zTg#^R#zJJ< zXRkfe_}1BVp26F)Otbw9>b8$NB_+!egOho$q`w=a9Dm(@B1YlRnq+tC-huK)7)ZSP za=$T2(*9Xbu5an*UGZjpA!J2DyoX6(?>&IRXBNUcYv4LzUnC1^06MX)beD#G%58Xz znX{RL`hA20CRZ|`+w2F2!k|U8k3|+L>&lA2IfNF6*N{_ySgEa>w+&%5+3)33uss0O zbO2Ce{kP@{VY5;Kf+83E40oUMrE!z-9_i*5zfVt3%|i)Q-F_nT;o~3FO-Bd|Lb}O< z{$*LH{abNzknRMZ<9=o2+z0}S5wyo63uz4YD$dUYx7mFv7SPk&{5<`I8fWYgW9OwI zYk;RV kVg(xffrzH9^@6 z d|HP<4#XxMJU>HhbTLfxv( zLm?In>v_^^Agd_A0XtI|Y5>Xg6$UgEonqxtPENb{CsvC)z%|kweMM89hfRUrq?T{O zk#*3N+2gE3TVOyVYl~=q4uJ;Sh3+-@Jgf2QZ+Khv6BElaX`bK-Z?(u{2I8JJ(2c8m z%niM5EePR_0!Mrx1s!bc3lf0g1EC(1 jjm{_5IJ5mH*niaK?)>fHoak`I1V}t-E z@?=j ^W1C<^kG@1la7E;K%Z?6*ux>()MP_h^6}_Ywlq3eZXDZ z@Hed_8y&wZ(PgjS>q;)AT|mokZFT`zR4=U=UC;>AGov30463fMiasc#Y@vi=Zka-y z6J)$>M~HBDn_Y*mij{uZkEwJoI8+k0qIBXUGes4)S-M7dvbxV2uE>(L3&`9vzFKR6 zECt7}MyXvD#i@C3KMLFWOoYM1S7PBKd4P}+XdL!GkkowzZkaICqr(OA;q+4T-z2mA zo;+){ZkK$FB9@xhD!v9Prl&_tKs+)8a@;T@S3oFx-R$zg!E^|#uDb_}H{3Sf+jQf2 zy3;)4NT0=*q>??wd1kWJAwkpE?KoLY_$Zt|7BFfZ*3?)0&?l}yFt}ahG$e(lG$Sfi zpVq{j&-TH(k=3JTSV*uQUZx9xZKdyEs^-QBh;Vkb$EJjGU7dV4#{-K}7ULplMX@KH z@m9mBUf{&pN&yJub^S?d)$S}xiWYyKaRONF5s;;1wa&LXc#yPw0Toa>zTd_wt?&x` zWf}KOykl)yRkUt%RpbLaO}dx&jwo6LFmBt@o(Z+C$@7%qr2<-jXSVfYiSRzamw8cX z=jONpAm*c{+Yr!RZO(dQIcx5xFGCL^r4OdviQz?T)e*l3*- j!Z1)TV??K;Mo?DZIC`#sX9)%C0`50o z;EnT>JP+Kfvu^<{qjg}oM&rWeJAoneY?X{<<`T_iHx_$66+L&mg{Z^PIGSQQ2Og_E z-~8HYl@_q-!lmaJV(Cx5_BBk$Z4YaSbNqA#YoM|}On)K?HdeLSE)mUYc~{_KcVB(G zYB#vpvz)j@J(%RSQdvV;QZUj*UW;xQ_Gq^N=#N-`J!4-;;JdRx`9|)w45f-l`p#|# zf2=OqcH6@~xX&0!@$Q)Smu{TfE_Hvvi(>)A)8<>yGW|$ELh*Hh?WVaL#(cqDv~11j z^LRlzt3YtcL6F3~8!Fwkhhy7(=wQ7{g0pg9ia-r&g4|R-zIkh*^_RMurR@k1*mchF z|GTZ3o26y>ktyIa`D@8N7*Fp%LCKZXmj}c Qi)Uk7+d3($vr?I`HMH^=)8 zH1BWX7IpsH6`9R>?K6S<{Z7_9!}o!agiZ1^Eqrhgds=QyfudZTy2YD;Zrn I-t|;4T@J6^TAI4Ys!)u5ed5&tEVL*xIEg(J`C}J0Gt;5L!;-%*Z z`{NfRE0>Io>@AkG5>+(By!0r>Z)@EKm|PRW*ZV BBL@`Cv-9o67rKt==)BVU4=g!6cs2N_~aH?1tXUIYQBnG(BScov=bA;J0)n12= zr^ug@RzzjFht#YdpcA1SFnATI%glY|LnOjAL;8LoG_HWSu+y`nfvO9)o{97*T5cSI24 zl+XY>o1?o~PzfUjyUx^>*mZ9pa9!);yr7>m=9+S{_WmrpPl$lv46gigo37Q%OJ<$S zv@fMEZ0>9^RF^?nKZ?|tjW%qMU+lQKIOUaPB)pi@hJfD~@|*8h2FJvzIo?Ea!t RCt8yET;eoMtCP&?bhg& z4Yg7~3m&F{9&DaY4bzz2PRBfO^KgsuZZKO*wZP%smaVXiA8lAC9Mk0nBpe$GM=dpQ z5GzP0`j@`S?}J*Cg#$hA9{-lILVgmuNd*w0j@%p;n|~RgXy2r>_N?|IG|ij}y??q6 zCh3uGy>Hvw1=y3Mv-8uDT1P~-Da)p1*OY?E<-Zo(@1~6Ue!wQ|ak pyu0A4X*n!N+YrXPy?)#nv?V!s zGd85ilf7ZlNi &v!6||?aD8Q*?*vZQ&MOL!EQ_A+ zJe0u}>NKoQif4D0bXRmj9%q+esv UJb`}d{?CvC@!m#tT75oYyg#GoZtout?} z#bX!6;w`hW+DX4W#ws4|O%O`+ -tfmRVI#W-q!wVd8CN&Uidz8zF4hFF<%zNpQE*rCrr8 zZB4B8OmVYKp7xwLE4o6la+Qz#mo_UXrld%#Vi}osi@h!AcekUW%Io845?Y_JT(XqA zF?Ffm0_KzzOk@^Mj@Cp_1q0pycl8OFdIiU0SP0d)4nWieOq15xKm~@vP2nY#JZ@1U zx6|6g@6R1Zy|C%QyS2I10m_XJsb^!EgFloxfO%FnJ$|(pc79KY4Y+ZCPhz5h1KV3j z>-J!%!cOL=mR*y#se%k?3i_+R-<>?o@_Q_79CWuT@!yID=F;U~mp{(E9~0@|h&OiK zXHvwu=BFVdf4NE+`x^~LPu{(H{3kbF=H^@73;G{ Y|4NPxm%#!>V-fKzSP+Q+F)kEq^oExHZW1`ItYv^NCJb)m)k7IQ!k8A zR+FIr#17w9)W@HCok{L)7|Kett=Mv>!QuCeu~yid4(IKb&M$d#@HQiS>MI6` XEkH1Oi MDXeiZNtU$tS(7JdYkCzowTdu zv5Z)R5fL C(ZY~$bOt&CNt>H zaJ0YAp^c$0Ve^F3b(Jlm6gJuN*7W#-{?p~VeYe =#7Cl zjHvQ&f1TB$&HwuKYxs9w!Q{J0yd*m`>OL>*>v?!kM4zql7aV$6VQ&}db)v3ZSK_hO zUubpc_`viN(?0~FD0cROF%KlcgSbZ@nGTFbKEw_34d;ImdyzdQ0q8e3zX4i6M8PQZ zuyx>U%GSQx-fCtTZK8ew+LAf!lmX5h+1M>PSNy{ 3f{5dB(w#X?|gl<) _cb@Ok05fW(%08p&B<%7 L zsvyv>JB{Z+Z&+~<8CWS);densrkDcfc72-75iq&=_Zl#hE>M;Y;=|Jv#&Mt+-FLg+ zOac?2rmSas7Y9UpN0Dw{L+A0XCGvfk<@VR5_SzEoI`}fkRPVoU{99Xth3Fe%o5MGV zmacg@kK~NPY{zPCP7?NZyOV%5x`!CiPzA(|xsreXw#|gl*~e@Ub5DG2@BkkO24tbP zcFAjxd~(*N v{f% gg#TYcLOg{r?6(_9@5bMdvrzY1QSD{%bJM{83u3?G3;+NC diff --git a/frontend/public/index.html b/frontend/public/index.html deleted file mode 100644 index 36782ea8..00000000 --- a/frontend/public/index.html +++ /dev/null @@ -1,33 +0,0 @@ - - - - - - 펀잇 - - - - - - - - - - - - - - - - - - - - - diff --git a/frontend/public/manifest.json b/frontend/public/manifest.json deleted file mode 100644 index 7e44fe2f..00000000 --- a/frontend/public/manifest.json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "name": "펀잇", - "short_name": "펀잇", - "description": "궁금해? 맛있을걸? 먹어봐 🥄", - "display": "standalone", - "icons": [ - { - "src": "/assets/favicon-16x16.png", - "sizes": "16x16", - "type": "image/png" - }, - { - "src": "/assets/favicon-32x32.png", - "sizes": "32x32", - "type": "image/png" - }, - { - "src": "/assets/apple-icon-180x180.png", - "sizes": "180x180", - "type": "image/png" - } - ] -} diff --git a/frontend/public/mockServiceWorker.js b/frontend/public/mockServiceWorker.js deleted file mode 100644 index 51d85eee..00000000 --- a/frontend/public/mockServiceWorker.js +++ /dev/null @@ -1,303 +0,0 @@ -/* eslint-disable */ -/* tslint:disable */ - -/** - * Mock Service Worker (1.3.2). - * @see https://github.com/mswjs/msw - * - Please do NOT modify this file. - * - Please do NOT serve this file on production. - */ - -const INTEGRITY_CHECKSUM = '3d6b9f06410d179a7f7404d4bf4c3c70' -const activeClientIds = new Set() - -self.addEventListener('install', function () { - self.skipWaiting() -}) - -self.addEventListener('activate', function (event) { - event.waitUntil(self.clients.claim()) -}) - -self.addEventListener('message', async function (event) { - const clientId = event.source.id - - if (!clientId || !self.clients) { - return - } - - const client = await self.clients.get(clientId) - - if (!client) { - return - } - - const allClients = await self.clients.matchAll({ - type: 'window', - }) - - switch (event.data) { - case 'KEEPALIVE_REQUEST': { - sendToClient(client, { - type: 'KEEPALIVE_RESPONSE', - }) - break - } - - case 'INTEGRITY_CHECK_REQUEST': { - sendToClient(client, { - type: 'INTEGRITY_CHECK_RESPONSE', - payload: INTEGRITY_CHECKSUM, - }) - break - } - - case 'MOCK_ACTIVATE': { - activeClientIds.add(clientId) - - sendToClient(client, { - type: 'MOCKING_ENABLED', - payload: true, - }) - break - } - - case 'MOCK_DEACTIVATE': { - activeClientIds.delete(clientId) - break - } - - case 'CLIENT_CLOSED': { - activeClientIds.delete(clientId) - - const remainingClients = allClients.filter((client) => { - return client.id !== clientId - }) - - // Unregister itself when there are no more clients - if (remainingClients.length === 0) { - self.registration.unregister() - } - - break - } - } -}) - -self.addEventListener('fetch', function (event) { - const { request } = event - const accept = request.headers.get('accept') || '' - - // Bypass server-sent events. - if (accept.includes('text/event-stream')) { - return - } - - // Bypass navigation requests. - if (request.mode === 'navigate') { - return - } - - // Opening the DevTools triggers the "only-if-cached" request - // that cannot be handled by the worker. Bypass such requests. - if (request.cache === 'only-if-cached' && request.mode !== 'same-origin') { - return - } - - // Bypass all requests when there are no active clients. - // Prevents the self-unregistered worked from handling requests - // after it's been deleted (still remains active until the next reload). - if (activeClientIds.size === 0) { - return - } - - // Generate unique request ID. - const requestId = Math.random().toString(16).slice(2) - - event.respondWith( - handleRequest(event, requestId).catch((error) => { - if (error.name === 'NetworkError') { - console.warn( - '[MSW] Successfully emulated a network error for the "%s %s" request.', - request.method, - request.url, - ) - return - } - - // At this point, any exception indicates an issue with the original request/response. - console.error( - `\ -[MSW] Caught an exception from the "%s %s" request (%s). This is probably not a problem with Mock Service Worker. There is likely an additional logging output above.`, - request.method, - request.url, - `${error.name}: ${error.message}`, - ) - }), - ) -}) - -async function handleRequest(event, requestId) { - const client = await resolveMainClient(event) - const response = await getResponse(event, client, requestId) - - // Send back the response clone for the "response:*" life-cycle events. - // Ensure MSW is active and ready to handle the message, otherwise - // this message will pend indefinitely. - if (client && activeClientIds.has(client.id)) { - ;(async function () { - const clonedResponse = response.clone() - sendToClient(client, { - type: 'RESPONSE', - payload: { - requestId, - type: clonedResponse.type, - ok: clonedResponse.ok, - status: clonedResponse.status, - statusText: clonedResponse.statusText, - body: - clonedResponse.body === null ? null : await clonedResponse.text(), - headers: Object.fromEntries(clonedResponse.headers.entries()), - redirected: clonedResponse.redirected, - }, - }) - })() - } - - return response -} - -// Resolve the main client for the given event. -// Client that issues a request doesn't necessarily equal the client -// that registered the worker. It's with the latter the worker should -// communicate with during the response resolving phase. -async function resolveMainClient(event) { - const client = await self.clients.get(event.clientId) - - if (client?.frameType === 'top-level') { - return client - } - - const allClients = await self.clients.matchAll({ - type: 'window', - }) - - return allClients - .filter((client) => { - // Get only those clients that are currently visible. - return client.visibilityState === 'visible' - }) - .find((client) => { - // Find the client ID that's recorded in the - // set of clients that have registered the worker. - return activeClientIds.has(client.id) - }) -} - -async function getResponse(event, client, requestId) { - const { request } = event - const clonedRequest = request.clone() - - function passthrough() { - // Clone the request because it might've been already used - // (i.e. its body has been read and sent to the client). - const headers = Object.fromEntries(clonedRequest.headers.entries()) - - // Remove MSW-specific request headers so the bypassed requests - // comply with the server's CORS preflight check. - // Operate with the headers as an object because request "Headers" - // are immutable. - delete headers['x-msw-bypass'] - - return fetch(clonedRequest, { headers }) - } - - // Bypass mocking when the client is not active. - if (!client) { - return passthrough() - } - - // Bypass initial page load requests (i.e. static assets). - // The absence of the immediate/parent client in the map of the active clients - // means that MSW hasn't dispatched the "MOCK_ACTIVATE" event yet - // and is not ready to handle requests. - if (!activeClientIds.has(client.id)) { - return passthrough() - } - - // Bypass requests with the explicit bypass header. - // Such requests can be issued by "ctx.fetch()". - if (request.headers.get('x-msw-bypass') === 'true') { - return passthrough() - } - - // Notify the client that a request has been intercepted. - const clientMessage = await sendToClient(client, { - type: 'REQUEST', - payload: { - id: requestId, - url: request.url, - method: request.method, - headers: Object.fromEntries(request.headers.entries()), - cache: request.cache, - mode: request.mode, - credentials: request.credentials, - destination: request.destination, - integrity: request.integrity, - redirect: request.redirect, - referrer: request.referrer, - referrerPolicy: request.referrerPolicy, - body: await request.text(), - bodyUsed: request.bodyUsed, - keepalive: request.keepalive, - }, - }) - - switch (clientMessage.type) { - case 'MOCK_RESPONSE': { - return respondWithMock(clientMessage.data) - } - - case 'MOCK_NOT_FOUND': { - return passthrough() - } - - case 'NETWORK_ERROR': { - const { name, message } = clientMessage.data - const networkError = new Error(message) - networkError.name = name - - // Rejecting a "respondWith" promise emulates a network error. - throw networkError - } - } - - return passthrough() -} - -function sendToClient(client, message) { - return new Promise((resolve, reject) => { - const channel = new MessageChannel() - - channel.port1.onmessage = (event) => { - if (event.data && event.data.error) { - return reject(event.data.error) - } - - resolve(event.data) - } - - client.postMessage(message, [channel.port2]) - }) -} - -function sleep(timeMs) { - return new Promise((resolve) => { - setTimeout(resolve, timeMs) - }) -} - -async function respondWithMock(response) { - await sleep(response.delay) - return new Response(response.body, response) -} diff --git a/frontend/public/robots.txt b/frontend/public/robots.txt deleted file mode 100644 index 7b8e4fcf..00000000 --- a/frontend/public/robots.txt +++ /dev/null @@ -1,9 +0,0 @@ -User-agent: * -Disallow: /404 -Allow: / - -# Host -Host: https://funeat.site/ - -# Sitemaps -Sitemap: https://funeat.site/sitemap.xml \ No newline at end of file diff --git a/frontend/public/sitemap.xml b/frontend/public/sitemap.xml deleted file mode 100644 index 9c261be7..00000000 --- a/frontend/public/sitemap.xml +++ /dev/null @@ -1,23 +0,0 @@ - -- \ No newline at end of file diff --git a/frontend/src/apis/ApiClient.ts b/frontend/src/apis/ApiClient.ts deleted file mode 100644 index 26fe6284..00000000 --- a/frontend/src/apis/ApiClient.ts +++ /dev/null @@ -1,84 +0,0 @@ -import { fetchApi } from './fetch'; - -interface RequestOptions { - params?: string; - queries?: string; - credentials?: boolean; -} - -export class ApiClient { - #path: string; - - #headers: HeadersInit; - - constructor(path: string, headers: HeadersInit = {}) { - this.#path = path; - this.#headers = headers; - } - - getUrl(params = '', queries = '') { - return '/api' + this.#path + params + queries; - } - - get({ params, queries, credentials = false }: RequestOptions) { - return fetchApi(this.getUrl(params, queries), { - method: 'GET', - headers: this.#headers, - credentials: credentials ? 'include' : 'omit', - }); - } - - post({ params, queries, credentials = false }: RequestOptions, headers?: HeadersInit, body?: B) { - return fetchApi(this.getUrl(params, queries), { - method: 'POST', - headers: headers, - body: body ? JSON.stringify(body) : null, - credentials: credentials ? 'include' : 'omit', - }); - } - - postData({ params, queries, credentials = false }: RequestOptions, body: FormData) { - return fetchApi(this.getUrl(params, queries), { - method: 'POST', - headers: this.#headers, - body: body, - credentials: credentials ? 'include' : 'omit', - }); - } - - patch({ params, queries, credentials = false }: RequestOptions, headers: HeadersInit, body?: B) { - return fetchApi(this.getUrl(params, queries), { - method: 'PATCH', - headers: headers, - body: body ? JSON.stringify(body) : null, - credentials: credentials ? 'include' : 'omit', - }); - } - - put({ params, queries, credentials = false }: RequestOptions, headers?: HeadersInit, body?: B) { - return fetchApi(this.getUrl(params, queries), { - method: 'PUT', - headers: headers, - body: body ? JSON.stringify(body) : null, - credentials: credentials ? 'include' : 'omit', - }); - } - - putData({ params, queries, credentials = false }: RequestOptions, body: FormData) { - return fetchApi(this.getUrl(params, queries), { - method: 'PUT', - headers: this.#headers, - body: body, - credentials: credentials ? 'include' : 'omit', - }); - } - - delete({ params, queries, credentials = false }: RequestOptions, body?: B) { - return fetchApi(this.getUrl(params, queries), { - method: 'DELETE', - headers: this.#headers, - body: body ? JSON.stringify(body) : null, - credentials: credentials ? 'include' : 'omit', - }); - } -} diff --git a/frontend/src/apis/fetch.ts b/frontend/src/apis/fetch.ts deleted file mode 100644 index 6c760b43..00000000 --- a/frontend/src/apis/fetch.ts +++ /dev/null @@ -1,16 +0,0 @@ -import type { ErrorResponse } from '@/types/response'; - -export const fetchApi = async (url: string, options: RequestInit) => { - if (!navigator.onLine) { - throw new Error('네트워크 오프라인이 감지되었습니다'); - } - - const response = await fetch(url, options); - - if (!response.ok) { - const errorData: ErrorResponse = await response.json(); - throw new Error(errorData.message); - } - - return response; -}; diff --git a/frontend/src/apis/index.ts b/frontend/src/apis/index.ts deleted file mode 100644 index c258c161..00000000 --- a/frontend/src/apis/index.ts +++ /dev/null @@ -1,13 +0,0 @@ -import { ApiClient } from './ApiClient'; - -export const categoryApi = new ApiClient('/categories'); -export const productApi = new ApiClient('/products'); -export const tagApi = new ApiClient('/tags'); -export const rankApi = new ApiClient('/ranks'); -export const loginApi = new ApiClient('/login'); -export const memberApi = new ApiClient('/members'); -export const recipeApi = new ApiClient('/recipes'); -export const searchApi = new ApiClient('/search'); -export const logoutApi = new ApiClient('/logout'); -export const reviewApi = new ApiClient('/reviews'); -export const bannerApi = new ApiClient('/banners'); diff --git a/frontend/src/assets/characters.svg b/frontend/src/assets/characters.svg deleted file mode 100644 index 6580162c..00000000 --- a/frontend/src/assets/characters.svg +++ /dev/null @@ -1,63 +0,0 @@ - - \ No newline at end of file diff --git a/frontend/src/assets/logo.svg b/frontend/src/assets/logo.svg deleted file mode 100644 index 26cb9858..00000000 --- a/frontend/src/assets/logo.svg +++ /dev/null @@ -1,101 +0,0 @@ - - diff --git a/frontend/src/assets/plate.svg b/frontend/src/assets/plate.svg deleted file mode 100644 index 1a5f2f61..00000000 --- a/frontend/src/assets/plate.svg +++ /dev/null @@ -1,64 +0,0 @@ - - \ No newline at end of file diff --git a/frontend/src/assets/samgakgimbab.svg b/frontend/src/assets/samgakgimbab.svg deleted file mode 100644 index a5e9872f..00000000 --- a/frontend/src/assets/samgakgimbab.svg +++ /dev/null @@ -1,87 +0,0 @@ - - \ No newline at end of file diff --git a/frontend/src/components/Common/Banner/Banner.tsx b/frontend/src/components/Common/Banner/Banner.tsx deleted file mode 100644 index 89af08c6..00000000 --- a/frontend/src/components/Common/Banner/Banner.tsx +++ /dev/null @@ -1,26 +0,0 @@ -import { Link } from '@fun-eat/design-system'; -import styled from 'styled-components'; - -import { useBannerQuery } from '@/hooks/queries/banner'; - -const Banner = () => { - const { data: banners } = useBannerQuery(); - const { link, image } = banners[Math.floor(Math.random() * banners.length)]; - - if (!link) { - return- -https://funeat.site -2023-09-25T05:39:39+00:00 -- -https://funeat.site/products/food -2023-09-25T05:39:39+00:00 -- -https://funeat.site/products/store -2023-09-25T05:39:39+00:00 -- -https://funeat.site/recipes -2023-09-25T05:39:39+00:00 -; - } - - return ( - - - - ); -}; - -export default Banner; - -const BannerImage = styled.img` - width: 100%; - height: auto; -`; diff --git a/frontend/src/components/Common/CategoryFoodList/CategoryFoodList.stories.tsx b/frontend/src/components/Common/CategoryFoodList/CategoryFoodList.stories.tsx deleted file mode 100644 index 25de7b81..00000000 --- a/frontend/src/components/Common/CategoryFoodList/CategoryFoodList.stories.tsx +++ /dev/null @@ -1,22 +0,0 @@ -import type { Meta, StoryObj } from '@storybook/react'; - -import CategoryFoodList from './CategoryFoodList'; - -import CategoryProvider from '@/contexts/CategoryContext'; - -const meta: Meta = { - title: 'common/CategoryFoodList', - component: CategoryFoodList, - decorators: [ - (Story) => ( - - - ), - ], -}; - -export default meta; -type Story = StoryObj- ; - -export const Default: Story = {}; diff --git a/frontend/src/components/Common/CategoryFoodList/CategoryFoodList.tsx b/frontend/src/components/Common/CategoryFoodList/CategoryFoodList.tsx deleted file mode 100644 index 921584b8..00000000 --- a/frontend/src/components/Common/CategoryFoodList/CategoryFoodList.tsx +++ /dev/null @@ -1,27 +0,0 @@ -import styled from 'styled-components'; - -import CategoryItem from '../CategoryItem/CategoryItem'; - -import { CATEGORY_TYPE } from '@/constants'; -import { useCategoryFoodQuery } from '@/hooks/queries/product'; - -const categoryType = CATEGORY_TYPE.FOOD; - -const CategoryFoodList = () => { - const { data: categories } = useCategoryFoodQuery(categoryType); - - return ( - - {categories.map(({ id, name, image }) => ( - - ); -}; - -export default CategoryFoodList; - -const CategoryFoodListWrapper = styled.div` - display: flex; - gap: 16px; -`; diff --git a/frontend/src/components/Common/CategoryFoodTab/CategoryFoodTab.stories.tsx b/frontend/src/components/Common/CategoryFoodTab/CategoryFoodTab.stories.tsx deleted file mode 100644 index 7cbb6e1f..00000000 --- a/frontend/src/components/Common/CategoryFoodTab/CategoryFoodTab.stories.tsx +++ /dev/null @@ -1,22 +0,0 @@ -import type { Meta, StoryObj } from '@storybook/react'; - -import CategoryFoodTab from './CategoryFoodTab'; - -import CategoryProvider from '@/contexts/CategoryContext'; - -const meta: Meta- ))} - = { - title: 'common/CategoryFoodTab', - component: CategoryFoodTab, - decorators: [ - (Story) => ( - - - ), - ], -}; - -export default meta; -type Story = StoryObj- ; - -export const Default: Story = {}; diff --git a/frontend/src/components/Common/CategoryFoodTab/CategoryFoodTab.tsx b/frontend/src/components/Common/CategoryFoodTab/CategoryFoodTab.tsx deleted file mode 100644 index 56817526..00000000 --- a/frontend/src/components/Common/CategoryFoodTab/CategoryFoodTab.tsx +++ /dev/null @@ -1,78 +0,0 @@ -import { Button, theme } from '@fun-eat/design-system'; -import styled from 'styled-components'; - -import { CATEGORY_TYPE } from '@/constants'; -import { useGA } from '@/hooks/common'; -import { useCategoryActionContext, useCategoryValueContext } from '@/hooks/context'; -import { useCategoryFoodQuery } from '@/hooks/queries/product/useCategoryQuery'; -import { getTargetCategoryName } from '@/utils/category'; - -const categoryType = CATEGORY_TYPE.FOOD; - -const CategoryFoodTab = () => { - const { data: categories } = useCategoryFoodQuery(categoryType); - - const { categoryIds } = useCategoryValueContext(); - const { selectCategory } = useCategoryActionContext(); - - const currentCategoryId = categoryIds[categoryType]; - - const { gaEvent } = useGA(); - - const handleCategoryButtonClick = (menuId: number) => { - selectCategory(categoryType, menuId); - gaEvent({ - category: 'button', - action: `${getTargetCategoryName(categories, menuId)} 카테고리 버튼 클릭`, - label: '카테고리', - }); - }; - - return ( - - {categories.map(({ id, name }) => { - const isSelected = id === currentCategoryId; - return ( - - ); -}; - -export default CategoryFoodTab; - -const CategoryMenuContainer = styled.ul` - display: flex; - gap: 8px; - white-space: nowrap; - overflow-x: auto; - - &::-webkit-scrollbar { - display: none; - } -`; - -const CategoryButton = styled(Button)<{ isSelected: boolean }>` - padding: 6px 12px; - ${({ isSelected }) => - isSelected && - ` - background: ${theme.colors.gray5}; - color: ${theme.textColors.white}; - `} -`; diff --git a/frontend/src/components/Common/CategoryItem/CategoryItem.stories.tsx b/frontend/src/components/Common/CategoryItem/CategoryItem.stories.tsx deleted file mode 100644 index 3dc17ddf..00000000 --- a/frontend/src/components/Common/CategoryItem/CategoryItem.stories.tsx +++ /dev/null @@ -1,28 +0,0 @@ -import type { Meta, StoryObj } from '@storybook/react'; - -import CategoryItem from './CategoryItem'; - -import CategoryProvider from '@/contexts/CategoryContext'; - -const meta: Meta- - ); - })} -handleCategoryButtonClick(id)} - aria-pressed={isSelected} - > - {name} - -= { - title: 'common/CategoryItem', - component: CategoryItem, - decorators: [ - (Story) => ( - - - ), - ], - args: { - categoryId: 1, - name: '즉석 식품', - image: 'https://tqklhszfkvzk6518638.cdn.ntruss.com/product/8801771029052.jpg', - categoryType: 'food', - }, -}; - -export default meta; -type Story = StoryObj- ; - -export const Default: Story = {}; diff --git a/frontend/src/components/Common/CategoryItem/CategoryItem.tsx b/frontend/src/components/Common/CategoryItem/CategoryItem.tsx deleted file mode 100644 index 051c9707..00000000 --- a/frontend/src/components/Common/CategoryItem/CategoryItem.tsx +++ /dev/null @@ -1,65 +0,0 @@ -import { Button } from '@fun-eat/design-system'; -import { useNavigate } from 'react-router-dom'; -import styled from 'styled-components'; - -import { PATH } from '@/constants/path'; -import { useGA } from '@/hooks/common'; -import { useCategoryActionContext } from '@/hooks/context'; - -interface CategoryItemProps { - categoryId: number; - name: string; - image: string; - categoryType: 'food' | 'store'; -} - -const CategoryItem = ({ categoryId, name, image, categoryType }: CategoryItemProps) => { - const navigate = useNavigate(); - const { selectCategory } = useCategoryActionContext(); - - const { gaEvent } = useGA(); - - const handleCategoryItemClick = (categoryId: number) => { - selectCategory(categoryType, categoryId); - navigate(PATH.PRODUCT_LIST + '/' + categoryType); - - gaEvent({ - category: 'button', - action: `${name} 카테고리 링크 클릭`, - label: '카테고리', - }); - }; - - return ( - - ); -}; - -export default CategoryItem; - -const ImageWrapper = styled.div` - display: flex; - justify-content: center; - align-items: center; - width: 60px; - height: 60px; - border-radius: 10px; - background: ${({ theme }) => theme.colors.white}; - - & > img { - width: 100%; - height: auto; - object-fit: cover; - } -`; - -const CategoryName = styled.p` - margin-top: 10px; - font-weight: 600; - font-size: ${({ theme }) => theme.fontSizes.xs}; -`; diff --git a/frontend/src/components/Common/CategoryStoreList/CategoryStoreList.stories.tsx b/frontend/src/components/Common/CategoryStoreList/CategoryStoreList.stories.tsx deleted file mode 100644 index d26be6f4..00000000 --- a/frontend/src/components/Common/CategoryStoreList/CategoryStoreList.stories.tsx +++ /dev/null @@ -1,22 +0,0 @@ -import type { Meta, StoryObj } from '@storybook/react'; - -import CategoryStoreList from './CategoryStoreList'; - -import CategoryProvider from '@/contexts/CategoryContext'; - -const meta: Meta = { - title: 'common/CategoryStoreList', - component: CategoryStoreList, - decorators: [ - (Story) => ( - - - ), - ], -}; - -export default meta; -type Story = StoryObj- ; - -export const Default: Story = {}; diff --git a/frontend/src/components/Common/CategoryStoreList/CategoryStoreList.tsx b/frontend/src/components/Common/CategoryStoreList/CategoryStoreList.tsx deleted file mode 100644 index 6bf2c36a..00000000 --- a/frontend/src/components/Common/CategoryStoreList/CategoryStoreList.tsx +++ /dev/null @@ -1,27 +0,0 @@ -import styled from 'styled-components'; - -import CategoryItem from '../CategoryItem/CategoryItem'; - -import { CATEGORY_TYPE } from '@/constants'; -import { useCategoryStoreQuery } from '@/hooks/queries/product'; - -const categoryType = CATEGORY_TYPE.STORE; - -const CategoryStoreList = () => { - const { data: categories } = useCategoryStoreQuery(categoryType); - - return ( - - {categories.map(({ id, name, image }) => ( - - ); -}; - -export default CategoryStoreList; - -const CategoryStoreListWrapper = styled.div` - display: flex; - gap: 16px; -`; diff --git a/frontend/src/components/Common/CategoryStoreTab/CategoryStoreTab.stories.tsx b/frontend/src/components/Common/CategoryStoreTab/CategoryStoreTab.stories.tsx deleted file mode 100644 index 7fca5880..00000000 --- a/frontend/src/components/Common/CategoryStoreTab/CategoryStoreTab.stories.tsx +++ /dev/null @@ -1,22 +0,0 @@ -import type { Meta, StoryObj } from '@storybook/react'; - -import CategoryStoreTab from './CategoryStoreTab'; - -import CategoryProvider from '@/contexts/CategoryContext'; - -const meta: Meta- ))} - = { - title: 'common/CategoryStoreTab', - component: CategoryStoreTab, - decorators: [ - (Story) => ( - - - ), - ], -}; - -export default meta; -type Story = StoryObj- ; - -export const Default: Story = {}; diff --git a/frontend/src/components/Common/CategoryStoreTab/CategoryStoreTab.tsx b/frontend/src/components/Common/CategoryStoreTab/CategoryStoreTab.tsx deleted file mode 100644 index b75abb7b..00000000 --- a/frontend/src/components/Common/CategoryStoreTab/CategoryStoreTab.tsx +++ /dev/null @@ -1,77 +0,0 @@ -import { Button, theme } from '@fun-eat/design-system'; -import styled from 'styled-components'; - -import { CATEGORY_TYPE } from '@/constants'; -import { useGA } from '@/hooks/common'; -import { useCategoryActionContext, useCategoryValueContext } from '@/hooks/context'; -import { useCategoryStoreQuery } from '@/hooks/queries/product/useCategoryQuery'; -import { getTargetCategoryName } from '@/utils/category'; - -const categoryType = CATEGORY_TYPE.STORE; - -const CategoryStoreTab = () => { - const { data: categories } = useCategoryStoreQuery(categoryType); - - const { categoryIds } = useCategoryValueContext(); - const { selectCategory } = useCategoryActionContext(); - const currentCategoryId = categoryIds[categoryType]; - - const { gaEvent } = useGA(); - - const handleCategoryButtonClick = (menuId: number) => { - selectCategory(categoryType, menuId); - gaEvent({ - category: 'button', - action: `${getTargetCategoryName(categories, menuId)} 카테고리 버튼 클릭`, - label: '카테고리', - }); - }; - - return ( - - {categories.map(({ id, name }) => { - const isSelected = id === currentCategoryId; - return ( - - ); -}; - -export default CategoryStoreTab; - -const CategoryMenuContainer = styled.ul` - display: flex; - gap: 8px; - white-space: nowrap; - overflow-x: auto; - - &::-webkit-scrollbar { - display: none; - } -`; - -const CategoryButton = styled(Button)<{ isSelected: boolean }>` - padding: 6px 12px; - ${({ isSelected }) => - isSelected && - ` - background: ${theme.colors.primary}; - color: ${theme.textColors.default}; - `} -`; diff --git a/frontend/src/components/Common/ErrorBoundary/ErrorBoundary.tsx b/frontend/src/components/Common/ErrorBoundary/ErrorBoundary.tsx deleted file mode 100644 index d8491896..00000000 --- a/frontend/src/components/Common/ErrorBoundary/ErrorBoundary.tsx +++ /dev/null @@ -1,53 +0,0 @@ -import { Button } from '@fun-eat/design-system'; -import type { ComponentType, PropsWithChildren } from 'react'; -import { Component } from 'react'; - -export interface FallbackProps { - message: string; -} - -interface ErrorBoundaryProps { - handleReset?: () => void; - fallback: ComponentType- - ); - })} -handleCategoryButtonClick(id)} - aria-pressed={isSelected} - > - {name} - -; -} - -interface ErrorBoundaryState { - error: Error | null; -} - -class ErrorBoundary extends Component , ErrorBoundaryState> { - state: ErrorBoundaryState = { - error: null, - }; - - static getDerivedStateFromError(error: Error): ErrorBoundaryState { - return { error }; - } - - resetError = () => { - if (this.props.handleReset) { - this.props.handleReset(); - } - - this.setState({ error: null }); - }; - - render() { - const { fallback: FallbackComponent } = this.props; - - if (this.state.error) { - return ( - <> - - - > - ); - } - - return this.props.children; - } -} - -export default ErrorBoundary; diff --git a/frontend/src/components/Common/ErrorComponent/ErrorComponent.stories.tsx b/frontend/src/components/Common/ErrorComponent/ErrorComponent.stories.tsx deleted file mode 100644 index ee51fcea..00000000 --- a/frontend/src/components/Common/ErrorComponent/ErrorComponent.stories.tsx +++ /dev/null @@ -1,13 +0,0 @@ -import type { Meta, StoryObj } from '@storybook/react'; - -import ErrorComponent from './ErrorComponent'; - -const meta: Meta = { - title: 'common/ErrorComponent', - component: ErrorComponent, -}; - -export default meta; -type Story = StoryObj ; - -export const Default: Story = {}; diff --git a/frontend/src/components/Common/ErrorComponent/ErrorComponent.tsx b/frontend/src/components/Common/ErrorComponent/ErrorComponent.tsx deleted file mode 100644 index bc66e1f1..00000000 --- a/frontend/src/components/Common/ErrorComponent/ErrorComponent.tsx +++ /dev/null @@ -1,5 +0,0 @@ -const ErrorComponent = () => { - return 에러가 발생했습니다.; -}; - -export default ErrorComponent; diff --git a/frontend/src/components/Common/Header/Header.stories.tsx b/frontend/src/components/Common/Header/Header.stories.tsx deleted file mode 100644 index b88b4258..00000000 --- a/frontend/src/components/Common/Header/Header.stories.tsx +++ /dev/null @@ -1,13 +0,0 @@ -import type { Meta, StoryObj } from '@storybook/react'; - -import Header from './Header'; - -const meta: Meta= { - title: 'common/Header', - component: Header, -}; - -export default meta; -type Story = StoryObj ; - -export const Default: Story = {}; diff --git a/frontend/src/components/Common/Header/Header.tsx b/frontend/src/components/Common/Header/Header.tsx deleted file mode 100644 index ae2431ed..00000000 --- a/frontend/src/components/Common/Header/Header.tsx +++ /dev/null @@ -1,54 +0,0 @@ -import { Link } from '@fun-eat/design-system'; -import { Link as RouterLink } from 'react-router-dom'; -import styled from 'styled-components'; - -import SvgIcon from '../Svg/SvgIcon'; - -import Logo from '@/assets/logo.svg'; -import { PATH } from '@/constants/path'; - -interface HeaderProps { - hasSearch?: boolean; -} - -const Header = ({ hasSearch = true }: HeaderProps) => { - if (hasSearch) { - return ( - - - - ); - } - - return ( -- - - - - - - - ); -}; - -export default Header; - -const HeaderWithSearchContainer = styled.header` - display: flex; - justify-content: space-between; - align-items: center; - width: calc(100% - 40px); - height: 60px; - margin: 0 auto; -`; - -const HeaderContainer = styled.header` - display: flex; - justify-content: center; - align-items: center; - width: 100%; - height: 60px; -`; diff --git a/frontend/src/components/Common/ImageUploader/ImageUploader.stories.tsx b/frontend/src/components/Common/ImageUploader/ImageUploader.stories.tsx deleted file mode 100644 index 02de4489..00000000 --- a/frontend/src/components/Common/ImageUploader/ImageUploader.stories.tsx +++ /dev/null @@ -1,13 +0,0 @@ -import type { Meta, StoryObj } from '@storybook/react'; - -import ImageUploader from './ImageUploader'; - -const meta: Meta- - = { - title: 'common/ImageUploader', - component: ImageUploader, -}; - -export default meta; -type Story = StoryObj ; - -export const Default: Story = {}; diff --git a/frontend/src/components/Common/ImageUploader/ImageUploader.tsx b/frontend/src/components/Common/ImageUploader/ImageUploader.tsx deleted file mode 100644 index b139a1b4..00000000 --- a/frontend/src/components/Common/ImageUploader/ImageUploader.tsx +++ /dev/null @@ -1,76 +0,0 @@ -import { Button, useToastActionContext } from '@fun-eat/design-system'; -import type { ChangeEventHandler } from 'react'; -import styled from 'styled-components'; - -import { IMAGE_MAX_SIZE } from '@/constants'; -import { useEnterKeyDown } from '@/hooks/common'; - -interface ReviewImageUploaderProps { - previewImage: string; - uploadImage: (imageFile: File) => void; - deleteImage: () => void; -} - -const ImageUploader = ({ previewImage, uploadImage, deleteImage }: ReviewImageUploaderProps) => { - const { inputRef, handleKeydown } = useEnterKeyDown(); - const { toast } = useToastActionContext(); - - const handleImageUpload: ChangeEventHandler = (event) => { - if (!event.target.files) { - return; - } - - const imageFile = event.target.files[0]; - - if (imageFile.size > IMAGE_MAX_SIZE) { - toast.error('이미지 크기가 너무 커요. 5MB 이하의 이미지를 골라주세요.'); - event.target.value = ''; - return; - } - - uploadImage(imageFile); - }; - - return ( - <> - {previewImage ? ( - - - - - ) : ( -- + - - - )} - > - ); -}; - -export default ImageUploader; - -const ImageUploadLabel = styled.label` - display: flex; - justify-content: center; - align-items: center; - width: 92px; - height: 95px; - border: 1px solid ${({ theme }) => theme.borderColors.disabled}; - border-radius: ${({ theme }) => theme.borderRadius.xs}; - background: ${({ theme }) => theme.colors.gray1}; - cursor: pointer; - - & > input { - display: none; - } -`; - -const PreviewImageWrapper = styled.div` - display: flex; - flex-direction: column; - gap: 20px; - align-items: center; -`; diff --git a/frontend/src/components/Common/Loading/Loading.stories.tsx b/frontend/src/components/Common/Loading/Loading.stories.tsx deleted file mode 100644 index 3b866175..00000000 --- a/frontend/src/components/Common/Loading/Loading.stories.tsx +++ /dev/null @@ -1,13 +0,0 @@ -import type { Meta, StoryObj } from '@storybook/react'; - -import Loading from './Loading'; - -const meta: Meta= { - title: 'common/Loading', - component: Loading, -}; - -export default meta; -type Story = StoryObj ; - -export const Default: Story = {}; diff --git a/frontend/src/components/Common/Loading/Loading.tsx b/frontend/src/components/Common/Loading/Loading.tsx deleted file mode 100644 index 7c58614a..00000000 --- a/frontend/src/components/Common/Loading/Loading.tsx +++ /dev/null @@ -1,49 +0,0 @@ -import { Text } from '@fun-eat/design-system'; -import styled, { keyframes } from 'styled-components'; - -import PlateImage from '@/assets/plate.svg'; - -const DEFAULT_DESCRIPTION = '잠시만 기다려주세요 🥄'; - -interface LoadingProps { - customHeight?: string; - description?: string; -} - -const Loading = ({ customHeight = '100%', description = DEFAULT_DESCRIPTION }: LoadingProps) => { - return ( - - - ); -}; - -export default Loading; - -type LoadingContainerStyleProps = Pick- -- {description} -; - -const LoadingContainer = styled.div ` - display: flex; - flex-direction: column; - row-gap: 36px; - justify-content: center; - align-items: center; - height: ${({ customHeight }) => customHeight}; -`; - -const rotate = keyframes` - 0% { - transform: rotate(0deg); - } - - 100% { - transform: rotate(360deg); - } -`; - -const PlateImageWrapper = styled.div` - animation: ${rotate} 1.5s ease-in-out infinite; -`; diff --git a/frontend/src/components/Common/MarkedText/MarkedText.tsx b/frontend/src/components/Common/MarkedText/MarkedText.tsx deleted file mode 100644 index 341b3c92..00000000 --- a/frontend/src/components/Common/MarkedText/MarkedText.tsx +++ /dev/null @@ -1,28 +0,0 @@ -import { Fragment } from 'react'; -import styled from 'styled-components'; - -interface MarkedTextProps { - text: string; - mark: string; -} - -const MarkedText = ({ text, mark }: MarkedTextProps) => { - const textFragments = text.split(new RegExp(`(${mark})`, 'gi')); - - return ( - <> - {textFragments.map((fragment, index) => ( - - {fragment.toLowerCase() === mark.toLowerCase() ? {fragment} : <>{fragment}>} - - ))} - > - ); -}; - -export default MarkedText; - -const Mark = styled.mark` - font-weight: ${({ theme }) => theme.fontWeights.bold}; - background-color: ${({ theme }) => theme.backgroundColors.default}; -`; diff --git a/frontend/src/components/Common/NavigableSectionTitle/NavigableSectionTitle.stories.tsx b/frontend/src/components/Common/NavigableSectionTitle/NavigableSectionTitle.stories.tsx deleted file mode 100644 index 739bde3e..00000000 --- a/frontend/src/components/Common/NavigableSectionTitle/NavigableSectionTitle.stories.tsx +++ /dev/null @@ -1,16 +0,0 @@ -import type { Meta, StoryObj } from '@storybook/react'; - -import NavigableSectionTitle from './NavigableSectionTitle'; - -const meta: Meta= { - title: 'common/NavigableSectionTitle', - component: NavigableSectionTitle, - args: { - title: '내가 작성한 리뷰 (12개)', - }, -}; - -export default meta; -type Story = StoryObj ; - -export const Default: Story = {}; diff --git a/frontend/src/components/Common/NavigableSectionTitle/NavigableSectionTitle.tsx b/frontend/src/components/Common/NavigableSectionTitle/NavigableSectionTitle.tsx deleted file mode 100644 index a24ba0ed..00000000 --- a/frontend/src/components/Common/NavigableSectionTitle/NavigableSectionTitle.tsx +++ /dev/null @@ -1,35 +0,0 @@ -import { Heading, Link, theme } from '@fun-eat/design-system'; -import { Link as RouterLink } from 'react-router-dom'; -import styled from 'styled-components'; - -import { SvgIcon } from '@/components/Common'; - -interface NavigableSectionTitleProps { - title: string; - routeDestination: string; -} - -const NavigableSectionTitle = ({ title, routeDestination }: NavigableSectionTitleProps) => { - return ( - - - ); -}; - -export default NavigableSectionTitle; - -const NavigableSectionTitleContainer = styled.div` - display: flex; - justify-content: space-between; - align-items: center; -`; - -const ArrowIcon = styled(SvgIcon)` - transform: translateY(3px) rotate(180deg); -`; diff --git a/frontend/src/components/Common/NavigationBar/NavigationBar.stories.tsx b/frontend/src/components/Common/NavigationBar/NavigationBar.stories.tsx deleted file mode 100644 index a9242715..00000000 --- a/frontend/src/components/Common/NavigationBar/NavigationBar.stories.tsx +++ /dev/null @@ -1,19 +0,0 @@ -import type { Meta, StoryObj } from '@storybook/react'; - -import NavigationBar from './NavigationBar'; - -const meta: Meta- {title} - - -- - = { - title: 'common/NavigationBar', - component: NavigationBar, -}; - -export default meta; -type Story = StoryObj ; - -export const Default: Story = { - render: () => ( - -- ), -}; diff --git a/frontend/src/components/Common/NavigationBar/NavigationBar.tsx b/frontend/src/components/Common/NavigationBar/NavigationBar.tsx deleted file mode 100644 index 8cbfbee3..00000000 --- a/frontend/src/components/Common/NavigationBar/NavigationBar.tsx +++ /dev/null @@ -1,63 +0,0 @@ -import { Link, Text, theme } from '@fun-eat/design-system'; -import { Link as RouterLink, useLocation } from 'react-router-dom'; -import styled from 'styled-components'; - -import SvgIcon from '../Svg/SvgIcon'; - -import { NAVIGATION_MENU } from '@/constants'; - -const NavigationBar = () => { - const location = useLocation(); - - return ( -- - - ); -}; - -export default NavigationBar; - -const NavigationBarContainer = styled.nav` - width: 100%; - height: 60px; -`; - -const NavigationBarList = styled.ul` - display: flex; - justify-content: space-around; - align-items: center; - padding-top: 12px; - border: 1px solid ${({ theme }) => theme.borderColors.disabled}; - border-bottom: none; - border-top-left-radius: 20px; - border-top-right-radius: 20px; -`; - -const NavigationItem = styled.li` - height: 50px; -`; - -const NavigationLink = styled(Link)` - display: flex; - flex-direction: column; - gap: 4px; - justify-content: flex-end; - align-items: center; -`; diff --git a/frontend/src/components/Common/RegisterButton/RegisterButton.tsx b/frontend/src/components/Common/RegisterButton/RegisterButton.tsx deleted file mode 100644 index 1601e560..00000000 --- a/frontend/src/components/Common/RegisterButton/RegisterButton.tsx +++ /dev/null @@ -1,36 +0,0 @@ -import { Button } from '@fun-eat/design-system'; -import styled from 'styled-components'; - -import { useMemberQuery } from '@/hooks/queries/members'; - -interface RegisterButtonProps { - activeLabel: string; - disabledLabel: string; - onClick: () => void; -} - -const RegisterButton = ({ activeLabel, disabledLabel, onClick }: RegisterButtonProps) => { - const { data: member } = useMemberQuery(); - - return ( -- {NAVIGATION_MENU.map(({ variant, name, path }) => { - const currentPath = location.pathname.split('/')[1]; - const isSelected = currentPath === path.split('/')[1]; - - return ( - -- - ); - })} -- -- - {name} - -- {member ? activeLabel : disabledLabel} - - ); -}; - -export default RegisterButton; - -const RegisterButtonContainer = styled(Button)` - cursor: ${({ disabled }) => (disabled ? 'not-allowed' : 'pointer')}; -`; diff --git a/frontend/src/components/Common/ScrollButton/ScrollButton.stories.tsx b/frontend/src/components/Common/ScrollButton/ScrollButton.stories.tsx deleted file mode 100644 index 50b796d2..00000000 --- a/frontend/src/components/Common/ScrollButton/ScrollButton.stories.tsx +++ /dev/null @@ -1,13 +0,0 @@ -import type { Meta, StoryObj } from '@storybook/react'; - -import ScrollButton from './ScrollButton'; - -const meta: Meta= { - title: 'common/ScrollButton', - component: ScrollButton, -}; - -export default meta; -type Story = StoryObj ; - -export const Default: Story = {}; diff --git a/frontend/src/components/Common/ScrollButton/ScrollButton.tsx b/frontend/src/components/Common/ScrollButton/ScrollButton.tsx deleted file mode 100644 index 6bfcc509..00000000 --- a/frontend/src/components/Common/ScrollButton/ScrollButton.tsx +++ /dev/null @@ -1,58 +0,0 @@ -import { Button } from '@fun-eat/design-system'; -import type { RefObject } from 'react'; -import { styled } from 'styled-components'; - -import SvgIcon from '../Svg/SvgIcon'; - -import { useScroll } from '@/hooks/common'; - -interface ScrollButtonProps { - targetRef: RefObject ; - isRecipePage?: boolean; -} - -const ScrollButton = ({ targetRef, isRecipePage = false }: ScrollButtonProps) => { - const { scrollToTop } = useScroll(); - - const handleScroll = () => { - if (targetRef) { - scrollToTop(targetRef); - } - }; - - return ( - - - ); -}; - -export default ScrollButton; - -const ScrollButtonWrapper = styled(Button)- >` - position: fixed; - bottom: ${({ isRecipePage }) => (isRecipePage ? '210px' : '90px')}; - right: 20px; - border-radius: 50%; - box-shadow: rgba(0, 0, 0, 0.2) 0px 1px 4px; - - @media screen and (min-width: 600px) { - left: calc(50% + 234px); - } - - &:hover { - transform: scale(1.1); - transition: all 200ms ease-in-out; - } - - svg { - rotate: 90deg; - } -`; diff --git a/frontend/src/components/Common/SectionTitle/SectionTitle.stories.tsx b/frontend/src/components/Common/SectionTitle/SectionTitle.stories.tsx deleted file mode 100644 index 05883aea..00000000 --- a/frontend/src/components/Common/SectionTitle/SectionTitle.stories.tsx +++ /dev/null @@ -1,23 +0,0 @@ -import type { Meta, StoryObj } from '@storybook/react'; - -import SectionTitle from './SectionTitle'; - -const meta: Meta = { - title: 'common/SectionTitle', - component: SectionTitle, -}; - -export default meta; -type Story = StoryObj ; - -export const Default: Story = { - args: { - name: '사이다', - }, -}; - -export const Bookmarked: Story = { - args: { - name: '사이다', - }, -}; diff --git a/frontend/src/components/Common/SectionTitle/SectionTitle.tsx b/frontend/src/components/Common/SectionTitle/SectionTitle.tsx deleted file mode 100644 index c9d649dd..00000000 --- a/frontend/src/components/Common/SectionTitle/SectionTitle.tsx +++ /dev/null @@ -1,54 +0,0 @@ -import { Button, Heading, Link, theme } from '@fun-eat/design-system'; -import { Link as RouterLink } from 'react-router-dom'; -import styled from 'styled-components'; - -import { SvgIcon } from '@/components/Common'; -import { useRoutePage } from '@/hooks/common'; - -interface SectionTitleProps { - name: string; - link?: string; -} - -const SectionTitle = ({ name, link }: SectionTitleProps) => { - const { routeBack } = useRoutePage(); - - return ( - - -