From af8809bdee22633d3fb1ca39e12f1d2309af3603 Mon Sep 17 00:00:00 2001 From: Imhwitae Date: Wed, 18 Jun 2025 21:23:21 +0900 Subject: [PATCH 01/94] sprint misson1 upload --- css/login_style.css | 100 +++++++++++++ css/style.css | 257 ++++++++++++++++++++++++++++++++++ images/Img_home_01.png | Bin 0 -> 13582 bytes images/Img_home_02.png | Bin 0 -> 17056 bytes images/Img_home_03.png | Bin 0 -> 10648 bytes images/Img_home_bottom.png | Bin 0 -> 56972 bytes images/Img_home_top.png | Bin 0 -> 49603 bytes images/Property 1=lg.png | Bin 0 -> 6365 bytes images/Property 1=md.png | Bin 0 -> 3520 bytes images/Property 1=sm.png | Bin 0 -> 2796 bytes images/icons/ic_facebook.png | Bin 0 -> 387 bytes images/icons/ic_google.png | Bin 0 -> 1589 bytes images/icons/ic_instagram.png | Bin 0 -> 405 bytes images/icons/ic_kakao.png | Bin 0 -> 1439 bytes images/icons/ic_twitter.png | Bin 0 -> 332 bytes images/icons/ic_youtube.png | Bin 0 -> 288 bytes index.html | 95 +++++++++++++ login.html | 45 ++++++ signup.html | 54 +++++++ 19 files changed, 551 insertions(+) create mode 100644 css/login_style.css create mode 100644 css/style.css create mode 100644 images/Img_home_01.png create mode 100644 images/Img_home_02.png create mode 100644 images/Img_home_03.png create mode 100644 images/Img_home_bottom.png create mode 100644 images/Img_home_top.png create mode 100644 images/Property 1=lg.png create mode 100644 images/Property 1=md.png create mode 100644 images/Property 1=sm.png create mode 100644 images/icons/ic_facebook.png create mode 100644 images/icons/ic_google.png create mode 100644 images/icons/ic_instagram.png create mode 100644 images/icons/ic_kakao.png create mode 100644 images/icons/ic_twitter.png create mode 100644 images/icons/ic_youtube.png create mode 100644 index.html create mode 100644 login.html create mode 100644 signup.html diff --git a/css/login_style.css b/css/login_style.css new file mode 100644 index 00000000..adf315a1 --- /dev/null +++ b/css/login_style.css @@ -0,0 +1,100 @@ +@font-face { + font-family: 'Pretendard-Regular'; + src: url('https://fastly.jsdelivr.net/gh/Project-Noonnu/noonfonts_2107@1.1/Pretendard-Regular.woff') format('woff'); + font-weight: 400; + font-style: normal; +} + +* { + box-sizing: border-box; +} + +body { + margin: 0 auto; +} + +main { + display: flex; + justify-content: center; + align-items: center; + margin: 0 auto; + height: 100vh; +} + +p { + font-size: 18px; + font-weight: 700; +} + +form { + display: flex; + flex-direction: column; + justify-content: center; + align-content: center; +} + +input { + width: 100%; + height: 56px; + border-radius: 12px; + border: none; + background-color: #f3f4f6; + padding: 20px; + font-size: 16px; + font-weight: 400; +} + +button { + width: 100%; + height: 56px; + border: none; + border-radius: 40px; + margin: 20px 0; + background-color: #3692ff; + color: white; + font-size: 20px; + font-weight: 600; +} + +.container { + display: flex; + flex-direction: column; + justify-content: center; + width: 640px; + height: 618px; + margin: 0 auto; +} + +.login_logo { + text-align: center; +} + +.social_login_container { + background-color: #e6f2ff; + display: flex; + justify-content: space-between; + align-items: center; + padding: 10px 20px; + border-radius: 8px; +} + +.social_login_container p { + font-weight: 500; + font-size: 16px; +} + +.sns_icon_box img{ + margin: 0 5px; +} + +.link_join { + display: flex; + justify-content: center; + font-size: 14px; + font-weight: 500; +} + +.link_join a { + color: #3692ff; +} + diff --git a/css/style.css b/css/style.css new file mode 100644 index 00000000..b1198c58 --- /dev/null +++ b/css/style.css @@ -0,0 +1,257 @@ +*{ + box-sizing: border-box; +} + +@font-face { + font-family: 'Pretendard-Regular'; + src: url('https://fastly.jsdelivr.net/gh/Project-Noonnu/noonfonts_2107@1.1/Pretendard-Regular.woff') format('woff'); + font-weight: 400; + font-style: normal; +} + +body { + margin: 0; +} + +header { + top: 0; + height: 70px; + background-color: white; + display: flex; + justify-content: center; + position: sticky; +} + +footer { + background-color: #cfe5ff; +} + +a { + text-decoration: none; + color: white; + font-weight: 600; + cursor: pointer; +} + +h1 { + color: #374151; + font-weight: 700; + font-size: 2vw; +} + +h2 { + font-weight: 500; + font-size: 1vw; + color: #374151; +} + +button { + cursor: pointer; +} + +/* 화면의 너비가 1920px 보다 작아질 때, “판다마켓” 로고의 왼쪽 여백 200px“로그인" 버튼의 오른쪽 여백 200px이 유지되고, 화면의 너비가 작아질수록 두 요소간 거리가 가까워지도록 해주세요. */ +.logo { + width: 100%; + display: flex; + justify-content: space-between; + align-items: center; + padding: 10px 200px; +} + +.login_btn { + width: 128px; + height: 48px; + background-color: #3692ff; + border: none; + border-radius: 8px; + font-size: 16px; +} + +.login_btn:hover { + background-color: #1967d6; +} + +.login_btn:active { + background-color: #1251aa; +} + +.plan_card { + background-color: #cfe5ff; + display: flex; + height: 540px; + justify-content: center; + align-items: end; +} + +.slogan { + display: flex; + flex-direction: column; + margin-bottom: 100px; +} + +.large_btn { + width: 19vw; + height: 56px; + background-color: #3692ff; + border-radius: 40px; + border: none; + font-size: 20px; +} + +.large_btn:hover { + background-color: #1967d6; +} + +.large_btn:active { + background-color: #1251aa; +} + +.main_img { + width: 746px; + height: 340px; +} + +.container { + height: 720px; + display: flex; + justify-content: center; + align-items: center; +} + +.content_box { + width: 988px; + height: 444px; + border-radius: 12px; + border: none; + background-color: #fcfcfc; + display: flex; + justify-content: space-around; + align-items: center; +} + +.introduce_img { + width: 579px; + height: 444px; +} + +.keyword { + font-weight: 800; + font-size: 18px; + color: #3692ff; +} + +.sec_introduce { + text-align: right; +} + +.bottom { + height: 540px; + display: flex; + justify-content: center; + align-items: end; +} + +.bottom_slogan { + padding-bottom: 100px; +} + +.footer_container { + height: 160px; + background-color: #111827; + display: flex; + justify-content: center; +} + +.bottom_content_box { + width: 1110px; + padding-bottom: 60px; + display: flex; + align-items: center; + justify-content: space-between; +} + +.copyright { + color: #9ca3af; + font-size: 16px; + font-weight: 400; +} + +.footer_menu a { + color: #e5e7eb; + font-size: 16px; + font-weight: 400; + padding: 15px; +} + +.sns_menu ul { + padding: 0; +} + +.sns_menu ul > li { + list-style: none; + display: inline-block; + padding: 5px; +} + +/* tablet */ +@media (max-width: 1199px) { + body { + background-color: #fcfcfc; + } + + h1 { + color: #374151; + font-weight: 700; + font-size: 32px; + } + + h2 { + font-weight: 500; + font-size: 18px; + color: #374151; + } + + .plan_card { + background-color: #cfe5ff; + display: flex; + flex-direction: column; + height: 771px; + justify-content: space-between; + align-items: center; + } + + .main_img { + width: 744px; + height: 340px; + } + + .slogan { + align-items: center; + margin-top: 50px; + } + + .only_pc { + display: none; + } + + /* .container { + } */ + + .content_box { + flex-direction: column; + /* align-items: flex-start; */ + } + + .keyword { + font-weight: 700; + font-size: 18px; + color: #3692ff; + } + + .introduce_img { + width: 696px; + height: 525.55px; + } +} + + diff --git a/images/Img_home_01.png b/images/Img_home_01.png new file mode 100644 index 0000000000000000000000000000000000000000..2afef3f35d665c9a37d7dac9362ea17cb635b3cd GIT binary patch literal 13582 zcmeIZXEV(GY<^AQELIIV}(f8wvtp zwGrS05N`TQMc@~qqtZJU5Qv!k-wzfjErS{WV!3E3z5-Q@KHULca4lq1Wk8_nXyR*A zJP=4QPgzdpjVBgrg)oLy7ru4m_en?h?Bxp@k{5aJS+Hi6l0ZuWW+XQDRV=nlIV9=N z5k^5>wDSWtF&_Mkbw&(N_dv4`5j3*7j_Wvsgpt73tuN8p|^TzBi5M;#t@XVQ7?Icv#(-5*zWT9$Gf zAH51BkNLNC)b_s%i}H^P`marx~kE;VsEU*|Z8wi}>ZTW7{ueS5?mkcG5T|%`<61BDU zETs!S2op#lR2c~v&S3@1Z~BS`Sai2(W8u`|d;(LCOZgTI^OXG1yFbuNb<{^SqbR92 zwN%-qfi-e#jKKel35?~R!*;utsuQhQn;Bxj{^)D>1ys!jyNP9GYlp6gvp_tH+ySYX z+H}h)#a-@-t>aS2S}(kxuq&=khE3uB5qgOak{#(l8RM&;9uTUcq+jlPt--?_Y+irB zf!tW#1z-P3Ux__vBAYxyi||+@2y}K=hm)^(DkFSX)vTm@6B2pNRKXn z5Cq+9DX&^DfAl5r7i&+C)~Tf!pSxVSKXl0m{MS-Y_dv3il|w(=?g9F&J|J4^vM(fm z3U4^>Gt}~4QBzhyb(7~`=k=m93O;QSG#xBI+sT}owsdgmVcB6GBW@6GjUQO*R6NfJ zqs@v-R8c2o`;4>QpYH&omfkvp-i)@F=af_>D=xMRqta<4XS^bFMfmDU^$%lu?h_(PXuvvDqwQ$($W2=02K3+t?{!9UnL#O+OB`BDR%VAW{7V*B9zZ$ z`2+hSP~RYa;)VsL4w?ZGDTXez9X@@$wPWqr>815s=x0*mNqy2 zB-f?oBpq~L&IDV7dX4oUY%kmPtnkMlmKmc??T;0!B&3u6g7na%zX&Noyw=dfz86^ej|~{ksUDAR?Kq zXR5w`>7BCm4@hl_mCgaBi9Gt8FTT$aOsc*pB5KR?K^zSI0@#7f|G;GZ{~G5^^*c1B&Exp)Mpq}|rraoPZBmXKA}G1>Uy z*H*;Hn01CA=ZvwKJm|in33iN4K{{D|Puyup=r)Q`;f4HQ|Db*rkrciLu$V@uQ#>b9of9lyS?{IyyK% zc}HJO`1{O7QQVKydh@OL$KSMLbx9Imc*Pc;xVxAs4k+8mo{MjvFuP=1SI#pHIf##t zd1d`~T&3-IUVY76Ey!wCn7A6{a!KkIc4n2-Ehd*^uAB&)I&-mj#xugnN1(ddDL&5- z6`0K;`9wmj@+YAYQp8R`uh3+ZMEt$14`}u?pzOxwpqX3c6$k`+R7F81KZ%T|Shjcg za;7umcl>!;c3|-NjZxuUWji#|o?0u?U1T!5d?kH4<23*F6{Op~kLAKBzU--xzcae;&4cQDa@jitxV`#;PYL5F(qXnmoa(8Jxls7|)VA1|lZV3(QxLbjx zSM5rXRKu@7^nV6XlVFqkU#Ic7sozad!SX$_w3>dcBXXMO(OFFGv*_Jk_6w{6?ss|@ z3v@D$T#z=#k?`kdTk0w+WJ)8PQR`TfuYk>Z--R6~tFw7PC<$@NfNecs(>~Bj>0w9zi@15dvb6IG9XNe%RGKi!%}S3!>O9dPCkO52JU;&`T;H z%Rm{sY)fk30+A{>uj}U(T9XsL_1%+fq>SNQ5e(cX{~tU#2tkbGK>S>07>+oZt`Tu@ySoh+bXR|Uk{>>8 z+@>lt2#39E^YhVZV;BuvN6xz73#(V)9- zhsbIkkWqcymBrv@PmwqMKBOfyS=n-Jw4r`~n@M#k8}J@aS^&7>eEovHh8j6JIIcV- z?ZjhVQHHmxRP(nq6d=7irj0sF&u(dwD#okcBzM$NJn`MTYm?Ehtn649ymM{=+{aBd z2#hV0ayR=#Px@WE$^%A<28`o-F^VoiX8Ar{6WqF3Arb zU1s21^Pfitr9ZgebF+2T(&M;RrT4~lo2RX_Z$BYzeoM$g;@$Q7N#H6s=ti&U5lAS< z2SxsyUf&)shLQSZYomB{z5Jm#%CvdZ?HWzPXMgJ6y_dICfH@PJ*1f3h$3vI^CO6OM zfaK>~fi=;&X4wC7%4CXG-k5y)pepUgRLPji2p=AD-%}mF9O?6Et9j%W^I&Hgb0Er9 z@Sc>=-}fK+w_{_}A$qoHl7w^c$zMI=m~ew-EX=cGqcw}q0ZPn`JrN=+RTSB{t6mkS z4$*C6pYf$Za3K6uVI6dtA03DbvHnov9#(2x?DJ0VUd=nV$s2pT6OysL*E8n6o=tlj zqvl{qY)o~--H2)MIOOjv+Gzr9%LAv0LP$P%`<>6B3i#~=6<{DtQpGDwbu`T4sV?Mc!YcYr{^@f7;j z>Ysm#PaY;IWCFs!<_*v`k}pK1M! zS(8lpqR%ghTgXpG%{xUxHvq$zTXc;=zKJoV5zb%m>?hDp8#mAmXvC=JhZ~YRN1WJ=(UEjjkS$Ceu z&K78+x1X;Z8#Loi@a`pv+o8QkM43R@?9bn8g7-Ts% z^|63EvW6j}1h=SdB3G9)c}HO^qW04b;uLB#s;TvWXpAoz{A%`OS!RruCPrtC)Uy*8 zW+eKRtiBtH%Z6iBsr?{>ji#pV4M_;fgpUWNe?6}q~# z7))S0E*S1wAyXj1G^HI+fslZqcz3dDRrBu>SW!z8GaceZ;4nMd^XqM!j|lSt^yt{{ z(=7YmNQe{#+~_?J`vUhhp6?@!`>;2iISJHw<8R7x{7Q>|z6Mt_h`wCEv*VkerG3Nd z+*}5S7*Md5@}_5S^%)T8f_%HO`pwHWGHa3{pjkB6A^{ z)%1BCS194#9aSRa^UJnR`_tSjW97HkyfQ-HAGxwi^625d6rSiLA^L+ne7Nv(p@j}L^Mt}$Ox7|eoOHoys zw!Yg)EuK96ot=3B+tAG8uJi3xX1oW^hy1bXQj7w|@7IYJUBYIs+qUZm5ZW269g24@ z>DpP`ohZTL_TO?cEr6<6z?;(b`ouZ}ifC7QY{R{6PuHBsX{0>z^ac)K8nm9^!(N;> zE(6{o)mw_j$eQb>B5eG&T+_=FryxIiCIQ^|FOoOw>_AuWFd;GfrnRvC{!%dj{eo}q7uy2a`InUJ-(kZsp1arBq#W#ukIYxzq+ z=qr=KoZ#MqZ;ga`MJs!-G#V2_SEDJ0)w#5}g!xhmdk3=GU=nb;LJH*{^EF8`XLoLWgPn^0&x< zS(GPeSAr5{_&vdeR z$LwOQ2%bnM35Yay!Lto33sZa9HjXkeM- z>V0xk7L$k-l74)KB2#4bWO3jaH#vjNd8at;vpzozdOFJfDQ`0&D%(3NeF@SpJJhc~ zccekyI{P5slw+A5x8U+mC?hE^L#)L4-;UCtJCegR37Ju(dtnB|B`#yrm_U=Wbz^!~ zW1&8JM@nZ$l*(XWr*)!zg-~JgP9LRuIYRYie}&5?7NZ~g5@pEDy-6Ox*?&q9+1t{5 zLN0h}8AI4JZ1&(&QlQGY%U%QcwC;d`oP7CWILP^klaD-|?$mpbKGlz_>88pL-v5Hk zwZY2YI=E;h^Fcwh>1SVO@8^Q>?z`3O1!-{-pj2`Ubz#d)-@ zUZ+C*uWIu_vBPWnwzIFg7sZty@svF8Ui(r=<|BFUc;5@x*le#X+a%@s zZk>uf!s7_~LTvD6)f%4!+HaE~t6lMUBhb!!gN)ZRd0sAbaTSH(HAn5EB{>(iIb>_ zS?t?J{ZJt}NtunlQ0bMvGnHu~_1oqCOkVQx+t+k7*Uf52>81+V9h|p2ZW1Z$R}_?l zPFV2QulB9z8C;c@9^xQa!FlC=S_LOjYkYbg^-;CwhXq56Chr}Z>WUOI1|(?05U(Oe zy6Nznciu z%R}PI#6DzYHjt?q@Ncux51Y+^Z1BmXmpp7DY@W+tSaXhP@^4+M^DE;olZ^T7tXU_O zWW02VK|_jxM)}NmtcZ`KVZ{#!pm<&Raxa3hxL|SbO)|be-cvN;!oM^E^2$d*5$^vp z&zRIFmCPW}{1?RM;SAAwpbJv*OaN6$oVe<`E;y)<_mp@Mr+?f76(ufD?;jePpI+yGj<- z@+wNI!R^=8O;7FBH3+Sa%MOw*$tYCUAaFT}FpF!A_C+3YitS>kRR`&%7_BtYRuMlO zNmTC6uKZLjxl+=NoC+A}3TKF>Mn<88$IkotNd@1Xf7axtCJAj3Oq?3R|O5rumB!j_U zUQzEq`2kC#n9!-w==;TVr#RYza#nl^_@y#}{_R)$!bG5tk%-UBdf)ko`_#RY@Pi9X z-Bq(581ODuH=d;6vy*7i4q`p!~0h&ju;N zmIa3;$oPEIPt+umM}J>Hn+4ZGndS~NX|AuVeobQ1QZpz)(y;BJ&@*WIU&He9f$!Vi zB*ZFAne2EVC8_|zS@AmCSsG|i$nVMgb|?%Blpl(~-Aip4Y}^|!12H;$->=HDD)mu+ zE7a+VfNgI$vcYkrTL_^4LHXX+-gu?_B?0ZQfV*I9s+Y58$*$%3+%vmw0HcV1jOqq4 z*ONZKT@)ZP@1x^BObP>Vw-o<}6RQQiOg&CAV^h_l#dFq~j_a@rXu^;HM0^T!tzXYp zpE!Gr8?`qeS0Ldk?*Ny&S>72;0D&fDOajkHp9t)<>eKqbC`nZMqn{=!w0ksTwRg5P zvBqm_%Xku%zbO^)IQ2YCA0BD!o=Hj#=qhfhfdctD1wZS(y;OlvEAxTC#F^gBj;gwP zi5L5J`5gkDYH|3Sr~;a%awBp;VZZ_x17(Wjo(Nrt(I*+fCYz7T8~v2kGFP4~N27V= z+Yi1HZ%$HO+a6k+_qZNmw2xdSu|NvIl1o!vKQC9E^m~yTjoq|nwHWg@A4&bZZI&&q z$j%SgEnvTEDtnvPHQ@}3q5K2xvOam~0!#T9e7ERDM{|+H(<{DrwbAtrs?bx2F}qi3 z>EYE3%3mv!yB?;QjZs;)>aCECWal|Pp!6m_Ma(~rq&F4Sni!Bz1Z1*w`xu)boo^4xb2scNK^=p z{}JOq(R56WI;J2l^#nYS2^kx_M?aKA{GZb>2Bg}ocGI(g{4)VNN!p3;zybl;N?<)H zIpAHMFagBGXC)v|3?3lc?K=$UWDj5iM=ed*wE%D{zy;sr8JiCds7B5tFp-p}7M~o% zC=M|F+4mOUgk}bJy(S(u#s+=-g1~(a6rKO`;AKE32=p-wfK(3(gBVqS!WYONC?4zW zXe62gpCK#&VqXuN{twPxRX$L-wE;#$SD%5TXMt&s`a}XVmTmz4Bvk>vfT&S033LNm z8~t|!m#Gxp*i z6+b{FFn0Y6grEi%mI$N+xFG+shbbnHqhfGCUvUBmbwmvc{;dK6V0J%c10h5J#K$@p z`2TwpIGUiZSOA`BqQn1v@c)2F{%Nc)7=de31+3r100=w4#~Q$D@c*smzX32H1Pt6T z11*Kp&BU?EV>%?J!^>XMkjUHumqlhWdB=cfc>dE5Q~ou-@M1%0nh;?g0n@R`vy~IS zRGwo4ce{-bN>S!`{&f>Qbq{?k_9sh$AqTGqPR+$%m zgaaX{db6iAr-P5N1Bw}K89roN+&+pS{Ig!h@IQ#sWM1`fqwdjTq0}QTY(|LJ_s8qs zkWW;IHy8qnLB|3ex3%m>jG)OLgN(@a)*&fuZLH~Cx1T}TOJ~}r0#EE41fNyu8d>*> z{9V~(2;kgu6)-bG`?%^Iu<-fVIFh_TrENHTD3zEAcN#y8S{wEOGJOLU3%tL>#fH9? zu!!sB(d;dkjqBe#oyi-AYDNA>Bh z^?$d~JwxqFWc^tT9jhn$SCscYjQIgE|J!D{McZI!o0dsY?o7C#WoAm+M|R%I*MUG6 zMkrhdRCGgMw4+oxHF~V`1dk`s)KY(>OUZw-;K3i8_93RH1_$=prDyip(JRrCjkSf17>$d{1~+Q6%42CmXR%;3%O$w%xZs>I$= z0J%I2s0PTI45sc55-GOkD`5t7tzTlHjOAyi;R;EI?)IbJ}WQ#%?QJPR(Z>d_w@GEWLOtiF`#6r1^YUy1a_ENTGU~2ya{@aqu%VK_vU-@T+n#P%;Yr3wy@K=TlUJ3Uz44p<8;^dj-sN`p@aT zPWhV;JFcvdadubq&#Z$N2%z{xIw6J?`0|dm2k3~t^2Qb3#ufMX8r-ug#6zXVH`aH@ zTwWtKMm$1O$h$t;PBsrD+{1C<3o&1t25-kXRnQ?bcZMQ;MDc?*mD}4x zhonls8_GpY$`XbH(6*e3z!!X0NQwCynVl2k^WP!F{fy<1DdJ6G-}Uw`yZ8BLh6X-I zy~l;ZH@{mtBXsz=tEs|BroNpvkKGh6?-)lDp;~QTpu7`+@+}iMGS&A6#;Q_o#GtG( zX}_iJdpzYlr7EnPR+o}uq*ou~d-_4w-g3;l{1oGdyjtC(nvF1TcRj3rdmn;kja9Pg zbs3|JmAcMTAJFZD1?7jKS87txkk`{hFCL`y0XZ`6n&lfN&U_at-p*^OLVfAnx}i&y zgP*sCo@y>KD5OvGz=>_*a4r0~BnR!LS4DyZU(+XtM>&?|;}^XvaLZ@WMFA*PMWr^&7cgaoEj*6-HpZzDE9+twLA1|%S zTgbFRuKIxw>gNGzTih_CxlBQ-nDmShy8OqM90E-uj0od#<%6;-c5KV@#c6`=ur1@P z>uECn{MqEYdx91BA0icicyYbe$_hDb^%R4)>_K5UIQ0Zur+J`CJ$9NI61qUzfKOHuoT^{kRHfnY~nO-37 z<+4Q9Iiy4)J`&o+AZyxW>M_7(HC6v692Xj%|ZC}(|ehP7PnHr1?HkmSV_jN@hO_}u6jyMyuKbj zl=MrqMeOhC^u{>GN+@06<-1s$%8Q|2x8zrt#)@o9!$V9Z<|>*F;x5r7>As&b|GU8? zOIFCjJ9OcnPUeFUADfo!TMeOkc$yKLURwu=+BdI?dykjfw=U<3aF-N%VyD!lc$&UP z%>E6(I`BpuK9XX?tlaqS)p2)w)ypc=*p4jy#(p4IJpmY0)xCh9j$#ZZ z8FkWGdsJ#XSzB2i6$Yo1$?j-2RhLyS@1VU1UYHe9h^OHSBgN#g>XmG4!axvyAcE1a zw+IL%TEr|)bnx2)Evg-Azga~CODy=!o)ImDdb?1)XGJpQ`}Vfmv&ub*LV5JgxEFO z84>m~JZL(3&yvj^TU2jR#b0-5JJC`74j@G#rCJoIcyfdOfWBq>s;_xGKFBokThYD2 z_D;4{h)dbKfvZqe}v=Mz)EFH1X*M}Os#t8_Y_&2+VW zIipW>xu(XeAFxDz%7uTR2I4oacY39tT~+9h)lcrOT087gM~ckZ51J1yD+iN1uaj-E z$eetl0>kS8$8`@ytBK1tWW_WC$uU0S+qa8Kz8!<|iKV`Y*mIkMyUlDdd?2GBv_$^- z1_w-slc>14`)7XVS^8n}*bPRCPG3*m{1r#YH+Xsk+Rz}wXHGz0LhA4P!(@l$Tel0I zyEHRv-b~`0l?!CkP0}wvUwM6;d$h7w4fjy3p4+AZ^FWMUZXTg8YOjm&-C$ur-?<;g z?cG#dkNF;`2lY4Ft}t`(E_z6gcSHcvt9Vc^{Ir!$WQa@AG;J3n$@qpBWfNMqb%#DV z@U3hYANw3m@MMncJ@fvsCC+@&8B3u8eZyG&a$XMlMURe&j+0QtN5(Oi0txcwpcPOGSAC2?*qIQPP}p}fqrPce zyS$4xcbGP+bGQ#I9&nQ%zTv$gE*7F;B=pX6&w+n{SR&EiLODMyzBJ}c?sZ$(`?2`h zI}es0N$-T?0vH=W={??)kQ1h*%#}!pB~+qcuIy$mZ$iH)EEIvZ6N04(NK-)+3JiGh z+NsO-%t#l76@mdc>55V+{j(P@-{qv3eXRSYruH__?>#kOiwcowJ0R25`k^VHv~+wN zUN&tVxIfVmE40}7jyg^yEbCIbRX0FzC*#QtgU|_mjr^4YC17EuO1yY2bISbkI;Y4* zpp`s;51hPQczO^*@Kp=@x4SA)U5c8*9$BD!JM69W5JkKG>PiSFz)J2Zo1fXRD~f?F zqA&;@=>(ivh5#$vZWeRBGSc7f@<*!EZ1FYy=gN?&EZ6DLqt83DI zMU$jYbWACl=(F$?a_iq)vSJ+f8`=hzPe0xc-dGbl${s4^;pkU?XFq9~?zE)gIPXaxPy#;NotH9H`B0JQRG85<)=6 z_X(Tsc#!jNr_-YFam4^ioCmj%Y49n35H>-eYyr2t?3Kbpih6iaFhbB@EoJ@76N=!i zW&zD_7o>F#6v`8e9%%$n{+79)tQr)m1p*H#X4~@Md0)aOJEr=CsV8V zzDpiD=YLqCt7ZMz-`m_)raA(6L;eUwAy{2!a5TO4T8iK}hWAJ84AyYS4bP-I+g$&l z_yQ1UPA7lMZonE>5}&8y6@ExTYB|c=fQU9l4?(I_s5rIlHD@b(g&()D*wJ4Q6QIlWEV6+ro$bqHM?igT zIXqf>t>YP6AoiYxN_q|)XHPNxU3xbjTjm^MmAy)`<(_qq5eJG^PwM?5rs?r6EfHE$ zR9m!)sqiouU=W#?%=s<{o4l7|UStaM$_k0-n;1$c10$mj;La)hRicFl|IkMAlC9i= z38DLN>~xFWfBfbpV5vH~UmQZ()lFQXOT-0moIF{+DaT-fe@J;B7XKkp)4@_hhHe_W zSJ}ZZ@{l^tMPV?ku+Cv>Lkb+55D+^B(dhSg(U|B6n0QeDPiMo-gdFLaoYtkNB}hCG z{y)fKU?(+BMhL9%#3>h!v-8B`N=UN;hkU(C8s^I9nh`Gx>=mqUr9(Ag$)RU6nk3)e zK-LVSxYB;JP)kaL|D)e(3W{Mmv3|iV@l_5>1ltV1QbB z(|jKa#mB4B9z3_CSrm@Re55$!w($bY--tB;owaEg?+DnhV$;?=;EL`U?3Dgfv)cfe zz`_T;if0}HVJsH@`{pxt>R0$R{Z$4k2PI_6)B{F3D`-Hf_x+*z4K8qf%O2-9% z6|kv&p{pwycx<=d5a<6FKvWi1A3I9=KMcAg0E4m?r%y3-c$s2L6qv!0aw~j^Q8?hI zo8iBKVU^;gEHug2Y~8=6&C9rK(Pl(n4fX#CHMtI#|vdJ{oe>B zhC=CzIugyV9q>Er*@{9$bi;xH$zBRC6BPdO&(Cr0cdD5Dn%^isW4W|{YH`hKZfKd? zPY;fMQKO8+Mu3AwwMNI}YSSVYVeZHV+tdqB;6GsOXtIFt500js)}(j~tT{`w-r>VV zkK?TaW+^Q!mkjfk1!Yy@b)YUtJ5t)~NTH1|Narc4b3hn~MyWK;y*^Nv^GVo l$nO_SR;}yz=}fP5bG&IM_Pzu#gT;CsXy^rU;pF8({?vV&hbww%)MhYS#A}XbKueFGXNK}c4h#PNQ z2Uhr4P8ESaH=W+;yAlym(p~)!6Q!m<02YZ|wG`!vN_roz0uQ8Ca%yr!MCH+x=jLQY zMDij^ujO>Sh&QJo2_M}d%e&j9^}b;Y*FOo4OWB!)NfGW`zm8u>2MK?6QP+9&uA;$v zjC9Y8ooT4{z3N<$(yg=`5&Hk=UOS78*HYN{{pFddw9>dsmHIJSNU$Jnfi#)e!q3d- z(}PcW4eMJ3kUMB9A2-;9_H96%5+w3hw|xE4zK)>LA;J!Uu=R}No>JU~gva^s(tO!- zr^hZO%4kv|A~P2DPV@I`l#o?_v#!?Gvl@HsQA}YW!r*uzUL&)iKJnc9be@Kih^U$K z2fO!rtNeBtVrGb!zn>mHJbbYnS_Z%njeR{N04K}o6JV9RsFl3yh}{6za|QPHG9;^MD*inZq*~%zHGc{BxCyLRwSA*p z!>x#`1&gcN+7iHYiNKmkr@-tv@aBm{3$=CyA`7PCO3*o_-9>&Fv-~(!Q7F z2c8P@hAMp@6Y{Tk$+M~<@m?{SSpz_m=&dv{5m5krAaF=?U^B2X^U92bh{)-YAh7=O zb~3Q#;SGT6MAW35z;ALAfYAZh{%8CDQ0D&^At>V}5*;!y?d$}_a%mhc94l*#j3ltH zy1+l~K#sEx@SV{x^!>ttxZI&vpd(eDByi0$KJYLWX=FL^!ybll9GnoX={-`loFHe_ z{vaEGIGWq~IV!-Pd#RXqA+VWvV0>By|B*rTnK+Kupn54qkn(CgicD1 z@`qb`?M@tr^7;bO)%J!7c37T@dEr*NvO7cnEIJ4mqm-{KB)B1mD?j}X|F+Ip6(h7h zB3Z^;b@b=%*!f}g5fYdeIh6i7766SPaVVfgh{fYW(n%>Dp1cX-itgzuqp*E<3Ijz{V98Il`tJZ#RPh#-a zjKm;!nG14)H0%Iz81C#Eo7~d#zEH45Z7SP?oKqx;LPOw)>aC+5q-LH>HJhY1E4Z1b z6ya4gEyv3clIJL0$z^!&rrImR8>+8VP*A()#eB~|B`-pM{;R*E-HebbAI%su9v_h+ zO)B-%3tPKoAGxUzw*K0t8$>}R-L~1m67+(g*1o=eq=L?Ld8?srrS-C(q9pE`fz$DE z>m$CDpjhi0>c1c6HX@Y~2;(-Qy9OYNo3iuv;W`l*tY{4l07PauaPUsa2Gs_LV;g#c z8uwPmNsT0hhO*SK5g9Z`@&^7rNQe7lLf{*PDwe4G8rFHZ9!Q+r-<_K(aMU`bAM#E7 zMa0X}M9Q0tHdULy%h2+!B8a=8VZ6I`S+}ZL4<3wU(ZPQkfDm+vh%@@kOZgnfhpSy{ zjMvCt*^zQS5|Xwm#AUq>*eK*};Co)g%M(`eZvaEYK5VW;VXwyJNn;@^v(`NnAV; z6_oq0Z+tC51JtP#AsC84cpQCI)|ymBW$Zah+L+QKzJs{8HJ{r!QY$ZEv<@+Af3|qX z?Fj9VCKm9Y{oL=85BLlW>BRS5n-cwQd&v2SR{Ab}%;h3$XvI%g3UWV*i@qxZ1V5x+ zj7RdGt4@HbLGIXk-bZ;hFr{KFS#q_dEi3I`cDIs&G7Sggcto5P&VuVS_~wj?kvREl zxzL+mavvmCy|@3NCx>7((h57ud3FN&b}RcWsD|>U8Opp<=Vdw7W=gd9h6nNHwBgg; zH46&qd3SfD@-)P95-$kie8kA3`iiu^KG*R{Oz~~Y;As1jIBD*P<7xgMJZ>LR5x=z9 z2h2+1vW*Ly8c0N}9a*%HMl3JE)?k8fnc{9L<{!CowQuF zJZZ;9_i902xc6!ETy*0~W+aRj@2J1btVD$F_Kj<6gI@AfzW~Af9ZHNv<*(vPM0RQnUfzRUiWiiAMWP|#S*h&I)NLTx3HCVgHt2MfvJ8-)}oC~y6CSex>`v2kI1dDQ>u~SF;nZN zQHvt4X^O~$O|pajNnM9eH-+T^^dz7>{*N)#4JlB5+nvBVnEjJmEumqo^bepzKF7P( zk_O;>1bgBpsESpf^iIO{bzAC|P_nABWw}0!$AZK?d=BFkAB|Gj+x!!PFY_+b1~f(- z!xGtrk_J2_q~DIO!!I`rJ7Xf|BJ+4Fk5eT*T-fjpypP1g+Y<_n6|)gTqAqZ5VZ8`a ze+Q$cI^}HFC{9T0X=o3~^SW!_Hg;^--mr$hkvLh^Ntq(`v>je+L@=T zbYrH5@fYcn%GLQVP;iHQ*er~w=7mp zuyl<-RBKg_kI|hfaA8vVdD+DGw`!)z)58gs^;tMvDZld10nw?FhAw#YQ@&dbbn@IH zLwfKy)o>l$k@P;mMHe>0G)e=S2f* zhCOhe5%06(4b=R{^8*Aeo_F!3Jws;ip+mw$H$=V6qT(irp$2S!uZEw;J4PwLF9x&`>wFf2&{~=Og zmi8e-$c2MI>%mj@wRuCmcsqoZ?61P?4ojekgW;!CZ3q`5E59>V+Pq&n|N z4)j<-Q>fZhHf)AwT&=ZDYpQc5_>hW6PmR|MGu?7rlYYGs-<#Frg^Gq623kXCPskM>4@{-4F5qbYs@}t&^o>a{xLv}Y@6&Faz+utVpU z;rpEGOzD-ZC#Z0;X3kk`MbcsZ7nSQ}WRckJwB)7e;0fv%6Ii_~{^i5A1=fvEWwE8= zpwlU<51wOi0&0`7rso$v9jW8F73=A%awEZ~12k2-(@1)FXv!+U#}Re7wOJL4pYE}! zOy4$a8mxiRjvjD)VG>D`f#g3Vu$7D3{kG-zyV2{Z*E223&gcD$=~*cVBvgd7+m`7B z^OwG7qoC2-I;@U?8E%Uh>1|17Uc3L`Rhn4T7yPuE)e8Wq|C{x$6Vb2JV&IQePFxHDC!+0#zaH(riu9#pMJaY_G$8GY2zS8I>o7nl76!(3t19R^2CA z6jGRuM>>4BmqfOg&(v-5nyB7oBm|4q@B?yrc8gTm>)7;c;o7Xe}B`Tdw?n#(;?j6n0CnA^_@!&ehx--@k zStn~Ayjc~9H~H8ze}Wop&UK@;J89QNbjTX0y6vViDN6;1Hz5{8NWm25Q4|R}G=<|A z@Q_CPou**&Lo%G0pNFe)m05KKO7y>%j5_cWXXpZ>&HjlkhYK3Ms z6RFdL**WLEgu*?h**bQOL~p4y;(yxiAE&O13c3qU7lbHunvX;{J;EUmzcwH~nxv;76GFBHYNk&H3h%r4nZ!OvDjO3hXPWNo?|Y%P zg$3OMy~D?D2NM6SLEP2h&{~TBj0JJHW=Y^bV2bc8LHi90xC1el&B2N>Tl69*yU*g^ z0V#a<0{9di_0XOkV>6O^-3vvgS&EmjjQHoNc7wyBwTO?O9oMy&6+GI)H_s987eVGA zj?y2CGl(1GVZ_YeZ0#vuJs_dGt(K0^(loqTL_3U-4<%=%*O7CUeQSv3HqZYA`YXFo z%PSAXIy-h9dJzpNn34Px1j9ISQl$aBc9j*IpX>I<9IU6>RX04S;lmrtrXYkKxbm^( z=ezY23`d;Ea}uxvX;MGw>o-8Suz%9{GI~e*Uv)*(Ua9E!h7g_Xks906G^XFL&&{s-8R|E(QVys&S;U!2(;Yyrdy^hV5mS5l3Zz z*-#N;h<)Q&$1R<}MEVOON)@)J;|!MT;|jP9M97>VNb9Ye%3DV$^FoQgV{ITkkvGM- zU)Zub67*WkFH`qxR)DT?x@Pbh(Q{;3>`bX!(~WF~UN<8G0RbEz8|-IH_2YpfH4b~a z1|-L?HkD26EwAt*b{m{?S{Pf$ugK1|0K@BgHAyeCw23Z&S8kz*-=%2u!-gM$9IR|4 zO<3+Gu1#`1&DGdn)0~3ViH6Pcl>W&1ZPDxbO62cE7=l)?7_H8_KJmr*(TU#ko~j%=`uK!3Zh#>c}uxH@&ze*RYWtX@TVIph}v%H zQtQ1Q&kvsO&Lmi&hRZ1BHj&;n)e6pvYN3^QcBGKctxmJYC%N%jl#iPZRD1^3pMf?? z%cdr2w3<-6MjX-h55kDKus73@9~pF2Z>YRlzlwQB#NV*(M?W^YVC6aFRsR27L z8VzW){p&n1WQ;jo#eaO`XUS@5>S+3miX_2cjE9Fx6Cviugp@Q|se}%+?^Dz!n|IbW zOBYc-VgYWNn!^!2I-La)<$qF<3)85E&6SsHIzQXjg{b0wX+K6P4&=Hje_#kHt`dS3 zWjxr@rfSo6>{@NJNjUUs3!nKwl~#u^WW(<1(GOh@U<$nXrCXAZAxO*8@FtCJn@qN= z9jzi+(Im8ypD95%DldB}!rZdZQc0pJsfZ;BdJ4Z+{kL@>ss(?}CZ0JzqpAO|oxyI7 zlmkaWA5eS6?m!T{b1$asu2Y=wt?}_|ua5oTAI{|7STF9*p662iz@zJrdgROuChK2F z?~oO`l1+X5W%ajE+zK-`GgU6l#PWprBH0NbeaPN! zixF4+kFt+Ytrx=zXTxqN`bUcli99qBW&i2>G2gNBKp$KwKkFEeaD3^-5{4x_@wq0eS%F0hppxw zmWAlWk|1&UQ*3`qag!;TO<76rYbPsrb{w>^@uz8pkLt(G+V0egiKqI8;{4xKu%k(1 z3hEc+ZKwUbGg^w#d|fW5hkvf&X`nI{=}=~4(F+1xd&~yC2J7tron2JuJ4*oL%c$boj&a&KU6Ypzq+mT*3^vvM2 zpKH4RX5RzFC1}3oekWOetJRqIm=yG7?Z8zA$8-LjKJ<)Y@7qNogcp;Lme5=w8iW%Zfi?JZ-Uf zb+jskosKy()Bg{>%OVWi`RBeVpFQA6-;m~o-B4XII19Ai3oLyfJ}8e=<~eYk**Gg) z8*K}HSr;)=1o2DtJ%<8nkUQmLkKmWCW>^>0hscj0v1gad5i z4*UJvSK#XnRjND5{l7{`v;jByxt7siR7q07sg8g1R!8A`5jQn1m{Y(<9A6-kK$d(i%Oj=ofA6!nMA`yF3!jyQewXI+77wChYSaWNz)Gx+*v| zU~Lu2^|_-eQMcUXEKW&J!foYF-I^6Yt6z_;-T;gDv3cE6>Lt4`{vu$~`D~Nq2P0rC z`TTD1KZmL+{rWx8aqp*{=Sc~*N(z+Vby+iJI1wAwY|pz<(j&EAZS9CChZqY6i@m zgowdFlAhb~({PTb%t@H@vRb$L*GcRtvo#-Y$CT6_d^m|07PQy(oV@VxZhw)6eEcLEAsI^V`9P+GZ5J8Rt@93Ia1DFUa1E|^5*D83tnck(^oo< za&t^umm*?DVh^Cc2QyD9#-9lYbn%*=7`lwZlQiu~My_m45JEXv{IxSuxxMVJ5eQRM zy2kWW@NnpJ+^@yp2xIaGv6;wRr1B|L`ESE=rbZ_`$@sA+4w6Ka#tiN>-}*&JJ=+8C zUE=Ooy|f>Lmhn45;|rtfwili?k7(#-2_LzVr5j~`Hn;Xe!!e?X_8C5NwyWF*joB>% ze&*=LgEwfYL$S>C>!YTZJazm8p;1wLM*N)4+sGkyGZ0<_v)*`Q z@6Ga%aA;4a&T?7*+XY)(^EVB5z(wMpWP0IOxB1L5Hbc@AHnKbY?JKflhMRn>u471~jJG)R;BQ#hKM+3z)rw3{Z2)K0V6 zgWZ;E_^!A8c>B|xa2cWF%s>BEr>ad|FSmI?+Qj+ut~2SxT@8-$Wfm#8#SPgF$s&G; z!iVFG^~-OQCxLh+u$!Py?>1lK8Ubi~|5rqZ$NOcL}CcN}^T;GNJ*=*s1)c?nnS(*v; zfEbIAMh2C%me&2cpr^`jFa!P-HhU*t66_hu;d61V%ykN@We2UM^~$JoxPY>u+u}R& z++`_zg`64V3z_L1Ox&JPcKG)6S*9n(7f0xA>9g+)|0bPl$ z+J>lDfiZ}u)aEH4jOqS8OBn@++lkbQC%5WE!)M(zeOf3>WA7Uge$G0j6_N_;-Y6wj z?z6C#Rr>U2hl@GY#DCw`kWxLT{{Vu!gpho^lg#*7Fxz&MoReOr99uSUuLMZbk@6V= zDV(x8<&xQkdcvq~RM%SJ{Cfws{t?n`Eltc-@Mb=v0H1a_!jed}Et%JhD% z{~$ucPyT2_92{`x|A-pkop6_~C*2|-5Ql=P)n6eo#EN5b>B2kmc(&TZ;@sg}SiB+} zeQ!A!imi7KU~xIiNppm`zTJ-(wxYFp!N+lQRG7apDOwwhFRnqocc|YLp~a#o1rnnD z&*>^`NBN1Xyd`n2`Hqhsb5sLKKvw$?Xp0)!KDL*oWeM-zy}^k1SwUG;u@7`%2Mb$z z=1O4Lhj0#KrTR?`$0X0jvl17*iu2NZid!n}%Vkw%JDzlskOmUSHOw_~RI+aH(L2?% z?FJ3#yqF1Fb0csEi5)8B0pZhhU~9TLsUbzXG8uBb{uRB&HSCA{j^>hm}dI61ABN3-t|_f96W2ckp95 z(aL=2{WYe=q!MVX>)z?>T;3Tz*X(pPih~#<7~u@x)koOqd!2#J4PVMU+_0h)6$@J+ zT1XC``Ryf}ryDlIN8BYI@`*ulzmTU+W(5p7aD2jN?T9)|{A{j7)3Q1%hAvC^jvi%z z?$e2qE?eMGkiBdg2s;6q{oCbmSRkP-oQ6_R1Bis(4rR$pwjOc~MhtRo9FsA}egeVI zQCJEUPt>IVx#{y2CiUsVe;QPrUT3q8}g3RTeqCqWK3|X=9D$Ej{&)kOL!= z`$D|0u9*zI;6h_iTnsb?6P3VJr(Q6BXhPhh1#;PF6Q=Vy9HRTzHsCa^m98``!Phh| z9U3u}3VwN@eIh1wF-v>4cHW^V9e{!n8+;I-vAO$?zoF6uwv zMZ1V7xF$0JF?)6ymh5u`GSK-YUy+dTT2j{X!YED?#3RO6Tmwoxkbo#)#y(K}VQABW z?>w?7;$f&}R>=4PSJ3`GE6$vFF+&424e$nP^#&h`_>>52wdXWYg7SJ(Yn*uoZS;#W zaiDjgRu8X_`TG3sGHc>UxXB;c?+>tyNaYi#ySzrVX~u<**VbNFmVnyS9+&^)tkVT9 zvSjzGve4j72crmz^!WrN55wubvoFh3d|k+g=A9F=cMSCgMn=???P}gU_{wBNl|-eI z$W|*c`=sLu*)WyT_{H-v78=1r_lX&Z1e$f2E2g45r!~?QJQtz#fZ=%tzC0I|YMb#1&qec;^Vv%q zZ=u%J#oc!9SkEPuqTZV9wBFYrP|NKLc%hp}>xrYvbrj#}^=wi}{fP^pBVAhYzJ&GoA=HC#9wsf;G9rKPu7 zu<_-1kAx=5*5PGf_LkS~o1XJ|@2Wu6Qh)q!&_7+k>~;!H)ofMgh`sQnr}F~wZx+iy zdXD1zr@bIX*|1i&b_x~5X#6w7ny#~fvZ1Q_+~sE}!REiC#hyy%J3HK;>6WJo)=EUV zl&t!3B2<$t0cL&eCbchJ>(7neZh~Q88Lht^6fW0L^y^K*sX39^t+1j$3{luP>OY0k z^7Cs0X43=W4ZI^m4W)4|{Ct;9R2ra%IsI!7L=WN1FPcuOYu?f6qzHBa`pABfm7fQ? zl_TD!jxu#R}~k4 zX}B|p>QLf~O(xF?Un*%_&wKx>4`N|}HXX>Ou4@V0AkXhO0H4npWRzr%1 zg8a^NSQF~QhT&PTdh<@lHy7eXXR3ODvke(`Jf7KNb(HdYh}jAmIl&l=E#^r6FpZyo$RERorKRr-#6~17#pG$RIFr~Ke4w3#}xUC`rd{vR)5N)en~&C6l?- zrQXU~O^(}}RV#?=Vik?ss58=JdO!-xJ2y#w+X7Wz1pC}`aHkPy@3PrMk!gJ=&CoKm z-OK0#jD&1e9wJrxAk&s3hp_O^4~tcmAqF>9K1_Q$GcnO8Rn1>I;!PLDA1*xKeyT(ZdY=&UGJ3rJvH!O(ob()v2KuR7A`lS#C*+z(d5x$A^- z%xiB{mfAka z#n%^8a%HQ4qYuDepa$lr6KE+;_lz36Uni?dC?+(bA%g3Ytu_}%sM!phmr@ zA8@IUok5{IjNXS-*f6WVH!18{9)dXR?cF(E@s)5iE?km!hC6NmB#j_>K(}Fwrig>c&&Du()703z1ztF_nul6{B=>? z&>bcin?JqpRFuMVXPW|+qvkvvpV>WSn$>9BkrT}lSAV2C<*x*K_T`1C5i_eS$`HHJwRas`hiB^khe7M4XSnaz{5WzQA|hoz~UWP^RmM8bYeC zGU?Wb5;pA;JcHNJ4R{X{_dBT6Nyb+=1EOS)D;ck)t2AbPqD5^uY`-TP;+Rv>@N2+w zIx!PH^gBl+eBr>!2zo=6N51QIyxFYCt^16sPn_=Edoo^W6+PtcmC_ut3i#T`6=bkI zBd#`|u8uEWVAx(HZ*4fvg{cQBP+aYZ?9?>6+peHJe>p9?zi%EcUK}Y|@Jp2T-VtxKBrSZ3lpUdvJq_IAyY(a|UviaX(1lEtJhs$kromFsw zLC*8}y)h%e8ETuDcRG`$|MIU)(>%4y9~!aM>$evi8eWgkl2(d~WK3P>=C)LkjH1=R zDmW3%Sy0pUla$sepM=p9uE|W~&Uz%^kIt86EXDpA>c!|U-+D40liLk$xsw<${u-bI zB6H06{j6X}T<6>ayaGjSsn$~wdXAqYJUV|cqlwS3AD`&68hnqmLL17vFm=4rB&okj z7IKrrkHTiodF4Ey*|xRC{pPhl|G=LOtPlG)h|hPwfJfzYb-fRpO|Z8-@(q9SCE)=H zPk=5UONmtKc2Ts!j(Vwf{bj7t$}#>c6|5TWzMV@&Sy6RN&qlnd;1|gB|)yL7d`lzs$B{r50u!H|?!+ z9~e_T-Z5LH>kHU1OC5h1$~K~m-=LW?A-it`VidNMH4&*3X-;Wa!^IJ;PyoE>7PR`q zn=n>5K$9m*ybmktj)x(u!TKP?*wSY`$F9WU3i~q#xi;7OP4VT8ScxdUaNO;GLXoz6 z!B0YtFCYq`jxSb=?hfa+x@~2;l3j`DBca8nX($KGRBw+`xsC#6Ij!vkxB2aLW077( z#qi_Vs^s9d;h?7VbdE`l`?~0Oxdm9_qif=j^TOYXhY|~5OP8?p-F++8+qS&i!xSo~ zdZ2+`IeMw{9R)4&Hs@se$?%(BK0j2oTZiz-<+xTL&>2dS&Y6O?xGw`*QRSOj;K*uw z9Gg^2TxjT<_tGL>$-#Xg$kqOq;E@Xx{Z;yM`1d zIVzMpU1HVQR)fY`?M^EtSu&YUa=;Bg9wM1_Nb48J+TCK!P`f@czLNnEyRq|x&xFT# zwSC9Tdewmyb8^LSeq~=FYch~K32@GE)xsakdCG#Her`bQxbD2p|FnfO72va$EEF_< z+ie{BRKHaIn(;1@$2t?-tdC9D-qfjMo)79Q4>^Ca>zFnqp=cN_NjPb2T2?V8r=HxN z&Wa^CetJqGs%4vIBWzljqol$B*ndZtCXZPe9@T>U^?gWwU}2WqE=^r=jbQgrbrV<2 zua`4RvF)OP(N6}d)4|^sL&D*h9|;RJh4)isUyp89;-T%0=&*^gOuVU8)&56m?#Lxx z`+$aRl;PTh=d4W2c}mAVVUntoqqDuyoJb#2spcS5U9J|%JMw+=LpZ$i_hGwvq01jZ z`E>84-ibDsaB3N$;=mZzGBcHQ=#c{Q6~!+M{JNAEyFf15LYa{p=J zdMiZrI8$-o2er*FSX`n6K1Bj4#gkO+b~t95y%Hn!9Xt`THD#Ln03nyVPQi9*Rc(&>7m>N~m-2`HE0}q82uPv@!mq&*!L;Y~RWR_z0w& z%%Tmd={}~A_C?WO4yLY&YauTtkI6VZcWg94F5hWFuYVa>s*o$J61qG#KJ)eoj=m4|DgxpSn31LFr-l>Tj>$$XAh{V z7!fP86XMIiHrNtO4!4K)SuEY7RoY)Jcu6|?R&T)M1cQs?gw8Je%L$r_wgG)n%~jPS ztbX=Yv(C3uMT4mzJ>uarlT$zsa86lv#lUUz#g;M0h?yqB+}8n_hv9e1G?)`pbyKFD z_H8-xe26);FRgcS?>1CJFg6mN5y<(azE9$~8rtN%XSugimvCVhk)Xq$okkpeSh5Fz zjMKTuP!&3aWFm{@3Uxr3QisRbOQ0U5lj;RfyK?Spolj8Pz)O*+>pg349u6P8wCR^C z?1VW_I9~Q{Q!I6SlE5j_s17o!-%#7P^|`DjuA#hLP6{6b!T))*X_SooNYL5t7!xqd z`g7rnH|bxgT&%J+y%^}6Lfaw^Yp*j{OLL2OeV9ni`k2GzBUa2WeKy`l+a2EHfr`GD ze4P$8a4mgFQ^Ns*8^+8C$qkpqcCpY>J`^C*XhTc z8^QDFZ)ZU+yERPyd41lT+9m`T9egjd0rl@-XRJFX4WAD1<@7HfcfU|is&@me4s`Kb z>lhDEOC58ZWNs52rhTo(KFQ$3CW4@?x?tVG(qAdwdjQi*JJ)!I^YmX7m)8C0I(ueG zl0^Y3ha3vLiQPu#a$KgH8UCE0-kLE^A2rH)&FK!5>R;TTg#;JFV6Ya8@h@ri zEqzt!B_s2~J$9rjc2~CWG!*V5mMu)Z3zCWPqNiKN$ZHP5visLGV_8xgjuz2NcFTl^ zpDsf>eJl%?v~z#IcwN1c$7K5CstRQ--)CHZQ4fyvUvBagbwc%3Ue9A^n8KQQ;d|xk zjhH#Ry-$lo33_g)Mhv;jv+?4!7S^qi0u7?yO6xLbRdpF8zS|R6)1G(h*i|~f@()z3 zH}W5D88AV4MKH2pfoM(3fi@qp#?zWVb+)XaoB2!e+WsT@nOcX`ugKv{j&>fP^dnbr z-Y{HPm>y_3lzxe8Fm+v9DW7lT3%ri<@Om?H8m6+syj2@OUGUqn zX{LAsZ^F8XqUWaB?~ZX_rGMa|ovS^| zukSM^oQEBTVZV!l3y=4`SQCed&xDn~Qf>MFuQYfN zlfL&7TUZa`=yAHgIYV>!%mL>erjCJpc%O$OIQ-Lm15W7`x2pL)b4x7;5oe>To!xt%hRymaVKEEVxJ z7X2WkEFsG=zR4G_{GE5Es+vUWUlcPIZdF?xz~VC~r{uq(1hhwmd%poX?#;S>GWw|v zojGBjs|<5t{5bB|f(kp0;C7c7`tj|=G* z&@hMehDXo05~XW{8MN4w((^{U%aVKyUWOw!O+fOgWVMq|%Q?^v|N1AdDz@g75RYg~ z$2rrdziazC{4S1=-A0$X+|ofo?;{g`VK$`~->i7xm-p>rlLqrkz_$?mpfakY`g2#J zpSuz{hcwuF`(*hSZKB8J*(gnG+)*@6$7M6TTFbiCC>uB;SJ4*bypV8kmN`tPI9||8 z?*yg7jD8YffKuA_J6IO3w2-qrP@Np1&lf#E=sQ>RKH-H9GIrNTQJrFH2WuRe{Mj+g zH8_5;>4Q}68p?t_<0O;>;k0SMg-0!!3%Dj#4F8(#HyU0R0P@j`9!fKj+=Q?h<*fOC zy}4VMM`QMy7zg~Tu56{jmemR2ml;hg>7t10p9%x3`Hu0x1#>S?Y>KBQ&$PS*iu^#K z@+5?_n-b8PATEvK&VO9G9q4eA?0bv}Jl}K@Hx1K-$Mc;nX{#f{5Y^*vJ`WsxbY;%u zuUi=4W*wznyS$jf{Z*9NGq0PE!WvR3r}FYe-cA*y0i;~zZFZ-?-_J_LJGU9zza!JO z25W_!#Ui?^2qp6I9!n`!d9$nG3vns}Fe|{vI4?d04Clf8>58H(pZ{)&XC9h0mj5^m zen94%HvO!>gtpiQSM$q>%R`rfApLdx5@l+C%}l%g}zN# z6HjVd&Jys&X9_ICO_%dcPx1W}3Dk<@tm4TsVP}ginIk_EWbH__FBjuO+}yzZ1sN-rlWOV@`yga{2$<@7KviYA$a~OW#mGwO#IY z2{14*NmK}DiG8w)A7Ji~tgeM5ZCrSkCOJYT1eA;c>hb`fW9PYa7mqtp>`ES)S|P|8 zJ_WyCPIr8YaSD>h{eGN{y}!|%^7YyIi6pd}0*`RzJ6yuvS?L9C-jG~a?sMx^8lHJz zn3FkOy;wCUUcmAk&fWXlp%le*HzBB6lHZF1mf?8e=x=u!WBm8eeOVRMX8wf{H3t8V z4?uv?!RV&j=j{B2@0%)n2`_5?Mjf0D{5;G0F`t=8wp$XUJxwK=hgf*#>ord?xUf<} zh{PoTHdp0<$*7l-AXm?Nx}&%d2_~!yFC1{(b8v{zR|vhCOyc8Gi}Ke-<5=&?kDO-K z+%KE_QW5nazohUbfuYT4cwhLOpegYhe>zGiZ=7fLyb;Fw^K1z_EmXiCx#HvsXiTm- z*Yu^WwsmU}kmq{U&Rl~w{@;~lc*BRjp!?{BQJ^uWBq^i812%FewM_p`GSQD${vls3 zxbF~RAE!l>a2k6O4(kwF^zw9~Pk<@c2P^-zo$y>;TT-lijyLP8e!4A!WVffn`$Kxd zfKgfMeF@bXUS=2Hf8R_W3n-xxVK}23YGbOvxa^D)I29;1x2Kf8T>U!mZ7{|S=rtOq zP}UFOw7Ulk(%ukGoj+)4*iLMF=HG0uigHbm2asX_hDv|rEei8ZLGZ>d9n7Ap_QOiy zIjr@^a}#Y2s2gg@p1`|bUV$^*KG#bYOF&Ks@phjVt?$Mi#H6u6*D11Z?tcdmd)7a@ zdOlE-;`)Yhbem%<-gTwEBofNye~lCfZkts zQe{qQC_^}_u2?a48^DAX;F?(*U^95Hc2K z##y3(Lix|F!hk*y<*6HHuR_T0krf1A?Nqi8$*X}tWBW1`o&oqY4}E1$b<;cTaJ-#- z`#(@N;rKnLU^dXMN@T_v8kPq(@#9&O&M2!Z$mxjM zUn3^!=7TuG#UKvvWlr(Kp1Y_W$+Nw08paHM=7Rx&qr??7)_kk0{{E*(OnMWxm{G*E0O*wAAR-W0{44IX#j+HoY7tMs)WSdaPilUahP zSo_amS4R}Oh^rGh2x%si6RKx{qzA#=&bsEjuAUFW6fr1NasKqy8+9p9fr-?44ZT!LI}Q$_xSlXO~W) WWfK9PVk`g{L`rYeUzf<61^q8)XLj!Z literal 0 HcmV?d00001 diff --git a/images/Img_home_03.png b/images/Img_home_03.png new file mode 100644 index 0000000000000000000000000000000000000000..ef5972b3413d0ddf989af40ee9f049adca3a7135 GIT binary patch literal 10648 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 literal 0 HcmV?d00001 diff --git a/images/Img_home_bottom.png b/images/Img_home_bottom.png new file mode 100644 index 0000000000000000000000000000000000000000..e50348069977f24460713d47b985aa3696562d86 GIT binary patch literal 56972 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

q}oi!}$6h zFo`yMgz{%ct($M>i&E{MgLhNT7?G{S7*E$aR8SEZiS2onJo49V?68<*F*h^nN%t!NMhPuo;TGeg{slb}vET-o}|=_-IyL|Td;Sy*$|cq9I{$44;!aFnN$NMj3n!rl`-%Vnu4}Ads(oC-RV_s+&wlxP-LPTPQ&N z3dZ!5Ci_<0^<{&MluJC3xi^l2*MArjBNZ5&g-pd-Z_yXlYpCjgtibkMAb`P$FWmn$ z@-HjLcFp50$v6DE0|{bhP$+g$vS^gqD3WXhCo69mGTXx zRYmY-t=3E@r)E$^=*O}a_aJ!mH2MgdM=V{0AB{@ETjFrrZ0Dd!J$Koqy;m|0euzNAP5272+V!ev*`QDJa{SL!z$7r>{rLcarsoR>$;?4PeR$_drQ z!M}8ZwFCi^fC(=zk>JXX8N+p1$@{MoK#IMuvyw9JFx%6x>Jqw-V#jsA3-826j4;-% zXKy~$-#L})1#P_a!gLix8J5qTH2o-52hk8qE27{$!u)>y806~0VAVxvvUM6DwCZ^u zv!ytzMYP3LP2khL)4uPf6C0+kNp$!MF^6*dm5rnv#R2^nO&lQ|Rid6)K6nLiMlbWbj8U=VthxZb zAHR_sszcy7Tq^J0Srf>9bY5=r09ql23y3erEJ*kRBW_BO$BMm4MI_3qije;_U0e!1 zThmAZ$M|qP?vfMLQFF7RLY*nj`Emy1V{H;FcVttm!{h z!D6bi?D~)c5E)o*U&*@Mi(*LswSerpLI9CHPTL9F;k{TfH2LD6jnoSskcJ>X6y!I& zF^w4vrkJ7;l*K0OKmV~iLg~_XkcAOC!Yomm`}K8AEIpA_ke+8B?b~8R@XQYpJbP3@ z$Zd&9A|8-9gG_KpK}qDGAE*{fMgLlTa`@P+>5Gxe#5w<)RgyZ~q0UyKPd2R8AO>Ti zMSxyYdzzX--`}IAcD0x4;G@N6P7zag--Vw*4SX&)$62x~tlRi|J zO8+ETWBR9@0H?c4^Ubdaj7JnB+&6K~v)TTqD6NkjK1u9q-b-le43nm+_pIDpZ%Y2y zXJ1?mzOsMIeHod6qhiXi3iMe?&n^)C>$39kLtEwnH2jEk_-3$~D_-@JM8ulpk+r#o z7!r`^ECvA1i=-0!$zIR-H6zdKDzQacHl}{+74w`>-9bmfDUUTq)W=#DBqQ)tnDeEA zP^cw^OZNllrvNKVRs6qQY4d<^LwXlv;zFx=zM3Ywlj;=GPlknFq%YVy{VcO0B-3}b zoD)yxqnD+sXni+W6_#Odr0p?R#=+-EW+necI9=#*>~=3wCkmVGq04tK=f9a-I4-# zwax*8mnqDRXn%npC8ebDpqm{93I(AhhoSUsgQznh_pqnND#%xgvrOS%K7+zWLy?$> z4`SKQk-yv7lD@1>fW^SSxv zMrXa(&JI|lz&IQbHLL4ND2sVb3^zX48YTq+6cdk^npRYn>jPnEHD^v>a=wR=xv7Uw zkpyKq?i3Tva+e2?h>ijAo*d`*j~V9SFm8V1jPQ)VTeLlnS8NL@uE|n-}81JDRzan2X`u>z<@=3m)t;>lz#K5sGc`miHcDIK=VQFT z)en+o)DDuh?23xv$ei*U5<|I!7d>@9FKV^wq@EZuvCmyGwI;BrKxa-B|C?1V|iNkMYI6@A<=E4B_JNP+n`viH#aL-48|_txAN>-1J%ld-`A;|MVDqpb=l5jNrG`5!x>k2ZH6h@!u^rgyO;^UB1 z%HCkUk7<=T4MrZu@4^1VErs)^=J}}izAv!C=LDM;sNeLHukq(y_>K_GmwrX~_ zU!4wh=G^9f@5Ys^*Fu(d$|WfF{tuxR!T~bAd-Y(C2u-%+;~F*|Feo*e2Q3wYk#uEW znHn~qE#q`3ZJ_b%oQI%;rg$JNqH zZ!lBku44fKwz||IsmzxI)=t-NUyl5xkaadZNcb69SG9UOwyEW$1(WxvIrrLVEa}fq z-Q`7$Ko{J~yh4=a$f?!~r*L)Noswk)$P8;T;gnk@-*_C+zFDT;XR&qX`JV+!wO zT&X$CaHO4G?Xza@pI|XsLjC(GEl6S-BWTl(NXu3;BD^+2ERXtrX%8;4F%_r~Fl^6; zFQ?BUGL0zoCEm>v=N~`UQyPiGR8#VYs9*V;o98jEm#Q6xOV&AlzgmFA1f&^W-l5BP zbChX${&5(aoTOLs?SMw({SMlJ_4UcHsFMfxnM{01Z#_@6>~}H8Qof|WO*}7HeW~Jd zJ$>wa7yo5z7mIJCj}n$p(JwJRH}H0&!vvov)=#7qCj<=+QVnR+Zj!tVyct$^wn|^4C~iEwj;p8z`eDbC~5v2vVrc*=`k-)93E;H z3Gotlj^09Zz)jzfXMhAg7u_61=Od2A*I!0mZCk5)#NjTh008ZEvlUJ;+ld3DafS*6 zE86IOy&PHiZrw(66C+HvORxwQ_L&o0*cB*M27DG%cFvcA)myKjj10|yt1WL zRgVr8``+uZCQy+I6%72gsr2Xd%;h2b_6h-JxWx|IBBWFd!bI|?2r8UPT_@$8%1@K) zV8w{Cdi|LeUE@i1_mI$Ia`6G%Ki+Xqj(P>1^L3Vw>E1(Si^Oik=)~>$CXsJE=xHFu zY@NBxZ10S9R;#w(gzG93R44@0SU2s~W!s^*X}4sUeX->7r*@muCK;{1&HHf-_!sg35AxU zZnyvYJkx=_!c9v$$xUa{HMWrm|AtBxeAw39P~Ad&KYWYm08t79V>h|vBZ}8Bem4^z z9PvIBLJJ_-8#n4gu(1Z$-HaYDS&n%*;I0mJ@SQT532xiyvwjoz{%I7>Qfdg5S8{&G z`1!Yuc8QkVKc%Re>M_loVL^O(0oSm_>8wliyqh4mB-;-=`}~o;;4a<=Y3gmh!yZQU=gdRb zcu|DJj5rRk5E?*FlWV7NGet})x&mxg>R#1c=(pml_Sjh2N)6Es=dL_7rL8P#^KhNb zAD6%A2<;f+X+zm)rL>46)bF##kk0oVDjGJrkPBflfmg-pNc}=^ZBR?GM%`pUd zez5-A&~36o!{LSX9wVT8vjz9H4!o z=BM0g1B>BdR-wv&LFm2dva#YlrrwjM&oV%%ZX8g(qyB ztmoc*vwb3HIhHg$S(zUjRvF5T9^Vbq&_PA|Y`jy>Q-K=Fe&d}I8vMAK z_P;%o-FWQ&Y7))x)GPHwMxMC%{WSU?i7gRT_?ahMMD0!9oaT?!(^oqj$)xWsug6wK zH`dhNyH%{I$t;upU13Y&FH-UCpH~K{)8FmF!gQ;X;|&@XpnrjL^PuwC741|Lsnb(2 z-#gImZ*5LZF^t!LZz8`@!>wksz*+t@y|sx{vrpF3*ok$i_6px1iqF+~7)UNg6Cbv} z`Mb`9uSg=tZ&8NxG*ifRUBgoZjUP(e!Ml;D1e;A(2aK@LX*r$uc}OZ8{v~NFB#to( ziK#crJznK}2XCI1Vvj>55C4;_)Cr@e`a?~{eAF-)w5NY;Zj>DRSptpRl-JNAezVt@ z92t5q?M*2NNQYJfO?o;*;bO2)9ual1{PLpi*BSm>Bl|r!98xI6n|b$-725@uhwBGx zXL}kN5u_5FLGA)w3}{Rw14z0KjWVx6R(gq?xRf3)BA8)NlC7cj4Ou_kc)WZK%EclrGO#vU>jzKU(Y0qa&uC_k9o%As)|%u*OGp^; zW;d}8nTADi%w*(MA!VqDG1mu4a5V`nMhH(>^4mzmR1(+bDLmEL-{Fa?sjdGpGM(Sn z!gjWcU3C{{CDI3rNerVT;!mkCwaN;CavH^TRov0704<__wk4&8euQo%*0Gw#<)x?*f#V*eJ0byIBnv76lt4Cz$@xd8lXL$J( zs#%%c8xJ}=?w$Y<*!YI*a{foD>zZIJ9d6@d4y6hh?Y}g+?P;rDcL%Q1M0aKWfMe@4v^1 zhlnCNVx*hSl%*yQ;CDoup98dKC@Mj-!y3YhR-;;VrTh|^Bq8NvVzJv^sQ0u0cWnLn zG+qB&oj=4TgAI4KcDxzPjCteLES^3g3drCZgx_v3FM1+_I6wsnXGqWeQsdr1H%)tl z&AF?!IqJe$&8VtxpIX#=-Se(X#BVy0j!)E{okjI6KC(cpRfwfZtD>RNMV&%|#GN%G1w{_ch}OdLGEgSMsVsad>zf zIVBRh`FcbWwggc4nCh9ILu?{&KouI z{{OZy=>iT>1lw}8PEf(c_woQ79FJG%0mT0~LnTn(U`L`pz~RMhc->m?anz|d_YWmI zbl}QRQm?hY38XhD!IZm8s@f`XnmljcWvsdWbpbZ1d7hMzlVl`*AX;!cBtBNuPcB%P z7;)fr%uHR0pG4Xx!#%?D4UW18;Lm=+=*HRxSp9o z?hwrrmDVRzw>k<4VkE+W2+?8+x9Y~+3?UNz(bY5SmL`&j%CKAkfMs?4+uYB@D|h=W zB;b@O9BEQFgnbN|pMJ-v$BklPz70iLoBmQ1V9dhKg(ck;5TYV1@kIRY!i+HSm$1%} z6G8f^yZ)!$;ZzJ;9$yv84EY>0ypX#sl=Rd@ZwrYJT}?R_=#l&7IH=YE0mYIq?8(7` z#=Lw9a*7Etohu8PVzYHKP(yvT-a-ey_gJ<2VM|F6y9dfg8&(bdZvycnPBN0|mqD(Y zcfTDVQ)gRA_7F`MoZr@r)MPqYb3PGnHcRu{OXnMLd7+G}1WRmI=YH<}(J%9WIA7h) zCb_;-Mee!>3+u0|{~@Fb1HTho^MMN7-9!}cj-c$Z4+tpF`xXB0;va7(HI*&!Q(2}x zUftz?42QakJTueNeDBBMc0`cg{@XqR#Kz%d2?X9h1cz4g!r?C-vdUxd*88A)O<*EZ z-KJJaKIS_gErl}sF(9M+n0=Tlnh700;6DpW(-i((BB9OkdiEJTaAE21 zbY~o~6x%HavF9P}TNg`xJc1Zjs4|szb1&C@Sr**X5t@)A$2gNqyq&ZVT?kX(iQDW@ zxXQ*0+T6U`9@$cfV4as(qHr9Og*EQn5GaUstIJQFVqovHGJu3-H;9_k7#7}Pv~>+4 zsA2J1giw)gnh`sRhWwQ{CxUV|XMn!6s?_>V5AAUuJI(Ui-Y5N2p*<$WCW9Sb(x25) zUb!3@dwg_x*n)iys%Km{%V3ubTvB%toHp<;{EC~-^h-Nr5Pa;Fsvqfj*SrT*X_D9+ z*QPH2+7fCG^==Mi<@Eo1pD@Wly#fEx30H;q33R_8+~kSmGkX!5XTld82O?K%+h-DE zO>!8JU%g8iZa<&4fM-#yY=)hq%Q=FkrfqZ5gXmZ{ueFJw4@1<{63{^#09GS?_+#Qg zGItr-rc<~Qoys-bp>O||_jw;Y-rm(3-`)Aj5Bw})vm}L6;ip$-hdkO(p}MZ@OvYp= z!WDEg((g8HFQ3mMvv~Ebh8Huj(&PJD(Tvta8k_MNhB#_e5jvUX2Nht7Mf zP%5BdEcxVk(@?=L@j`N-XX+8Z95+677wX@3`-{_dO&_GdS$w-=Fltf%~ zx}5=3<2M%c^K;rIX3m^mf=+f7iJVm%bv%2NCC={4`By|G$F(3euidCd8Hi+z5x6T? zvP?4Qk)Y(0AHc#8jCy$v0%kqO9JEycoiA^crI^t~+lv=D5ZrW(Vrw&E?$+h^i&K9k zZ}6Xg4f<6KY&}X3V*gXibo1`24J1MJuDUl05e)0OzS0C8?H^F~-nkfDZ9MW}#;KQ; zO5oU&4@Y;(Qm>f{l5nHX*~pNNU*>hHDQVzrk|e09vez_VwO;xx?S(9%b>>RpYboh; zsXgX%V}ODdZ?#r(BROaOku};hpHUs(q^7xnZvCj8ASM%Ws(T)J?HS7{<+;t?UkbD5 z7ybcL^VUgwYpcwp0>uI;yI#_d2xn7^0@Az2&l0)A7an3QP)yhGFze#y&lMHgUrV0j zKS6_io?8`SI;>85$^Eyi*f+r5?R~p{{?EBAY(v`uCJT9HaKg`1HfUz5!xxMjJ zdITd+KWl!JJpgo0iYjRcxRnEMq+{_>`8WagbT&3FAFM4#b%^S6uN;Yf<|ZGTf*ak% zLA!Iz1rCd5)x@ahu#xb^R zT$t^UE%(EQz&nD_jp>M(&MMNxJQMBOn2Z+ElFa@(_|T5$S=*Q0=O1Q;pBv~dU%x$K zvWc*G=)JwlDL3(;>b3P;WG1@cTNN+VdR!rHo`9njw_1OqkY@G0f_^*7uI^#+-dw4c zqMNJX3sAK27{o|I9XM12_RDY_Mt?{={PleZ&(RseaQ>U;XB?^NZoqnQ@ROIb&7@Eu z1m}yo28w&2J?|t*i7?n!E~~BoODrC3!TNFjV;tq^#1twCvUdHE8DH9S zU-}mTlbq3-xb)y&c7nFXb@hBh-!`S|GAR4wK4B>7T*chP)kIw{YeP6Z%V8)WRUPvY-8L=TeOcwhxU%{3yn~V5YiWITvp(a08iti= z>`$Jz(W5wRMh4|-)hQF=k6X_oFCX-8)-5Xog3>#MhEG%>iKrt$b)wL*HnvjBC{fn_ z&!Rn_R1Pf*GV_8uGdxmlEXNz4Ak#r3HXk{)R3<>cpTB)n*Ug+A)T(M&a+YsX1bfr3 zdFT<6IV}!}{TLXK8BA(Y=l=Z*`9w zKc)_TCJ0L)K6XKyeA>gzLo&P2eFDGU{^9R_`Mvh9m#!%{6yH?%w@sW9Om8TW{kA|` z$eEz}8+E!}4|#gk%y2q1%$?au2T<6 zY<^>?G(9_G-(~AT`(8iqkGpdG1tPr$7|e`5vg9?W4=E@*v|G=8ntFvl)Xo_tir3$Q zJIIn5h0?u*!GK`f35nQ1Vc4G0gk%?IsDxrcH7;TS%&4Q-GBtU5+r>iYe`B8aS(VF8K8B=uClkneQS!TL(Qm~j3YI~uzw6#r zCAS`I{D@K8;#EQ&o_`H%r%k*I2Pgfzv$dkZxK3ujdo{*JSEd zPUd{$dJ`U0-=JjH;FIZ-vr>zPdlk*PjbHUMLyOVI(S>`OL5pCVuyHp`B*vKes5_bFr|_Yob*>CJ z_hm0_0R){DET9!bIvYq@wnbXo$jN z1hYQ<55esfvIb=~x_FGlkYU23s$NKWvmDnFx#@?(&+$yOK1!Y`N}F}x^BTFnW+?EF zS^YLR(jHAyp10IDHBk8{;}hz(rt+Ra`O+s1WcMpre59CnO+bOPP>l^k+)EFNp&3Y5 zwvVq#az^!+q1n%oy_|v%JLsV=QW>=8hWc%7E&Q|B*3UI6M9d3^C=!nLm#XDtP3Km;kz%pgMVXaw%yXvzFK-Q8!HtxD?ADt z_-&*I9b>mMbqc;j{n0Tbl~s8-v5I4e!uhBqltoL0VCbf-%5ZTXO3QXBlw;rSKxXo1 z4ls$EdR@MqG-BxpWy8PXr&M|+v|9YytF3ghnK~Gg;>vh3Q7vL;^&(G}H&WNC= zSJS6JDmT)tcyQ2HFEP|)lBtknO?gF>Hk}6YNz)T37Z1@V9n;<`u3r-cp-P*o0Dl>v z$M`+fw%NVpbKItcMrxXJ1*ds7dU6zb45Yg|hve7GvL!~-)OO-7df+Nc(=`DX2L16;m$z~4G$Mfgt1F2`- zD+YvA)FK=yyM=@&I>h<`VT4MnI>rboOC;bs_M&7a9z#LgV{p6wnGi*7F8sS;%_Z=Q zgdSl>efQ?{es%iPP)fEUS*99c_uigKOS1~YyeYW2Q`e*V&A!(AxKO2oc1sM2o9Ut2 z6#RwTCWdy9m<~ye_QN!o72xKPF|M08Hf%w9vTCfMaI6Y698)pmrgeF^AH(O+T+=%g zy4nR@dqA+QOHxORZ&WBJ$F8y+1|CpOI!vldaaAZlPO~YAmus`l@sEsi2BUH14=NAh zdI23*Je+)17Z@6p@z3r7i2%jJ)0quqc^%DzQ!wW%1_8u+3AsCK1Bs26BERM(=z9;l zJx#o9EMT!-_e)8uaHbtMCVT1#dd=_iLxs>xz zGU3O?GA_fbK6wW}PA-v}E8^^)zo&KVD*IZ>yx)vYJIui5W)qzDO;Q@9B>`R7-ycen zQ>2n5Gjd611Bz>oBt1O*G$eNG+fouu6zy|5sWI?^9*s>a7G$KjE(M#fbgCFzPRRJU zua0qeCZ74^p5lXc-9>HxnhW5jU7}35p%!xl`kxxsq@68%D)t=rtlSeUh8RB$y2cwn zEamF%Jo?D$QxJPK4C%4lrK!m=NHBV$OwH$WcifZr_8`d2Re%2YjKXzTR&S?6cOC|S zz)(#rN)~DtX$iY-AZ%I4o_YRaGerMJ>foMD_Z41``=ucdbU|Q|b4wXMzNuF=lp>?$R^HF2wdr#MK^FhB`#5>~r9BDAO)I zh}*xsgmUnyPm@2@c%)lfflAkH=Deh6dIlRj;s0_p`7yT;vvTU8cIA{mkD#v~TXIgq zl`J;S>1~$!tgQ)1!d>wG>na~yDAl-W0>^%SL`Vd)vDlO@eh}GVU=872zW8&H_lDN} zQZ@Yr0L{$TnjF)u;uz~z%jeL4Bd`D9B}nil>nkMI1NwH;h!y;%#J7x)bn3F!-hoi{ zW|!91l<`5a?T3Ab;*qHf%{OtfK-2U3R zddAhT_2;j=$8~Q@H(xnJeJXKmt&850lk?3`^KzWKv#93qE6$V z;ay|Mi~GHeDgI(5UpO~yAxFr%@G82Kmmga!^794*SNsXbszb&kruoUIHb)Ywd$*?< zTcy4fkiMLR_(@C{?KjmM12|O}R#tV?$#pRd|ag26$O^KWD zq*qzUJqph^A8I_-yqZZT+*hYOHPP&HKEyfTy(M%lf$$8!?!JTcf*&lr`s##2X#EHa z!+K!xWd}+M#mxGtBzLwuKMdz_Z`PO)P&gMI&3p)*4>6=xb``Zm&zT53Qg``J z78Yb=-g0%9yA%jM8vw@Ddc4#!E(Uk|f5g0>4_1ij&+>|HDP#PqARBzcm^G6T^JV(M zU_rw8y<)1gr7N#LjyQud4LM5-g<+@g=npx?J+x&85$-DLF=%UUqFG5JT^Y?7om88e zYVN6MiPN9s5&T3)Rp19%={}SxcjrQy zjYciMbbnUy-&%KX)8z(W{I*8^ww7XzVbpormCq6e>0a^m>EAeRNnbc4q#O8%)q{IbYag6 zrDv3Tg1>)#+r7nn^|>qq(Dk7n!#6Qw{mc>gh68jhMB~SxBXM;6k~_%!;go}~k!;_? z?7H1pgAjF1`ebPGQ_*{WXo1x0krmgohg%a>+y|u3%X~AJH#EuSWD|nzU5zM~7zf04 zu1aq3`@e|c-cKpND8vf3eP8+E*1CeGa7(C1<_=}I!>p)TzfQ{dQ8o z?nr%YO~hP9OR~kC^SS3Fo%4r{6v8R#DV`zGke9HsX7;v=izzHI2^EqV}4Z}~r z(Hpg>SezGfX1KQ}acn-x8D<`4a{4HlE?Iub?HhC*$&!tru!ULYHVu(>R^CRJwQml` zsFp`S+{50V_#b77dgnL90Uu_9#vY)7!pqMtRcS0|bR3ZQND&%8$xTxr(s2zleEEBo zW6wrOfFnfalbthTkTW;6x<%4$hxa}Vk@ca&7!=q~Fy(ec(Eer+rQ%Q-wx?}fepUcl zI@6Cs=99gTS%b!QxUJm>4{GiA9+QtNAgVr^p~|qe(maghjk}?Cj09NS@4Q!J^$@zx zpBLq88TmZ$>uAYo8~}8aO8$0MvniAU!Xsr?Zgsm%?y0$<=+?mQn}+}dh|6)2&F1?XJ4CD zb8*NPaeqM^0mo!gepVG{&V~#63GWB(YJVbmto3|YM5|&N`I}=#?q`(mzyY9%5{}=5 zVGj=CEESulcs7H~fHuMg8_Xa7D%>9&0%Gc)F8^XkCDC46Sopa&JNEyF3&iqjDBSM6&<0)$6g0^grO*Xbq2XdC|K0Q?>43Bj5|9Tc_RWR?!B_ zUEPTm8^I2HwX|;Ps~)QBFj2!IkC!Kn@)!T@pA}-ersLt$tdVb*6SuPUm$AMAjmDUjfLk@shnH!HMw1vp~!TZLBnZ0!0;m0(IB6 z2LrUf8e-Pkfx9OXVITk2dHth13O(St{fC~<)TZYcs}-^AZ0J!3&_ULW3FIWp$? z+kTBknvW(1OtaMC_t4;ziBX%XPJWYsT{ip_Xdl4zy3}!riR5GH6Cle)f&6>F@n=>r zhwPt^spY@=72(|oiH7iY(f6S8}hSiYS!*Q=?N zJ?TbP=$kWXs2Ur{OOeCyzCKmKi?uPTCfrrKT2t9jT>yp$FT)rV11>iHhb_;WyCMrE zS2n&DJgJ~gz|wi8-O)qxmBDwr{b+%bV50=3;-F&diO2_5Y`&fI(@@ z(tZ25ZlX4uzUt#Y@l@Mru|H06K30H2Pz5^Oel5%=^wkg)Z|w2y!amnwkh0NS)+B_U)8N5N$RSK2Ey|J!kiCBrlF`8|# z)ywk@YRyPmS;ExD!Lj>9y4^X!0ahnpc}wPpB6w=p;FynT+TZ`|^NNla7cqv>dCR)Y zmKy{#h*;^jNV@Fyz+GgfD~Am|JP$lRlP1XGJ0dPQY5v~BlIu%^fPB5_X^~-18tna7 zIc?OyFh9A^C$k7EnR$6?NmJjp97{MXVB`PMh}+`?f__`<-P&Yk1+|{+4H(lH{u$3xrn~__zW; zVt`MXyv6vo|FW^fRu+$Rh>n_ZdOBC61AI^3C_cmv9Z(_ZNKMJ7cM5q_MdHAHpIBnzZ+DazvXFaZ(ZLw7Y!+Y}ym2pJut+r2{{klO8{H zEClQ(EU~}b8PV}#AeLN*ctjo*N)1`sH6>R`)gBxBaP7mhjAkQhF0uD*UM0S#goKjy8)vO}^4( z|5_z^x5@^-Q;_DzrWM1hY{1yg7d<2-D*3T^POMUL!$FrvFa&7qDaQ+WkQDCt@}u01KI-%kh)mwRCGrL5r~ZwI#8@qHPO=2c_5r&Vd=pzAr%J z(pu+xp>ieO-{??^morBKra<5S); z7B?+bc;yH0U0m`&2k!IjbjDeK4G|XizJ%`jd!bnBtLj;Sq-pOAroaQr=s*GdMcs>I zi_~TsUMZG5g1`Z8TFRhYBK66a-|dT+g3hnawx~Vf{Y6^fGkwu$@GG-qig!J@0t7A z{PezN<6=t>(T-9#7)bge#mtT%C%r{HzrI-3Ygqt7eG!~5)^SRuF>9ClE~8R3nVEC3A+{@KAN9i-)f2YrFA@Fr@W%YA2{%4wJ^RWMm1zDRJuHS2lO zAD;T2%}S5ym>WhHQaZc@S%5_rjq~LDX;)>d}#|@>Y+O()&m!A>#D<8@UmI@kfXSSNlHM^HJ*rJ8nngP<82p_dl za%**jbz|jS(ZciY?~*IsXBu0{}XK! zmbGb?PtC)mJDqko#}V6RYa5TJN1tn)=E*y3Bgk(SGvuGnTxulmdW$KEFz8)0Rz*mxF?PUW_$o$P90Xqs+V_+CleIsFQ4FScwR6cqr*l!6i8@DMPm~9tRmi zfB`N70XW*$q9XM^Ox1zA`rZm%PuJd|{`1bd*YK##F7Ik2RpXBeP)2jrilt|rZo#U7 zr$hbvOL{5|ho0tN#xy6*NcHuXA8rTi(b>v3Hb+4RA4c{9wV7+S*Ws(U*U>!8Ei89J zY28q#PsD?YpAxzYs`y^=eI4#S0~i&~zjRpHofgR1f8JyVam+wE(3aTm=}nk`QkB zA|AcrVevGhOCyieiB-(ICxq?Bu*)&NoxD}p|Z$&!h)0~Lk<$|y;#5H1S!MgG1OvP4Aa;0EOyEJ|jS zp`Bjon`CNw#Izvs!QH`+Kf*q)sl-MS^f~5Q>zd6J4pb0)>;W{SCqyd2-_j7NK|iNk zlQ9KB`g+vjZ?zrZ*L0IURB}Qzf%|6U&;NR)|9HlAy7DrPCzt&&n7S$Es-Jop;yZhf zm|t;8MtVJ+(V{VUBRp{Ne4kUic2c_7U!S#n8?-?F{?2I!K(*dnz848QoY^MpVXdF? zDkhwSB~{+y=*iYm_y_0G38d2xfCy;vo zuWgYfH~bb?PgE+MIIx|kpi<3!^RxUpk8GkFdRO^0BAvwd9gmm~k)AK&|C~})@yRIS zULfc$swR%=uH!bdJIubVO59ZbAr{YA;yM5+;UwVg_cJl#HuqIUE5^+FpI}c>#?0(j$<^Vq9gt#lK&lida1E36VtYYm%n}=Q$7_c8s-cikX z=em-5=01BPoGV>*VDPbgpuIz8%}bm)h+^lzvpUAA28hT$kh`MCd7pb}a^RB+tT&pd zh4p*R@T`rmZUiyNOlV9H2Q;@-+2ywXNrX-A(+8nX)8O-`^IP2p zJTeN!vW)-JOL7j=dr9vcPf;{`bIUyNx?&aX8{@CXDb)V0>$3~gXeOya<0MSjt)ELp z@`$y+gEno7iQ^=vD=>l8XTFYVSG3(?AFB)O0$*RMf;A;j#|d7aupR$%AIgW7 z^J6Fnu*IbdxiR7I|0CX7E@e9==Ue+2@V3QC4E=e9uM2PdS9Zo(2aQp~O9cd|8EkNX z(2!YFY5snm@FQiQZ+Pd{(xg!H;Vt!m?pO+V^0er-yEHvpbAsrE=%!d6dJ}wc{A2#+ zN5>ib!2N$IJo$W*uG(8hN&w;f_dKRNRNH%xB$tDd8v-li9z38EG~FlX1bJB>@9W{v zZD}x^+hVL=DnuWh^C(b4MhF6%V(jp|RV%~1T9FL+WMAN~wOc%bocFxOS3!Az`ca9J zHvK&xn~(_!7m^wB&Mf};FdaaG&+%-^wm#kR+uI7SRg{*1%%iW+xJ&P#CzQs{m7*7R z$XYWej+Oz7x$VZV_jp@zLWyS(y4(gvWk}~!>SJ;8(bgvp#YW+(m6xmdD=+_3_=xDN zytF(5WQ)0Yb&|L-=-&Sw%(KgI)l)EXQ1gFidhc+yzyE!lD%vWlTBBCC+EhvHqNr7? z_6SwA#flNTindm5YHw=qEk^CVOAvb`wG$&G&u?Du&+m6#u8S-Gc;=kvZr`xall95=L43L`JlH0N0G2w)O0XW3zjP7@U{V{P zhpf}$KJ{^lZmNFnYP4x8&ytPwo7w~g=jPmbG14nrS}sQ_vwI=$!iYX0iS4z{fahn? zkxs=&vq@wVf*ZNZB;^9)0t}ZkA_*msiv~>pzy_8i!Jx1}Sw5m|68|$%l@W*9U^P*# z@GW+-ED@gCcU4o>U#@o>ROW*yCpE1^n0amW*znDW_9}%wnw#gNfl^As557IwP%thj zJC!)n2^>3wPQ`}z9? zj@@;8SdZ+3@MQ+sG7hqncJC;ux#KxhalFpLcCMq7`a#FQQXXm92+faUaw>+7(iCCy ziJWj1WKXq}r+;mHR^4Sl#%6M5c>w0F3;Hnb(YAjwV9`gVn^^MV`N9 zeIJmtZKf%xZaLnXbSh&hp-`BQ@w8Sy``@{nK4&y?HGy3%6_8tLE#}h0_mFHZ(j4R$ zw~1))hgHexE?|X*0s9g%&9KwR01(OBk)N6sbe#OKzOM+ciO6tvcj1?K8nW<*)FnqP z$kUhk_))CdmjNpNDyK54lm8Ne4W$JS@mu#%)|l7+DEYqNuV#C%UB-|wWy7s+Pz$jJ zi@Q5F(EozUizk*a0{_nI(pnycAYZ~$sjuhVe5|%?;U6|2^G~{7380mRYbq_*ZRx5? z%i88jhsh#*lIqZJw3B@H+e_}6qQ|r4*C012C{=U(D$f5P8(Eoo!@WJ*QhOENvxNRo z{Xr6PHqGTX&iVB;zFqoJqbgE}nvfypmRO^<{G507^N~{%aVu4XS(pNUy?c%Zc}>CCg)kS}Z&I-ie<4z7m546w=D>1uL0*+vq@|iT@gco^P_vzU>QVx0ia zob4MJIg^!ShE~y6R5ps#H3sx}8U#eO61J|2^*UTI^_H31L_9 zwqM{pF664EHDY&{&-=j~%L1SMAET0nlPp(615nb}UwOdmAaym`2KGZqc@&)5oR3}& z-uUZ@_CB+1_-JUtfL*WH3$*lU=&14=>m;I)pSsV_YTKW3aYNoAs)21o8V@RUD9fE} z;zbFPe9~M^c0q2DH$CYw2{P1#*nJqX^D_*lx}ajlKgm<1LO0n_I(Yqwt6$3LozYqh zOe#5_^{B2-LN)#J_t91=B#3AjQc?L^X0!FNiTi{?)H`B~v&i_rG&j43^=tHVS=vga z8fg@kVMynK^F+%M^vb7quY=8r1hKoC_#=k!`LJfto4UwfS6q4iWVdyONY zzZD!8362Jzk1wV@J9iEo4yW=66$y~niVp>5$3kpV%KVhEOD@PM$wd6Eg zqSPpl!Kw}O`cJ=3l?7D6jT^)zLUoWY6*Eb-%VUfoY}Xzd8isbY?PM{O(HU*xNRB-us6hAX-e_gmQQUT+-u9 z4NSmng1^C6hIK-2w%+-BgKR%-4J+;Xew$on`%cYGqS*e#2jq_tfrf5l@*rgaRE;Y@ z!KUbPN^JAfPvUjrqnz-SBck2zbqSh+|J-8RtJ#zG*cSEaPF|n)O8i0{X-$-$== z>{13ocV0gR8pdM&M5iv)mtQ)i9+^#lBo+${fts^^Y1of37ciA~(l zPoRka#0=*s;q z3ltxHZRBnv8o}H{*RWwdAnz-7?dXr@!5zp}ZJj4M~&c z+9&`9Fou29U5$$7TUBU}r}*`o=n8+cZ^kO#@w!4Dnr~wIn)=5#``!f%W#Iml21(N! z*Lf)FOnU2ZHs1Q;@V#s1Xvh5K^GGu#^aU}Q)OY95faq>T1q#?58du9Ax9QnDYAt`C zI)=TH+He!_DSModN}>aQ(wrYUKxMVz(ce1s+9rg;!VU;!Nlk59Y!CjCMS#30F=5>N zn~Y*zyV70w<|Db``{md?ah-fi2co@M;HNnoR3F7WJAkcYpvmyFVDGu66};9=^pwqd z6OEWDXQPN^U%GI=V8H@*uzWz^6Pv>mJE4c%KQ#qvwh@_)-;dT5C$x_<6dhk7c5L6M zl9@Y|7C3Ia#BA1wH@@G5g7(feyg(zXXr%${8Q^y|Bf@8#3; z{t&-$Znclya(Mum$s|_ImUIfyyjbulIgz1bnV^24LORVtLeyY8-RiZ1wOcIIl=12S zIRuEbhdP1$H+2|@wV0S% z;Ael<8@f!wf~a>2gE?E4gQgx%B_yc_cXulguXIJd5e}B#4G>?2ggjgF>-dfR!YW#p zX>&xc>WW)fuyY)`n$!duAlBlbx_HQ-@W10M=#8*LZ*)$7d^tPM>yv@pWlJlHvR$WI zMo!P8!^t4J9C6hzf4~28{ikU)S!-g=NW@pHprp0)mNM{H{c~qpexn`AdzO%Cr$L+TyZO@PY8DTwlwYl}hiPa^+ zn!;~d$xMK0&XH&aiRxtYU2yQ-lt~|-P9zF?aLm4LYix3PmJwDm*{mQfsusP+#(4Ne zQNHOMj)c*J#fQDHab5QDHTjl7cZ}NCsB(6t%5{z(u3~BS)(7`?b~0W_UuOACy6%`UdBs@~(_IH}6C z)^R%)&wxwI5hBBCM5qt?u+Yw0ay#lfP3><>-qX*y2E1LmKsJ@X^T@r| zjw%iamcPaxep2Ui=6T9~N$*=@_qkmbUJ7E*M?+#YtdKa9-<7*}Cg{l3zV0 z7#DzTNl*dCgfonh<^E_#&grv7@0kY}KW#+O?&GoFk>8a;x1=5`D8viOcU#(t7bNH_ z_ud}LZ|(=tfYNmG+g**Cd}-LVvcEkm+Aqw2*ED^Il9XF2v-Vy(ToJWQR!qApqWjOR z@z>3JyGqgQ&?_nH_XnYrGBQ&xVFR(qd=^H0fV!FK-5t47AIbq`Ielq>{n2A8c9Lhq zN!4;gW=`m1Pp1d}{zshPZuSQaKM@D2wrWZyrEMfY#u2Kv;8pQh=eg|{!8A)WYPS;!5aU`6Q%&ZUGhU$%Gy5COrFvFbkZgak#a*+zB z@cj6SSdcFwROe7fTF_og{#hA#h4|>_E3Z}t_Y|tpZ=9jN46;M8u~PCG@@YW+EMRp0 zx0I)89mPUKJsoOi{lodGZmI&pfD|_}<#?ld^?C<_iDyr(`9?5?JBJQiQeD z7W*m-pE&d?f73`x5=1XXD<<`VO>W-o;8hlTQa1v)@9z9KSFwXxEtQ-YP9DYP_7=vU z6ui7VsZRN%s}xwgO{~q0cgn%DO;i#M;!b>?>Nti)kqhHPC8=n=G7l%?MDk)@Jsv^j zh%e22QxC3B;SysR$?OBKHE9f>JBiv(C6jpnY>)w$(ErA+T51mUa2tH_DfZ6z%U1<+ zi7it(siSRX8W)}K8CYQ~WSVmW_hYT~r^zWm4%@R@WBTs}WS+iz{YdM{HEZS>W)`tq zPn4GL20&mYmWpAt5;ZXlN?|=XvZzY^oo@oCf5@$SWrkc$B&#jR{<~o9+?Vbdvix~L zL0=oFr~ytMgM*C9)30U`k5S>mHtz23xvvMjvDesNlEGQLl994Q7#brDwl9h3&9BN3 z)m*%EJsN2-=nZHY)|-Al-A#zmHEBKgw?WOUB~-a@)@MrJr?*7RNsn?Snpzv1UmTaDBcH>p z`2$CbIXnMmgNgvM=_!D*dLkxL4#AhXE<66`PxXHc93;LaDQw zuMEiyPjXr0j=p?(SxKRKLc>X`S;Fjmy%0a;VFhJLfYgbxA|7c{SefF2l_(KvYaIkh zol{XTXi}UE%q14?dTPRuUnR}ig54xM#b}q5yw=MfGO1K;$GfeZ+mHGDft9&qPG!qE zGm7-i>#OcxO)U-Jo#1$u(KAYRgM%AT&n9-)M(f@txuSK14GO?w0}`#*bBW9K_PVNd z03pmcE5z0|yM4R7q@3=t-J7GxSubA%h(Gf zH(xqJ4|hLlR{tK7WAmF9Fmu;h3YM#3RbngK>F(|pl$PGV;pPtAMg112HGsy_VrLFA ztT|>Gm6J#7{QXHg<|MVK{N<2(lnBw`%1Cf3nY=Vn@QOejlV%e7j7Sm_QOOoYD_C8b204nLTJBUOvv)ne;nO zasG4j7jY6=)xQzOLJYPmz0cD1%hLST{p_<9Yz;ZEQb@ud$F!QDNdb6hdAQf-ch1K~JAqs3+A#YrG;0PdLnpjDZ))g6F~enMx1vSgSK^#8BfTg(UY|AR9S7_b=$sD!z2-Zgpt>4#IX7pe ztAu{5$Hcs%mcX`^7FuTg7Z3{U>es>nDdsG4|H z^=)f`&GjcUuS(@#^hf>u+B90|Z_WKm*hUB`VNjiw$@5mc{ib5)zUz+Wz&6san|Es7 zvpSIl8vtBgC512Q-K?Uq_Ftte$?hq_?#Fo(v1%Xsb%{lR7W~qu?bR>qHUy%+6F82F%53_-1Q_ZtFNd##h@kS=iXw?r@Z!o!PN$E4?-ajrO3|g- zlUiESxfz!WP22p=r6`d9 zD#bP-a|18|LhGpQU5le}_z=%)6cp zA0Cq#7)94<2_J~!ULtxPBsWQp1sBDS;`eC=*AsEc$4R*yB>E>WXS=l(4dgZ?Hd~Rw zyYQ2nR#<%3Z~v2|_S+U0vkmR52J2JiUd|G%2(0^j!Zwq8CPuU`$r%-*FSi{Z_t5E7 z2B+`rg@A{sjSM=*_%P_hore(Ks(`ul5Pl&swP_hty36;1LdDY<1W{$f5H_9c7ie|F z?r4Hhz%oq!uP@);W1I9swjkIQ_vZZjr(bP+LLE2PM>ajSpI2f;rkWDM4~q+`d^^!S zyNCI?;BTMIZ5a%Krl}AENO=+tO|egX|0yXSx`A+!#0FwwVVd;OkgP3R_x zilki=&9TRi&Dk=tq8x?Mc*8_D`K88erABD+r$-zDP$7n5 zh5JI3*z=YhM!U1t{%tcx_^}7OB=`0B_D*WQKTC>EL}4iPh_0<$fnV&r(~!z6~B%}nvLqsTj1$SZ-syhOg zJynNptrvC&NZ^VS>Cu_EbgskVGtnf(P`c-`u1=}@20&O3jtW`&6U5087_3oVNZ`;1 ztbM5t?tE+`?*hHFaZO{|B|^lWIbW-6e)reHX`jUS$V{!z%@(aNsgA`#Z}RDaH7u>N zW-F?f%feG>uV-?#@lJ{2q#sDsm$j4VJt|_=p;_Y0xLFv0@fh!%3w+(!%XVKNnBm5~ z9VQ=9C(Q_sCH%oNbkjLzxO9*j!v*Rm|E^_CTV?z=O2NNb(RH!|UH`ZjslD+Q3d1JRDw(*oxs zV__2ZsPwQ4^y0ct=A9icA!Cot*uQcwbMA0>6YcohA;w}`mmWn)wv2os#f*yRM7N!! zu2=%(%v=BK{hfBE5A_3+*~U&0+tLG~9Awjg{fp`<0*C4ac9v`8v;B^LHu`bC0w{S# zN&05R$?o_t5zI6Co~;+YGF`-|;sitMMKelm&z`SDE>mU7^ z3^CQySgy-U0`GoZDj=RmX2I=shQy!)eB%;s(tmE6VKjeoFebXzYDTnHDPct*J83Bm z2md4n<{MxX$>Q0(A@@zw{c6n|E(;q{U-1vhI)Z*nQ;2LJ-$@k#sV5Yb*Z?;t|!I=Hu7)O9oe#3zd3T*`nu9 zRLW5PSUY-RL~u&!>=X87shvXrz7*+To%sSBX)=QCY<@IRfay4ofV@rY1wkY&4~5tS zrf`DzPQ6SU92`_;+hzhGaU&GGf*C;r8ltvW`}&Y%8j*Z~rLGI{H0M*QoE_f65*BNJ zzK=@Y8@b-xl7&!xlKi!qe#!oFY!F@qaLxf*rQ5&WmkQfFR(agksKt8j3oYJz&R(l# zR=B;M)V^HpK+Rp`_E+3q6MrTC+#oUaK|opZS&f+|T?CJGD}*JY{V3;&yDo@9r%-f; zk{69X1tWWbWcN&W3e0FSEt_0rON>Qj#(ECHW>epq1R#5T!zzgpNH%KR550BkX3& z1c&;HcpVmFCp$FCBsG}*K^xzSvFC+R+0+AQxjGJ2b_;}FnPX)EW*YDtcn3iKNfLVz zvL7Dq-@WZHCfmZh?}QlBCf46VFM=C1w0$SS!on=v-D`LM;PfGY`0d+^RM;={5Ao~W z=me{04M~u%!$CN>kYg?$KJW*oGc3CD4U_YHGJ%rI^o`)UKC%}jb~Joh+1u@e)_?b{ z)x^s?2*UDd>uSTQfYR;IkYWY$!Bsj%3Ov-F9e(Tmq4VJYB^w;eZxPZv@b%}~Azfcr zAj64eOQz7dQ%&GYIg?k(?X;Syhp+0x9xNzpW|$WjIO2wI2k7N%}{ZxJirH1d%H^>kF23--ONanAW7N~?S5vOn%-k$p>!1Wi2dxF%)Nb| zAB9TKS6sSss77}}-QMq=esfD%Ue@-0F&oV$G5hMHpR+T^t1hBh0ftwiddXT&0tIv; z9t;&V0TREoZH5Z&pi>x8x-p~288z$dUKelso%eK>$0NOYz!;38b;~)5adPm?wXl;M zmaca3g^RkxX{`3GQ<{#q>$N61*Kr_=`G8Wz@CqfBbv(gjE+U>tj4^PL|3MPY;qj@zD~=3y|9iYFt%+L>f1NuY_Tn>$@z(! zT19~_dd2hJ!E;iXy{=~o2Zb8wuk9IWcXrsEf8E)wd+SULU|YL7KU#O*=%?G+-w(~m zVDEn^PfCv=cbVTz;(|{w>0;FdCCD~f(i>F_j+SLtDuQb+zNmTmW(OIt~pC?c*M`;@J zd%n~}Ux!gnpGK-m)w`P1Dhe>}%r1F3Z2p0XlR&SL6~A9}b>M;CXuj2`@Dlr)tmv}1 zmU(}q+Lf5GF>Vj{!xyd@<*IfqQ>?$|ykGJeih}K?q zW!pH;Lz>%xvX<52u_Sh>i3lN311J8P8lIyF&;i0IE&-ylkCn>z`;vAO$+3L@@Cl)^ zd`IuOW}0ve=m!*I%)!DkR10mZ2x^jYCfV%?=hse5FcGV>XD7h|7##c#+84hsB3D|$ z`kI9K+0;SCU#-3+D~rwRuc-}i<*!_yr@y(VXdPZkREA?)#N!CuU%HJX_Jp$>H16)o zq4qWMPi(9j**@6*Tb$%i*`%Fb@2)lLtrh3lMEB_-X{KEz;mls88iVz?&jpqpyyy+L zfjSxaEw%PLBp*ueC4^^ew(2G(oCOVB2)VUwWF{P#AZYRD%8p}GiCIP(n;&Vi>W#fQ z-s}lyxN+&m4()NYVqIygOdysmG10Uo^)6OztE_ICXPqAyumMH&`jyk+Dd@)>94KHD zr3qBz)nNiyhdG{^nwkoFA8-7SxNS5y5!PnFD>s`g=0-6+l%Nj_=4ACn$)bRSr-r*g z{j|7irJF{;FTy+SuZNn%gF4C{`5Kl{Ms_@np_5 zMn2-Jakp8D-5BU{E|vN+@S%VY+$R5k|NX2aR{SD=PT-?Ov;@c@Hvp7Rc|$({j>im* zdH6qMDrk6Qtf+>!m1HPr_46-bzJ>*eKC17DtAhzA3aIZxCwRl=2C#gWD#iRcYw;uJh2+(=OMU^0~5d0*H=T``Q`alNT zW|5j2O5bI9-zxGkh8vB_j;p^anKlCHZHv>hu1Sb$oi-_E6F9&rE*t82csphn3#|Gf z(q#!QL66x?KMIbD8_hRWx<*AuD~YGNxBVxN=cIr!IkjPjGWJ;Qn~4wY?EQ2K&~n?q z*cY*X82riUG)M|*81>jM!P`-kf6zra>vg_vbtT1Y*xtYS+?W%hLMg`bMa9^U7m?Rc zzz8W8=xrF$12}xpR@SZ!jk4h<*@YaT-Nppw<*T^^DtjW-a0kLi7w^4haeqLRa0Jn7 zNb!P}y~up8EID)&vqkXzQJEJ`N_d&!dW)&)ksclyXX#RWA)idh?HI0Xe%@Ws_g)<1 z%(G+qxLxJpgYVqK_IF6|UkVaCBD`Pj`Z&*%)V(T2nZ2~c|J!`oeO9?y9f&l4fjHf5 zNH31cKR`*RPMvQve^AuS;LS3V^%gE8SRhQH_QtT2DxqylRZIBI^K_-H8WS+BG`hPX z03tmNv}H~M#l&W+D&Mviu(UC~3blZ)Z*0PW3c;&Mw}gSfA5Z#N?WLQMdCwLmUPfIK zhyn|W0)-g=xbwJ9zj+`IPIr0tDl`x$LuAypnJs|r)_~1`=B$T*a5X>ax-tg-&g0WJ zsT8b4S@aW)A-kVcf&=0;nD^aWs19>ur?|)#RGRcoHjM0aY>D**f@k^tL>C=|dm>P< zGRbWlm!ex#o^e^0=F$bd;u3pC{PN3sBVjDjv1yrnv^NY2_gW;n+Nx=8Uplrxy-&_+ zJiMbSYSY_B>)me79&EWfc<-PcK|VSXH|F41L)Q=ODVNvjNw5JZpq+TY%Q*uSnx4xh zbBEYR#FA-9-Jr~b^|y4511`sszBb8%m)EQnZ9GMHUdxu?h!}~SDA0k;W+wx)AoyzI z;7-;%Pq~-c0OU78pgmpY@`TLzA(>!5Nxs2ur55Y2*0!MQ=5~e0-(NLYLWE4(S^If> z2Y+9Qy0aTMC5nFDd&)lXFkgG23{=)0a#A+g+1fX23i+K>Xu>|d(o`FX|9CwE`#{AH z6HXE6$}CtPa_0r;I`HaYlAYwTdE;z6{N3(|Rfx@rbeOhSK*7n5KG>}Ci*=5szxR)J z5zc-}L(}zzoN9$=yNHpz%!u2OXgp=&URNn?m!33jQzY0ZE|By_fdAELPyOft zD{f|P)_C90^8t-CKWVjqv%V+aEBxOWOtg{liA|Y;7owi2M_O1B1V0Q^}^EcD6{=yK6VESNzs~TK!C^1nK4lmBc~TDEN;-_t0SXBk zc(^SNm{>|phbx~fuN(YDA2Ih8@k1Q0*jW+yh&1R^e8BnU-uv2L!5T>>wwk4$RN+1v zhK+rD+`<046~H-SnwV8j)a=l%yj$z}`B=7vfyZZ`5Qp%pYE&sB=V^M3s!)T7DQI`ufT zAYy4f`(Gw-UsH9E2pLcI-e;kt}V@kg)L#RC@w|G|62EH+^Ie)9xWEfh;o{AFEJ<&lIB@IM)e-OwymPSKk>{ow? zPKA6?R&@^$quKI1ndRH*y5Bl#9Oa4Z(9S@59~&2N$WWMHJl_UOWz1Z0Z&Nq~!_=JR zZ)H+Bz5zS?1cAyfUW)8SkVnOeugqlqN_ zmT$-xE|+>+;c3gV>SBS9Xi0RMaGM%s@^|X~1-B}c;X7-~F2hxer^8*OpmTGm3xvQQ z{|jwEA8q&B!dB|P)zgl>-mw^Hf!^ZI%{_RVd^-9}(3{}%@J8RrR&m&$Z5oYs;$s&8 z94qO*NB_p2a@;IP6uy7+#bi$$Mp4Uo+4M6++#jShmHk13R{$8|RUh(Su!BDg-PKlW z8LxRT^n#B{pQ7R)=*-sl)VF)4qWRg$08cB^u>fd?DRpviw|nV9YoDNsS`r<6DAdu9 zZ}Y3+erA$y6twd$!S{MPB?=%Q;uE!quNc@^%p&n}n}|0#%Fu1XTe>DzCgZeh$h)k3 zl4QB^mwevyC?fg);XOSDxR%*5mg(nM9jvOur1q;NQp|#>ZHG~CDr9hWb%|3IQg~+e zVI%HFZ)-}O){ZUaYGbd_LIC3@JQJyGi)nr-ctClQ=b6+<+?4TJaN$acmxA&si$4Y4 zc@GRtA7iNOojL2$WqwZfTkRlzV<{~!oR(T0hf|Y)o+^^&c1srqFrSBbc!i*&S|_yJuKqSQa8+Vrg>NEkom zzNmJAW<0cGo_V(1{+?J0a1gQg&Dwlem`kW20v|AO8p@QW{}b26E+O%8_kTXTeK+Ud zaW#Ukws}1t+&jt{DLzZv{x5wKXW^nLkgj$)lFy2n=C60%*i-Wkgi18Elo(eYzpyEH z(D6&$oYiil*3ig3sA(4{{XlB{WJV&~=d=gr&y7x=R&KNgbfe#~|Fqr(m$M3EBbrrP ztv?V(^Pr1yoHkA9&6Kmc=4d3c-is%w3D5f2M06dAeEYFC30g}R z9O9afPYOsvn>o^vY^@J-E6JJC3?8k`5@hl4>VRpWPEr-n{@+T6)Z@kiY8YU2^u#(~ ztAhSW-})y>%RxIot?#ENFZc!QKrYsU*AC6DZ%pSOOootWv8um=HRaBD}Jvw1TN3de!cs8fbpYPkY7Ma(%S<_Ta-~Y zNvP#eUK?o1=s%$M-_}N)T@!vRP_P4#FB_}<0ZY-%C9y^97#`8$R-MLaRy<$j>aC{E4}SY8 z?Irh6{;&|3U&QGdWmDLfyU3aaf;aTF{%=nm}P5w-hRR6sOwz1}i?x0k~K4FLi^=dNE0Zy#{;Y-)YIOMmwxjf77kA2{I4a`z=Nfzh-5wj zFO$hKT1M;^?+CZRPdJAZxX=dqF1mAE6yIFK$ey#QoSh5rN!WN7&k2+3q@W;p+xMmr z`S-L1umtp{-@oc^^MegGtn8SNkG0tbM+Wsctb>~Q&ROXZ?O%M`dC`vB{T{xK2o%=+ zz>qg9Dgj+-mHCNBwdc3RU%nY_J-ib?tFKRNjS(Vgu!^K|KiB^%9;%&@;chO|JL|@& z&(M0YaO~0G0=*^7M|s)gIg~@7od$w%GXL!ZMErmqb_E#G`lEzJz=%rdZjSP7^!l+j z>-?~*;7F~RSWM#J2bxw)u;DR@Cay&Q)*Ul+wtF`7(g8aoaqI8pw^m3Zx(LGg((F9h zy){p6$!{86X5x%-luzR@PH(K$QK6hXuG@Oz*N`4C)ij5O*bDfx847e42iMaMMluff zjkxVoTTz%jebg9veRYmP-IjE?Pw1bw&M4zod-#9Q#$LDlf1|D{L*$I-v;d;Jf!k}6 z(#xy)IiyZt^0ygmNav1tB9FS=pM06KhRZ)(0ww;|lLOk|Y%Xu13(t#$Xb~`%##slN zarAiNYWO%77Pu`+oU5ibMQg4A{Vf8IIB`HcZrafm-om|$0w=_eW9EyLdY zfK4m4-PVVW2cl$VyDMrc2Zj~n~hi6~x?E(S3{SuVW(>md)yiIm*I|MxPcmI7ye%+)cn zw~2lfUR{4prAS!S(tGg*AeJ8hkmG_V~?=@*!B9fY+;E}wm9b&UJJ z!hwnX4|W@|ziZM0AkBoabJCTg#*ROqv?|&uRzk@h9TfSKEOxIsZA+`85-Hl~UDi3{ zRJ1j!j1zHh(FG?SnJDG;S;-mXKB3sO{{w`7^PgkyaBRuman@{ebLPtKQ=F9{@smn@ znAEh}XXz+4u8L;0HqAk3aeWZ#Xu`fb0^xPmW<={|EzBm>#+M?%WXEooI*Z8k|HNG6 zn8~G-%p4^}d9Y~=zvy>t{v{wh4Q}^JjpEg@Gu!L7d%tDYReK^weC7T(^2aX^+VzI6 zWf2Yv65S@;@(Gzugt2wEpzkI{2kn;{iQ&=y_%}O|U8V)R`U@#UIUm~xrGqP&AyER- zniiC8_R!O}fRAjb+HM)=S*H`|!hvy=RUIocPKjZGw@T6WC$Y3wb<{3f+6<2Q)ChqS zJKTxNDPUk?&h+-({H9fIk%Jlk!y>no z$@%&z7UlejZ~@7ztU((vAFU4IVIdSgBoz^c5HM!zDy8!K_n;`+l{xm-Mn;_l%JTiH zXKVNN-S)^2vy`sXRFl9Ui2-xI;lI7clZ*c9XczP3r?I6o<9dC&?-b4EliNe zM_dXN5-Oa?-r$i9w^2Yr8S#t&sQ%Sp;Y{MCpT{pqXFRP0p%>sfK91Gq{FqRaPnn!F z#JmeUo1> zsZkDQ9by)Q&eggu-ENGpu%r7O^}BqwPjQ#kE#DvaEx@y>KL4aJ+6ly%!wwSB@PluN zW;+!|QzTKXJlxK|r^!qX3BN~Tz90i(c1=%Seah8mBG#a0SUxL@vY&kECvgJP5g|5^ zt=L$^3w_j}BsPaoF+)n!_uS7VfK8R~@Z;3~UK~DK9ZUetRA8i%IGy$Ag^6$-E2j7yuPbOgL~8!b{6r%E`d(@lre!AoC#8Z1!?)ka|` z!VcT-SjAZSX-@>&2oqlJ|6Z3RcNp@yyWTKg7SAZ4_)4u z@=U-_I6Y0^@=n>k_Gm81c>Nb@TPt1BSbTX#zQ}aZ`vT0*M*MMWdR6YT*1n;lx?z}=Po78l@X1q(Vva7d zbMkKVlcl_YJ@l@8MDED2&*K#r-a_sn?zIWc zTvE>N)t{fJ<%)ik|t~>3dF#IJ$W1mF( z&S~U~=$IzedUzXs75vR##(!_@uBw{r;3{W~!XZf3;Ix(}j{>p1r+MFypO)%H2dr1& zhv0L8D@Fnp!10ifxeiFT4=}2dN9WCfABOl|A}d12e#s%**S4;j2cC`UOhffPQ<67k zr1Yg^~Ehfcqs%(Sh9C;;l5Jx&LaN%?c)%@vc9|n&_7>o$n-r92d-{KXZ0bqk|6CJ zr_b5GMMWEGx@O$>R+xKL5PQ@-@MlEHuXMS7zQ-mx$oRWPjmeFea6dq41o&6UX;_wD~Tle=bk4%~3J%$z6*` z4R(o~+$HjFdjjvRYf;&JAI#{fT-4d7W%1wW%;H*lGufiiJA??rrKQZ!+AuE6cx*i} zSbVEFQ)T~`G`x(Xew|M6X4>~Q;ut^(_lQ$q(oXyncym;7KEMelM9ZwHz^2)tF%bAy zdo$#lAeOdwr$osu%F4RpCCfm(`hR0Zt;?$$94j{lMGa z9SH@%Cry`kL8|k9gHS^;XnWV6Cm)vQCeR%ua+ifNk9-AvMY)CA&6&vLQ1+m(9Uh6^ z^EaE;(i?3(4whq5XHTX;(MpL|i+zNUWId&N7ZsHJDm;Az`5;HLJ?PA4#ts*VgOu=6M*-29y)08-+J#s$uU@U%6xQ*n1N@nZ? z?bhX!)@D$)KKAh&eif=1@HyT>ux6w+oTd0W^4N^$%8mPq~jyxE{s;Q{@II<`)LU5` z9`MH$Te4gP_ivmi={|WKa1rC9o48nM{SDg$Bp`Mi~9i3gQxA}Le! zPKluFYat?2=%0?EeVBTgcHQ#*2mQMlGNaZku!zknws}nYE*X-n8o*3h`dWzHU~RmA zpWtT7!+qrz{ojgaUwkODknHs{laZjI^95iO2skTYZ2VH*lIzb2c8~#@`syWW+4kgb z^l~gm-wF|UXYw2!Cn93m;NZI$5U%6hfbsLdx*}M$Uf6W zCDTUDA*D;|zpD+-OQU2;v`3-r?`+qC)2F@%HU05j5Q^4w>i(GNBs=SxZk5IgN`r)c?hU)xPI_Tm_X2%(DSP-ge6c|= z8KXCK!D9o7J2RY(7nbY~R})en*NZ3!GX1{KGHO=P5a|wgAg4^gEbb)oEcwxuBSp&3 z-EKBRoz9NERvCVa%k-RYePrsjqJ* zo1yrzqKPn{dEUJ}DK*|b+jxRim$hjvpCf6{Evd>@gx}X3Ky%2U`I@mts~rFBHJ(L> z9L0x7hFie8fwbfm66~puzhc8m_)eTLKI%D)oaEpMUw)_8Kj5g;km9JLDO2AQ_3BlN z?mgeoo=9_66@g#HbVjUOb`Fc?o7ae)AjRV;LBfDuB%_}LDID@Z$Rh;tbCG{tb{dq{ zST*0PeVc{$TFJ=vzV)SI%LwV6yNsuNmNgSJ%|k9=?MG1Ln@?`^pdU*zHS?nFlwwN` z{dt~(Th3?Tu;yzIoE?rW(DhvRJLc-k8W{PM>fv81?jAc-UE@ftHCRxzJ}O+hXb?C4 zcb~YXg#ZQ!sc&5}#Mdt1;nVU%AjUr^?x}S$$9@5FAjx;;6H+9|DHM0#<=|R24cAmz zQb7UoOGA$`=J5%3+}D8Rmr1AP$8AA33%~wU+t(8&qXU-qJHv%Fga_^a%6sBJ4&&7* zQx_|ShPm0zf6>nwYMl+Ak>QJoClU-}Y?Tr;;=DWqr>UksVdB_T=fW?d-vC57cyh~ySRu5%v=U%BTpjE&sJ zm~FOwe$(%FemiI9?61#xozGtH=j-u&zCZ7cKhTb9F%Q1Q7BJxQ9KgzFkDOH`6MuU$ zFk}SW?v>Fn^iu0AC39GNTk1}@62GBts#N(&3+o|!OM;hnA`@vkgyR}_# zX;Vh`H;XgdKXF{S?uXE~6Ai9c^;>XmegP$9tcx}<{dLjt2b(>Q=*^K6%B zq*O32jo-}7Yh{0|BnHUKW1nlmG|#jnQ}Xv4J3>ZLxZC#3HO61wi&FUy)z+oN%(-!vkaZa7$78t8%X2^yoyOc)Gw!>GjWZ7UNuG18ezuR8Rm`Y z=qhl9%6z3opMns}%0BoZQDDvUB4^7XgOmOUYvY7nM;Vtvs$#85`ikK>olK-!c5&VF zeK2`F5$6?{x+Pax{|6?DL(ev|MMuse1~B;FJ_s~y%4r9rIsq7S7iB{0^2a!O8wOi2 z=bgToW@Ti*Fd|46WY^W7REw`P=wiTqhSW77RSOOs-VXMHHgE5d-%Rw3mA0t)TLq`_ ztRmCL9}NVm&h?uloX=N?s;0fW>FTmM*)S@!|7!HH$ljN7G-Q&{!-(Im`a0ZgB}YD@ zJRl*$+W$`49RJI7$a!QJz-$MY<4BhDiRB5Ypiwb{jQ2v&02u$Ixp1~;5>|!ox?XMm zV-fn?{@AG<4Q2NhD3lj|Tw5OHosvLZ65>cnqBn8E5~>2K(Yo$g@PMj|9`rLqV%@{C z@GwQ6f9exC2lm9CLx#$4F1jU7N$=NiaD?)Tg!y#{mt9`F5&Y0k%ise^j>(={M)^^e z;f|(JW>qamLuIkL=s8$fZQkQ2)YteCP9msUr@QbYsUdHXTfxXWf*H*==Eihdl3oJ40 zsN=_28kP6I?ovo{5tqfNA^we@#$#;eaRVl&S-JD8U_hG35qBG)<_{L?$8YdPBzTvq zsK=Sa>7P>Y6|Jj5ba3qs@eU6S@CE(8R)v23kpPGL{3aUn(+FDA(z;3V7jRK{a#hOs zay2bpI}Y%@j1qp70KrF{TfD#jAi)y9uNff?IZi$cnU+HPOBZMN{-`W;V~DR$*=<-5 z0&Op?c~m7j@J?^YWH|9pO=}^>%G!~{^9*_g~R+R*e4e467E{S*)hfBHjH6V&;uku6dC(SC!N7?ch2m zHvb=q0VMcuQBSO#Eh%A>K~iwWCc0%$0N5VFA-4OFG&#i!n0yxfMgb^=GAKw<@id)F zm7{SCU%AK*s z>ZE%K_f+DT?6V&-STY@GXCC_wu?ulVg}sZB?Z&dvDyN8DbX8SJR6OF(nkcKeE8$A#TF^#G`-V?S7UGT zQc4F~Src={O_q`UCeM*SVUr@QOOxA;n3}VUTvFmgu1XICxwQg*-hEX>%>E+I{grfA z2E##K-Kr*i{r;7$N?wn5G$p?X1o%X;9wqd`#zR4$7y&&_`V3pE{PNlTT*Ag#9Mm%D zV1)Jo9P_}pA5L?42G@rF9Uh1C1XgHVwh7 z)>b?D6|0~Fc0LXhzfx=W>o;F~zH!z<+0y-=!4yL+LrK*H)C!CyvFm|2@lz{x_cR}= z^pP(9JY$dim-7GDAIilc+aM-13s%7|MsmYKbv=ACDQ?n|mD-TR`a@xUrl_c<;d0Z~LR||=s zH` z3`VtR$2h7oh^y7)Nk(GMQ6Setbtj45fpvLG)VD&NpM9Xy@G|+KBgEQ5udL{sNZ0^q zNw=wPY!~z(Bzkd?X2lva-Y(hn7vz+7(<1D0c@#Yix^~+mK-+#fy4lTJHc)(5EIrL#LkkL z+;4F4gaK&a+8g|Xq?I0`BCWQf2VEj*q^uue_O^e9{wILo4^E$t<0dyOg&ER`iUZ41WBIS|K9Z162$+em{gLRuOY9yZ!dpaG6{&Z(vPQ!?J?C>B z&oc5!;QV%=!)jj6UkV6$JxGoGum#s(>gcZx5jMuX-H&GH4qu)f3`2ZKQgUC{#v%K$ z%6HPiZtoGbH|mN@FIDZo6T2!nC_5cO|OOcex@b ziQn>2DVupE#S%~?`u)Y9T`>e{$epKqYZ_+7pcVq?-70)J}DNzifM&PYXDHlVWEF!Q|# z>o&XgDSAE$8OXrlrXb&(m+|@>?=YC2FW$BR0fCzLLL7Xh*^lD>@K$O1=hiRI2ayRG zh1%LX?<3Bo^Zq=BUiOr~Ma?qPbLP`r93#Y_L;B}HCE}ThZezszkdBP9u4$<3QE1(9 z3?VYs@-6clm@rAW(M=x`_n1~Ljf&QtdSNxYU3}E|cqs@{j@5e8CGOt&Y9{26%awFP zn-`@oIYBmW*fN1kw7kWxRE)(T%r3d^hkq>4*l54m#x;ooAf!t-r+c8SUa!se8af zVrC8+Rh?D0q9C!>uFHUC09dGt^@RCOren471+y zBhn0z*GM6?=3i8262Ic{yFHGLZ02lc`TDULng_ViR39*(YxB3d+|Ko~;$3^2(AKOn;0+diw6Mxd=z}H_s z!hP+m%3j*9nk_F=A>#*V-wKb%-ZY4Q^B)09dsnC@d7R=p4=BRtk>w>MNYFvLbTw#R z4(G&fqqdm~D3}uSLS5_gH!pHlp8K2k*9uPl%n`@&Iot8qx_<=Jv|#0<9!v1M$s_BM zS1Y7v28t6DOZLfu3y#gTeWF^v7lD zsxazc*ny?-+>b452NN|In6nJrW#o0;X2v$zi%MAq-($4$2AuLlj72BP#RabUbEatT z8xFmS%Rz%xS<9;Ah*|-;A+EfHr8K4tLDC4?>{Tn_A$4a=L&Cq-WQvsBskxeIg>jn^ zL(8Z=(TuViPSkb^mWkWEwx%T$0}LIPa;moqnMW4<9b(`=9Na+biC0Ln!ETfVvk}v@ zeAsSfDfeXZRYCIL00(@|v^(P`6j>EE*}PLLVYY7#`aN(dl?G0T=~@b03sTu`;_zwI zf%y%5$F$5sXGart9GhDmfDwieDd)j-l*{q#lC0%u+7|jsrK`lwK8jd5i~OM;T%3bz7{QX~d41i#)GdVMH1u1)^>7+_)`K`%tf| zAK^xA;f>6E<8GB{QD>NF=L5HS{bvOAwJ;RS40>>xFb~;Quez4t&-dIA{wO|9PZG5ot51 z8AiqEZT9Z7osb;<6qm00*-fZ}-0r+u_T*x@vP-K-Px7UJmdihP2v3wYL|pwXqZ)_Z z&+mCl^?oiPJCwz*f~eSE*XvM0Yv=F&`15!}jqNG?~iSjAy`){pO(ExnEZp5Da)$;jB-ivqk^E+1x36#AAgycx|8fK?8U?(+3#SVKoerQL!;UiFh z*MYmDt+p*C(`RPLjO{D?_f)1k$)6#KCP}O3FLhP+ZS>bF^;e52P#YosNA`toy3yQf zo7Ml-z2RoEt(f`U@92tF{VOQvme?#i!Oik1qEvtym=+2`f;3_4ePAssp-nQF{AQp2 zI%`eG^)z_ELL!hd_gv7XOz-(XZDBmk+?)Yd530^*Fu(tb4P$G`m_|JNIP~ zd6Ir~n6fo|N|<#XX7!M*K&S)J<|$)OMSkuaZUDzznlGm>B{j?<4M9TQn&KypCq6N# z?DaG8esr_lAq2&-y5ll8vE2IIewnkS`Flmhe3>q}C-?F*I*mk9*R_VXGn^Qx=LKRtCvI}y%bd)p@ z%A%9D3iq)uIvxm$OI?0v)F=~Fab5M2(?hO*2B6Jlq=)ds%SvlhQ-v7on`N>YyBVdW znq!2h43a@aq0Q(8T1nOuXMPz_a>%J#=Sg#ciayZPIob3IYZJ<$R-c!=j~*~VpuH6%AA7m#>e)y$=_9j^*%ipJ;sO-DB~M>uQhlS3&x3 z%0^2VG&c#=Se!Bb6xSwti;9)hV3QyJ0SnB2EW(0kZ!?UH^;&^)BYYs`F$4dSij9ax zj;tc%0ZPoT^}d36^2*^{_ZqwWkMiTkDe*xk;;A*4t-1>(Pgd&sr1yJ6z8-z5?Sziw zTs!OUtQ-?!#qlUZxQ6Ds8S9`^ti$DDSgVg6gd{x`e_TOoWv4&xtId7U)NI6I`f@HJ zMU5#pm){|l=g$rL(z{2$VgdjTQBz?_9AQfhAWNL26U*$SPLofQSwA4xPhNB z?U-Tvzse^x``v~8LCA3qh}t*x-XBee5PwjBCrg3hoFV@L=8};wAszUC^)iU^MxxrXGIFL1QvOK+xNvq*_;xB zXPfYRDw3rcNn0Wgl4kUf?M``iUv6oerkC($FNbD6+4^WENW}4mpM%YQ5>GIc!H!L_ z`8SjOeq|N|=&{qSJmq{;6e-^*a(}(3gy-e1PDgYO&(iM2Ez~6))%VmC=QCs71;rBu(TUq=h4AElaN1s}dRxP+&Ye>Dg}tCV=NJb& zW#%!!)UA2s!%ys$iXkQDM-pOl;AGU2afuIhNe>3bMCgW7NJH{R?4KcazDBE>p_RDr z+owrKN`~fj2i%N(Vy->^#+~9Ean>lVD_V@KTD-EH z(wB&knA-}M@j*7s_I+Mm*D2*oyjbx)%(89~Zg?@xb0o0i0eXCYLbUD4p<2k%7(h37 z_X7#M&E}hAwwBM6$(Z72$pq)F?o)12okAe3T&n z0{J}D{!F*_A8~tg_P-=5j=tXIBvNX&9(itO>;0~p5+$0wu9h^!IiyZ_xwxEI+llh1 zSq_c~md5X}E|f&hn*U3!Yj86@;Df*AZW2qQ{1w>uHhZlab()fFIK^4|%kEpH>$Jer zV<1qZV!-Ae&(h834hDO>8xcxJC;q6s@03X^&Jq@*ysKD#M4FkTA3j2fyYwh!{mCkO*wwl{l9brV4{G12+Qnty75=j+h-HdS*j_Hc zsR4nOlzAnOK5~CQe&uC~|I*1hvE~(mXyNu7cZ0->_?KfKA1JkVw+lX>yHfS49a(_I zBWG(L5Gt_XMMaEL10N86h81uam>^-cQ&$r#l96>!jxbOy<@Y%&*tGnEZ*@1>D8UG&dX?+~_tmL?VshiCuztfuWkT}A%Ry+iDmrPDixtJN~0%%eC6&NbB(Gle0rNu?V_j7?m`|+UQQ^9{g74 z;>^YUqw7a^(AoK!#QoqIq;m)UqqOw!_rrM|>?0l_s?7iIpMyYuM$CX6%FfPCx$i2E zm{$8@fA|OeUprM1*&4b`ucw<5tRvddaGE8(uMX*yC>(A!lL*vDDlejR%C-z?Y0Nv# z&fgLB=B1C&h)lBV#f?%#3bGY7|K`~SLJ0`O<&fa*piF>Ly>Xy>-s7a za(8K`)E7sSioCFv#+KNa21ug^cnq5?~>gjlz}avcIVAsPia)d#UcI zyu(NmBE8{3U?{T zl=Gv%sXmAu9}~$YKG8w{AD!Go@=6-IAb*s^(>uXd%Vq5(5 zz~8Wrc){#RNS!z~#yk&3MJ}TX<2Y+)rmzFX(<7q)+e!LsYDXeL`CxFmjUvG zSiq^mkXKjo=r`E=-K|(UYG3T%C?+H^RsJSHdC~?Pd`A}sBmHu5HskGX4;+%p!YtqLS&SJQ$$Wdk` zF{;c)aFCb`q5QKCFYj4)UI-NLCK;Y4UhLq1@j}9w9?jMSNYg+7C16Yq>1<+(i)1yO zt+ZIP=P0dT!{#z*e5GsjvbMy~)0FblPCkwBzFW8NNnTP2J>WbH@bRme!v}r1HTK*i3(T zF@wDDL%`xoE@KMq#^jo9po__+m8&-=oJo0pzPp75qjo;Sn+ARwz^x3D> zgt_tYno>WiI>h+w&>bV!@Ii>NSG=Q>0HjHAq`un6c2#TC?7Z*!a8oez|6$?HPmnOi zynjG^2cl&L#zwexS~r+0K`_3{)7^yd-dR;LU|L|yT)sMY`nTIZp}y+tPBLnxLK_lu z8hU;7$9vfu!Z=9gd+HhP67P8(ujKG}zl_(_M0z?j4)ZHnYH~jkdAh7;|1K-_(*t4y$5M%dk%kp0$#IS4j%fLF*<<JmBQ{|aw z4Z2m%EY}QMx($z23P@09bBVoK*nVKl`kt|Rxt-21-!tMBGM)(k(^YaAWRHTxMFKk2LAjFgK@+BJ)#F8!bGW%56N-GF;@;r}Q4EkD8?mNl!iYZ`P7?aMG2 zo@{w+AYh<4ObkyJh#qH0ws!Qcq8{h@_`opriLkcs9uNb@T;qVFV=}XSQaJhy&=jjI zB|#li``?!+mANB0Au>;{uo1WN$zlFv49alHiX(9)2u$XU3M}3Owtx0dxDJf+w1tlTZt}TCOsiS zjH;pXPXi~Je9tp2X*cTL5z6;5K5>tU%6xAb2lC<-j7nX;^?IU!`b2u{Y!V~du3KXL z`ec3W2=$Ud#1CbytoA^@e6hRIVxVhze8nC-S{&eCDOEe|)xZ7oAa9%4xBZ`eiBl3VV#lciX=^;~(k3f25V_!p=kKp{UFC?n)+- zyiFqR6;7MM{wB-yCtG&p2hXRm0(LN;?tO=&pJzPF$El2Pi@@aWlGmj~#GOguj!o*s z(eTMt41m#};?o@dlWu#32t>NrNIn7nTziZt}xB>P)`!czYx?2^ay2jSk8AD~=#aqrnM&6czt!-nt^ zFgZr^&|1C;)+U6Ha_6g}HX#DwPtjc;_i68~*T8K@W-YGSW3pz?7#dP5U|%lZFODQE zvRcX_O32J0w7|`92R$ACEU{5}Ie2b+RXn0P-S<>jNtZ9Me8PU?b24n#WENtR+f%i!GRuY3=ApmTHLk&;S5U>WFdqZ@DdA*B_k$AS|}$iu&4?N zG+zKaVQt*X0=6g@RuH{rMI+WbxYvXHh3^WIF5-#}^4;rkJl;%_`N^Vin}tYvjKCQd z=dCDvj2;;C9d=3}q&8F`lvia0bfK#`cOpOroWl}N z0{dXqK5P|~FiZZdv?fHMNXN04VNmH3=`{vi6!}wV3G)ml+%?~cGj0Tl2KU|biZ8xW zE^fM6@h9AquzW=uw?@q$Nz~n#~8j8|( z0O_u~?@gqn6*vh+(RaIc9wo;J6{1Rk2HhLv?3TCOK$atvH+@p5+&wt3Y@=NVIVs69 zZu-Jr>OIN+86C%_Sbp*d7B2_TT=kD+1Q35;22WN%ybr zhfvOjJ9yA;fkSn7aP9D@JfF_P8T_1z7Qz^22^eKHs#L8vW?&8c=K-#*DUX=<+C&&axjj zUeA~<)_@i!k;W`J;&qcyR0~H~FwKU6qio@V&hLp%oWYF!R20mTJs6gh^ZmoHh~l^M z6O&*gx18wdb4&CXa{u&DF!oi?!_A$D!-jJC630(Mn9oJGM?rb2vD-gf_3Q1yK5E9qojBVsQ1@vnK-=)>YPI7<%XVwieUSOLj`&nLsf zQnNf2u$`C&8xU_-`1FI%4M6K^3W|OLThmxzxi1-or&$*@DS^Q*WifrJ_>wvnEcfm z_fF@^Z=8T-e3}1uA#-X9E9utmAQzo~bS0V2*ifW(n4A8@yl5xRnEuO1^uQF8|FLRK zNxXZOZemHkRb~T4vc@q;*nq-gMU}_?IU2*Axt?^BVp)%0aL|W z7Q|cH&91iH^GY&=qSi^T!HtdS&_e~nvsi^9-XLKSzyI+K@0f;~u=3)kAwmO1m;|!K$Kg0lu0AtRQ#a}DS_}p~YXrURC zee@GvJa*Po2hKS^7tfsbA7@Fs@II5qA^e86VhVzExsKoOs=!33@i=r9MXyb9)C@FV`f1$w9dtJck7;t#WIYl8c}9kaf1g~L-;N}Css0#NQRDue_QX>e zQOOwTg@YM%oJ{|E671V=CO^Ctho-XTgI$f@7K}(EzW8{d{seOh`~w z1StV`%Q>{7NQUr@zEoI3Fbrg-gY?K{X{sx;s6O#8vZ(j@=&l#tEIosQ^B$C^2o7#IzhQ!CQ5I|0JWbdC#n5gKe(4$YeK%hq%$5WSVAN#FF=7Lhd41O!$(pfOPaVryN<4VC zZ$=|SfssISrU($$H?++wFt_|UA4?j=of7PMPuU)tgPB`n$2-26 zryS2y(s%SYlXk3Rd~0T)P_&V@+``~{J9OzC_2%(x`EGs0eZ#{7JP?|jTbP-!?%-2R zbt@n!L-@{1^A`@k2iwkGHqm(Q(g#Ez@*;+aF-m~-iBgQ^i-;ym5NFqJ8Dh&96J6ac z;++H|0xo>Ccg+ub)Da@nM>o1q@SRS+Gkz8YWSJc@BUl%y131fJoG^iy#MFIN^&N715 z;iDOL3ZMB?qo=>|A!0)5()99g&fxjqHs)86=^XitAzuizGWT$1<0c(N>2m?@n*0%R6Sbs69t&dle}PJ;Ei#-h z%7z=7|Hhetr9{Y9(Y2g?Q-GtO%MbckT%MM1wdzl5~ta*RR4!@|2TG`EAPm zx3VzyqvPlnlUa-BZ9Z_n@@Z408l0aO7-E%R27o;^Q zZb|D<#{o&OWQ%BW^+2-ceO?G!V?-7|r>ezjW&Zu-W@iw{V6?~lGebJFS5l(nuf7x` zMB!F(p6_J9tYVm1oV{p-$Am`Svpk@93j(;a@*cH#^`#`ym})2&6Xg2n;#}1u?|>Vh z<)tndMLxD4ML(Xp)R*$Ezhj(r^M?6%IAZie)iw8nSxKNzFq+QGwF{ zkks=X(VSuJ(nXYzM4wzE>|;es%Xl;B?e}egiHqAv%KaPtU8uc@BNKEtSO&V=($A-_ zEVx$0H9^#9UG|>0?xHnJbm?XgcW#gm@JF~_&U_p_5OzxVF!LjIMv4NIi+x}YtY_GD z9zL6R*T1%Djc%XamR5JJ1*%NrdfNhkltHxebAt%DdYxzHsiIBY_ohL!mN3yNalUL9 zN+1ZL52d_sBHKE8c4en1Ge`^JD9;}u6XlFd5=frlG|RSHRF@q3Y*e)X3uqX3pT1#F z(6g6E%)18qhUZf%M#i0)3wQbp4QufKHnT0_A%09%V#snCFrW50I4gOWR|+;)`NA@sk`P`+KWuov6cN zfLJtquW6{t-~@Za;6Mc$5;N9gzHAYSX(%_jQP?r?;=vBCpy`4c$ea@wjWVZZoNRU# zezT^4-NTo=6q%gl>>3>*Rst$7-SsTL@Uiw8a7B>ywEAu62MAI|+_%n2V>2B#z6#WK0pGv1t zbhPqI7Gv09o;%3nLv~hUoe9zqBUrQ2^6d$EX0YW6oBF2^Dv>KqzMd0hQy%VZ&18a7 zeHui+@H2%$N^{m^_4_*(Mz3(w>M%vJ*|LqROX6`vrQLg38#!`!zKQ4Q_Ijkzsnbbj!zQ^dB$1zZ#o5TC zT){{&WRLh$fLuY3y|jGe`-pQ01KpdeTBOY*5{>UX)+lWW7)w?vBY97;=nlb&J`F^s>(jwlNAj8f~+J(CshS-hsVRQ(VVo5){sY*KJex-q>-eLAu{%Q(fxjLub!>QlR?g$Ij7z%Dvd& zrjcUUXIcd4+Cn!P%pBuYTUu6Xx`%nMTaWN4a`sl%T#ro{8eoKUO8S!n67JV%+hh`Z zn&=h}V(`r(oPPipU4C7#n0fHf7`V$%1!S(B7~vvgW3uvFR4{U8W+8iKcs16KQKhYs z;lVT^zJse5&tbLU0K#V-r1j!@j%A+YILM;>3*)Tt%s>OlN!mtGw#9-0|1;C6N71*Q00N<4!5QVB zO+x{joRL+#&c@K+j-;sk7|m$iuCB22_KWL@J2yq)|*6vBqc)Vu~%L4!Ga56is9qVfN_`A2=dD^Ap)oD&1*Tpg0<0dTE;UyW6sTl#f1rz~E z4i6&OjMur_r{7anJDz0&g{{#yW4f=b-|n(7i?{ST78EZgzpzIsP(G6xBrE%ScnDf_ z^X{>th$laAOYqOzzxx~NOO&x?zJ{m7x$FON4jTC!z`26Zv0SmvaMJP}WmeK4@j}ZD zhSQdodY&I=1_uSa*T{}jIDo#w?JMjbyU~8hb$oyRjL9}Xn9ZlU)cn0o%R1Z{WUKob z_KCv?z=|G?wUD*xf4r5u-E4|`*w3i`Jy2QGFT6;zuOx2cN&|pfcP5O4^&fD(lr;E! zv@s3K#-}Ept1z5fT2;mqu%S)0ix@awd?q|2A8xP><#u#T^}2a|V!1;ZvGtVE!dfog zRnyq0J<^#@jdTjb?vUIh&ttD?PLhIsj^ng=`$PSj1>1UMegiOH*^fo#ESDR`G3=kO zAtweQV~Q_=-W%fsAT=8CuIqIUo7)?Z^`P9((aVB&rkCe??VW+?QWf@a(KX(?fdH-0 zt6Z<&4OWylFLF}+YpK6IoX*uFn@KST-P)1zfqzHOhJQ!EX9G9>Ky1|XmHq1H)2yD)Pf9?(Uw%w8##@_RBJTAs1hVqGH2Ch=jtHW7}97;;fnih zZ>x!)HMvuNpJibt$7qD8t{#Dzlwb_`DmT4+QQY(asA=zNeyfTnxH4tNmy{ViJk4A( z?}W57F#^g8V?%rJPcp8}=RkW1*J1-8Oxom^+a^f_thMcVJj*r zVL=@o(01au_pww86j~(9K&p)x#977(^1PVbD@2hFv>_`PhxE1tTjjtj)iR|`9hQi{ zaB5H+Nk_(2wepp@f-^}A$NLvQSGmjA^g`|jC88uJJ^1!C17_F~ZqUY6unS~JbPW%@=G)p{iMO(BWrO1eEMXnvIW#TCP!{cvOq z5%FslCflP2rxRn|@63y@9W?bPe4k)lv!?3Y(6t->^>um8V-Pn?^Rw=(+_K9&#(%bU z!Y>74xRk~ig8s9(%`li3o)}&m2r;-dv08Qe^H&?lbJ^qG>+C3kT!Cb)`X`W+okgY7 z3q&)cCtPMZW8EfN+;wet8V_j~(_!!*t<(s=Xc}YQFwqqKRZXYt>tGZ9uF6DMHdUFx zrb|bPbYXmvwXA%Y7|wM1*CG{z&Q2(r@hpM-ytociVf@*nOP?6ilfy>Mk(LGfGb}-9 z>SrF{G^yFM?V02K+}lp-Rc@-j?r@a}TqiFTQC187ay8rTkMlBv;z93|?5qEb=B5~X zO!X96{TX|gO13|~D0geVP4;^{7c%dALb~q-dsfu5u+bg7RF?p-CQm`PX;Vjo zv!n7*77BJz*#OwdPYEts@;5V?4}QOlYG%aT)o2^YVohXaBoej@e^X7vVfX|Hpse2h zS`9Fh!#?-DXuoLJdA}{7(=@0wJkG4(k@*VTp^v?#nE$!@JIfLOKq%6U^y#-5L-B1y zgvnT*{mXOJT2V?eF$mpL2Cn>z=D0JK;cIACV|q%S*Xf0HvT9^K9EFE_0cW@c6+$&Z z{SGD;Gix3?ii?w2))gRZm_V(FulaRa9jt%Y(u!=k^bZSEJHs21<7qiRjc+=72ox`a zJxFrXyfT!8D282Z&AqKs9;hK5b+Sw>==p;j&lR6|$f`Dt8wFCv9%pIGjrsZ+ z4bNWZ2)I18g_ByZ(W?Ig8YGy$`3)HA0LBQJ$cyz#V|sK6U@RUzk9uKra#lE!DMCD$ z&Wr)+Z_o0SZ+uR8)nohyPm4qP8vU%uN_XInob0$gml-zNFPW;|G7vv~rpnV`t233g z2%yQ9llS9UUY~hm80-&o_#)Blt)X)oW)DngUKsMXsNujqhH>wOQ@GuvT;XfXAf8t` zbwqILZz0vS6sCE@nd&VK5lYE41Z?~D-AsSfNr}vCy6*-CsDX59C`a{8z;?5kwWykTCXl) zw{S+Y?+hJ1VMLg0`#Hn zE|)*&dyE=;KA?|abDeeLQLC9w(-1vsS{XR~WCcgKY>>ich0PeDeLvi>@{H?fq7Zz(8>&;iz{&@{KukYv#`|C&~3` zn-V*FmN!(T{}rd|SHHcYWJ&N{-04aQ)vvT{x!| z3-wRBDws0RP9r?nCL?SKr!C`iSeo4-EDBbD(8>pVfnAzw>MlPURzhYnTBZ+o7|wl7 zW{3C^YZZd~m*;Zf>~AOoHJVHU&|<@nNL2^pzmPoZxEjUPMB+8PFP-EQEQ2M?b9XCL zOt97Z^JJ*ETr%oX5zWj@tsO+y|M`ovwp9@dc9?4RMuYYNgBPS_`E{l-J{p)8UxH2S zUu*HgUd)a16Sf3b=khjtl*dUlX~1U*hp@3VPXMMOU4K^38j&7L-H@5r!xkBb^5_l7`)6-zfIxUUd)wVrkpoF7>oreCrKcV zSv-^xHJ!hu>Q52U#dlg0j9bF2gz)({KWDBh%A%t%#V<2tmCC|{MT;VB^Ig&+SR!YW zLf-A>w1DAudh8ukkpZ9II84=+vWgj+F4ek2HkC??9DH$x=;d6nQ_l0?A%T^iO^^e=8~k*vPjsp6(x9PNa1k)*B~K+@tSfcJQrCp=1E_MizM#3>Z^L#dlRFd?S`!r`W_ z-1Ke*7pfD6T;s_)&l=Y*-!b2}WalbkrtFqMvD4X`aD{qtF=HES=%5M4zmeB)t zkT!1rLk68+Q>Ip9qQfycuTm+`2(&xh^5m_&@ ztGh_~zvj)#nvDO+YlWevvQD82GM%qV6ywGAjeS<2yOhL{BKnRZDZS}!4htf9@g?h0 zrp2e8-ecSE2ZSYG)pi1T-dsl+%uF)nh8gOAP!$zM|K?<%-%OrruxRvlCT*^f@OWO& z)xW$nHYSj94rt_&UbpwuMNl`Aq4C{}lcXh>;o{_ncC*_Jboj zX!Z#f(!{vNd%BnPnI^s6Ube-TfkB!Ut)%d=h3$%Z?a-*{%Md%RzI*a#3=M5art)^K zAoam(VtdOl^z77z$&62bQeY-@;jX#hxcBP*fYz~KS7HO{!P2=>ICaK%)-Oiqo?Ya% zYr8}2an?xeh&_2hDw${Y+FKzW2IXc4B8_3UJ<)&O^Q8$vP_rINmgU7$pcm}<#(fWB zd>VFQ5@ z0)ME7Gs^xN`x>BJ_Pz`<&Oe@MVpm@-BA-sp49wGIAF4tGKdwateg{0QP32j}om|hzS3|_G^E@p_T zdgQrx87%PTFZE5-mxt{dzTX612cWW6+K0$qckm<5>-sH7=COj#mCTuv`%U?b=EbY5 zn>J%;J+}P}f$v36Q>pKZMuN&;R&4}Qt=@Jh$k8sT=UT?)2xe08gI_VYSm^7n^0MxfQXxQ>aKMkhht`2FmdMPV$nmyLEelTXV0gmF?N=x`{eOFvz6|1LAio*2s~&m-ap zfhuRQ2tpv(8`=rE{Q>62>14wiWk0m<7tZiQuHl0Y<7$8Qj9-la{Z!l@@P0s14ZLbj zP*9cT*Y%g#hA&NPFC5@`NwL@IN3xOdAXsDneg%pDkr>wHDI@px{Wcc?VoWuJR$}fO z^SiL~*HKlALIX8o1uD()dg%VssMVtL4FZQ%rJqEqPkv$*c{nNm&LnoagRw0kg@y9L zI;JJ7{n3+&yXCO?A`5rf(IY)wUv9tL9^ma5980P`ux27YQk(n_awZe@Vz5;ce`#=A#0zf3t%I(u@1O!%F5ZK3xjQ|_ zC`CF%n{iZiZ7bKwyDZ}T>cC_9m=rgl<6whW$Yw(|*SXdCK$_B5fj#>f6sRc1ZMvUC&3@`Q3F|lbp&a zbMiJ53NKD(-b{V94!Ex|e|6*ySL$xrsEs*V$r`or$m}XvmXe;ci5zI}*HUIPI)E!`p!9^9vO@P7Kv>8e+&0sp&)A{offyMQK8` z4(U%F1PAm)pKT~G&G379|J+)|Jb@%DW}*lu+vRcRav*SvGED0~Y7{VAZ$|Oj_*}Y! zCNu^b@oX%zB%#>Az*JzexMuo5EE%^)XB?j$u3M+vd-X^c_^H4E--{%cFM@TRh4YS{ z;m$*AC87NL%cPRazhp6<>9K&b@a>K)aJX(ilC; z9dg%NkN=|kMhflmoa)qS#GiB>GG1ZJdH)oK(^Yfv^MIiMh zB-YR*tOJ-gc=v=bn<7mBkYhKEYBKu2602J1(I2%zkowH%+)3@32 z-=EMiCMl*MuavGvJYOg3k4%42R(TTh;*MN@5++G)fA7Z8h+k{Ilj3{L^B{D-+cp+= zb$H#Tm=jPpdr7sl$j7iFsvc?4^BrGnVK9T-YcH`8)+B}XmRZ;m@dAf&$=~a~NJ$tm zC4!mzrZ+b;Z8tC%9_`1-)hl|MXE0#+E7OY`fSBQ|;cqvPCZ75R>W|X}a}OFno0V}K zhra(1iq0n8dr0uWVew@v*lO`00P6t*Yah_jSGei-FL_}qj;%R5+i!G;6nDkVlD@4N zcL{x-GAgal4>IlG(BEa6Y)`$F*sIvXshXuuF|#Za?+BW9pK@bp?B)BB(9R`js`>W& z>RYYNw-u{s!rE)m@{m#+LF%d;d26rNua` zm|CK~m}c>~jU6)=3y>esacU(b*_n>rBIK6CC;f^JpWp#oRbqU46+&zrqS<6c+O@T9$8kK{Hfv8c7>VO0^=MP=TaevzQC zuQJKU?ogKChU(nd08B#Wd;FWCk-6Nzy>cM?e1oBnMII7E%<9*_G46i++?%$||Jg+} z)KD7Xo{wdZqFq-iD5+>jKUKAKI7B~mNO`^L{hs0N`^`NWh|t*cPa5_}Kp_AN0;X=h z^#saf14xmT1>C^P&eG6EElK;ratE|ce9k@4Uxa|}T2%Zha%pmH0YIK*MoGr{?T&Yo z=+WcF^sY-++aN*ab9m{`rbrw9kpnmwC$BM;ZxZD3DgWa#!9?y?-P30Wfo~S{#k{@Z zC%13;E0kLewj<&V*xC|{=@-ktm6DkakA8whxBb5IPo_{drEe@wr}8GXGPObn zK*e^G_m6{)752t!oRvb&58c+}#uAL5I<8Y!_KGY*PR1AGWcO~tS$8PsFa3?{T@-AN zV@D||eD{K+m!+8({i@QY8hTkMb8iMaVYhF01Po zQ~c?kC*H43jp~A$^3@Xtn_C&C1mVnc1L+m4X~h!AKj)`Rj0-WoN9c41LureZH>9;V z{vO>cZiC|FUC1;O?1_B8^i6fg#O3e3_Ae@xrdWvTUYped36K`#^)7n&De;K@Kemu+%?^H9`+j-@m;GsBI1FI* z`wpEGZ2fwA?Hmg@wY|g0XGe5fc5=L@MnM?Mv5E})@6$VoDTqN@7PUSnF zZ=SJK=FWRQ3j1nbzLEP~Uo-#9wI{BPnU0%A`^zsgy>N3(OKvH_nXerNysX4~5#6nJ z{8n2i$orcU@{;DeNg7IuZq4?TsQgMhiFb|)UDK;cDN0x zeHMOEA-*ZC;*}^9bp4%T=U>aO?m4*7qd$Z_`md-%ht5f04=0(I#%#s5N(VSU))_TV zB#uIQ-J7K<1uj|33|c*%vMmV>1)DgvSf?pG7U$>`3GOG?3(54Dxfg|{-txP>35QH~ zicX|#;f_R|1{Y3CxuLQi&6#M;zZKezp9)DvPc`M-Vqy_j49U+gVi86Bz=)WUbomqr6{5-o5S*UZ{)jdU5+JBO&=onX{NrsDjgek{zO`*YkE-lvI zWuI3NRoGC<&+y&vdK~lTTIvGr*h1~I*>E}kSZ~4J_M-c3qf|PFapPg_GH#24%PnD; zr`pt&+mC^`fcvLO?zt~Zc)3>bUsd!+>;Ait05M!g62$bCIew;@;=oC%RGY_gR@zGC zj!ez23w<5x@h3G^oFsZ%H?->2U_~g6Mgl?+*0d_V$EW_U*8Q-$%!qF%A9nQGP`vI| z^PpX&%-z)(mw}9lq4+~{M(hIu6qiD;emWvMiM))C!;0c_F7@EU%=tP z;ujY*&>7|ej)xu%F*2ZTpvb()g!yOGxv{DA9v>ga=}=i8PRU|4C}O&D%-Iv?X6#S_ z?;%Js`Y-YA!D^sG)kjD82g5eZ!t&pSBThFL=vwKYo3gqS4NH;e!zTK3B5yXD4|0Ny zA6JO$^0zaGLewP6ALa+fx)Hru(Z$csy5~t2Uc}h;N>J?HtScT&qgdY!Q5ScYb(47a zbc5V41Z&T72tco5=z*F3-435@0cP^DqNW<$z+~aU<_BWSnBm0>g{Ps19pClcNj|5` zKRorfLJ0|xye+nM?B+VYZ$375D386f<3A(k=vC@o2EUSa zIYjIW&y-zJxz#H)9G>Q?8bZRU1{Pka7nmq3igf!xlD1OKE28%f1z)kaF~+Fchpx=@XK@$~y*Bor2|Tajm8>wfrPHK+c(jRmKvmG|w0m#eKYQf*!mnz#Dx zuNkfF}M_>?!>&_6ik=h~N34v5TVO(Hy@!t%MikN{5gA3ljEQs8=X6 zw3VJutggb=N<*?TTCnX806o^omj7Tw^B%!;h3?$3#F0C5JWWV1GUQ%iwfK{^j+gwT z`cemSeR;N*(~ctZO?J_MFPTnRw`jA|Qty6J@}zNm8=*Z&LJz$1v7&yubY;Z*uq2n; z66v9w-h^@Ji*yAwXNzF~NpX>O4n=uZ9@t`x(b8*Ap?(C93YeF(tJnJldFR$Ns_DeR*wH3OoW7#bffR z=a%V^0X7i|YoSJ4!)8Lm&QL{S#@v!4YH{ZmdijH6xY;Vvi zQ|p}!8CLpCe+m0F4?AmzEd&vtk%%ujbDmXD`4f0y)=4;Et$#PWKwn$m{6l_E`b%oB z=5@Yp^wo(x?Zv8Ef|X&hz1MyxL3A!gval>TEhQM;j~G38u>ZeKb;xP=QMpWI(jhdawq=1F;pUp{eU<-jB5rPKNuLegRy3s`)e0oWzcF)73!)zBv z4C-dZ*4v^`o->e>HhJxIw;$M?B^VY16XaKl{rmz^(Cxrw{ZL}&lAUAqMUGt?^RJN# z`d>g2R1q|0`b9XIg!^MKL$Ho)(3!Q9T`Zfa&zU*wc(mER3CuZJlcHzcFVBo}vpK?H z`q4f_g8WDky;Q|<7@a&vz=QlYWZ3@v$D4IvGQLPd^QkdJlywH)(fIiuwidyOyb292 zubrrl?Pl!3SJrr#{HDHo9ZuqLXbrl|fTEx;BY2S=m)Jit%~|0~#!RUDSd0vQ87ZM* zU|@q?pcBf1vk>X?+yjjkw8|OLtks4r=hb0gV?)8tAe%I)ll=7RZ3^%4pgo}+0+x%Q zOv``JW@fTgTofwAQET;;PRKjW zN)txwHARHAXb#qWCVVczN7Om*1gi*#G<%D=il(uP>gHn&^Fa-dSlct|Ex`jT7re5| zYgH)mOA8cg_fxjrbB<4bw1KO<)*mx&?Y;wt7kA+kk70uV;jxn^@RBB@%g^sVkN$z} zfBjJIuGaesF4s6t*y_AdRLhV1@pP|i)3%-ugWtl=cdpygpr01yvh?}!nZI3hVDDXd zk9{bPM+1}S%_h2ldr|bJoh{{6NRIlhE&t+vk=zb>lyLvqmtK2g{aZQY1a@oE5OnM9 z-t0ca6-o#%UQ#bg{M!A)xXOzyWJli;ibe5FGlP>xcKKq*TkkX8>BbM_ST|P77^<>k ze^&yChYRgl+&H%D-5?h#zx&*30Z+VHix=YKU?x<}8ve4mJ?|Hn1ScVU2&ghoZwpm< zTF+01a_^U(F_Upj=2;ta$RmPf2aP>9H+36bW}7Ka#>IF_*3>00K9u`NBP46w?Y}m4 zmo@u#Pw7@)CRLaysDg&Yd5Y@|=x&Zux zGSK}&&+?YrKJ%7Q+ZncN&XB}(FyxnN$1TD8{k`u91mr4s6J!E`eW%7GPv`q{9^3!IDcM7q!8<(U)PR*aF6GOrpwgF z#IGtn^3AtpFIz|iW7zlle89PLLKtspr{8`PFNW9DVJc^+wzL9sQy|`8;D9k%`n)R5 zoj&Jd1!|MAv&DrTFpjM6qYI?x8uHwWe+e=T7AyxbFj{PHEZbxT zjog`dOCBd)i%X?0p@F$%b^Ibvx5z^)VNM+^t9@}vg6+n!l7#(?ff)PNG7ec{!>@87 z?AR_S*uI4*a`_})7HsI$$=B%cyV2C;?DMHX9b>Q*T2#YTn!`yo?rX61N5S%cjQO43kqpYa2 z&NfmuEY;W!Hb+aAE_*2Lyg#j35|{U$Ww)-^@wKCL)^CsSRxD}f&|^9)gPb45fZ6&T z)S>IbD`1Eb7_Vff*u2zYD-z?UpsvY1gKH&AHDf%4&qeVN1Mjo!86&GBJ|<>H_Rl7n zwA1he*KJ5_gdXXM9F(zC*lmZ{FK&FOf3y4*QeMEb6~!{U*G?iM`PIZYv_wG68hayu-5tQ zOqXPKxSidkozLN#^9uPxB4?m;Q?}B%7|Q~vwcNLTZp>3)#%n+=&|h42#flyu36GNu zbn8hPWcK}Lv-~kqS%S8VMsn@ILNPy*djWyhJc%&Me=pG2hN$;9jl?} z^;NZSi|U6ZKEYvy^Z0y|z}-NGN1DGADQmld8*=!$d>0mWle}7HQv%ZpQjv>xpIhZe z*UpZAs7TzrU~OK|bx>Vp? z8%w%YUy}8=K0D_Y$G{0vX4%33-kQ>Ifr33yA_JdgcMlGZn^AtrT0f*cv0|&kE^0(* za_CKke*gl9mafx5Szcpfuji;b_2XM1;Y#NZntH(Enod_RzTAj-O+7aw>00FV{{THf!oDchV*!>Tu%j=N z>ViKiRoyBcYCZkyrMeKe##jDT#XJj-qy8Js3S;=En<>_3!#Rcya)!;w2hQPe>dROg z8&+>-zF~;Nh0ZTbQO8Nat~}J#Kk=%I>iT(Qv1?QE!2$Jrm}a4mLd6A$6?#~b`gJH4 zM}GJ#KYH6ge(3K@Yskt=OC)s7#l_o&z=B>*f|)slVDqO=qI&wMb2>dqW$8H>IQLQz z^8@)%Hg)8=Xa*RzU;vdx%Y$j(q{Y3|!rX*mf}MZ$a+I7)F1dW8=$yBKARG*=`VnDC zcWdF$f!Y)L^x`#e>(I|+B^?&(u!fF}3Ew>W;4y)Tjffla0 z$(oG?V2LzLD{n2Ex`2+pEXv`U_uVYJ>FSXTr{rfk3~=p1WXoUt?9R>T0Po%LfsLNW zwy6&wsyj<v(#Nrkt`9`R$TuZ}7rZsHs&|zz zH{lrKM|Q7a=dLYvN3?I>-tCuMa@ozI;~W7&7z94)Kk-TDerZKNcK;oieSIHVfway` z_nF1Qx<0V#N3CIm2-r5Vd2B8Dt1EE-1<`>*ms6?*+9A>-%V%V5j+Yr%ti4IMk~poJ z{av5R(dK*tXkRp9@qF(!>#}YB_c$dzU%PEHc}(GsdK$v&Tjl6TAN{@^>xbdZ+!5D3 zQ{HH>_;mwU+=`+js=bwn{K>T{Qe0frALV&QeN&=Y$)UXUfa1x{Sd^}jdM&N`ey+I9 zK-urr-xkDg0VI7wkD{Yv1DeG{!SF**Y(z=tJU_Glam>8Fzafzx;-Bg0TPvak1YZX2 zW|1B;>y4lbs8-n~@k1h~MO=C175Ixk--&(C?ZubA_=T2E*SKlpN3i>Qj|6#r_OqX9 zYQA?V($D(9e{;IK%p86kM|b>c%S3vJbcs3sz-FA<{eN6RhEEMv?f?3VB8&uM7_J^5k+qpyxW3P%d%yZ`VHf)6K2uDRyj`0Vd~2CYD*{pnBtW+cvUx^Y7w+~>gH zsI+uXeCyv8?&^}p>F<5PDb_t7w_W?0L&G5IR7O=f$5TXmaxH0X5B9Lohq*3r72yaa zj4B3gVwxG!*(Rjby;|Hzjq*tFMfrrv(8$ZSt{mmWU;gyYwp-K#YdZMG=r|J(A^LJ8 z%9&UH)x)Xvi2A-z(5sJOwYW-XW}bn#hN3EEu%C;1fUqpOs1MU%QGAc-j|9QGhg(N> zjCAc7sTK(Ja$3`8PaHurNPp&LKR-_pEy2Te=o0qrduFHjxeG+01Yb5aEa*~Dx8lpD zGF_7!g;<{p(l=cG*^n0W6My@A=mcqEonvMjh=85%|H?SzTe8sb4Yy!c*ORU?=`vof z)dnXr-Qvx(BPk31KA4qpEHIj!W(tDsr@CM@y<(K4i;x|{~JOL%_Y)3=H4a}-3& zkzX$@E7Ij<(L3yxcVq z)iAd7)cB04qAre=C>wK^&ya>r@g1fU#Zlh?s1Ghd-rjv^Ge7g^>qkUcMq<(H8AlY? zjr!I=6}&pS=njsGsp7t_!s~Uf)||2@K2Mf6BD$3vN_?j0qPWJy=YVPHM`=VB_U^T+ zx5D+MFr)=L5azFr;mnKQ!O&M$x z>$(V3!^P{)xzt%a#h)sq85{y$D~q|#5_#)VR1X`t@YD~z((jL=&4@a=LwRC={aMBG zFv4PswCUEOo(s(nT{}0*1B&_pz|?bAkHO-!Z0<2otoZR|q|1J#z?%DvUe;ju&}^4l z)r%GClg$qllL9;t=0bqWuSf>M{Mg~t=@X}49nW-2sVsg2nl9Vq2@pgnVeAHU5z=4X zud;O@vEGwNYr4zjC7gk!3{-*Y2de!~4O>$rXrV=K277q$nj3_u3FB*mkBoH@ zQmj|JKIz;{Gr{y2(wgoD+e@xEI0%(3? zy3DRGDWY9HKP(~3W6=wid^kyljjiBeiqV6X=B}dGWi4bRs1YZ@46A*p=9xvXLrcvP zW@u*C+lVfs6|OH2Vh%`4x|}+3uFRf(J#~LD6`v66%@TejhagG?#}Eely2|}U^6axe z*dxUHI?OY%?)!dXUS^_(w5H3C8`(Iu`wOLTc`>mLEM@4bw^*%22%s(Mnv2jX&A^mk zOt)(D_*YlxN*H$*YMBsQz{4pN<9*IJEVjBw!kp>xA|aZiiC0+vPPCs97``qn`FNtQ zY2rE*%}ThsU%D#pJxwO-qP?!M5&FM}DMjH_Kk_IAbJidwMFvfbtJjhF5T!pXu~_Wa z!ggJ|ZGli{qnHED&dQR<0$&+yeg=dp&8JS37Jmd?h!pF7mB|lMjHAnu;(TiI3}&V$ zk>>x}%PctmDzN?~)_qgY{58smw5XfD>f*M)h6a_^`1m-NP%Hf zRIA5p6V~CsEb(xn3vsPZ!U&P@wm%SrWwA+mDCbzU?jup&@K`+PSB)OdbbU$Yg^`gR z>$~dhbMZobsyd1};LlE>8Kg@}HN)ENEj$a&QayDP1W`^{*G$uBG9P@_rGS{8niRi2 zyvjWIkXDOW__iCZ+of-M8LjCdXMV6Fv5f|ms_=V~;x{B-=Q+&KcBvOyN1-jVSe3^j zj|1i)$3$r@e&#GGMXhB^94Cv9Dt@@&(tLXl+74TyF(DV)_mB;kcC&;cUDDUL07Me$_R{x;ORW2(P%kr6 zFZ_LSBMmBz@F%CYLK#%5Vu~@A5Pj-?JGO^_SSZJtgqGXD@*Y~a8FQv*E{E8x@wQUA z$}P5x?tK5(N6~JW{H}&eEJtB#Kg^Yc`Y%&7Izw_GYAp}1{uc^trV4As(q7AlnL^wU z`ijtw$^!F&f<>oT&&60%guUnStI8y>RnEiAw-CCAr8i||wDG@m+AM!M8b zT}6uZ=bwLCy1{hSN0DY{W+IWUzrH0@`W?RMa^Cc^%=F@7_O*SssTzmQ^m`jY1cORN z6WF3|)2yWR-`boh=3MIGzSuF{w%;X~!+avUHZ#6t3cX$CnO8j_Dve`tiO)Df-zKz~ z^*h!Nd5o>`(%eTB0j+*SDz;1`^6FRd>Y_PvOEN6-VT@2(^k6vpNC56wA zSMlo#(t~L?&EBR>4auR2Q{6JpRKsq4d%CbUg|HB{ zZTC%=R4bJc`5V0ra6Lmn7wy3t2mm%o4dWq*)n#K%wMT&I! z_0TlY&jy-vv0;4!!Bmd~QA!x=s#khxJpbI&TZe})-|1EOF0nd{lA?-qiC1aAP=D&c zX{`HC|CHEXeYyBCHTOJt2wym4RNW5DltH3k+Mw0i3@}RiJYMHK zq1(rORJNc4unG^}sH(>p&0PrOU zQ3gbPTTzU=~!4p>a1T`om5r+|^lZ!kwl+yPgWu(^B?pd22aAbBWQ@2%Lzl zbsr51WoFrxxM8~5QL#82W2?|5w9?snRQ%o1NCdB-4-!cim^7>Tf}s_to_-yC#_m_i z77U=WXt}VypA}g78Tq6W-9*(J5&w4LBO5J6TGz$T>WeSEe6zUA-wL4PZw~ybudOq$ zg|?3j_)C9>s`z7z-UxpBRkRXc3iYx3MPIoncV2S-bZ2^9BGi4?^pPAR*M8>E@I#+k zF%AMd*KMEpxxfC!4ZdI9CB(A3ow8U^NA4u*FHeTowy73+hnQCbs^T-W%g2Hq+H#|a z9LD=Q}V(qA?jfQ;o0zdU429?fC zr|y@2=7Sf!6@9|8F0JKKn9JqH@yS>Z(JQ%_(`M_U5AHxZQXnRxxJg^ z2a-gWd=EN^U!9F+dI{--+lxu7MS6s=;y03)oSL!Q@s^zD+~@n#8$m>T?Wex9$CLi* zP;8m14|Cmus)@hotE8HeCi8;#-wEC+5Dc18SF5(9#z24ROH;1|!rBd8tG^@H6 znn9oD5yR*bT5JB9i=TP{^Qj}pJm*rZOJP2^@~WCJ7t2ztlQ1W`9*(Y_PdyLPx<0mV z??&kk(<#AT^{a_(UI#7eWydvt`h0=hUy^+7{a@KGth!smbwemc%c@UvWDO2|i535L zW{As3jG9(<+p=XJQ!KY?c@QNV&!wImpsI*pADeb|Sfq#42E_&o2|xQNOz>}VrXAJI zrT)|urKyHthG)OfQ$dTyxD)lGM^=(4Xv>Cfe1bi}UFQT5M5o{0oE9PrVtd_JXrkkX4)@ zIPdBYA2rHz&+Q%E_uSrf?Xs}@zHf1R@z9Zhq+Nj5za({kssJt#m5jFnK}OWu7Hwcv17#9}3_Yu-YB8 zRH)C@Pkk;Hap~LMfBt3Y8(IN^=y@1=@*^x3mzZ(108^w($eQk^l3`Kr7PpwbvoB5E zPwp>nY+_yg4VRg*-wul{w@}1iDDdQuVrj1jvJSFTl7!9JtLCWwivDHOH{Snen^6`f zCnrqtYofZSsNxnDYr83aqkUl%L-3p8SbxCsBFnle`pt8#<{N)CHJPrOSNH&egb-(z zV+kKt&{am2*56tD#$QLvsSvXW27sP*el!3y7#v!_^o|5EPZ;Khb`PUR2?e{HgI#pc zn~HXesa9?N>75@)T2`{g9(99Im+m{2B^j3g`p1tzSP8_s&#hk^HpQjQ-6RahEMXEB zdet9Z5to4oWL(>Z&^oVV5`T7UGx|Mm}TAtAk>#ilp3gg<72*-_& zCmFM%XagZ_KJT?JXzp3yv$erToytkggTboHne)L%Ur$=Rld_*BV>5LKfX&)&Shnjs z!u-N%9O1~bwuz}v39!MC6#Y;iBEoH~T;JqKqxA}R7NeMhp-GB$DaQG1ZLV`h9~vTv zMv<@Kw_~1j=rivdmcO$QZxOgZBoy-y_hyISdqd(@zbXjC*bq1$685(s>~pV8x-K_B7E>I@5SkV-hr~xzv@SGh2tKVLVY_3Cvxh>4}JSX z>t=w>LOvhX@ zDPc^MjSsn=Z^HUg{q0@U+=N&(r+OkQMXYlr<%G4{m}^~|V;#o14bMq5)__~{i%M9x zvd7b?>*3Y8*6X8=Yq5Ed$1!vXEf?x+<=Q>`@Z%GrV&?QZkOVqG%oRR@E@N!-`k}#r z$)P}Wi$A%I!ygtM>{(2TaCkzDiyM&?-YmEw4NXH4%|S0L*8Q4j=JDMas+sB1v-|OJ z`FHK|NVGqGXfjyNLcQrk*)rBuK9B7t&m8LgZ~D>F3Uz5s&vbhU;pC^Dhx(l38*lvf zhej(5cZBV|hJ7kTWNb}Za#>_WcUj*}kskf>+8|2#g;mDcrh7l|)lrlj(FN_1AMy!Y zdw5cmn|5$hENf}0R&0fE<{k5mL@k|ohi1WMEcPnmx_?p9+Lyt|=G8IPlnn(0^OL{=To2XjYeWgw_9rXh3D;UBdLQzFN?%&&d8# zYq~XF5$jsI^}U9L-4+{4yjmOtPfh9vO4YX}@k2%2`)ihd<>4SKna})jbP4Sd>dY5U zc^(OMf@n9~lds`hcB7GQC)J8KtdKl(6^ zis#)2#H0H^Ek&W&gr!Zi*9Rj`K)Sh{IkRNjzJ4L%J>hfa%cY+{@_QKfJm?P2>zF^Vxus=IH%qwg-6yc)3lXJ97SGM86`W=3u zGZNrDDX_IynH-6JJnDtj-qd0~(S*5?Ui8kCE5hAOPv*mwUzm3WZDGxd!QfA>pPcgX z-0M@=bMOoveZj-`_MeJMPhTW;lgI5Pq>NVe2CeA#x$xg@IH!7Cyn>~GId$$Snkcwa3Q}uMWl7w((fZ_zAZ42PaTZKAY5!q_m;l4E*m)mwlLOigB%fXiZD$$t@i#}|Ph$q&WGOk2bv$k#Ke$yoG ziU&uWto-tjR)(y2EOY;fsVbg*^$fnf_c-p~H%UI~4&)%rv##HqJAC!z%b3{lG5FIb z(PA?cQxzgwvKiri)e`#^qS9aUn1!gech~UegF6UmcfL`Pr$#J@Z+} zkKMU(s5&@x)V5Cw_J3L;eiw4c*AqpEc7;)q;DhqF#51`x#7%$o3rD3ZVV=jE$l}fc z_Xns_rogm?xA?HT(sl3C{xR+}+!-gz)^M#c?N%D1FJ?^f&PqW&$>7urN9OWB_$T3L?m zS^4E*uELq++P`$5f_GfF1kWG!@xb#_AnYtS`{IVeOE;5c*KfweU;aCE68R=z@f@t_ zA!B?c-pZb_>`A=7sZo0{UQ@S2js)W}#G4wq?hQ`jh2MR@5c0kh?&CF!y#Ipdvpw^{ zwPtp3a*fO4eeq=NPuADbzM619)DIk#e*+v-UcPA@x%~Jd=Xk|niU4CK(ty$U?i+b&Lz?GMkx`n_M#O$e~VtGPXBwxq0 zTt68asMwvMOGvG=@*LI<)eK^@YMULtZM!YawD>7;Bi9v%?7Xu~IOg&2jP15~+?vnf zlZ{XB*h{cE%#SYJU!=eKsonnvokBh=u#68irST}%;;oQEUAcC&%g1$XbNg~I;F_%w z0%T1sx*QOPx@*n*WSBk7!vyystnm;co_CFi_qaH&9M9F#HRgx37cC5vqC0!Nul6fB z+82ine+Pvz{_P+A@^bV5;z8~{@jy2ct;2L-3AY>ZqA+!#TX$*E27ac9cU7$0-bsf3 zImi)f!vpRDf0ptlVKK{Sj%Jt>6u z>q3wp!t~KYV*L!JUVa|_)R|zPhU)mIZmacn$$;8`97RkpTX-`MW4kSQq(_(*H*Lza zou)SMd~OViW4<7JR@JWYM{btcfiv4HlLLt{fx1X{zlC5*7=1fSb!$=6^I)Hg zzSiyP0y;TYJB$8JmN|So!sGHJO0QVr!>^u34;(=O#{c4Hc8;QpXq!-HtJhBOLywP( z#bFQxVMU5=X$_w_dN8n#ODp;GYX?z1RkMzV{ThsWe>8@YDYtfJS~lcP9_a?AigBe+ z);2qIw7M_sJnPC>PfIn%u-NS|oNf#1vDl7DIcBCDP!!aN8-xw(fdTs9B52F1ep2g5 zuOB0lvKk)H$?4?BkBFFNzBnqyIvZGmlMmgEb|FRjqIdiLT^fNA} z8b(v(9L~v&G($Vj)&AEA*|Ns-uwI6*vMRj6Dqi^P2LgY1ajowW>goj#l|8ekIw0T~ zu6F3gqUb7Dhi2HhZs){J-~NSBu{fe`w|-!#PMYgbI0rfp`*)7W;vPn`r5UcfW{!z% zB$0_c@c>{SL>lMA45LZZ2$Zw?7 zIB`d+kKR{0Sg4{4;q?hWPA)P&M7LOazoq`84RXzJzQ7YPI6np z?Z5UR!VxZg;>Gi3Rs6>m>H^*u0=}=s0-pKO^@XEV1U~(}1m|~&w>cxQyt%Z!#mo}z z(OrOr{Uwhq+d*ve^44P6(~fQ5h#x8$5>|5C2a!xgA6d@1`(Y%!Gxb%l1zkpag?cb= zW$PLvL6i;CWhJnXi{;pV+=aa}!tExV(E|n zyTCWTNPfWIB82*WsBJSJ9d7?MfA|p*W`qR--WLLX8skF1BM|W39v}XL;+{Uf`jdaz zlv~Nz-5(mR2H#s~A;J9Oy+d_sdbF}=AowCY)2@d)$%{wXrS_fNx?c;c`)w&C`+jZE zsio%*eibWuY&$WhdvrWlgb%WuS<5fBjqZH^&T(`Z?G@_er%udcq$r;}{CrJ}3sF8L zmjgi_TeOl`dQ9U(6o_K$VO1+Iw}wSBZRl3LWM`TdJ{xZQ*5WsoM&9uDy!7MY4d*eJ zvJx&>6K*fIv=(3cYZ!dnO@UyaeD<%=EZ)EpEWC1qu%h48)WA^}FW@4~tM(rWcs?Se z&~0+p`0su|?vX-xoO|p+v40Qxg!TRQeAajQ#o|`CqQ1eCJtfrTY&QS$+aJ11SiJ9$ z>pXdZWDtGR6Is6P(ZJKt;vTx8n3tK7Mx2BC0BT&@EEd~5cb8mGjVWs!aoWtg2VF>8 zg?iwpe(-TQB7F@AqKlCNTw2DbULF&|{PmiZ{L}1NEz z`h-?)vZklwwLtvJ=^K~+#J>;x*XJtOTP@H-q(wbo{Q{?k&Z z@8MjE_v#*(^*!&5FLQ-)wrBOG-usx;?BL|qzUhUxit|5Y4(#L^$~P3`F5h!ocx5HZ zM^68_BFL}Z^rQD2}abs5dDN_)_SU2y%T0Sg!<7bw1)DF#-ChBRa`(R0nDPe6z zc4%IWFpS!HGg~BPbi}R%9d%%8A2W|A9D~)k=*-SIul00jAZa?y`lqK63ic(!%0BhN z-v?hat-ihwGq3GSgq6ZvhVMK7Y7DIU5%isXX-frq$SXKI@Ks+dKYY}C?LY8;XN-@4 z*XB+f|Gl3H<}wd_-|Mb3RS(x8T{kv`&-@qAgUCUp(yA`b%^kJVXu3|N&p)3SjF}P6 z7BB8@YXVyxglbRM?y?egyXwHu+V-@LTOThauD~tmQra)nnZHwXn>3)5C?%o$%G8mu zNTB;OQk0vjPVX@4Jx`2!BUJ`(B|8;IN5hOeG*iN=%R#yvR!f^E1~?r3qPrZX$W_bF zn7wSa3^-2-V=K2>W+M)BsA~qJEQr%k^I}H%6X!{d&y)EvOPWMSk%D{h%|8|Vh4AT9 z;8V2;x8i6 z&7ziv8o#Cq$!${7 z&FKsocS}oJEG2AOn5=Y=Bb~53>b^$H2IGd$8pvPG({?^w@$#f;TQ|i9eC=gr$EFMF_3gFNMYVdajr6k3$Y3>f!e=4Olw8DY^uCxh5F8Q z+b3@N&d=X2-e~MlT~T=b!7UQ$EEc!g;7~*KsvkEBf8&oF@o10DQXdL%bxw8d*|Prd z$G9P~6AuV+Wc8S$DIXDA^AY8_U=zBSwhQ&zeCkh(qW+0nf@l{t3;7skCJqI^QlPtO zM*QX7*KGJK(OCpVrPFL4tckddq?tFpSh%cQc_B7!{7CS(fBykI{KzBth7j!!J^Tm= z;st(@xJ(|-8M?RHKlePe8o!T?qldZoU;Nq5pZm^-cM1W%J`&67d95#+qTM#@ilV2L z=;_x;stZk+SCD4%t&jO&pf20oUV<%A(8$GR%g*vY#8#e^&4-2t= z|NRdLOZ(oQ6zH|Ix#RERIdmD3Wuhg5MBFxNL6tw%Cu{|>nHC?4_U`9SH znVy!eStj$wYy=6-4%#daO2S%y$l_y*dQzkOS{g`}*}BarLnH`bf@BfeXyP{Pu@7i7MZf6;|~pS4D5^8y<^tC4?5<443B59&b~Y6(9OIFH1QA_kPAE zz$)u756HgLv;aP~dk71?G1R__Mi31X4ElU|ESMfKaATQJ+*nMbRf76WP`%-)an+k; zXhC4gI$ZmWbc|rm{DAb9=t`fZENAJ+wEd}dk~59DTi1Lv^UK92las}Q!C9u3?$Uo}n6>n}xg(XK=ag98mTd(-M}74S-4+C1=@aIa^} z`IenO{q@b5Cv?X3C7}ACXhtI-2n%ju9ul_Nu$M4@P4w4fEO)$G41GVdZq1Xod)XE~ zPgqy@M$%X7CR|I)4^8Hm7QPX2&2!}0D6TR#Th_)|CWNo*Hj_pu*rkXMkplnti4$mq zWlNU^`G!cb9TJN0hSD25CQE`|XPjSH7wXjh)$PpZjp(_Ck?9+(5xxH!#&H{FeT@I! z2ZeBl5bnHZg!{ek`|52sefvX0Lf_t;6;_{V1+m|HeV-|u6CYF3o(F3S_URW{B2P(KN*M33Tt=&0Oq9uyPI&B5S(PIR{wMZeVzj)a4_WxbVqOy;qP{^V2Ww6*tGRK%fV+vLxC) z(`V?@_Cc8lfko^3q#+E6dlI0CJ0)!nYhLl>2THeO#0~9FVR^XH(Z|QYqO_v?m9nad zsWYEN%gk~+FwJS?t5?O8C^A@TWFwnGVL?vrAVaI<8f_48zhOdftx z^eMITAuZ#B=e{La_NPvwI&(@W!YX)my0*X4A8ZdrxG+e<~g+gAq3M%dn57#XJh~EhH(U*0PH?gFfZI>zW)BNY!qUB9Q6UF zE|H$x$B+qA++0{Kejd^7dRRz}&)MxeKk(J9n5T4BsI#hgQuRha%v+>?xfJHXulS4M zis0s&86)a36YFx>RN(53L3!a@k5l`Y0@v<~uq~V0>ZYJLJw0FbW>i<=aT!(fOjyR~ zhNUPyH4fv+W0fD6hz`fBr?|jeE1yw+Oeu;oFD{hzu#TV|zfo2ostfg=t{*=v=Z7WA zqLw{8)?lfgR^*h#jALfu@v3wD#$mbT8sWBlnbF}#b!5BNSR$N$?!=p+<44f9>|79? zqk8JKNTf@oOUvZpr!*m+D;*);Tfu3*klKGr`>#yRz_0o>vF@>8PVHu3qVBxunPS^N zFf9Hyiv1f=Wm340ih@2Ug755RYx`%$G5Qb7*d6yT=a|g-Ty46isKhQa@xSK2@Old^ z?@`d;Qc|Cy?0H0S!N)y#o4)>muZ&_I(_xD`XpYl)hHf?A3x8(P2%(sZwDoXV#ipv$ zI`Bk~91H5`hg-rK0^6DwgVn^U9gFd6D}J=@h@+N8xmj^*BFP$aXXq@5C2jLK)w+Qt zTry2}8uoIT);m2sPYG}4tNx~8y9UzI;jo`)4u4WuYnOqruwtk^x0u;euO_xND$*rh zUq4#GDF~siJ@irgPoy+k4gP|4A=cq}LeP1Ea1WNfJngzJ(kG{Y)NdUW(*8$8X5x?C zG4|irk3(A9Il9i;&fwkrqsKX}Jk9X=6&y!XnymH9rpoqkxt10jycua4%Sqe7jnSUbuOKRyBSQ}1d*U-Q%Z_Zn7n8!Tl#P1zO&OWBr{C(Bqb zf=0xqEnbmjXl5JBu`TUJ>WXLEUc|9CdhX-x(xTpf?rIQ8R-D!PFHZ&(^o2{-BB3q^ zljbae@tc?V)&7IoT6`hgQB^jwnph8hD|G=MTi>NXmjgn*nHl65MCvGaqx$Vzwr{o144~Gu-s(|VX50qOS>x86JkDk ziKK{j7RRXvv}HEIeQf#0Ja%<4>8wRv;xlnU*G3)_-NWROnk&o6eY*pp9>82T8Jnft z-U8j7w`qA-(=gLBt+C9Jr7gZCt}{H=iR8Kc=#GF0(8u}K$G1p+! z#$oy*wSP3!{^j7rYAtRo;A`a$K0hyg(yg?%{W};Dg&L`g_B|r#D14M|CYk5{@WboH z5e%!_t{2VdhfdZ6`#&vp3wGyhEEY_^^JvzVa6ga5ygGYKG;>TH@%(ldpPbsfb3<>< zf8Tkb?o}TYkH;j`OHMF-;>6*=o#o`dJ@9AiE-gVLQg1*^*&c1QXklYRX8&)wStLGx z4SN`MQ=$xNM&S>Ow{c@X91jtyU!8d`41yRp2J3y0S;}SX*NzR2`-G8>>sV9MVkr+d z4ECFu?Z9EI+wx=fJhk)dD7PBUag&ISU#kb#uPr{a+?V6@re7HcVQ0ypC&W6#i7AdU z!8|XRmH%2pW_2z2}mo^B?EPHsf z3D;fsL1rvi!!mpRi3b)W&xM&DkbZq}mVRx)h-0f$EgXY3ZytlYJ}mX_Pm@JG4e6(T z;^i5%l9>}PYwJ>kdkY5Od40k8t%|oEe%)uiZ(tEB{qYox!E7(W8Xx-0Rwqvcv-z<8 z;-+a_gwyuEg4%!AxBo<*HsUf2Lk>pusvCu97gk}mQykBIs8rkT*FJXV#-S>vHl~HS zSlseIdYIv0Kk)a<+!ppU(q?gq!-ThK<@#o9f>-@}7BIH87yQuE=(td4E7p#apL%%+ z#retS9}m6;S{n>%G%}XBd&G;d+(?*dK1%Do)pgr;69#R@gD{RZi$YqO=6>jL%$Y}E z+*sB4iJO~wHvtln8Mmw($84J&LaTEa`_%HVdNu%5y+ZQ;zKoAHe0C@gp6Yo@1` zS>2(OovHODAl$t9+>8WK_ zca*>VC+~m8_NY7wh62&f#GmhB?7!bAjh6Sp^LMsGv{whGb9*veFkQ2-Uq8X{{Gbr* zOCYT5JXhSbDIeo7;R2IS%zL=+-&LKO9_=+37Z;tks7vHXX=H!SmS_#SI6rL6)WWit zQ>W50ZXQwGJZ1{lcH6$Zaal$g)6&Eo!!)ultK2MS+`Q>zo!_i_PFv;~`K6`l+LkBZ zxu%yD#~ya}_$wgXyyd(F_}2H)GUP{&RHX0@Mf%UY^E{k5GmBk&4#eSoA4?YY;Vl;~ z352>0zu@`t&%seNcRf=3&!6vH)60sJR;RA}nHh(t?H9tCuNR_yTU$gs<2NIp){c-a zF+X&&_BZL(M7#Vu*w1ljfZ>c6CzxyA^hlWV#~EWgXV0A3L*hJ1IfOd%_kepO)Z0k9 zIJXgYMvc-)$2wOUNy~N|d2U8!qtRo|+Mnm#HhK+|x&De}`js*CpR*c7lC^IdKr4|J zb$vs8jsC@BHJ2DwF!1Uu4jr8o`zGtbIsDmaw31cc0Tc_h|8g#?Jq3%(LNST?|8;T@Vk2{wjWr47s5Cq)VOS|m5R4# z=G5tN66N_Qi$$IM)Z0KfAXJL;(=R&8(~^Y)NM9vxoJ(eEhA$a zGQwu%WsBn~lU!v=9b_Ggam=Bwqm~C?uPc^uJjlq?l3wCInij{zRi9bM4WyqtTONS* zRkeBTMae7aYvIgoM*PHjTKQeaV=Je6t<;vMkGw!a-N9SV>u>9TQolMAxUp3F7i!zI z{Zpq=8CX>FPd{@aDfSCym`R~d?cct?``f=p;vND=x{l*chF>qzTn}EkGZ5__?puBP zy*tqaRd^%zbJQHt;=Ww@e8F|cv1Rowz3pFK1f>w_fuH)J$H&FuFo?nl27~T@8YlNX zZg*=*%vh4>@hyECGdf4L(_u`|6Kwg`m2bAu$qPgd00&B@uNXZK9mY zjTEq-6Ek_WUbHf1)K}WMObg2$VO(i2%XU{9T=`{|ZEAX`AD_7|Q9p2F=93l{$~A1; zr7bfd)Sm?5=DN2mY?)B^`WFR$>84e@D*C-@(D&JKiFDRCfWF0fKTwp-mELn$B&TQW zhW2l3qm8tG+jgFkHc;;N@7kp;8y#kphq9eHmSIWDRUdlaIvj|0&Nq(z4*IG}u{T$lE zhq=$_RpaBfrROMrB=il@s2zJ4UMY`tmI6mTFjv{Rl9sx^9!9NO<~RoJ+EB}&26x1< z-6#|HHEzI~PO}Db%+<&^q^*1!r9#j1w=RS)@oG zJohaqlItpug4(}Y2F$zmAFrDC52ZdijJhzx*0(2SwMnVlTH3?ncy0rqy>0Byn?{8| zzDGR0j=Ds9wYuO|pf&AKDb@HTzxL&(+;fPS@(A_G>P`%L+dwpobZwdV{@-FsSkbw# zAjRECqGwAqPp0(#+}LCOt9KSmOH&P}cYzGHu1Vj{>RlPLbkA|h>V7>5{5_VyXrD7FIVE~X_{fxvcWh9_G^eK z<>1zE=6Nx5Hm8H;M&9Oesx@xjR?RwhUuWtbmN>umbC*mTma@v<)6YGMW$*ZD5J}{R zk3MkKVtn<{lV}BfOV6wMn;$!fxxlCk7tDRm z?DtR>)r(#lvph;!I2+-NjR?_>u{(cmyV#m=jS;Di==a#-5oH(!Q5Xy*f**Q(O#BRk z$V6JtkL`V=?%I-^u|@4{!*%4`W^2UE5zZAp4P9j0J6_v9z$`;7o0EB{H<4uAtg->F z8$x>hWc}LW{uu=-TV@9_EY^3S#c)*Cz4?|u z9R*PcW%5y%XZJpFLEQ?%iWKCNFTa3eLYzz2mZ0+sT70s*Gp#gn=TQ4BuXOjbelbiY z$-_pT*0r!Gr?fCN*GV%DVC$y2l459yF!zOBK7w>%LCqtKtCq`F*7!DJD_dMHBaTuA zZVhW5ORc`uFku>64b=-1r@#_jzV$st5Frd7p658v=*X3DaT%f2jhZ*K@UTvHz?CKK z=2L%-8+{HM;q}0xx4P!F#*MmH-~NVfxMoh=h@0GJUaJ5%Zm~RZ&SAu}6NWvr|4AVb zPYdza$`9pqFYkEMK=3C8d#jMHEB$A$4wj{8=hf+&@4Ebx^Q+50IrubKZtd;w9QHbH z>iZ7n(*8NM|9EScw0|{p{pg_{m-<#CzV{}NL0^syPFy)J(OI(I2NTCKEdJTZP~GVH zm2vK&rHGuzFC~#)DCH9BjO{Tmd!jZl^wfc8aN_AlP@S$@&+B4a@8QEfRb7eG;q|*f zv?)wO38y!DmJAp442UO&iTvr9(kHPf&02a)OD>96e^`jpFvBJ;1r{HNnwJxnTvyXo z;%mv618LRcB z&Ocn%!&zHsbZ(h;f8t8oaWYE%MdyR*$794(tAU&KoJd1ij`k^{L%mkb@ErDILUOn5 z8a=lATUdVW&w;RW`}ITk<^S(xv;!&H*JPm0pX>UCH$>_%2bV_NZm2(V z%oEq$T9a@sHOQSOLs*|bU@9|H$a<3G?l6pN*!~OA6)Vn7xoNDZR<9o2;ZV#LX-55s zeoBZT#q&5^ca>~&w|<_);pC{z?VDTCY5_B})QG-<_OQ{*a!H}Lz?nt;F&<4Qq*4SLwstSxM%ZS#b=%fq3Qf^xJMas@d(L@9MO>LVPDu@Kko>#*Jcn!qJF zuxce=$6sV&`c7-d4sEHqU9*&OPGyo>FA*Dk)~e}aSi=2hrao(0bQ_1TZOLHhm7?MO zhVc6-ve~Gf-*kKnqT2NrRkVKxQ|pK-u!8Mi#QKd=l`^bSdJ@@r=d+*4o zhZe`ani(D&)hT|ze+gD>Jvx9UL6;5Y-WQrBzOC~08Dldgb;11PA7_&Ex+O*dpIPs2;!%$ zbNo#$U2$mQsC~v*Cl}7#w6TuhdwE?^49>3~nlUKTR*o0M-y0hFMS|@0(LFCIzUA`v zxXVtFjqmt#mj~I>wMFZL-{pFmEr{m*G2U-b?q<`_^J|AR)6Si;W%z;bP!P2qf6B8@B`7RQUsDqoN%Wgnr{nV9hJIs7#DqW7_PDJ^_M&!GGK-Y zzn?wU)Lu2|CJ0pD)%fYk_e1%qCE6ff3S~8RLRh|E-K-p!bwZe(KEgtBGLHd z`!kELRmhs@1CB;wU5387zSRO3Ne0xr@#jsQ7kW0Yye2T%kDI%XjKdDJT z&GR0pz(Yx6?L#m3`U@4Nfx#!Z6|F9~U7)oDQig<$5U40`u0{wtS0+VNNeq{*Hrl5M zSPqxi;p($)3SxUDDE;*E*MLAMUFV=dN2uhy&-Q;Id-G;3V=gvf=s%7WI}_)CyaNM* zU4@%~%6=G~8E3iEAq)&8l!vy|->@X#)w?)$$I`1gGny|XM0jm9WYg#iALR#)@pL37 zJ@li_iskcJjwOg^_v$YgCSU)(73$pX`3891pnlhZTTuo|v}|_Ph}T7apxGi68H$k* zI>v7PFe&P$rtE{_cCM^r!M0qkZ(hB};YaEbnTQ%sRzp!Y#1U%0$7t-Au~^qCWl@hTu>YP2m24>8wPd`k}ec&#D1%JsN$&t$(UIn@ly82%%a;VoIe$GG#BKxG~A z?N*Rq>bPl;x%m)6dKMD0-dLXLhp z{=RwR?BK!J6LxK_-^J}CT-T?jt~N7lz`~Y}1-(vZdL@E4%|pxD^6vI=A!CjP*G$es z)k6_g>Z99189HGV_Z^jzT4o%#5zA>9Vw@}_+9VWk?dAU#(%zczk+1t@)?D&8$*$aE zl9hZhaiN~pv+Rf4O*^Fy-xyWx-B53J75mJ6sDQE#BAcOrBiiT+79FA1Q2+9(}Z1RN-rEcw@(^_lVG;P|~g)Kyy*Pif`@oDSIkA@Pka4gf`xUXNds!IrHyWAXo3FXCg!^%JISklS)fFq+ec|g7@i~Dg=hDQK_`IB?*V! z@e&e}2I?Q|2HdME59lZTT;Tz8UZUO|OQHa!2mhi6#sg0Z9RoKCp9V&DoGm`GcUClt z5bxyJ4ZaxHoqOZA4}}|i#~i+-e04SUK>XjPgl!WRY%%3het)RqL(w-_EZx%Zr z?DZi%|GdflJ1SQmZb`Nijw|@uyVgVEvTM9a1R$U(>B6q9Jwut`eXYw{o1|is6lzVx0L4pYIcl&P3H#L z+^$C(6;w8EG#EN35{_kUVSi~cK4Hy7=9`ri0-IOJq21#)UfacidI_VC;!$IA#^fY9 zO@~s7)&B4Ut8hXGZin`cuSIB@0uWJce7)P3(T+G^MxMS8^-S3b*Mv-esLx+IZ}8={ z*1Iqw9V|MHy5y-Fv+!&1=cHD6T-Hyvrl34c97kQHcNES(&UpAK#du$)OUkjOg1ah0 z=e)#HO-dk|cMh8o0h>*Z&M+hPej-K0hfMw*RfTVryF=cPzj9|=!(Nt9!m(@jlP)rwwM`T<{t%u6}0-5Muf2pe;OcP97Kj>BaRw zF!A#ze3KVW99#7_QU>yJ zdx`zl;%?dgv&|sa2Nek%yI*Ke6pD^&fAuwjW)$LEJ#cl3&oSyi*uxP1*L-tB9m0t* zqZ~E)^Or|Q&NF}GNe=R~&j#0W&z8`MhO(~Pl;z5cBYPx=j6*1o)Yx>J!X|W*B3;?1 z=;QDb`dLD&_TEh?Rik{&`wqKd75QdJAp+L0tGnd*8?Lc>u(jt05&yGwrUc?(yJN`X z1qlwcjolm+pRQa`hk<2;RRBh<8bIU zo80?fdQFjvW%JQ2UOuN}`M)`YcLHq>&bQ3G`@@Eu{|>@g%sS9n5jFbr9jytoM)k}2sd26(mW5kQ-bf-5%uK`wof_=vn{~?|6B7`(! z)$HA9AT_#@bqNqnWQI!Gzr-IJOwJvksFf=faSMJ8Jdxopp1gTTbMVga;QxWh{bV&U zY8cm?O*>V0cnn)j?&wBuczsh}eIJ1A_43fW`MlX)yGPDb%6>@RdO&bXyFSXnMs|Ej zBS=|*Te|bx+{Y$oxC{?G=DMfZxY+=x$2&LSHSdXc4;lI@PKD?G#_Py6q2R%jL>LKw zi=!tL`B{Qr-I>u56H7jcT}~%|;%S@FU)uZLSpDNuBCl;l-s@n;#J!oNE<;(kQIrOb zwiE{|c^EEjqq_~0QiMtO+Fb^O-p=`a6sw1UXrSYM40W(dxtd|R|JxM)w1pP8`lxCL z=-2bo$e`lWiNZ%}@+Ygm!KRn|61R{GZMlQD^$`y}@D5$h82w>H9i`|?an4qH<7i%^ z=gZlQB7$7JqaErxpD+I|fwZh@2333+5GwtLHL`9MvQ6$QxiBeTAY~&0H^HNf49M0yM}-Huvz~F9 z1T_&&G8VS%{f~OMgC)c6PWNt~{*<}Jl7jmxwmWkl8*%!`@cxKkQfmso2IbCc)E|H*QHr4P;?uJ{S})a7L@)t9d!+4c@Y%5oLAUELdN-}o6=g=>1R zGjB0RZgH=ZP%qjVTDDFP4^7-F>-7|FSz}`;;1edEN?~C$6&rhT1<4YXQ{$zfv-yRkz47g~#0QcyS2mJXHvA z-#=Nhql)Xc?-{ij-u7hJ{Fyav8!bt(OyGQ!v!e7>zWjI~fjCj6``iE@m!g4qV+_~G z{6n9PKneuCQea@VY8K%b^1tq=+cA{^`SAKi=$v<=`(l%TsB?;)3a^zS8g;uopq@9y zHxI#PMgeWquJ}t#EB*Dlu2baZzlmzKxmPAZ??&hLGQKu3LEATnUsQw}QeKpg5G+co zO~zY_b_9j8&QjS@tV?o(sFLZVhm_4Yh;Xpn_eX@>cUU!+;z9<3T7T{~tuMmk5SExg zC8Eu5P4CRgGkm3wQ0&#OyQ;u;61Q-ooTz%t3_?VCy%Y<>`CAF*%beE~{Dggz!3*a~ zxNXQv&v4K>(TJ*gRFnT=|20YtuBm3x+uyo5W zSR2q2t7?C4(Z9xNK+*4=4!TMes@$&iAH$+W^|U`6U#w)L(EMm?)2{TzLCov>rp{}9 zM4|&cLtr3(+YywBlsdCfIg6Ip5SHx%<-E;rMVm6=6r~Qz*83S8;eAFu-Az%~FteU3 z15%s!ys2mo1ng{LD2#&7#*YJ26PW; zid_uzvJN(UTx1GN<~?s@9{ulV-UYERPmQx$YDBZcQ$~Hh5T>6?Aq|*|iWvd?emV;K zQVWTi0z1`%>xysA2dDrgJ*$>_7P`N4ndRwb2T^nX?lqvCqm(T0oO`UHivm|0W-`5avD=+l%1l6vRqlOk8;1GL&@;S)B?TVnz_ z?)RNs3(ET_Ip3W&v~a9rJcBNtD=KDwpOK45I-&c8w^Vm0XzCUp?@&_dRC9&P83Npg z176%)Y2Bgg*v+NCx&gQ|FUVkqW?I84bq5d*M{jvL*mRszd6ow7s+r^Ty%~I;FNoET^%OO)V;c+1^9fkghQ>AYs;Mj_enSH zLwVdptt`#0n&BZYJAOWsBJp6MwW|*BbMUIoX8wdf$}M9uNqwgmW_xo@nVc0&HG?dT zp#9EK;f36w5NSr~Rt^ol2Nm1DwFX96S*Fx2bA%n-No<~Ydoo|^-zy9i$86?)yUcml zwcZ62lfg03Q5{e739!DKYEg2nWDTNdFu&r@m3M9O^*fT;)8v2;J8Jc`t(uHQd!cB~ z1>G(NaFpTauLrrdNgTb|Uq*=@yGBTvbf=mISO89&-c4uf({T1Sjs1}IC5H4K0^FPf z=AG}lT315%u1k>@k&gD(aah$9_eFN%mZ5-`rInY>BW&dBrc2jzgnWy`D(a@Lz~d=g@(!lT9|39L#c3r z^QU~MQsrZvbhMwl9HIQ7J88AkN3>=8GAO%5dDWFR#^dY-6r8>v(c%}o0b9;`@1f3L zaXgk}HMAu~>W_OjQqLP#81EnW_v3A~r5h>aY`Hv>Uo|>$O{cFmC(6WQ9FJ`Oe#v`G zP#a3acC-&$=aFHb0M6Lh9E}4NoZ8>&AKf?lY2a~w*k&=4YV=gZ&Cmm)cYxpjdKiUZWfsDDEPniC!0)gJ?}FP}9-E&dbM}dYc?MIPigF>I z<4X@SiwKzy?(q3?jRa!Vv*pY(ef6d$Svx&^+iZb2&H#W#VA&eu1qVA!cx~n{z|g8? z{a$)rmQR+BbWD#D=kK8-_&cH07dM7ADeTI`#sI`Hv2l>vo4;W+W&}CS84t+ z#Ma^4Xme){?+m95i-Q?VTtQ6hgpb^3UY+L+T6>5zjWKW0^;q05RkNd3$ZE3~mjakE zo6VU%OAzL3mrp8-8W`uT9eZ<^yPmevt}#|!XmuAj%W&fu4>FMd=>o`a+irJxteVxw z9^sZl^6f|gDu+#W^D$z@sb+?YC1IOC;>8T8{D~@L1MQf)sYh#gxkRrUfrE_SQ02v+ zS>zZTw-c9sTr+zvH*K>ZzPJ7=!?pM0Iw?7mb#|ldZV^&y{Naakj82L{zncy2rH9K{jA?Q(*$p zf)HowVYTQ-z1WUy4(F)3_LBobBy6>vN5bz~Uhc_?Fxh*hx&x>tyc~2Us{1IqdzCG! zx}q%9v2iHRh8r~7?ew~($K7L&VK|j(`hIvtR=9V_qo6|8$M8BG7twB}1LC5Q-4{G!!L}nBN_A^b3AtFce`}Ynp2iSVLy?XTzKKcQ zN3N?>7B1FzP{Zf04=Xp{8$7cAs$7S``HsJx(w+QmdxNd< z)Rw%O(p`_;C+@h3Q0ELr$E12DkM-w+{1w~iedjLF`NypZ7JIdY4r^)a$^wT!+ujpS zORshMa#TEf#|`N;>UYSl?5@5=X*S)jsu$c=4v-Q4m;NFrWjpy@NLj+o2Q+qRmZFReIzqsSS41@5SEd>9Ds1FH2Ou%3@ai#FHsR zdjfqD2XiAYuVO8^d3#LvQypiI%%^3nmb+I+D{nckTEGO_1P?(`hKq54XABj)18v9V@og5UoaJ1 zlhElcnn@~%Mg)@^CY$Oh!bM*v4)~rm%$c~aV#X)OwQUESq06U4;y4a=S_z$dCXds$ zMm5^}Btx7HrtoNF4O}sFW8@K(1IW=in32N zhvjgrKWOCs6sq?^+fA`;j9QP5UzX6pO&-!lwIe+?S@DWb+5T?rfVp?sQL*26O&eOW zDk`47Xy~d&)Xy>G!wcA@n(y$#D0kL|DA0W!|0?9^tZQ+kj*i+a7%nEPwsOf4ep$g3*lwb%4{8i-kEl^1)%M9J>P&ENc)}(|AP2uBdl@AnHVSBON`egK_kkNW)Z1XmZqUju>IA z*C%4~k#3N52*Jtv^W&=nq(=m`HeJii{~NX9gIvR@98VgC;*4-UwvXu3R)dk*be3%| z6lULy%6qMR7~N5WIBq9u@{RdV4;h18K(`5sQsaI$cuQr0+ZO}Wa!|uJ=S{`TxTL!Z z3U?l4m8s@1UOzsFc6j?bxPQ~w`gnzqa{{+jk`{lau^PB&as7KUUxXv z09%uZz;hbJ(U}jOt+nHtovutx<#1j3rHSj^;_W($;6QaPH(fClJk&6Lp|V zuzSw0sftwv(J=d;EnN~rp+jv=gD3;5?TrJq^GSs1fQFH;0`K$gZjrla>-xJ@zE&@+ z43`au3$BDKB&3j%M==?h8|LG3U1u;vlRA1Nub`nu{fk+{?UPDYG%IgnP)+KvKSZe$ z1c4i=nw5?BpKrv=Rb-=x9^S^C=6Hhy`U1Xlz5*9r5RZa-S6e-KfNZiBysSMpW6_-i z_h)PzafJ9M4s=!zCaFn;x2#xf;c|FuybB|)9VGwBFR9fnYO-78@s?*K20()PNivV- zHP^zz(SCho4$u9^DHlMr3WKa${o2b@Dxbr3+o+H-@NvGkUrge0$*^8QEh_=M(p`PA ztFBD?bk3Z9pevr2PaHHgcne!DRmGR=KBC}Tqk#G34=7wQny zlng+$jong8Z^s06|EJqS5dfP0jxOCjAp1!eAza4$3@8|n7LpQp3~CDk~jWHc7ZpHNpfK2+?MW3?%; zeDVspSF)?XoqQHV^O~w%Z7iYiQ;x>ROi+g8hH_)_uxYrRrv=}=uc{JXdvQsclnWpM7}bT5?j;AG!$Q!t#m6tTUmgIKijg`mGnkbt!Dq% zgO&d;NkOR`DMm)-M4v6q?!@9y48^ zfDj)c8rvbD0HUF43}ROG(x}+nI>?Del&sW2bcc`c&1uARvVTpDV!hW~B*D66tTtz5 zma(@c+w|UwNE#iR@hMeJwNL;i&e?} z$J(>4JShB{y-qJg@7zK2P*xb?APsZ2D8~gv+x9741jcmJ|1Gv7gQ=eO8aqLq^Y(Bx zBo8YWXO^d2Evz{_re0;ST=ZlD0IsX}sSNC=kPl7HAXMvnE54`*qD< z|2YoA;w!%vW;Oqv;QtOl;P`N(5m@lh%60|g>l;-6fEW$V$N7s~dMzgCdT#ZUj*N$E zSc^e6O9&dOm@OrdR#R7_BFBjU@FdOopDF0LR6+?5JWgyf+O-tJSXu7R+{sB-S~Fg< z?z-B>Xv05uxgPfQ(jU$ZV9lh(n#Pgfdc*gN?aO2RSZyAxfseAkr#i`ma2K^FND8=1 zA=}X+P)SXMbJM5Qs^a|O(xTo)&>da1qGt-rt%T!fvVuG0C(p1gsLfj^$a&^d?@y8A zs_xyt-Mbl(A0iv88~WBxWBWC!CbUSSp*p`M#bpej|Dcuf&T235ptjB}O#zkh$4LSo z$+bGNso9r1b@->(L#eV)8SU#Hja37vA-*g9S=bH>4d8~u^49~foin^Oo!_9=x(|R0 zfH}rc%S_rS8N&^pn;KE9S7ZGC+GJPXCVgCaS91bRhk7+d(l075G2Lb0==m1OhR^0A zFU6VhC|$MtPgjRWTk$dXpW`e;(6Z}N)yZi3BztOiwOX>VsI~ma?d5L?j+>BD0)0O> zCeQK}WtwPofAzN)JjZSDy~WV&qz3+s=*)}ZSVIAwe8lqo;gd7myg6>Xk)|IEndzNo zZ^m;*#78L|sga4)9{(Zr2d>g>hA{L?{;Nw5E`SAA+_t}q0MGq>sS?C@zm?bLb zKLg?ZLm%8^oL$wBcb;(`EJMJLL;piYB%ItalQcfiH16bF9m+B_ov(j1LPmR8rB{lE zT3N&^GT|lmj~d(EshgLZmm{4-6r znxpv#|6sp?0}xhlBe;a#+L1bfIC0$}MI1~X!UC&VfaMMRJt24 zOM++_8%E@*W#C4@9MyupJ19?ev$p&}hrA+pwxOx8_lq$6VU zIM;g)c+>dg(iy|yn>RoIyztujKM}E(CLW+V+3Q<5Rn)8GwVwkdslCR=*r104J@Gzg zwCAKK?2~oz8XT)mm=@DqxZ>qB4&QFMk)i4gxY1R@$4RLyh)a~qLCv>~+smz*Qzb$3 zsZu42lSG@ze9xD|dM|ASm_1k0*o`&mJDTz$vI!kz>pK(j9vgeiUAroI|qAKghiV+~w4Y`{yA;uGeZL{SQ}Z z^9p#-p3s{Kvds!%Wb@9jU->;lBaJHkc9g#KwQ$|=HJ?JH*(Xi_cU!P~HeskHOPG9=H^I!7&?*KepYxehl3|UU~>kn7+#psfxj&PrX%};_toDE-{M~$O&h}Cw$uI{n2&dzQcbha@eUprex!`vTpf)qTCOL^k`&+JM`Gm8l@9`_E0a4${->Ad{1Ilgwq(bKpA zcVNMJQ@XPh0$0bJxh6f=-Cnnsv1{RDb;oeux+$>>!ZdMfQ^sv&(5U|h``EynB8PIT zN;>BPk6KUf!V=Pj?Pd%1fuUwSC2>&8E4a?M|27bi+JD&<4Fx)5_Y}>d7V)p;?5-uN z5oGzVj`m*;zz8ti1obnt>JKM-=FL|;dJ-;q)GgY{G|xLNGiG$Fm^-t9^<{geW=XCB zf^{T0-_6+LOAJ>Oel~qo>aeu8Go`MxwNdmx-xOm;`0^_`vQcfGmy=D4Y>MK@o(X{1(LV_xMzenmlHc`QFO5?5>t<>{n zWoez;m~zJ^2|UnU-ttWF)zg2s527RfyAn*h%s^JGMzI^pC6&nz3zlh>1D+nWLh-JL}ov-nvfR0b*3YYhq#Y?wt$m>Tz z!;UQGF!Om8rE$+~e8jO_t_~cuWwrW>ZkO6`*ACJ6NFsW#ndR*vR*v^qX8=x zM1y`g$khVCNl+<8hhUwP=^hwHib77iY*VK-ysdE~l4D}!8j1{GDJv>!e!NyXa#O%{ zgY8HxOaZ`We*b}JoZO5}-&c^ynFI9xu^?^@t11--e|l*D{9vzUU6O4Z95}nq*V8F2up|c2tRP)UGu?K zduvWBZzzrpcbm3zSANZQsNLij6~9OpE-WXtPJPa201}*yd%8*o<%;ga?5{t3&K^8| zhH?w%Cx-wS{<+&{jUY6us<7H>8Wxu5$Ft$`HPna6N zcNsZ~zH~mojgyZUzuObNuL7j-*SzOyCn5!so+;|u=|8J=H>-B~thL~yjGnH5tGIu0wsc)b zo3=j-6_oPjjxh3HmsChJpa-vI!0TB|vpNT2$~;l8TKq*;wYI{^%@4bpmdZw1$SD9) z{1+7IsMh~CX+Y}Pm<+C?_#y@_+)Gopi6QbBEWoL;@ZLeO`+%8 zasxjczy#|V^e1R(ZwW$rDzePRc(yTWLQ(F@5L#Je)r*O{S_b6Yz1VlM1h1=8os<`H zz6px{xx8Fu8;-h;Cf3y-I5qXKM1zHLMLkHZM&#(QHjd*ma(qEWFVOgZ%Z^{iSxER1 zf$z&f5^xKgqvf1}y~Wx0XA5|7tWK{{Ep@A2D(F7{AB_O%Qx9Tgso)Ns89TGJs?}Yw zFNesBHC9~Sm^NV{S!rC1oo~JyW$@N#kqMRn5 zVve)iRGe+_NVopTeRJbYRhh^E6#ZL{jS{lOowtC0 zfyZ9wlcq``ZGlVA=beH=y?lX!yb+`Q?}7Ld%WydxGDVM)08daHPy9LiBi?6n$u}MP zy#%&@DzrWw#5>4HI%jC`4w_I(u9zzI&bAiHf@Y%)1r2W$-P92m52s{4+~gE-s$q3G5t0>#8FWIV z#tV4zJ4o?~OLu;KceELX+g*(Pej)C0A)>S^*@tst7! z{An4ik%MVWbdz`cW9;62`X+R~h#OE-;$qT)po5_@iLJl+xVR_$Q!aqf%F>ctkA3)6 zxOR6XL|dEC^%|v!w^%;uenw4hmAS^&k;GUIymNEkiP3O`CD<8zug~{eRQ)7REgW#q z42n3wW`|i$OiAhq>xyzHH*GbsyL)fzZ71q7OcAe-t*7z{r!AW=^o$d-T3J82VwbWu zqy`{77-8u#C(H=|;{N$-|8^zdslMg}4E@HPWIGVK1LBVJc#6!?&*L>8f45jABuH-` zY+G*g1sPR9{pO10EaX6N1$RBww=LJzd9IhMFebAv-8FrH4bRJXwicgdRcm%!f!*xx(E)LXdiu#^|9HDz0I8S{-OmoY$A?)Mq^%t zfYdal{#1V^cUK7=h0dT=q23?%Wo7_F3KW#{2cUf#ljZiq`PFLOK|mN^G*J{No2BJ0 zeF((R$G;r#r3rfgZ~66x_H=xFyy3??fQMARp=_vb*(t>4zvud7p+B3gk@o?`-p!$g z^Kz|cKmhCJPq2Z~Y+8I*N?pb^+a&Nn11f=ohox55$5|+jlSvCMx1}{08dPk*wjB1} zK=w=&aVivKiT>1pP!(~ok8l`;tsU2=MsiF=l20=SMwSGo*wKo0^*m&mv+TW{pPXtZ zWdgRA8Ba0&gDg0O3AbcyhX-Kdum6iIkp50k^S1sGcNgZUDpgjC-!03=G84Uu*xYKw ztkp|A${5jlvU5jYjhFGRk>Np~j|I9kCU5?f6h9|Zo?+T5rlc!vP`f`eVDFZQ3b7`; zd-21HCQ~co4b7L2+zRV1AOog`>a5p)mP_BVU`BauTbcOGLBu>dPIf0)2k8aN+=Y6t zoi}J%8{0cGOG-0IdJ6=K2YQurgG?Hc=gj*Tv1x)pbnvw*GF0~8QU^R>V{+wB0EJiL z)Rwd6_eRxbna-7|=a@v)Fz*{7wmr_hNl4#4Yw;kl%pt|bTIqh#3KzJ>?vV(GI2M^b z-F?X!LZL0p*WcCjK0lgv4!g|tz0=M2+{*QIE_?A-@4z31=JK7_0vGeA*Q?kR-_K-T zD<~ZG3&516O^Q0aEBN){>YQ;ZX>WC1X5!7=`-?w@vN(eVApXxo@{=6Hf#XAEVKn{7 z)+WbGDw)@O>}h|+dc(^5C7HFiSHa-dd3NQyzN9lB0|!%rKAtFdbh~=YXW6n)mXoD_ zj{cVa;f>b(d}K_%8ag?6)?z5=@v#qqE83GB2431Zv2cw!xdoD)s3oc`rcez}!24f( z`q}SO(x}(A(s$mZP}9su{t~KqBdCO%-G8JG4#8@d>xIrGc5E z#f1+x*wKy#a=n{_H7QGc86axAHBN-Ds{P)EP-M{9oLWq@rKQ881CS?m# z@Kc2}D0qYR15aCuCmB5+T;7}N%I;XmwIO0AD`ORuC0f-y9>yEXuV{XVDSX)-sDI$r z%jFb(e&P9<%{Mm*82R$QnW0U;KRV>C%F~!_EaGnr#J8EAdsKFdGk8g`RrT+3;}S1h zTR}+eaD8SCY)K7WUEkUgHH>&sjr>C>Zf2xS)fpm{7Gsl@n=q)`%Sw8wz{t5%Y(>lM6lL^!LpxwJ7F4iQzV59xLjCP*fi#a8r>=y< zOAG@TiNL{qw`t*Y9y+%6m%frw=6KcRp6wjC3HtfA^p?Y{ss!h1?y1F{K>9;;Ll@7g z1~FG4yLL8UWVSXoG`nFm8HWI;mcao_p0$Cz1nJDR5V-0Xjh`gV6P(kMUuZ&WBICM zbK;&9NR`1$)7IYv^`0*YN|29eqHf?Fk>wJwu$b5W*B|v%yzLOCame z9LczGS{TiNnm0E0YOS{cJGuUoT{lz@e@bYo8vdlxb94#yP%X>(`3K2}%0zfv@K0tf z`nlMJ$hKzW<-qRVFZ*a2$1Fo-+3yZ&*|=riW##zxIj!pS*dYFHiEo-KOMS}Svn3rN zk-n`y6(Qf38=XH0FQ$L<#fXm+O77jrt=5Z=_B~6iehn3&94ai9eS1zcIk7_)(h%o} z)*HF6?o;rPn|4vgCwA@=Bvw*KS6pB4QG9cbtxZjj)STIakJI0G!zp@$=M34*^&6vD zD=ql$+8o$hn_Yld8XPEk>tDYS_nSvItL5#_!gTLO=;tDdp4Dp-UteTe`%*67r}`b9 zhTpmS=;^0*SLT!Xs$cXTwwY63u#M@OeEx^8h%c6dC0!nIsX1s+#i|;IYpAG^r}4=u z#!k79c7!PTL^XnB3U#tAU6>+1HKvv@2HSw0bfNGxer&+R@H~|ma-15^kj=1t{rahi z^?s&S4dW>~`q{9DdsSs^y?*F;-$8qV02-P zS)?<0Yo=2HAup|Ql6KX&N|otxWtQ~K@D1*8uPyd-hc}*a-)ol_yR{S7H$0*F>H6xU zp9?>)ZaqGoIw&!JU9rr$K5_9_eWSyoiWkSiTL^nzNi=AbauIHO56^3C(@PpmwQ)ALGHmKU@Ej{-XFXm7LPz9FIFFQJ82{W(+A=$SG{#~vuYO(bC~s}=C};PBteAY28rxxfg+>n_`_#i9pc6pJ8@bcO z#04~!+_rBCG}Z1THx#h8^CYTgpN1=NiHUdqQnOQ#r P{5@CKe};Tw|Nj30%WT{G literal 0 HcmV?d00001 diff --git a/images/Property 1=lg.png b/images/Property 1=lg.png new file mode 100644 index 0000000000000000000000000000000000000000..8b56d8b58e997b70ff274884019c4c6226f5b40a GIT binary patch literal 6365 zcmb7Jg;x~J*G9TaIt5`tT4CvsWq}1mx&&5`FbL^bN(7cgm+qGCRytiIM0)9^!KFcA z38^3NfAD?xoT=x`oVn-Boq6uP6Q%!LlZu>;91jnVN(%xu#KXIXyz7UP65rKfoE(XF z4VfFn!V?dV;{Jc-9$rQk%N=;n(@+zHS3Sb9eK#O{t*WbvhgTO%ab-({hsWZf1y(io zySKmS zd#K+!l4J?Qd`%PjhNwP}ZTrl(*L-|0Ny1c4%gcAYnP_0d27_;<+8-BAn{Xm`e6u_$ z-~)O&vaMWl>4m*8`KBeXn9Y)KCU=OVp{4sjiGhVA?T6wH)8Q4o44eEV#G3pNNJ#`; zsyCIVc)~&qL+jNnNd0kFXISJ`boB~Dlp-&fSm@~quFctjwICw!eLybP!;e0w?@pZT zNFQ3dcV47bxT|K=nPl~4C z6BDC&B`B$Qg&wgIgxS)`!injUkzYf3Jeg96#7L;1qi9*z_wS`)s$hm!@y6U%U;E4L z%o(07{$M%%h!ET`B!au-aa4oBAV26wL50l?a~Gw4(g^W8%6=;cF7!{5Upd zme!s%KHoaDc>zZTZ~oC8V9H_nRQ(~=W6(C{0WW!8UH91iMZomOPulR}r(gzK#D%iG&AgtrFo53xU@SPG*09OjZVUwUz zN}o(Apk!VQ&f%emrU1@i|L4;8KU}?D%pTiNgmZ z5Ql7S1tYU|CZYp3aXONn&?}7l$@Q9h@8$E7AmlMjGUTXrmsW_B0;gMkW`uH^Is?<7}|yFXPmPS?g=PA z*ymV2qa#uy??wZC@>H*1qu@tNmrd%o>HVb8)}zB4w}Nqz!+>i}_sb@FN#5pRaxI$m z?=`_m(jp03cy}t1J#z|VGuq*Pev!7i%=x{$r^M(~Xrco;9Ck?uK%LTwE|Sid{*%{e zPBDq?^?t~Fb$dw&4S1|drgkVOqB#|wUt<2Hi*9HPH6}U|gaT#1%gMwj${2p2xMcwu zdf*aTCsHed#Kk!Lp`&WX=$PCE2@||#DvC(LWXgy^H#2i2*dUfyDkE`j>;qT6=)cuW zW=(HY9gBLBZ1`7dbtZT&(Hw8NuR$bjT%SBM0ZHzJn#JJAVZf}BxvW^ZKeccqmWcoR zziluBZ+&GWwYs!NtMIy_8sM*DI@$-K$3HWZP|G4e{i#;pcBK13{uqLX(7ux=lU35u z<^a=Tj;_V?baFCK@QrDGS)mNgZk~(X-L?GK*%e^cv9B2t!X3k<5Hnfwd^HUwe0YX) zI8YrR^lSB}Dg*LR6hi zm!svl?Y&nMzooR5(Vdr_A?!PZ7f$w0;G!b zv>7ibV@~#|XXqy~n~DCkGSJ_@)o3?w9!kibr$kz5)vU!6uiPxqzBt1;lgtlU`}olo z<-;@BwRCZ`LviH8QTr=E_p9aOyePc2F( zJC4J9$6VhqNJ(sbx{e6gS^C((Nu=8Z*>v!W`Ix9 zUlg>wcav6f?*1lm^Q*iThazWUSvFHsRI&P$r6tRucp?_VsRXy{kKMgYmtNKK8(50A zM7wO)7yWZlPTX1UU^_3l+#gG$JZ1yiPnMwJdu}7I9zkq2*qG=^FPB_@^n^v8)SK0e zCSwO&-hU4ALhS9EH#$c_H8LrbvV6GJ!VrKGQhWePABqC8U1qmI!FH2|if5SP9274n zS&l$%pmxUreFv78nV#+TJm?lag+OSle+lJ@uJ~o)w@Ua!3@5$NqSunJDk31Otn$aw zj~`_;>>G-BV@T!<(XQ@x046O6yL;L*V3n^$Z}zdbZ07pU(0={+R*bPWTfZ!fM_TFQ z$XtVczG#A>@|15+=H8VazN?%TIr zeP7@3LxXPm&xcBGnO=8Z(W}DtLZ{4cS9W@5xIf6rhL_LJA>Nof4pZQJ!g5ZQpgG zB4CW|VFN`^;e{JJmVnkpmYW@R?}!lUl(##Vp4I79YIYY1iYdkpZrG}j z%9qPz6p<%xVmHgo^6l+@fVB6C2tlvFL)!sbbb%O6dU7p`^4YKhcj}m*&++n>M$o8A zS5)i`HnAPXF*R9idokf~-T+sZmzbzqE2gdy!Ua1!0x@yWq`gVMh?4yKx*B$xs5`zF z!F9qGoYKw7V*5i`e3TCV>}4!@laehHtlz+V)eIhXspLKpNs#N|QC7N82s{}SkPSKz zd7h;h)k(oT7GjHcO|VnEl&W8vqin5mTI_#3b-mr}zNE-V+qBkqF@vHYi!L)WZsp2J zxW(p%{L&2qZ$f}KRfv3na(q=?|5J^rs&}Lv`@?+>*dXBkw|B%Owaicy{+n%#O=af! zpWbxmyg7n3CmUI_g}F4fRJZM+n$-xYe^BXI?m#-Rj&hZ*=nhKqs@7+( zWd@V??d52OkZY2-2FT?FgyW7baH?T;%FfdEZ*`_OMLphNZMvvG%lm!#p5Kqa`q8_F zUdTtT3W=btLZ$j_1(vZzlCP~*pfFZUrmED%z&H<8TNSD}0ySWJ4k0>ijpAW6?IePq zh;6hNIoq>nv#lG_a&t_my>^xDpybWqDAddgdqtS*Uv~W@Cc@=EHz|p98D40w>Dwsm zOh#T)5%)jM)2$mC~Ar;*eevs3npTps>%OlAT?NIw^TBaVq;GF z5?_t&C%dCVFp~0cpo$?n(36YNY}jjRD9*OUkQ_wq>#M}d1%s`bUb1GFA zF9~|9^F)Iij2e1EGpo?n5Wlzz&62z1msYvuxN*Q93@HnA@Xfig zWXtpK?hcG@m%(LcUT^Jec(vI7$%#9f&_+xfR}0?JRv(IVI0S2j5*cdIHlw3((?bEBqy~eB=LI#N|qu>+EMg% zS_LvLJHP0huxr{88lg~?4UOH5EEcW*Lz7D;T@flz@;GxWP>qvO(y!AG$uGtC&B3wd27@59XR3!~l zh+jcwRyxm?Ok`nuX*aW3b2Hr)Au2Yh_Q^s4a|3Z^LK7&rf>!#ZT&_74+q82`QV@fI zSIBwuIA>$nY-zie_`}JKCS~hs&_a^zi;o$(V*<;(*R=D5_q!swn)zP#53m2FMmnR! zO%-DTA#x@yI9x!@cL5!bY!lO<>+5P}Lo+=+NtHE^iOUz%S`PUE_Ye2GaN zXJ3n94^>HThW*5AU)l3+h??}sp!+7&>`9UQ8YX=z3$+FJ;Ov;$U)Fw9n%f- zrRdErLM^^7mM7ZHEGl=V^^Y@)O7yA?nXN=B1g~w&jXZx(79~Udb*;NCvhVacgmiER z@R}gUc=ouJ-U;_N`E6Jqg4l381yRbkv54=uFz#$zJjz$Lu>Z}c$rC58^D+?y8ZcZ$ zadIO$g?U%&9;j(eNAbA}hdz>@fDi;GUS5s>mw>(SijlNuGkyv*$hX1G-y_H?(&?>CQcg;E{2ZJ314t0Lt z$D%`ApWphk_QgLbNe3YLrGA$aFTC9_ir07lzUrn)vh>CY^|wd|cR4XTA=Xy9 zLwP}lZ^aY)jl)Fm9rcAu2X%juWEG2UmO8I63vBzj%{X;G?zm*5Qt;v`rsNh%(kH3V zxQim>HoO;i<>&9Roep_}9QG}}^f0XY<%!w$m=#)kmD+SZ>QNTC>OHDPx&PEvxLQ#1 z5ymr*TlgUz#xcXKYa@0*vy%``spBB8SH7ko*+2}B%lSwtELZ5RCv#7f=V&(kf|xA9 zE9)Y`OSrr~YB;MpK-;zU1N|ndOjcF|$ZGr)@~x*Q7(HmP(883MPy0DX3p2 zpGZvB*P+DXhbTkCx)I$sd_&$A&H!i_2(nuE)55G3w#OVqN%`|R$o35>@VDTOC-!)W;67z1btTeH_uys9b-SmCrw!@01M>7Vb>p`TnL<;?=TwVH z1&MM47a1j~FMs_Ab%B2kza1^KmH*KzHy6YW+|P}Ror3U#{E5oIPosUm*d$C4@s!>+YU@2Fg4}6&p8XLRqa3BOI~B#U5c$nLb4M{VZtT(B|+AX^8UP0 z``xeg=2^Pg=hd3do`J*9(+xi%o&CbUt-`j@LNlZBwk^Ifp$NeO^|mU&l;mQ96Pfu? zH-M2Xv+(#`U#Nk1e5+fk*wZDKfjL)?wAUQDLlS9Rnrg0?)h zR8kgH%iVEO9Zns*N-(zGGv(fiwv?qeI>gfRb>@24sR6TOe$@{pITi%4ze8xlOYDh~ z<^1Xd)l4Q55hi+*m+I|=5plKVw?3zwhhXIdmA_fqk%qP+^LA5%lfd(sR8LA|WE^W~fqVsr!X{T)0bPe0|f) z=x;2PTImC9()EK=mWewIm{p_#FuMT$MsRNZASa#KJ2d-vw`(McPeu;q_`sC!@nTL+ zam{HWmO5)}>|Q>M+c0iW`vg>Y<@7UOW2Z(N-hu2joQ0@I1XYxyBYA$a(GD){{FXq2 zcgi1^hY|Mpj%FOjY9#awCI#=d9+XjsaYRxHkcal*41I6*gTDqY z{LRGej%6&5tzV$Iyeri3mj1EG=2wStS)>I)A9B9kh)5;ddTCFhj{VOsI(kC*{e8-J(0g>yc-B1^fH0`LT zPH`mg-;Rj=uvxRi>8yG*^7u}SRWHA<$xqO0`6TQgRfi+mlP^^x5#eFzUK<<62fPl5)UF0roMF@;mG*4u#OFjBNG-J}iA|4w{Ri-5k zj50cTEcdoOyCNWxBmG8m>eQ0+LDX4x0eUl7enOIk<>oY~MT>>fs$LDG%)GN%>%pi7 zUbTDwVd&OjBYzCEzyN%mvYTa^ZagA&^=bC zWFJ>4pYAoVGcA20=5veCU9wnxdTrV|6Ir$Q_FM;^$HD|Qepmk=SHc;8>=T>c6MN4D z&3y8+_Cfx{dKoo>BiZRkZK{r|C$G9$8xT~;~CXth-RF05gyasE+=|DR}&apUong=JRt|Lnf|jlk1Ve-5q&*?jyTD%?iw literal 0 HcmV?d00001 diff --git a/images/Property 1=md.png b/images/Property 1=md.png new file mode 100644 index 0000000000000000000000000000000000000000..bc9cbe01c60107be72b4402f295ccda31594b348 GIT binary patch literal 3520 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 literal 0 HcmV?d00001 diff --git a/images/icons/ic_google.png b/images/icons/ic_google.png new file mode 100644 index 0000000000000000000000000000000000000000..49852a6bd508728700902c9f7fa4208fad04db49 GIT binary patch literal 1589 zcmV-52Fm$~P)?vK#8&or3on!Mk`TRKhiCz2&ABX6b4FB zf*>X>g#FOnureuk#Z^j#oh)*_?M~~CGjncV?|XL7IOEQ)=giE`LJ!NFvoGJ}Iq&zJ z_xs-WC@2G@lu^sF8tAssbrDq*B|2nJXqt!*UbRlLCr~036baKb8;QUwDG`$jV!|Iv zQL=+d@5lRvOINbD(WTurv|SNJiK7xAPsU8sI+U?2Y1xi+TvyUxAaGmm!+m)Sdg$jd zRu~|U@+6jJdlQ!m#~CD^F|Cf2lnp2+$P=&d;5JQCZurD$<+h?!(0Ebbt7UNNh~Tk# zj!eed$8(|>q*AGdjA?eW<|+kV!Hj8lk0udiM9*4Qhbq(tRTZct==}ikjvKl7RI=`+i*WmTQ3{yDpd^(K^X&djigq2LC_4>JLs-axD@c92 z7v`_O!2Z1p6rZxQ>T~C#dc{f@bQSftAuMd$feqOd(e<`G!W?huiDE*8d(l#RcO&`b z=N{?Npw>@A_39@v;qhk>27Cr_Y^TjI^rkFfU%O$vE3YQe|MnZ?)guUl+V?(!vEac_ zeN5|`mOXb0p^+TIdG^W&EuqQQtlbcrEQ3Rxl*($p_gqR+TP8xhX~{2kAal5Fm_0(v zUA1T_w3+t+x(54H7t#k>k^a6FHP3Cp1R`7v6hTK;7t6eR>FsKEpP>hoL;6o7nm58a z)0Z`=x7K6wTkk`=``&_G+ik&2cI!X8iW}jnMFv*P4JJhvf#bMQjT6Sef-o;&C{w#OQ0>BkP0wDw z@vjWn3&Bba!7)X1#&9zWT2#OMkz!I(^t%~YAQ-A*n6pJa7!W~+et0n~!ekvXW zO6>!r<96?UXKEG(&Ys5Ry5XC_?oE+lws-fZapJFQb4{Nbe1VywqKG)ZZk-Y#2-iJ? z{@$OkrGEjASyO;NTCx1j#klY08F}q)nVe6iht@HdEMxZVVH7Fh3YiePuE&{uP|D(t zjo6fYWRUC-w*0&u|0FMr*oVo!`c*2=cK=-h^|iqX^C763sz-wJCa)sn2BfS-@#ySz z`Gk@ev8weYv>g2ezg;*9lU~G(W8%c+)7Wux51u{nCeBftTr@vyASnE*(GXXF((7$P z66a}q{D)}O9QT_!~3p0!VLB@rAV<->k+-_1RUvNYNQUOV92|j(b}mx1 zb(2KA@_xC&dgZaxX|oyS1XqX110CfePRpP5Du+{y6}V{VeX{aDdpW_x;`$`*L67nn zyt^VKiryc*dK{IwxN1Z}K9;R*6!@?x{r@D|9Qv@RD)O7$nr}r2=YpIUO%E1iqFgq} n{dCJI7;QtHHIyin*l_ zFGk`+rHBjmWK$Xd4{s`G#>S}$T9ux*Lb+RVOJo~4hg$MG!jr@gPW&M8#7Af>A+)iQ zmT#cz$2;1ZuETiJx%bP#Ce? z@skX&df$AGwPed>hmv{P;P%eqS%x*)Qpw9{CcLNhOY!Lvf`2$oJnRoUlp}nH^d+J# zYfmIi9^;S(XmWS)yj8bQjm3H^2mvm*LjzZ>o+>)gfb)F=k1%hWb8cSpOxEpSM{E?{P5(bhAlg&rQbkpw z6_sbG2^0!8J=yq&Qcw43YpX~*yN6WBTe>e8>Y_-0Hw_H-Qapa1hCT>VKVLTkX$y`7 z-u9aSHGh8dw-b{Dum;vD6#TVeNqZ9iTB7^g<9p;2GiMT8w6$5J zc4BDgJS{A~>o+XN5g;b>Tx|G}gu2^J5=f=?O*9lfOQpD!wzmV79p~igZUhLy&jg@; zsf4=fHE8+!=hZeG;6AI${e$|ZrZ4JtFxaKX4S#e&Upt6I&Q$wD9JcP>dxr)G&$^!R zw-*K2XH*I$Jk<{MI4BfKEa3x+Gr4|#INFGvQ`2widms!94D{-22Z*D%2H}Op7`KCz zXXkYAgu|RS#QX62sMip;ZQ{-E-uXkf*H-s*8xrmBKSLY8yrALXkk?Xl=iU__+e5e5 z<9Bxss`qzX?FI--YOz9c)I2uUM`@P&56jPW78-I%vKDwDkg9b|gD@4Aej}jbx?OzMJeudSAg97RZz z;p+A5*O&BvzLI9w*7lf`)V2&QY*cL1OA8g`n5e?44T;{Ex~T2X4Mc);dS9#Z5!)(4 zjPpQ{K%s&cL_gFDLXbY{g2nqg`o6osbY9p4S@H7O_>a81ob(#?Sz?nmH(yaFfEV~~ z`904uLWrca6>XCbzMQ>mWJj$4;mQxZ1AZ)(O)Gu_>p4I>@D&R{n}H8FdnRRx0_n0t zc>}d13W!L=e_=l$J0VlS@eGjDWghk=?5z(?W|XU)m?qsSFc&r%_xJQNL|Nn7_wt$X z5h>L=83KjM^o?Ilhiffd~zRQV`z!DIoa zqC#;0c4?p^B>BW-!I35qaCesMz+8_!oKPMW71C*h?QC}TlDR`P33i<9IXW{}bMGjM znQOcw4W#Jw&z-13C@XAh)GbZmSoMSf%C<*MVr%;$a<;8LsU->2E%R`i2C{fNIyHzK zo>}iCPxpFFg&8Q>wXQmR9@R+QZg>{XnE0Ac)l8#7E70Dpj~N@21k67+uyn1iz>-jA zvDOa==9WeCp_thxo#sE^fG~B<2`MI;j||!lAM*F86;p!MnREh_YXllmg06D<1?lL2 tXeIuO$Guk`e6>7FCDBW2D5#DXl{W z%l#i5l6@^?pe+_0`7&r)(|?)W2}UoZ^8}au7xb7veMa8YlF9jNAF{u+Tm3V7@8$cS ZSwfp5jFgtWzY6p$gQu&X%Q~loCIDzdd)WX0 literal 0 HcmV?d00001 diff --git a/images/icons/ic_youtube.png b/images/icons/ic_youtube.png new file mode 100644 index 0000000000000000000000000000000000000000..f51731d4091084e7f089930baa2cf5a328ba421b GIT binary patch literal 288 zcmeAS@N?(olHy`uVBq!ia0vp^A|TAc1|)ksWqE-VXMsm#F#`j)FbFd;%$g$s6l5$8 za(7}_cTVOdki(Mh=6C-KhYWaJ=XO*ZJDDZ0M6_}y zFiSKFO0c>mG?g?@jEGw_}Qh)J=eKMyFFTUcim|^L8qg!Be#)azc$S;>H zy51?aNTx-GR9Ldc1Y( fJF-jW+HvW|<9Bp#OWLFZJ;31U>gTe~DWM4f3?^xf literal 0 HcmV?d00001 diff --git a/index.html b/index.html new file mode 100644 index 00000000..d16685e0 --- /dev/null +++ b/index.html @@ -0,0 +1,95 @@ + + + + + + + 판다마켓 + + +

+ +
+
+ +
+
+

일상의 모든 물건을
거래해보세요

+ +
+ main_img +
+ + +
+
+ hot_item +
+

Hot item

+

인기 상품을
확인해 보세요

+

가장 HOT한 중고거래 물품을
판다 마켓에서 확인해보세요

+
+
+
+ + +
+
+
+

Search

+

구매를 원하는
상품을 검색하세요

+

구매하고 싶은 물품은 검색해서
쉽게 찾아보세요

+
+ +
+
+ + +
+
+ hot_item +
+

Register

+

판매를 원하는
상품을 등록하세요

+

어떤 물건이든 판매하고 싶은 상품을
쉽게 등록하세요

+
+
+
+
+ +
+
+
+

믿을 수 있는
판다마켓 중고 거래

+
+ bottom_img +
+ +
+ + \ No newline at end of file diff --git a/login.html b/login.html new file mode 100644 index 00000000..a2260fac --- /dev/null +++ b/login.html @@ -0,0 +1,45 @@ + + + + + + + 판다마켓 + + +
+
+ + + +
+
+ +
+

비밀번호

+ +
+
+ +
+ + + + + + +
+
+ + \ No newline at end of file diff --git a/signup.html b/signup.html new file mode 100644 index 00000000..400fa432 --- /dev/null +++ b/signup.html @@ -0,0 +1,54 @@ + + + + + + + 판다마켓 + + +
+
+ + + +
+
+ +
+

닉네임

+ +
+
+

비밀번호

+ + +
+
+

비밀번호 확인

+ +
+
+ +
+ + + + + + +
+
+ + \ No newline at end of file From 1acdc854f2bdc68d46468e3382b5b694cba57076 Mon Sep 17 00:00:00 2001 From: Imhwitae Date: Thu, 19 Jun 2025 14:37:42 +0900 Subject: [PATCH 02/94] =?UTF-8?q?=ED=8F=B0=ED=8A=B8=20=EC=B5=9C=EB=8C=80?= =?UTF-8?q?=20=ED=81=AC=EA=B8=B0=20=EB=B0=8F=20=EB=B2=84=ED=8A=BC=20?= =?UTF-8?q?=EC=B5=9C=EB=8C=80=20=ED=81=AC=EA=B8=B0=20=EC=A0=9C=ED=95=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- css/style.css | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/css/style.css b/css/style.css index b1198c58..77c9f364 100644 --- a/css/style.css +++ b/css/style.css @@ -36,12 +36,12 @@ a { h1 { color: #374151; font-weight: 700; - font-size: 2vw; + font-size: clamp(16px, 2vw ,40px); } h2 { font-weight: 500; - font-size: 1vw; + font-size: clamp(12px, 1vw, 24px); color: #374151; } @@ -91,6 +91,7 @@ button { .large_btn { width: 19vw; + max-width: 357px; height: 56px; background-color: #3692ff; border-radius: 40px; From c5c6f2af455c843a65dd6bbb39b4f6e4c2561843 Mon Sep 17 00:00:00 2001 From: Imhwitae Date: Thu, 19 Jun 2025 14:48:43 +0900 Subject: [PATCH 03/94] =?UTF-8?q?privacy,=20faq=20=ED=8E=98=EC=9D=B4?= =?UTF-8?q?=EC=A7=80=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- index.html | 2 +- policy.html | 11 +++++++++++ privacy.html | 11 +++++++++++ 3 files changed, 23 insertions(+), 1 deletion(-) create mode 100644 policy.html create mode 100644 privacy.html diff --git a/index.html b/index.html index d16685e0..3a2c6a00 100644 --- a/index.html +++ b/index.html @@ -75,7 +75,7 @@

믿을 수 있는
판다마켓 중고 거래

diff --git a/policy.html b/policy.html new file mode 100644 index 00000000..d01f779f --- /dev/null +++ b/policy.html @@ -0,0 +1,11 @@ + + + + + + Document + + + + + \ No newline at end of file diff --git a/privacy.html b/privacy.html new file mode 100644 index 00000000..d01f779f --- /dev/null +++ b/privacy.html @@ -0,0 +1,11 @@ + + + + + + Document + + + + + \ No newline at end of file From cb328a247ef5305bea25170f2de6db55275ca946 Mon Sep 17 00:00:00 2001 From: Imhwitae Date: Thu, 19 Jun 2025 17:36:23 +0900 Subject: [PATCH 04/94] =?UTF-8?q?=EC=8A=A4=ED=94=84=EB=A6=B0=ED=8A=B8=20?= =?UTF-8?q?=EB=AF=B8=EC=85=98=202=20=EC=99=84=EB=A3=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- css/colors.css | 12 ++++++++++++ css/login_style.css | 13 +++++++++++++ css/style.css | 10 ++++++---- images/icons/eyes_off.png | Bin 0 -> 847 bytes images/icons/eyes_on.png | Bin 0 -> 709 bytes index.html | 2 +- items.html | 11 +++++++++++ login.html | 7 ++++--- policy.html | 2 +- privacy.html | 2 +- signup.html | 15 ++++++++------- 11 files changed, 57 insertions(+), 17 deletions(-) create mode 100644 css/colors.css create mode 100644 images/icons/eyes_off.png create mode 100644 images/icons/eyes_on.png create mode 100644 items.html diff --git a/css/colors.css b/css/colors.css new file mode 100644 index 00000000..391122bf --- /dev/null +++ b/css/colors.css @@ -0,0 +1,12 @@ +:root { + --gray900: #111827; + --gray800: #1f2937; + --gray700: #374151; + --gray600: #4b5563; + --gray500: #6b7280; + --gray400: #9ca3af; + --gray200: #e5e7eb; + --gray100: #F3F4F6; + --gray50: #f9fafb; + --blue: #3692ff; +} \ No newline at end of file diff --git a/css/login_style.css b/css/login_style.css index adf315a1..a37030eb 100644 --- a/css/login_style.css +++ b/css/login_style.css @@ -1,3 +1,5 @@ +@import url(colors.css); + @font-face { font-family: 'Pretendard-Regular'; src: url('https://fastly.jsdelivr.net/gh/Project-Noonnu/noonfonts_2107@1.1/Pretendard-Regular.woff') format('woff'); @@ -69,6 +71,17 @@ button { text-align: center; } +.pw_box { + position: relative; + display: flex; +} + +.eyes { + position: absolute; + top: 17px; + right: 15px; +} + .social_login_container { background-color: #e6f2ff; display: flex; diff --git a/css/style.css b/css/style.css index 77c9f364..48184e15 100644 --- a/css/style.css +++ b/css/style.css @@ -1,3 +1,5 @@ +@import url(colors.css); + *{ box-sizing: border-box; } @@ -61,7 +63,7 @@ button { .login_btn { width: 128px; height: 48px; - background-color: #3692ff; + background-color: var(--blue); border: none; border-radius: 8px; font-size: 16px; @@ -93,7 +95,7 @@ button { width: 19vw; max-width: 357px; height: 56px; - background-color: #3692ff; + background-color: var(--blue); border-radius: 40px; border: none; font-size: 20px; @@ -138,7 +140,7 @@ button { .keyword { font-weight: 800; font-size: 18px; - color: #3692ff; + color: var(--blue); } .sec_introduce { @@ -246,7 +248,7 @@ button { .keyword { font-weight: 700; font-size: 18px; - color: #3692ff; + color: var(--blue); } .introduce_img { diff --git a/images/icons/eyes_off.png b/images/icons/eyes_off.png new file mode 100644 index 0000000000000000000000000000000000000000..fb4eeaf42441f38906f05f0ecd133f9bafcc4c93 GIT binary patch literal 847 zcmV-V1F-ywP)8Crv3#sQ4pcx7B1c>Hv*b85eV@@3z~Q<+`P5Dd6V8Sq0rt4)}%&2J-OaI z(RwHv@UZ>|)suF+^L(##m+evlF`SHFvhB=!GxNP4-weQioEM3?Cy~jSg(O@sG-uGX zn{feRV{&%k+V0kR&bw&x;bR>vTbDvcc#c9fgpjrE%{AjJ0^yxZO)nP7GLHhYq2`r* zGxRepQ7j=q_>}!7eMT@4%vCm5%`*wSB;;rut&oPWRVfe*)|^AQoVI1@NYouPvh?K;FyfSp=5cbzX>QWEK|UP?R6^Lmm;+-U@W~ z8d8Z&B9RQc1c@1vAwon6>}t})Tr%P)h)c&MbOW-nMt@;$xOb0KkY{^K)AZvEEX(Bj zN`$V6-fb35S51BrAvmLkU!F<=`%SIYs<{N*D4|4(hH-C{orCgSQzDs~U3g9nO`?L5 z*VoyrlL&H7^W7#>lT4?nebE>k)~g@cKG-*0Lro6QaKJ;uGXAw&E{uB*XL2IV@0Qn} zxhug3S8f1B?+v~GU@>7!k}9<83@9PpzVR|tvTSREv!_0m=zb)-GKL;#OO{ndjb|dd zv9B-5?wf2W>jV3p9@z>~Z&_VF^dw-gg0z;FM2YhqqSN8KT<0S2g31=hfYJrZwqzA5 zQk*nN_lEa@?DZC12)J)kGmCgafzacz`x_iT6QsbQ*mrtnYK~9B1%aOl(tkIz1a)>z+N!Qv5b6d4snlJ#0dRtrU8O)Fn+icAxhf&uh1|e5sE=T^ zs|Nc`XB>LI%}DT`$20TI&o>5mkbf<>kJ0hlcSTr)MTM#$&xG1XRPJ=to8RZV z6Tq^X`P{G#Ux!w{d1e^y(Q2Q|&dZK?`IWbAYOSx;Ho2zl(k^9q% zT`&Tp&5^2HO?x)}+}R1R3QpLWe(kkm{j*Zznh%q$J$~mCP>~Rv+-+EMoS`2j@aCk= z0If}sRf{CU)Zpd%2hO6%`oqg{|6n@lJ(l(;0yD^Enz5buh_A$8FmnrlG!3{QHyJ!C zk0FtMa~( z)N^%RJ_-@FV*qDz=1PCL?6r(!z}z0+04%~50zTn?f0LeCL5mM>_T|i70Yvs1YkZh8 z=#4;8D~`$yD^^8}Lb91v=SkD0ugt5qa!(qhF~PFze2_B+L?8ezzsqxgg3y=;ewYlN zMv|>Ph(Y)|QzluhWwLzfxwqRCLr&ETm3Q8v7lh}e?B3y?Y3F|GOCrKX|00000NkvXXu0mjf=FdQ` literal 0 HcmV?d00001 diff --git a/index.html b/index.html index 3a2c6a00..dc56d6fa 100644 --- a/index.html +++ b/index.html @@ -9,7 +9,7 @@
+

비밀번호

-

비밀번호

+
@@ -32,8 +33,8 @@ diff --git a/policy.html b/policy.html index d01f779f..6ddd54db 100644 --- a/policy.html +++ b/policy.html @@ -3,7 +3,7 @@ - Document + 판다마켓 diff --git a/privacy.html b/privacy.html index d01f779f..6ddd54db 100644 --- a/privacy.html +++ b/privacy.html @@ -3,7 +3,7 @@ - Document + 판다마켓 diff --git a/signup.html b/signup.html index 400fa432..c7320190 100644 --- a/signup.html +++ b/signup.html @@ -24,25 +24,26 @@

닉네임

+

비밀번호

-

비밀번호

- +
-
-

비밀번호 확인

+

비밀번호 확인

+
+
- + From a3b7dd2299fb4ed9757d178d4c1f59a6291518a8 Mon Sep 17 00:00:00 2001 From: Imhwitae Date: Thu, 19 Jun 2025 17:44:44 +0900 Subject: [PATCH 05/94] =?UTF-8?q?css=20=EC=83=89=EC=83=81=20=EB=B3=80?= =?UTF-8?q?=EC=88=98=20=EC=A0=81=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- css/login_style.css | 6 +++--- css/style.css | 8 ++++---- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/css/login_style.css b/css/login_style.css index a37030eb..fda2b198 100644 --- a/css/login_style.css +++ b/css/login_style.css @@ -40,7 +40,7 @@ input { height: 56px; border-radius: 12px; border: none; - background-color: #f3f4f6; + background-color: var(--gray100); padding: 20px; font-size: 16px; font-weight: 400; @@ -52,7 +52,7 @@ button { border: none; border-radius: 40px; margin: 20px 0; - background-color: #3692ff; + background-color: var(--blue); color: white; font-size: 20px; font-weight: 600; @@ -108,6 +108,6 @@ button { } .link_join a { - color: #3692ff; + color: var(--blue); } diff --git a/css/style.css b/css/style.css index 48184e15..f0fb4d73 100644 --- a/css/style.css +++ b/css/style.css @@ -160,7 +160,7 @@ button { .footer_container { height: 160px; - background-color: #111827; + background-color: var(--gray900); display: flex; justify-content: center; } @@ -174,13 +174,13 @@ button { } .copyright { - color: #9ca3af; + color: var(--gray400); font-size: 16px; font-weight: 400; } .footer_menu a { - color: #e5e7eb; + color: var(--gray200); font-size: 16px; font-weight: 400; padding: 15px; @@ -203,7 +203,7 @@ button { } h1 { - color: #374151; + color: var(--gray700); font-weight: 700; font-size: 32px; } From f90b8d4ccfd5153281683b405789c5dbd79bad5a Mon Sep 17 00:00:00 2001 From: Imhwitae Date: Fri, 20 Jun 2025 17:59:25 +0900 Subject: [PATCH 06/94] =?UTF-8?q?=EC=8A=A4=ED=94=84=EB=A6=B0=ED=8A=B8=20?= =?UTF-8?q?=EB=AF=B8=EC=85=983=20=EC=99=84=EB=A3=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- css/style.css | 156 +++++++++++++++++++++++++++++++++++-- images/Property 1=Typo.png | Bin 0 -> 1352 bytes index.html | 13 ++-- 3 files changed, 159 insertions(+), 10 deletions(-) create mode 100644 images/Property 1=Typo.png diff --git a/css/style.css b/css/style.css index f0fb4d73..4680c7f2 100644 --- a/css/style.css +++ b/css/style.css @@ -51,7 +51,6 @@ button { cursor: pointer; } -/* 화면의 너비가 1920px 보다 작아질 때, “판다마켓” 로고의 왼쪽 여백 200px“로그인" 버튼의 오른쪽 여백 200px이 유지되고, 화면의 너비가 작아질수록 두 요소간 거리가 가까워지도록 해주세요. */ .logo { width: 100%; display: flex; @@ -60,6 +59,13 @@ button { padding: 10px 200px; } +.logo_img { + background-image: url("/web_publishing/panda_market/images/Property 1=sm.png"); + background-repeat: no-repeat; + width: 198px; + height: 66px; +} + .login_btn { width: 128px; height: 48px; @@ -214,6 +220,14 @@ button { color: #374151; } + .slogan h1, .bottom h1 { + font-size: 40px; + } + + .logo { + padding: 10px 24px; + } + .plan_card { background-color: #cfe5ff; display: flex; @@ -223,6 +237,11 @@ button { align-items: center; } + .large_btn { + width: 512px; + height: 56px; + } + .main_img { width: 744px; height: 340px; @@ -237,12 +256,23 @@ button { display: none; } - /* .container { - } */ + .container { + height: 800px; + } .content_box { - flex-direction: column; - /* align-items: flex-start; */ + display: grid; + width: 768px; + height: 100%; + padding: 20px 0; + } + + .introduce, .sec_introduce { + padding-bottom: 40px; + } + + .sec_introduce { + grid-row: 2/3; } .keyword { @@ -255,6 +285,122 @@ button { width: 696px; height: 525.55px; } + + .bottom { + display: grid; + width: 100%; + height: 1080px; + align-items: end; + } + + .bottom img { + width: 100%; + } + + .bottom_slogan { + text-align: center; + } + + .bottom_content_box { + width: 768px; + padding: 0px 0px 60px; + justify-content: space-around; + } +} + +/* mobile */ +@media (max-width: 767px) { + h1 { + font-size: 24px; + } + + h2 { + font-size: 16px; + } + + .plan_card { + height: 600px; + } + + .slogan { + margin-top: 80px; + } + + .slogan_heading { + font-size: 32px; + text-align: center; + } + + .large_btn { + width: 240px; + height: 48px; + font-size: 18px; + } + + .main_img { + width: 375px; + height: 175px; + } + + .logo { + padding: 10px 16px; + } + + .logo_img { + background-image: url("/web_publishing/panda_market/images/Property 1=Typo.png"); + background-repeat: no-repeat; + width: 103px; + height: 51px; + } + + .container { + height: 480px; + } + + .content_box { + width: 375px; + } + + .introduce, .sec_introduce { + width: 344px; + } + + .introduce_img { + width: 344px; + height: 260px; + } + + .bottom { + height: 600px; + } + + .bottom_slogan { + padding-bottom: 0; + } + + .bottom_content_box { + display: grid; + } + + .copyright { + grid-row: 2/3; + padding: 15px; + } + + .privacy { + grid-row: 1/2; + } + + .sns_menu { + grid-row: 1/2; + grid-column: 2/3; + } + + .only_mobile { + display: block; + } + + } diff --git a/images/Property 1=Typo.png b/images/Property 1=Typo.png new file mode 100644 index 0000000000000000000000000000000000000000..0fd0992d9c39496f9ee9e555dbf04c82bbb59546 GIT binary patch literal 1352 zcmV-O1-JT%P)tQK~#7F?V4Xw z+eRG6zbkn%r0q<6gDNM8A41?Q<^+TjG(2`%{`drOPGAh}^fB}VbxsiTl3;kKbAqZj zP$vz;5TwoTx0d3y5ZJP01D@Y!#>n2)vfBOa{{F21K@bE%5ClOG1VIo4K@fxmL-C*0 z16_|I)R7kl{gW-#c}neF;FVqFUZU~7q53G1r~7)>Raj4cYapQhH&8Mw2l}1;TSquL z*-_2(earj$rPA;)1}DN{_yAQ$W5+J<{i-%s_H~P-P)o`pjsEGjYVh}pDPX~<(aD_z zday&fboc>jqUv^CR6#X;|FgC}q<(%v9yDGj6GMZmrTX!+nmpUr8hNq$q1JV~N~!FA z92!e{+?iC+bt5zJFH<#}EEu~#M_KwWYntEhe1RKeQKqxoU67etS@(WueAjR1_d5w=SG}%OyOT@Hbb=6|#!hIjSNj zGZPM}j#n$cY2%sE%Kh_rOLZaSVs^q|_b_&7$%{O~V&d~3%hj&ZxNG(eitnL%wsT0; zjpM$nH7|Bz3@6*_F=hZQt{2o#oxjuMzdhYiyRjxP{ng*->e>Hf!!(+yrhy8v#*UM5 z6p+tRm|i#)nwSG!i?lI->&PGWm4$~HW7`Z05+5by@q|DB{0X}%!=_L+WAj4+kJbn$ zNmuApDuTBt*XfKDMdB`+Kq*5oG>ElDwKFs)J2d_#eT+cTJ^-t-D8$Bxg6S(GoOHUv zqIyH!oq%I8%$`7Tti))1q>ob9cwglFv>!%jb{i_U>zt+xn-j1Pujim%GVrqk!Lp(8 zb*P`sW!H%dkPDya&YnM&3D&_^P(ntFCyu!INBAn=g&Kpt*&hrXb%3aJEjvX$} z;9Z2MyAGbvfmdDYTd`|J$(^=IC?yDWLlWLVh~MBHH%VLj)G>~tt9(8C6vq`XCy|BV z12MawXwc8hVOxx}a3cJN2`NQ5v4`Sg3bI^vh0^inx$ADo7$8!3PQm-%ah5uuh4+z< z`)LsdOFxha*&LdXvBKd%lp
diff --git a/src/pages/auth/Signup.jsx b/src/pages/auth/Signup.jsx new file mode 100644 index 00000000..8c187ba6 --- /dev/null +++ b/src/pages/auth/Signup.jsx @@ -0,0 +1,163 @@ +import { Link } from 'react-router'; +import '../../styles/auth.css'; +import ic_kakao from '../../assets/icons/ic_kakao.png'; +import ic_google from '../../assets/icons/ic_google.png'; +import visibleEye_off from '../../assets/icons/eyes_off.png'; +import visibleEye_on from '../../assets/icons/eyes_on.png'; +import { useEffect, useState } from 'react'; + +/** + * 회원가입 화면 + */ +export default function Signup() { + /** + * 회원가입 양식 정보를 담고 있는 객체 + * 이메일, 닉네임, 비밀번호, 비밀번호 확인 + */ + const [signupForm, setSignupForm] = useState({ + email: '', + nickname: '', + pw: '', + checkPw: '', + }); + + /** + * 비밀번호 보이기 / 가리기 상태 + */ + const [visible, setVisible] = useState({ + pw: false, + checkPw: false, + }); + + /** + * id 별로 비밀번호 가리기 여부를 변경한다. + * @param {string} id + */ + const onClickVisible = (id) => { + setVisible((prevState) => ({ + ...prevState, + [id]: !visible[id], + })); + }; + + return ( + <> +
+
+
+
+ +
+ +
+ +
+
+
+ + +
+ +
+ + +
+ +
+ + +
+ visible-icon { + onClickVisible(e.target.id); + }} + /> +
+
+ +
+ + +
+ visible-icon { + onClickVisible(e.target.id); + }} + /> +
+
+
+ +
+ +
+

간편 로그인하기

+ +
+ +

+ 이미 회원이신가요?  로그인 +

+
+
+
+ + ); +} diff --git a/src/pages/auth/login.html b/src/pages/auth/login.html deleted file mode 100644 index 3342bdc8..00000000 --- a/src/pages/auth/login.html +++ /dev/null @@ -1,81 +0,0 @@ - - - - - - - 판다마켓 - - -
-
- - - -
-
- - -
- - -
-
-
- -
- - - - - - -
-
- - - diff --git a/src/pages/auth/signup.html b/src/pages/auth/signup.html deleted file mode 100644 index c3b82e11..00000000 --- a/src/pages/auth/signup.html +++ /dev/null @@ -1,108 +0,0 @@ - - - - - - - 판다마켓 - - -
-
- - - -
-
- -
- - -
- -
- - -
-
- -
- - -
-
-
- -
- - - - - - -
-
- - - diff --git a/src/style/login_style.css b/src/styles/auth.css similarity index 91% rename from src/style/login_style.css rename to src/styles/auth.css index 8c54ba15..4517f4a4 100644 --- a/src/style/login_style.css +++ b/src/styles/auth.css @@ -52,7 +52,7 @@ input::placeholder { color: var(--gray400); } -.auth-login-btn { +.auth-btn { width: 100%; height: 56px; border: none; @@ -78,12 +78,12 @@ input::placeholder { margin: 0 auto; } -.login-logo { +.auth-logo { text-align: center; margin: 0 auto; } -.login-logo-img { +.auth-logo-img { background-image: url('../assets/images/logo_lg.png'); background-repeat: no-repeat; width: 396px; @@ -104,21 +104,20 @@ input::placeholder { flex-direction: column; } -.pw-label { +/* .pw-label { padding: 10px 0; -} +} */ .pw { margin-bottom: 20px; } -.eyes { - background-image: url(../images/icons/eyes_off.png); +.auth-visible-icon { width: 25px; height: 20px; background-repeat: no-repeat; position: absolute; - top: 26px; + top: 45px; right: 15px; cursor: pointer; } @@ -141,14 +140,14 @@ input::placeholder { margin: 0 5px; } -.link-join { +.link-signup { display: flex; justify-content: center; font-size: 14px; font-weight: 500; } -.link-join a { +.link-signup a { color: var(--blue); } @@ -170,8 +169,8 @@ input::placeholder { margin: 0; } - .logo-img { - background-image: url('../images/logo_md.png'); + .auth-logo-img { + background-image: url('../assets/images/logo_md.png'); background-repeat: no-repeat; width: 198px; height: 66px; diff --git a/src/style/colors.css b/src/styles/colors.css similarity index 100% rename from src/style/colors.css rename to src/styles/colors.css diff --git a/src/style/style.css b/src/styles/style.css similarity index 100% rename from src/style/style.css rename to src/styles/style.css From 5f0f4a15601a73cb6e04a033b8070d0397beb5a4 Mon Sep 17 00:00:00 2001 From: Imhwitae Date: Tue, 22 Jul 2025 22:16:10 +0900 Subject: [PATCH 37/94] =?UTF-8?q?fix:=20header,=20footer=20css=20=EB=B6=84?= =?UTF-8?q?=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/layout/Footer.jsx | 1 + src/layout/Header.jsx | 5 +- src/layout/MainLayout.jsx | 1 - src/styles/layout/footer.css | 88 +++++++++++++++++++++++++ src/styles/layout/header.css | 87 +++++++++++++++++++++++++ src/styles/style.css | 122 ----------------------------------- 6 files changed, 179 insertions(+), 125 deletions(-) create mode 100644 src/styles/layout/footer.css create mode 100644 src/styles/layout/header.css diff --git a/src/layout/Footer.jsx b/src/layout/Footer.jsx index 0e7e0246..fc20dca7 100644 --- a/src/layout/Footer.jsx +++ b/src/layout/Footer.jsx @@ -1,3 +1,4 @@ +import '../styles/layout/footer.css'; import ic_facebook from '../assets/icons/ic_facebook.svg'; import ic_twitter from '../assets/icons/ic_twitter.svg'; import ic_youtube from '../assets/icons/ic_youtube.svg'; diff --git a/src/layout/Header.jsx b/src/layout/Header.jsx index 8b240cfb..6882c6c4 100644 --- a/src/layout/Header.jsx +++ b/src/layout/Header.jsx @@ -1,4 +1,5 @@ -import { Link, useNavigate } from 'react-router'; +import '../styles/layout/header.css'; +import { Link } from 'react-router'; /** * 헤더 @@ -13,7 +14,7 @@ export default function Header() {
- + diff --git a/src/layout/MainLayout.jsx b/src/layout/MainLayout.jsx index 4df22f7c..e0e2f203 100644 --- a/src/layout/MainLayout.jsx +++ b/src/layout/MainLayout.jsx @@ -1,4 +1,3 @@ -import '../styles/style.css'; import Header from './Header'; import Footer from './Footer'; import { Outlet } from 'react-router'; diff --git a/src/styles/layout/footer.css b/src/styles/layout/footer.css new file mode 100644 index 00000000..a7020f6d --- /dev/null +++ b/src/styles/layout/footer.css @@ -0,0 +1,88 @@ +@import url(../colors.css); + +* { + box-sizing: border-box; +} + +@font-face { + font-family: 'Pretendard-Regular'; + src: url('https://fastly.jsdelivr.net/gh/Project-Noonnu/noonfonts-2107@1.1/Pretendard-Regular.woff') + format('woff'); + font-weight: 400; + font-style: normal; +} + +body { + margin: 0; +} + +.footer-container { + height: 160px; + background-color: var(--gray900); + display: flex; + justify-content: center; +} + +.bottom-content-box { + width: 1110px; + padding-bottom: 60px; + display: flex; + align-items: center; + justify-content: space-between; +} + +.copyright { + color: var(--gray400); + font-size: 16px; + font-weight: 400; +} + +.footer-menu a { + color: var(--gray200); + font-size: 16px; + font-weight: 400; + padding: 15px; +} + +.sns-menu ul { + padding: 0; +} + +.sns-menu ul > li { + list-style: none; + display: inline-block; + padding: 5px; +} + +/* tablet */ +@media (max-width: 1199px) { + .bottom-content-box { + width: 768px; + padding: 0px 0px 60px; + justify-content: space-around; + } +} + +/* mobile */ +@media (max-width: 767px) { + .bottom-content-box { + display: grid; + grid-template-columns: 180px 150px; + justify-content: center; + padding: 0px 10px 0px 20px; + } + + .copyright { + grid-row: 2/3; + padding: 15px; + } + + .privacy { + grid-row: 1/2; + } + + .sns-menu { + grid-column: 2/3; + justify-items: center; + } +} diff --git a/src/styles/layout/header.css b/src/styles/layout/header.css new file mode 100644 index 00000000..5aa83885 --- /dev/null +++ b/src/styles/layout/header.css @@ -0,0 +1,87 @@ +@import url(../colors.css); + +* { + box-sizing: border-box; +} + +@font-face { + font-family: 'Pretendard-Regular'; + src: url('https://fastly.jsdelivr.net/gh/Project-Noonnu/noonfonts-2107@1.1/Pretendard-Regular.woff') + format('woff'); + font-weight: 400; + font-style: normal; +} + +body { + margin: 0; +} + +header { + top: 0; + height: 70px; + background-color: white; + display: flex; + justify-content: center; + position: sticky; +} + +.header-link-text { + text-decoration: none; + color: white; + font-weight: 600; + cursor: pointer; +} + +.logo { + width: 100%; + display: flex; + justify-content: space-between; + padding: 10px 200px; +} + +.logo-img { + background-image: url('../../assets/images/logo_sm.png'); + background-repeat: no-repeat; + width: 198px; + height: 66px; +} + +.header-login-btn { + width: 128px; + height: 48px; + background-color: var(--blue); + border: none; + border-radius: 8px; + font-size: 16px; + color: white; + font-weight: 600; +} + +.header-login-btn:hover { + background-color: #1967d6; +} + +.header-login-btn:active { + background-color: #1251aa; +} + +/* tablet */ +@media (max-width: 1199px) { + .logo { + padding: 10px 24px; + } +} + +/* mobile */ +@media (max-width: 767px) { + .logo { + padding: 10px 16px; + } + + .logo-img { + background-image: url('../../assets/images/logo_typo.png'); + background-repeat: no-repeat; + width: 103px; + height: 51px; + } +} diff --git a/src/styles/style.css b/src/styles/style.css index a9797e40..110eb2f9 100644 --- a/src/styles/style.css +++ b/src/styles/style.css @@ -16,15 +16,6 @@ body { margin: 0; } -header { - top: 0; - height: 70px; - background-color: white; - display: flex; - justify-content: center; - position: sticky; -} - a { text-decoration: none; color: white; @@ -54,39 +45,6 @@ button { cursor: pointer; } -.logo { - width: 100%; - display: flex; - justify-content: space-between; - padding: 10px 200px; -} - -.logo-img { - background-image: url('../assets/images/logo_sm.png'); - background-repeat: no-repeat; - width: 198px; - height: 66px; -} - -.header-login-btn { - width: 128px; - height: 48px; - background-color: var(--blue); - border: none; - border-radius: 8px; - font-size: 16px; - color: white; - font-weight: 600; -} - -.login-btn:hover { - background-color: #1967d6; -} - -.login-btn:active { - background-color: #1251aa; -} - .main-container { display: flex; justify-content: center; @@ -179,44 +137,6 @@ button { padding-bottom: 100px; } -.footer-container { - height: 160px; - background-color: var(--gray900); - display: flex; - justify-content: center; -} - -.bottom-content-box { - width: 1110px; - padding-bottom: 60px; - display: flex; - align-items: center; - justify-content: space-between; -} - -.copyright { - color: var(--gray400); - font-size: 16px; - font-weight: 400; -} - -.footer-menu a { - color: var(--gray200); - font-size: 16px; - font-weight: 400; - padding: 15px; -} - -.sns-menu ul { - padding: 0; -} - -.sns-menu ul > li { - list-style: none; - display: inline-block; - padding: 5px; -} - /* tablet */ @media (max-width: 1199px) { body { @@ -239,10 +159,6 @@ button { color: var(--gray700); } - .logo { - padding: 10px 24px; - } - .plan-card { background-color: #cfe5ff; display: flex; @@ -316,12 +232,6 @@ button { .bottom-slogan { text-align: center; } - - .bottom-content-box { - width: 768px; - padding: 0px 0px 60px; - justify-content: space-around; - } } /* mobile */ @@ -362,17 +272,6 @@ button { height: 175px; } - .logo { - padding: 10px 16px; - } - - .logo-img { - background-image: url('../assets/images/logo_typo.png'); - background-repeat: no-repeat; - width: 103px; - height: 51px; - } - .home-container { height: 480px; } @@ -400,27 +299,6 @@ button { padding-bottom: 0; } - .bottom-content-box { - display: grid; - grid-template-columns: 180px 150px; - justify-content: center; - padding: 0px 10px 0px 20px; - } - - .copyright { - grid-row: 2/3; - padding: 15px; - } - - .privacy { - grid-row: 1/2; - } - - .sns-menu { - grid-column: 2/3; - justify-items: center; - } - .only-mobile { display: block; } From bdfe4d52033872a10bd54e4d795a2c76c83364bb Mon Sep 17 00:00:00 2001 From: Imhwitae Date: Wed, 23 Jul 2025 20:51:10 +0900 Subject: [PATCH 38/94] =?UTF-8?q?feat:=20=EB=A1=9C=EA=B7=B8=EC=9D=B8,=20?= =?UTF-8?q?=ED=9A=8C=EC=9B=90=EA=B0=80=EC=9E=85=20React-Hook-Form=EC=9D=84?= =?UTF-8?q?=20=EC=9D=B4=EC=9A=A9=ED=95=98=EC=97=AC=20=EC=9C=A0=ED=9A=A8?= =?UTF-8?q?=EC=84=B1=20=EA=B2=80=EC=82=AC=20=EC=B2=98=EB=A6=AC=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- package-lock.json | 17 +++ package.json | 1 + src/App.jsx | 7 +- src/layout/AuthLayout.jsx | 39 +++++ src/pages/Home.jsx | 2 +- src/pages/auth/Login.jsx | 168 +++++++++++++-------- src/pages/auth/Signup.jsx | 280 ++++++++++++++++++++--------------- src/pages/auth/validation.js | 277 ---------------------------------- src/styles/auth.css | 27 ++-- 9 files changed, 339 insertions(+), 479 deletions(-) create mode 100644 src/layout/AuthLayout.jsx delete mode 100644 src/pages/auth/validation.js diff --git a/package-lock.json b/package-lock.json index 5e724042..b1c04feb 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10,6 +10,7 @@ "dependencies": { "react": "^18.2.0", "react-dom": "^18.2.0", + "react-hook-form": "^7.60.0", "react-router": "^7.6.3" }, "devDependencies": { @@ -3822,6 +3823,22 @@ "react": "^18.3.1" } }, + "node_modules/react-hook-form": { + "version": "7.60.0", + "resolved": "https://registry.npmjs.org/react-hook-form/-/react-hook-form-7.60.0.tgz", + "integrity": "sha512-SBrYOvMbDB7cV8ZfNpaiLcgjH/a1c7aK0lK+aNigpf4xWLO8q+o4tcvVurv3c4EOyzn/3dCsYt4GKD42VvJ/+A==", + "license": "MIT", + "engines": { + "node": ">=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/react-hook-form" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17 || ^18 || ^19" + } + }, "node_modules/react-is": { "version": "16.13.1", "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", diff --git a/package.json b/package.json index 71c52af2..d12f9467 100644 --- a/package.json +++ b/package.json @@ -12,6 +12,7 @@ "dependencies": { "react": "^18.2.0", "react-dom": "^18.2.0", + "react-hook-form": "^7.60.0", "react-router": "^7.6.3" }, "devDependencies": { diff --git a/src/App.jsx b/src/App.jsx index 8022dfa9..ce510800 100644 --- a/src/App.jsx +++ b/src/App.jsx @@ -3,6 +3,7 @@ import Home from './pages/Home'; import Login from './pages/auth/Login'; import MainLayout from './layout/MainLayout'; import Signup from './pages/auth/Signup'; +import AuthLayout from './layout/AuthLayout'; function App() { return ( @@ -14,8 +15,10 @@ function App() { {/* 로그인, 회원가입 */} - } /> - } /> + }> + } /> + } /> + ); diff --git a/src/layout/AuthLayout.jsx b/src/layout/AuthLayout.jsx new file mode 100644 index 00000000..24bc8e9a --- /dev/null +++ b/src/layout/AuthLayout.jsx @@ -0,0 +1,39 @@ +import { useState } from 'react'; +import { Outlet } from 'react-router'; +import visibleEye_off from '../assets/icons/eyes_off.png'; +import visibleEye_on from '../assets/icons/eyes_on.png'; + +export default function AuthLayout() { + /** + * 비밀번호 보이기 / 가리기 상태 + */ + const [visible, setVisible] = useState({ + pw: false, + checkPw: false, + }); + + /** + * id 별로 비밀번호 가리기 여부를 변경한다. + * @param {string} id + */ + const onClickVisible = (id) => { + setVisible((prevState) => ({ + ...prevState, + [id]: !visible[id], + })); + }; + + return ( +
+ +
+ ); +} diff --git a/src/pages/Home.jsx b/src/pages/Home.jsx index 1b58be8a..ee36c82c 100644 --- a/src/pages/Home.jsx +++ b/src/pages/Home.jsx @@ -19,7 +19,7 @@ export default function Home() { 일상의 모든 물건을
거래해보세요

- + diff --git a/src/pages/auth/Login.jsx b/src/pages/auth/Login.jsx index 96be9af6..a10806e3 100644 --- a/src/pages/auth/Login.jsx +++ b/src/pages/auth/Login.jsx @@ -1,82 +1,130 @@ import '../../styles/auth.css'; import ic_kakao from '../../assets/icons/ic_kakao.png'; import ic_google from '../../assets/icons/ic_google.png'; -import { Link } from 'react-router'; +import { Link, useOutletContext } from 'react-router'; +import { useForm } from 'react-hook-form'; +import { useEffect } from 'react'; /** * 로그인 화면 */ export default function Login() { + const { visible, setVisible, onClickVisible, visibleEye_off, visibleEye_on } = + useOutletContext(); + + /** + * 기본적으로 비밀번호 숨김 상태 유지 + */ + useEffect(() => { + setVisible((prevState) => ({ + ...prevState, + pw: false, + })); + }, []); + + /** + * React-Hook-Form 사용 객체 선언 + */ + const { + register, + formState: { errors }, + handleSubmit, + } = useForm({ mode: 'onBlur' }); + return ( <> -
-
-
-
- -
- -
-
-
-
- - -
-
+ ); } diff --git a/src/pages/auth/Signup.jsx b/src/pages/auth/Signup.jsx index 8c187ba6..982bf7a7 100644 --- a/src/pages/auth/Signup.jsx +++ b/src/pages/auth/Signup.jsx @@ -1,15 +1,27 @@ -import { Link } from 'react-router'; +import { Link, useOutletContext } from 'react-router'; import '../../styles/auth.css'; import ic_kakao from '../../assets/icons/ic_kakao.png'; import ic_google from '../../assets/icons/ic_google.png'; -import visibleEye_off from '../../assets/icons/eyes_off.png'; -import visibleEye_on from '../../assets/icons/eyes_on.png'; import { useEffect, useState } from 'react'; +import { useForm } from 'react-hook-form'; /** * 회원가입 화면 */ export default function Signup() { + const { visible, setVisible, onClickVisible, visibleEye_off, visibleEye_on } = + useOutletContext(); + + /** + * 기본적으로 비밀번호 숨김 상태 유지 + */ + useEffect(() => { + setVisible((prevState) => ({ + ...prevState, + pw: false, + })); + }, []); + /** * 회원가입 양식 정보를 담고 있는 객체 * 이메일, 닉네임, 비밀번호, 비밀번호 확인 @@ -18,146 +30,172 @@ export default function Signup() { email: '', nickname: '', pw: '', - checkPw: '', - }); - - /** - * 비밀번호 보이기 / 가리기 상태 - */ - const [visible, setVisible] = useState({ - pw: false, - checkPw: false, }); /** - * id 별로 비밀번호 가리기 여부를 변경한다. - * @param {string} id + * React-Hook-Form 사용 객체 선언 */ - const onClickVisible = (id) => { - setVisible((prevState) => ({ - ...prevState, - [id]: !visible[id], - })); - }; + const { + register, + formState: { errors }, + handleSubmit, + getValues, + } = useForm({ mode: 'onBlur' }); return ( <> -
-
-
-
- -
- -
+
+
+
+ +
+ +
-
-
-
- - -
+ +
+
+ + +
+ {errors.email && ( +

잘못된 이메일입니다.

+ )} -
- - -
+
+ + +
+ {errors.nickname && ( +

닉네임을 입력해주세요

+ )} + {errors.nickname && errors.nickname.type === 'maxLength' && ( +

닉네임이 너무 깁니다.

+ )} -
- - + + +
+ visible-icon { + onClickVisible(e.target.id); + }} /> -
- visible-icon { - onClickVisible(e.target.id); - }} - /> -
-
- -
- - -
- visible-icon { - onClickVisible(e.target.id); - }} - /> -
- - + {errors.password && errors.password.type === 'required' && ( +

비밀번호를 입력해주세요

+ )} + {errors.password && errors.password.type === 'minLength' && ( +

+ 비밀번호를 8자 이상 입력해주세요. +

+ )} -
-

간편 로그인하기

- + + -

- 이미 회원이신가요?  로그인 -

+
+

간편 로그인하기

+
+ +

+ 이미 회원이신가요?  로그인 +

-
+ ); } diff --git a/src/pages/auth/validation.js b/src/pages/auth/validation.js deleted file mode 100644 index 7569cd40..00000000 --- a/src/pages/auth/validation.js +++ /dev/null @@ -1,277 +0,0 @@ -/** - * 이메일 - */ -const emailBox = document.getElementById('email_box'); -const emailInput = document.getElementById('email'); - -/** - * 비밀번호 - */ -const pwBox = document.getElementById('pw_box'); -const pwInput = document.getElementById('pw'); - -/** - * 비밀번호 확인 - */ -const pwCheckBox = document.getElementById('pw_check_box'); -const pwCheckInput = document.getElementById('pw_check'); - -/** - * 닉네임 - */ -const nicknameBox = document.getElementById('nickname_box'); -const nicknameInput = document.getElementById('nickname'); - -/** - * 로그인, 회원가입 버튼 - */ -const loginBtn = document.getElementById('login_btn'); -const joinBtn = document.getElementById('join_btn'); - -/** - * 비밀번호, 비밀번호 확인 눈 아이콘 - */ -const pwEyes = document.getElementById('eyes'); -const pwCheckEyes = document.getElementById('_eyes'); -const EYESOFFIMG = 'url(../images/icons/eyes_off.png)'; -const EYESONIMG = 'url(../images/icons/eyes_on.png)'; - -/** - * flags - */ -let emailValidate = false; -let pwValidate = false; -let pwCheckValidate = false; -let nicknameValidate = false; -let pwEyesOn = false; -let pwCheckEyesOn = false; - -/** - * 에러 메시지 출력을 위한 p 태그와 내용을 추가한다. - * @param {document.getElementById} box - * @param {string} msg - */ -const addErrTag = (box, msg) => { - if (!box.hasAttribute('name')) { - const errMsgTag = document.createElement('p'); - box.setAttribute('name', 'err'); - errMsgTag.setAttribute('id', box.id + '_err'); - errMsgTag.classList.add('err_msg'); - errMsgTag.append(msg); - box.appendChild(errMsgTag); - } -}; - -/** - * 입력창별로 표시된 에러를 제거한다. - * @param {document.getElementById} box - */ -const removeErrTag = (box) => { - box.removeAttribute('name'); - if (document.getElementById(box.id + '_err')) { - document.getElementById(box.id + '_err').remove(); - } -}; - -/** - * 입력 창의 테두리 색을 변경한다. - * @param {document.getElementById} inputBox - */ -const setErrBorder = (inputBox) => { - inputBox.classList.add('err_border'); -}; - -/** - * 입력 창의 테두리 색을 제거한다. - * @param {document.getElementById} inputBox - */ -const removeErrBorder = (inputBox) => { - inputBox.classList.remove('err_border'); -}; - -/** - * 각 input 태그마다 유효성 검사를 진행하고 결과 반환 - * @param {document.getElementById} input - * @returns {boolean} - */ -const validationCheck = (input) => { - const emailRegex = /^[a-zA-Z0-9+-\_.]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+$/; - const pwRegex = /^(?=.*[a-zA-Z])(?=.*[0-9]).{8,25}$/; - let result = false; - - switch (input.id) { - case 'email': - result = emailRegex.test(input.value); - emailValidate = result; - break; - case 'pw': - result = pwRegex.test(input.value); - pwCheckValidate = result; - break; - case 'pw_check': - result = pwInput.value === input.value; - pwCheckValidate = result; - break; - case 'nickname': - result = input.value !== ''; - nicknameValidate = result; - break; - default: - result = false; - break; - } - return result; -}; - -/** - * 로그인창, 회원가입창의 모든 input 값의 유효성 검사가 통과되면 버튼을 활성화한다. - */ -const activeBtn = () => { - let countInput = document.querySelectorAll('#form input'); - - switch (countInput.length) { - case 2: - if (validationCheck(emailInput) && validationCheck(pwInput)) { - loginBtn.removeAttribute('type'); - loginBtn.classList.add('btn_active'); - } else { - loginBtn.setAttribute('type', 'button'); - loginBtn.classList.remove('btn_active'); - } - break; - case 4: - if ( - validationCheck(emailInput) && - validationCheck(pwInput) && - validationCheck(pwCheckInput) && - validationCheck(nicknameInput) - ) { - joinBtn.removeAttribute('type'); - joinBtn.classList.add('btn_active'); - } else { - joinBtn.setAttribute('type', 'button'); - joinBtn.classList.remove('btn_active'); - } - break; - } -}; - -/** - * 입력받은 내용에 대한 검사를 진행하고 오류를 표출한다. - * @param {document.getElementById} inputTag - * @param {document.getElementById} box - * @param {string} valdationErrMsg - * @param {string} emptyErrMsg - */ -const checkInput = (inputTag, box, valdationErrMsg, emptyErrMsg) => { - if (inputTag.value !== '') { - if (validationCheck(inputTag)) { - removeErrBorder(inputTag); - removeErrTag(box); - } else { - removeErrTag(box); - addErrTag(box, valdationErrMsg); - setErrBorder(inputTag); - } - } else { - setErrBorder(inputTag); - addErrTag(box, emptyErrMsg); - } -}; - -/** - * 눈모양 아이콘 클릭시 비밀번호 표시 타입과 이미지를 변경한다. - * @param {document.getElementById} eyes - */ -const showPw = (eyes) => { - switch (eyes.id) { - case pwEyes.id: - if (pwEyesOn) { - eyes.style.background = EYESONIMG; - pwInput.setAttribute('type', 'text'); - } else { - eyes.style.background = EYESOFFIMG; - pwInput.setAttribute('type', 'password'); - } - break; - case pwCheckEyes.id: - if (pwCheckEyesOn) { - eyes.style.background = EYESONIMG; - pwCheckInput.setAttribute('type', 'text'); - } else { - eyes.style.background = EYESOFFIMG; - pwCheckInput.setAttribute('type', 'password'); - } - break; - default: - break; - } -}; - -/** - * 이메일 입력칸이 focus out 될 때 값을 이벤트. - */ -emailInput.addEventListener('blur', () => { - checkInput( - emailInput, - emailBox, - '잘못된 이메일 형식입니다.', - '이메일을 입력해주세요' - ); -}); -emailInput.addEventListener('input', activeBtn); - -/** - * 비밀번호 입력칸이 focus out 될 때 값을 이벤트. - */ -pwInput.addEventListener('blur', () => { - checkInput( - pwInput, - pwBox, - '비밀번호를 8자 이상 입력해주세요', - '비밀번호를 입력해주세요' - ); -}); -pwInput.addEventListener('input', activeBtn); - -/** - * 비밀번호 입력칸 눈모양 아이콘 클릭시 이벤트 - */ -pwEyes.addEventListener('click', () => { - pwEyesOn = !pwEyesOn; - showPw(pwEyes); -}); - -/** - * 비밀번호 확인 입력칸이 focus out 될 때 이벤트. - */ -pwCheckInput.addEventListener('blur', () => { - checkInput( - pwCheckInput, - pwCheckBox, - '비밀번호가 일치하지 않습니다.', - '비밀번호가 일치하지 않습니다.' - ); -}); -pwCheckInput.addEventListener('input', activeBtn); - -/** - * 비밀번호 확인 입력칸 눈모양 아이콘 클릭시 이벤트 - */ -pwCheckEyes.addEventListener('click', () => { - pwCheckEyesOn = !pwCheckEyesOn; - showPw(pwCheckEyes); -}); - -/** - * 닉네임 입력칸이 focus out 될 때 이벤트. - */ -nicknameInput.addEventListener('blur', () => { - checkInput( - nicknameInput, - nicknameBox, - '닉네임을 입력해주세요', - '닉네임을 입력해주세요' - ); -}); -nicknameInput.addEventListener('input', activeBtn); diff --git a/src/styles/auth.css b/src/styles/auth.css index 4517f4a4..7b0ada22 100644 --- a/src/styles/auth.css +++ b/src/styles/auth.css @@ -57,7 +57,7 @@ input::placeholder { height: 56px; border: none; border-radius: 40px; - margin: 0px 0px 20px 0; + margin: 20px 0px 20px 0; background-color: var(--gray400); color: white; font-size: 20px; @@ -90,26 +90,16 @@ input::placeholder { height: 132px; } -.email { - margin-bottom: 20px; -} - -.nickname { - margin-bottom: 20px; +.email-box, +.nickname-box { + margin-top: 20px; } .pw-box { position: relative; display: flex; flex-direction: column; -} - -/* .pw-label { - padding: 10px 0; -} */ - -.pw { - margin-bottom: 20px; + margin-top: 20px; } .auth-visible-icon { @@ -152,13 +142,14 @@ input::placeholder { } /* 에러 스타일 */ -.err-border { +.auth-err-border { border: 1px solid #ff0000; } -.err-msg { +.auth-err-msg { color: #ff0000; - margin-top: 0px; + margin-top: 10px; + font-size: 14px; } /* mobile */ From 66ff7bfe627d6bfbfe8b5dd4ca2d447e0694e0c2 Mon Sep 17 00:00:00 2001 From: Imhwitae Date: Wed, 23 Jul 2025 22:49:14 +0900 Subject: [PATCH 39/94] =?UTF-8?q?fix:=20=EC=9C=A0=ED=9A=A8=EC=84=B1=20?= =?UTF-8?q?=EA=B2=80=EC=A6=9D=20=EB=A9=94=EC=8B=9C=EC=A7=80=20=EB=B6=80?= =?UTF-8?q?=EB=B6=84=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/pages/auth/Login.jsx | 4 ++-- src/pages/auth/Signup.jsx | 19 +++++++++++++------ 2 files changed, 15 insertions(+), 8 deletions(-) diff --git a/src/pages/auth/Login.jsx b/src/pages/auth/Login.jsx index a10806e3..76dd1b74 100644 --- a/src/pages/auth/Login.jsx +++ b/src/pages/auth/Login.jsx @@ -91,10 +91,10 @@ export default function Login() { /> - {errors.password && errors.password.type === 'required' && ( + {errors.password?.type === 'required' && (

비밀번호를 입력해주세요

)} - {errors.password && errors.password.type === 'minLength' && ( + {errors.password?.type === 'minLength' && (

비밀번호를 8자 이상 입력해주세요.

diff --git a/src/pages/auth/Signup.jsx b/src/pages/auth/Signup.jsx index 982bf7a7..ded35885 100644 --- a/src/pages/auth/Signup.jsx +++ b/src/pages/auth/Signup.jsx @@ -94,10 +94,10 @@ export default function Signup() { })} /> - {errors.nickname && ( + {errors.nickname?.type === 'required' && (

닉네임을 입력해주세요

)} - {errors.nickname && errors.nickname.type === 'maxLength' && ( + {errors.nickname?.type === 'maxLength' && (

닉네임이 너무 깁니다.

)} @@ -128,10 +128,10 @@ export default function Signup() { /> - {errors.password && errors.password.type === 'required' && ( + {errors.password?.type === 'required' && (

비밀번호를 입력해주세요

)} - {errors.password && errors.password.type === 'minLength' && ( + {errors.password?.type === 'minLength' && (

비밀번호를 8자 이상 입력해주세요.

@@ -150,6 +150,7 @@ export default function Signup() { placeholder="비밀번호를 다시 한 번 입력해주세요" {...register('confirmPassword', { required: true, + minLength: 8, validate: () => getValues('password') === getValues('confirmPassword'), })} @@ -165,9 +166,15 @@ export default function Signup() { /> - {errors.confirmPassword && ( -

비밀번호가 일치하지 않습니다.

+ {errors.confirmPassword?.type === 'minLength' && ( +

+ 비밀번호를 8자 이상 입력해주세요. +

)} + {errors.confirmPassword && + errors.confirmPassword?.type === 'validate' && ( +

비밀번호가 일치하지 않습니다.

+ )} + {location.pathname !== '/' ? ( + 프로필_아이콘 + ) : ( + + )}
diff --git a/src/layout/ItemsLayout.jsx b/src/layout/ItemsLayout.jsx new file mode 100644 index 00000000..95bb641f --- /dev/null +++ b/src/layout/ItemsLayout.jsx @@ -0,0 +1,16 @@ +import { Outlet } from 'react-router'; +import Header from './Header'; +import Items from '../pages/items/Items'; + +export default function ItemsLayout() { + const menus = ['자유게시판', '중고마켓']; + + return ( + <> +
+
+ +
+ + ); +} diff --git a/src/pages/items/Items.jsx b/src/pages/items/Items.jsx new file mode 100644 index 00000000..b3fc35a8 --- /dev/null +++ b/src/pages/items/Items.jsx @@ -0,0 +1,3 @@ +export default function Items() { + return <>; +} diff --git a/src/styles/colors.css b/src/styles/colors.css index c13efd2b..a9c156a6 100644 --- a/src/styles/colors.css +++ b/src/styles/colors.css @@ -9,4 +9,5 @@ --gray100: #f3f4f6; --gray50: #f9fafb; --blue: #3692ff; + --menu: #4b5563; } diff --git a/src/styles/layout/header.css b/src/styles/layout/header.css index 5aa83885..9ee671e8 100644 --- a/src/styles/layout/header.css +++ b/src/styles/layout/header.css @@ -23,6 +23,7 @@ header { display: flex; justify-content: center; position: sticky; + border-bottom: 1px solid #dfdfdf; } .header-link-text { @@ -46,6 +47,31 @@ header { height: 66px; } +.header-menu-box { + flex-grow: 4; + padding: 0; +} + +.header-menu { + list-style: none; + align-items: center; + display: inline-block; +} + +.header-menu-text { + font-weight: 600; + font-size: 18px; + color: var(--menu); +} + +.active { + color: var(--blue); +} + +.header-menu:first-child ~ li { + padding-left: 30px; +} + .header-login-btn { width: 128px; height: 48px; @@ -83,5 +109,15 @@ header { background-repeat: no-repeat; width: 103px; height: 51px; + margin-right: 10px; + } + + .header-menu:first-child ~ li { + padding-left: 10px; + } + + .header-menu-text { + font-weight: 600; + font-size: 16px; } } From b64fb8792790b464e6096463da1bca40d269f464 Mon Sep 17 00:00:00 2001 From: Imhwitae Date: Sat, 26 Jul 2025 17:43:31 +0900 Subject: [PATCH 42/94] =?UTF-8?q?feat:=20=EB=B2=A0=EC=8A=A4=ED=8A=B8=20?= =?UTF-8?q?=EC=83=81=ED=92=88=20=EC=99=84=EB=A3=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/App.jsx | 5 ++- src/assets/icons/ic_heart.svg | 3 ++ src/components/Product.jsx | 34 +++++++++++++++++++ src/layout/ItemsLayout.jsx | 9 ++--- src/pages/items/Items.jsx | 62 ++++++++++++++++++++++++++++++++++- src/services/itemsApi.js | 26 +++++++++++++++ src/styles/auth.css | 10 ------ src/styles/items/items.css | 48 +++++++++++++++++++++++++++ src/styles/layout/footer.css | 10 ------ src/styles/layout/header.css | 10 ------ 10 files changed, 179 insertions(+), 38 deletions(-) create mode 100644 src/assets/icons/ic_heart.svg create mode 100644 src/components/Product.jsx create mode 100644 src/services/itemsApi.js create mode 100644 src/styles/items/items.css diff --git a/src/App.jsx b/src/App.jsx index e036b20a..b4467001 100644 --- a/src/App.jsx +++ b/src/App.jsx @@ -5,6 +5,7 @@ import MainLayout from './layout/MainLayout'; import Signup from './pages/auth/Signup'; import AuthLayout from './layout/AuthLayout'; import ItemsLayout from './layout/ItemsLayout'; +import Items from './pages/items/Items'; function App() { return ( @@ -22,7 +23,9 @@ function App() { {/* 중고 마켓 */} - } /> + }> + } /> + ); diff --git a/src/assets/icons/ic_heart.svg b/src/assets/icons/ic_heart.svg new file mode 100644 index 00000000..b30ce7c1 --- /dev/null +++ b/src/assets/icons/ic_heart.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/components/Product.jsx b/src/components/Product.jsx new file mode 100644 index 00000000..7df0e737 --- /dev/null +++ b/src/components/Product.jsx @@ -0,0 +1,34 @@ +import ic_heart from '../assets/icons/ic_heart.svg'; + +export default function Product({ products, width, height }) { + return ( + <> +
+ {products && + products.map((product) => { + return ( +
+ +

{product.name}

+

+ {product.price + .toString() + .replace(/\B(?=(\d{3})+(?!\d))/g, ',') + '원'} +

+
+ 하트_아이콘 + + {product.favoriteCount} + +
+
+ ); + })} +
+ + ); +} diff --git a/src/layout/ItemsLayout.jsx b/src/layout/ItemsLayout.jsx index 95bb641f..64632871 100644 --- a/src/layout/ItemsLayout.jsx +++ b/src/layout/ItemsLayout.jsx @@ -1,15 +1,12 @@ -import { Outlet } from 'react-router'; import Header from './Header'; -import Items from '../pages/items/Items'; +import { Outlet } from 'react-router'; export default function ItemsLayout() { - const menus = ['자유게시판', '중고마켓']; - return ( <> -
+
- +
); diff --git a/src/pages/items/Items.jsx b/src/pages/items/Items.jsx index b3fc35a8..9fa0f4b1 100644 --- a/src/pages/items/Items.jsx +++ b/src/pages/items/Items.jsx @@ -1,3 +1,63 @@ +import { useEffect, useState } from 'react'; +import Product from '../../components/Product'; +import '../../styles/items/items.css'; +import { requestProductList } from '../../services/itemsApi'; + export default function Items() { - return <>; + /** + * 전체 상품 목록 + */ + const [products, setProducts] = useState([]); + + /** + * 베스트 상풍 목록 + */ + const [bestProducts, setBestProducts] = useState([]); + + /** + * loading + */ + const [loading, setLoading] = useState(true); + + /** + * 전체 상품 목록과 베스트 상품 목록을 가져온다. + */ + const getProducts = async () => { + try { + setLoading(true); + const productList = await requestProductList(); + const { list: bestList } = await requestProductList('favorite', 1, 4); + + if (!productList) { + throw new Error('상품목록 데이터를 불러오지 못했습니다.'); + } + setProducts(productList.list); + + if (!bestList) { + throw new Error('베스트 상품 목록 데이터를 불러오지 못했습니다.'); + } + setBestProducts(bestList); + } catch (e) { + console.error(e); + } finally { + setLoading(false); + } + }; + + useEffect(() => { + getProducts(); + }, []); + + return ( + <> +
+
+

베스트 상품

+ {!loading && ( + + )} +
+
+ + ); } diff --git a/src/services/itemsApi.js b/src/services/itemsApi.js new file mode 100644 index 00000000..b0584f37 --- /dev/null +++ b/src/services/itemsApi.js @@ -0,0 +1,26 @@ +/** + * 서버에 상품 목록을 요청한다. + * @param {string} orderBy + * @returns {object} + */ +const requestProductList = async ( + orderBy = 'recent', + page = '1', + pageSize = 10 +) => { + const url = new URL('https://panda-market-api.vercel.app/products'); + url.searchParams.append('page', page); + url.searchParams.append('pageSize', pageSize); + url.searchParams.append('orderBy', orderBy); + + const response = await fetch(url, { + method: 'get', + headers: { + 'Content-Type': 'application/json', + }, + }); + + return response.json(); +}; + +export { requestProductList }; diff --git a/src/styles/auth.css b/src/styles/auth.css index 7b0ada22..9b750c1d 100644 --- a/src/styles/auth.css +++ b/src/styles/auth.css @@ -1,5 +1,3 @@ -@import url(colors.css); - @font-face { font-family: 'Pretendard-Regular'; src: url('https://fastly.jsdelivr.net/gh/Project-Noonnu/noonfonts_2107@1.1/Pretendard-Regular.woff') @@ -8,14 +6,6 @@ font-style: normal; } -* { - box-sizing: border-box; -} - -body { - margin: 0 auto; -} - .auth-main-container { display: flex; justify-content: center; diff --git a/src/styles/items/items.css b/src/styles/items/items.css new file mode 100644 index 00000000..9a8046da --- /dev/null +++ b/src/styles/items/items.css @@ -0,0 +1,48 @@ +.items-container { + height: 1200px; +} + +.items-best-container { + display: flex; + margin: 0 auto; + width: 1200px; + height: 300px; + justify-content: flex-start; + flex-direction: column; +} + +.items-title { + margin: 30px 0px 30px 0px; + font-size: 20px; + font-weight: 700; +} + +.product-container { + display: grid; + grid-template-columns: repeat(4, 1fr); +} + +.product-img { + border-radius: 16px; +} + +.product-name { + font-size: 14px; + font-weight: 500; +} + +.product-price { + font-size: 16px; + font-weight: 700; +} + +.product-favorite-container { + display: flex; + align-items: center; +} + +.product-favorite-count { + font-size: 12px; + margin-left: 5px; + color: var(--gray600); +} diff --git a/src/styles/layout/footer.css b/src/styles/layout/footer.css index a7020f6d..7676136c 100644 --- a/src/styles/layout/footer.css +++ b/src/styles/layout/footer.css @@ -1,9 +1,3 @@ -@import url(../colors.css); - -* { - box-sizing: border-box; -} - @font-face { font-family: 'Pretendard-Regular'; src: url('https://fastly.jsdelivr.net/gh/Project-Noonnu/noonfonts-2107@1.1/Pretendard-Regular.woff') @@ -12,10 +6,6 @@ font-style: normal; } -body { - margin: 0; -} - .footer-container { height: 160px; background-color: var(--gray900); diff --git a/src/styles/layout/header.css b/src/styles/layout/header.css index 9ee671e8..149ea50a 100644 --- a/src/styles/layout/header.css +++ b/src/styles/layout/header.css @@ -1,9 +1,3 @@ -@import url(../colors.css); - -* { - box-sizing: border-box; -} - @font-face { font-family: 'Pretendard-Regular'; src: url('https://fastly.jsdelivr.net/gh/Project-Noonnu/noonfonts-2107@1.1/Pretendard-Regular.woff') @@ -12,10 +6,6 @@ font-style: normal; } -body { - margin: 0; -} - header { top: 0; height: 70px; From 3baecf0f9460b54457a73522c872f372e9b64d1e Mon Sep 17 00:00:00 2001 From: Imhwitae Date: Sun, 27 Jul 2025 00:06:57 +0900 Subject: [PATCH 43/94] =?UTF-8?q?feat:=20=EB=93=9C=EB=A1=AD=EB=8B=A4?= =?UTF-8?q?=EC=9A=B4=20=EB=A6=AC=EC=8A=A4=ED=8A=B8=20=EC=BB=B4=ED=8F=AC?= =?UTF-8?q?=EB=84=8C=ED=8A=B8=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/assets/icons/ic_arrow_down.svg | 3 ++ src/assets/icons/ic_search.svg | 3 ++ src/components/DropdownList.jsx | 63 ++++++++++++++++++++++++++ src/layout/Header.jsx | 8 +++- src/pages/Home.jsx | 4 +- src/pages/items/Items.jsx | 12 +++++ src/styles/components/dropDownList.css | 62 +++++++++++++++++++++++++ src/styles/items/items.css | 30 ++++++++++++ src/styles/layout/header.css | 10 +--- src/styles/style.css | 13 +++++- 10 files changed, 194 insertions(+), 14 deletions(-) create mode 100644 src/assets/icons/ic_arrow_down.svg create mode 100644 src/assets/icons/ic_search.svg create mode 100644 src/components/DropdownList.jsx create mode 100644 src/styles/components/dropDownList.css diff --git a/src/assets/icons/ic_arrow_down.svg b/src/assets/icons/ic_arrow_down.svg new file mode 100644 index 00000000..8308690f --- /dev/null +++ b/src/assets/icons/ic_arrow_down.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/assets/icons/ic_search.svg b/src/assets/icons/ic_search.svg new file mode 100644 index 00000000..52241e6d --- /dev/null +++ b/src/assets/icons/ic_search.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/components/DropdownList.jsx b/src/components/DropdownList.jsx new file mode 100644 index 00000000..7838cd88 --- /dev/null +++ b/src/components/DropdownList.jsx @@ -0,0 +1,63 @@ +import '../styles/components/dropDownList.css'; +import { useEffect, useState } from 'react'; + +export default function DropdownList() { + /** + * 드롭다운 리스트 메뉴 + */ + const orderList = [ + { name: '최신순', value: 'recent' }, + { name: '좋아요순', value: 'favorite' }, + ]; + + const [order, setOrder] = useState(orderList[0].name); + + /** + * 드롭다운 리스트의 열림/닫힘 상태 + */ + const [isOpen, setIsOpen] = useState(false); + + /** + * 드롭다운 리스트 열림/닫힘 이벤트 + */ + const onClickOpen = () => { + setIsOpen(!isOpen); + }; + + const onClickChangeOrder = (value) => { + setOrder(value); + onClickOpen(); + }; + + useEffect(() => { + return () => { + setIsOpen(false); + }; + }, []); + + return ( + <> +
+ + {isOpen && ( +
+ {orderList && + orderList.map((menu) => { + return ( +
  • onClickChangeOrder(menu.name)} + > + {menu.name} +
  • + ); + })} +
    + )} +
    + + ); +} diff --git a/src/layout/Header.jsx b/src/layout/Header.jsx index e8bd99a8..07f25cac 100644 --- a/src/layout/Header.jsx +++ b/src/layout/Header.jsx @@ -26,7 +26,9 @@ export default function Header() { - isActive ? 'header-menu-text active' : 'header-menu-text' + isActive + ? 'header-menu-text header-active' + : 'header-menu-text' } > 자유게시판 @@ -48,7 +50,9 @@ export default function Header() { {location.pathname !== '/' ? ( 프로필_아이콘 ) : ( - + )} diff --git a/src/pages/Home.jsx b/src/pages/Home.jsx index ee36c82c..576cb6ae 100644 --- a/src/pages/Home.jsx +++ b/src/pages/Home.jsx @@ -20,7 +20,9 @@ export default function Home() { 거래해보세요

    - + main_img diff --git a/src/pages/items/Items.jsx b/src/pages/items/Items.jsx index 9fa0f4b1..679ceb45 100644 --- a/src/pages/items/Items.jsx +++ b/src/pages/items/Items.jsx @@ -2,6 +2,8 @@ import { useEffect, useState } from 'react'; import Product from '../../components/Product'; import '../../styles/items/items.css'; import { requestProductList } from '../../services/itemsApi'; +import ic_search from '../../assets/icons/ic_search.svg'; +import DropdownList from '../../components/DropdownList'; export default function Items() { /** @@ -56,6 +58,16 @@ export default function Items() { {!loading && ( )} +
    +

    전체 상품

    + + + +
    diff --git a/src/styles/components/dropDownList.css b/src/styles/components/dropDownList.css new file mode 100644 index 00000000..c54197da --- /dev/null +++ b/src/styles/components/dropDownList.css @@ -0,0 +1,62 @@ +.dropdown-container { + display: flex; + flex-direction: column; + position: relative; +} + +.dropdown-btn { + width: 130px; + height: 42px; + background-color: white; + border: 1px solid var(--gray200); + border-radius: 12px; + text-align: left; + background-image: url('../../assets/icons/ic_arrow_down.svg'); + background-repeat: no-repeat; + background-position: 90px; + padding: 0px 20px 0px 20px; + font-size: 16px; +} + +.dropdown-box { + background-color: white; + border: 1px solid var(--gray200); + border-radius: 12px; + width: 130px; + display: flex; + flex-direction: column; + position: absolute; + top: 100%; + left: 0; + margin-top: 10px; + z-index: 9999; +} + +.dropdown-li { + width: 130px; + padding: 10.5px; + list-style: none; + text-align: center; + border-bottom: 1px solid var(--gray200); + cursor: pointer; +} + +.dropdown-li:hover { + background-color: var(--gray100); +} + +.dropdown-li:active { + background-color: var(--gray200); +} + +.dropdown-li:last-child { + border-bottom: none; +} + +.dropdown-menu-btn { + width: 100%; + height: 42px; + background-color: white; + border: none; + border-radius: 12px; +} diff --git a/src/styles/items/items.css b/src/styles/items/items.css index 9a8046da..543bfc53 100644 --- a/src/styles/items/items.css +++ b/src/styles/items/items.css @@ -17,6 +17,36 @@ font-weight: 700; } +.items-list-container { + margin-top: 20px; + display: flex; + align-items: center; +} + +.title-text { + flex-grow: 1; +} + +.items-search { + width: 325px; + height: 42px; + background-color: var(--gray100); + border: none; + border-radius: 12px; + text-align: start; + font-size: 16px; + background-image: url('../../assets/icons/ic_search.svg'); + background-repeat: no-repeat; + background-position: 15px; + padding: 0px 10px 0px 40px; +} + +.items-add-btn { + margin: 0px 10px 0px 10px; + width: 133px; + height: 42px; +} + .product-container { display: grid; grid-template-columns: repeat(4, 1fr); diff --git a/src/styles/layout/header.css b/src/styles/layout/header.css index 149ea50a..9d98d873 100644 --- a/src/styles/layout/header.css +++ b/src/styles/layout/header.css @@ -54,7 +54,7 @@ header { color: var(--menu); } -.active { +.header-active { color: var(--blue); } @@ -73,14 +73,6 @@ header { font-weight: 600; } -.header-login-btn:hover { - background-color: #1967d6; -} - -.header-login-btn:active { - background-color: #1251aa; -} - /* tablet */ @media (max-width: 1199px) { .logo { diff --git a/src/styles/style.css b/src/styles/style.css index 110eb2f9..73d4a693 100644 --- a/src/styles/style.css +++ b/src/styles/style.css @@ -45,6 +45,15 @@ button { cursor: pointer; } +.common-btn { + background-color: var(--blue); + border: none; + border-radius: 8px; + font-size: 16px; + color: white; + font-weight: 600; +} + .main-container { display: flex; justify-content: center; @@ -79,11 +88,11 @@ button { font-weight: 600; } -.large-btn:hover { +.btn-hover:hover { background-color: #1967d6; } -.large-btn:active { +.btn-active:active { background-color: #1251aa; } From 4499eb1d4448197527a1e452157ee0db16134f15 Mon Sep 17 00:00:00 2001 From: Imhwitae Date: Mon, 28 Jul 2025 22:48:06 +0900 Subject: [PATCH 44/94] =?UTF-8?q?feat:=20=EC=A0=84=EC=B2=B4=20=EC=83=81?= =?UTF-8?q?=ED=92=88=20=EB=AA=A9=EB=A1=9D=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/Product.jsx | 8 ++++++-- src/pages/items/Items.jsx | 16 ++++++++++++---- src/services/itemsApi.js | 2 +- src/styles/components/dropDownList.css | 2 +- src/styles/items/items.css | 16 ++++++++++++++-- src/styles/layout/header.css | 1 + 6 files changed, 35 insertions(+), 10 deletions(-) diff --git a/src/components/Product.jsx b/src/components/Product.jsx index 7df0e737..bf8fc702 100644 --- a/src/components/Product.jsx +++ b/src/components/Product.jsx @@ -1,9 +1,13 @@ import ic_heart from '../assets/icons/ic_heart.svg'; -export default function Product({ products, width, height }) { +export default function Product({ products, width, height, style }) { return ( <> -
    +
    {products && products.map((product) => { return ( diff --git a/src/pages/items/Items.jsx b/src/pages/items/Items.jsx index 679ceb45..e1e560e1 100644 --- a/src/pages/items/Items.jsx +++ b/src/pages/items/Items.jsx @@ -2,14 +2,13 @@ import { useEffect, useState } from 'react'; import Product from '../../components/Product'; import '../../styles/items/items.css'; import { requestProductList } from '../../services/itemsApi'; -import ic_search from '../../assets/icons/ic_search.svg'; import DropdownList from '../../components/DropdownList'; export default function Items() { /** * 전체 상품 목록 */ - const [products, setProducts] = useState([]); + const [products, setProducts] = useState({}); /** * 베스트 상풍 목록 @@ -33,7 +32,7 @@ export default function Items() { if (!productList) { throw new Error('상품목록 데이터를 불러오지 못했습니다.'); } - setProducts(productList.list); + setProducts(productList); if (!bestList) { throw new Error('베스트 상품 목록 데이터를 불러오지 못했습니다.'); @@ -48,6 +47,7 @@ export default function Items() { useEffect(() => { getProducts(); + console.log(products); }, []); return ( @@ -58,7 +58,9 @@ export default function Items() { {!loading && ( )} -
    +
    +
    +

    전체 상품

    상품 등록하기
    +
    diff --git a/src/services/itemsApi.js b/src/services/itemsApi.js index b0584f37..72c1315a 100644 --- a/src/services/itemsApi.js +++ b/src/services/itemsApi.js @@ -6,7 +6,7 @@ const requestProductList = async ( orderBy = 'recent', page = '1', - pageSize = 10 + pageSize = 50 ) => { const url = new URL('https://panda-market-api.vercel.app/products'); url.searchParams.append('page', page); diff --git a/src/styles/components/dropDownList.css b/src/styles/components/dropDownList.css index c54197da..c51e932d 100644 --- a/src/styles/components/dropDownList.css +++ b/src/styles/components/dropDownList.css @@ -29,7 +29,7 @@ top: 100%; left: 0; margin-top: 10px; - z-index: 9999; + z-index: 8888; } .dropdown-li { diff --git a/src/styles/items/items.css b/src/styles/items/items.css index 543bfc53..2b156b94 100644 --- a/src/styles/items/items.css +++ b/src/styles/items/items.css @@ -6,7 +6,6 @@ display: flex; margin: 0 auto; width: 1200px; - height: 300px; justify-content: flex-start; flex-direction: column; } @@ -18,8 +17,16 @@ } .items-list-container { - margin-top: 20px; + width: 1200px; + margin: 20px auto; display: flex; + flex-direction: column; +} + +.items-menus { + width: 100%; + display: flex; + flex-direction: row; align-items: center; } @@ -52,6 +59,11 @@ grid-template-columns: repeat(4, 1fr); } +.product-all { + grid-template-columns: repeat(5, 1fr); + gap: 35px; +} + .product-img { border-radius: 16px; } diff --git a/src/styles/layout/header.css b/src/styles/layout/header.css index 9d98d873..fdb828f3 100644 --- a/src/styles/layout/header.css +++ b/src/styles/layout/header.css @@ -14,6 +14,7 @@ header { justify-content: center; position: sticky; border-bottom: 1px solid #dfdfdf; + z-index: 9999; } .header-link-text { From a56533642f067e6556dc7aab82c663fed2897cc0 Mon Sep 17 00:00:00 2001 From: Imhwitae Date: Wed, 30 Jul 2025 00:27:55 +0900 Subject: [PATCH 45/94] =?UTF-8?q?feat:=20pagination=20=EB=B2=84=ED=8A=BC?= =?UTF-8?q?=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/assets/icons/btn_left.png | Bin 0 -> 1175 bytes src/assets/icons/btn_right.png | Bin 0 -> 1173 bytes src/components/Pagination.jsx | 105 +++++++++++++++++++++++++++ src/components/Product.jsx | 5 +- src/pages/items/Items.jsx | 27 ++++--- src/services/itemsApi.js | 4 +- src/styles/components/pagination.css | 32 ++++++++ src/styles/items/items.css | 10 ++- 8 files changed, 167 insertions(+), 16 deletions(-) create mode 100644 src/assets/icons/btn_left.png create mode 100644 src/assets/icons/btn_right.png create mode 100644 src/components/Pagination.jsx create mode 100644 src/styles/components/pagination.css diff --git a/src/assets/icons/btn_left.png b/src/assets/icons/btn_left.png new file mode 100644 index 0000000000000000000000000000000000000000..62bef86ac143f58a2784a28ac295adaac6e71e30 GIT binary patch literal 1175 zcmV;I1Zew-P)bceHFI|l*Xnx-o`N1#oDDQ`C~er+<&y5ovf|6MQhc)>cVi~mAsKS*xlW5U;oY2 zg=8k>Il)udI5xw)qB-@N ztksWhGfn*GI2{|K*ZI!&hCOcxiA%ne&}_S|HxRqy^*A93Avn%v(@TRRB{1->uVr-1 z9e<`RNY-OUSl-&SV3~j<+S!d(2ZnvVK~~f>WWA(mE**|UJ9{mY0yE|5wWx{EjQi`^ z46KUiC$3XDq!4jB%P!X8^oZ${{Bb5zyDr77P#Bu7zEug3?YiX{QNU* zy`O&hRa-I+(TPHAoGIpFk-}EYD>yajaWJMK1;j(kJ6j#&9(Y|zXJ3wJ< zy{WpWwN5YHu6k%uv*4oEIE7hMbDHN53E9D}LbcYIdh|@qW=2Et;h;Y(VLRep-L0EP zFS@ufMn!MbJDB%*?QUvE`1cURsij9_&+OJWiTX7)jOx^Mj02Qr`PjZ^XRVm zXX>pvj$;R4oCw4CgbMsD*3e>s7BHPwbRb|jIg_K_2{vHdyPlh?`8Nhdw5LKOY^uDd zA{2sSif+8pL`P$R?@Qf8$3q{`r7nJaCWqIjvw$rGcw4%t#+n*yn>~!5Hf}eYYKWJk px|9fG(Nn^^XMuv!lLh~V_#epos9jW470>_x002ovPDHLkV1m>9D7XLs literal 0 HcmV?d00001 diff --git a/src/assets/icons/btn_right.png b/src/assets/icons/btn_right.png new file mode 100644 index 0000000000000000000000000000000000000000..e7873a2055ace8238ecbd432ad393221d1d0551a GIT binary patch literal 1173 zcmV;G1Zw+UhlfYh)hQh`1+*w2KY`sviy&QCLA@)Gwm`edrhNl@+f^)}y9TJe=)P~zN3ik) zRbL=d;7C+-u^7v`@pdvl9SKRG#F9u`{s94`E<7J*=FFKHX|$p&t6fwY?eOI;DQ$=`X$M9^nue5Q7zs)wBr|Cw z#O33HK#?E#Hd7fY6kII7dQa-;~TXfBZ00EXvdruhRAe%{3CY>T(7qpCg zKcN1_kS319*Xo~TK|iWyv%6n!c6#Uif#O9}RIw!$o>jLx)t6T5H;ST0v;9}I)m4t` zs<;JEJR56#ieavcLzkw!f79t?@y4W^xEK{1SkHDY$nXP)AvFP z!g`t>R6oCK(mDYl?Ce&jN8_Q`gcU;?STAW9Ylnldv$L5L87U`>#gK^2Slq~E=(Y$) zDQRLK*Ai8UE=A!sSZ^w@7>R^=%4{NF>m|7&iK4+^NUc_f;uJQFu4qS)qHQB0;P0hB z`SmnbNEl5~P!x)&Af--G^xf{a^s3#76%sWjY5KO{s<$9SwD|ks`#pO6%cEE!Q2>*s zOt{#L3J3u(PROuG0UO1rz1;_t&1OQ#=Pynv4hc?zb`S&2Nahk+^X_%SCPJ=iUZmRy8lhIc$+5xvXjf_hk(vl9t}8#;z&19 zF&fF|^EKShP7-gTANB`B8;#4la@{0IP6>Pi_*j$5VxRqxIiBmbul;WGsIg4aXH8M_jAB!{O2E zK5vXk*_jL;(z1fPF^+JrA&Fz8hi5PB){hDEng(Ze3?1VD#SA7KVDjnpve7=cYW;;~ zYnEjde9{l4uK$V#KgT_^Tww%^(+URyr;}rEGC1S`jD6MbmKy#|K^bjV%0vO37dk>I z1()dhdqZ?K7P+n$4$&RXt?W{p-#+%n7e|YLtpxb4!ls&gYVK{eIe!*-yA{wwynU*T nLYSML3g10L#q{Nhe?z { + e.stopPropagation(); + setPageNum(currentNum + 1); + + if (!(currentNum % 5)) { + if (totalCount - currentNum * 10 > 50) { + setPageArr((prevState) => { + return prevState.map((el) => el + 5); + }); + } else { + setPageArr((prevState) => { + return Array.from( + { + length: (totalCount - currentNum * 10) % 5, + }, + (_, idx) => prevState[idx] + 5 + ); + }); + } + } + }; + + /** + * 화살표 모양으로 이전 페이지로 이동할 때 이벤트 + */ + const onClickMovePrev = (e) => { + e.stopPropagation(); + setPageNum(currentNum - 1); + + if (currentNum % 5 === 1) { + setPageArr( + Array.from({ length: 5 }, (_, idx) => currentNum - 1 - (5 - (idx + 1))) + ); + } + }; + + useEffect(() => { + console.log(pageArr); + }, [pageArr]); + + return ( + <> +
    +
      { + if (e.target.value) setPageNum(e.target.value); + }} + > + {currentNum !== 1 ? ( +
    • onClickMovePrev(e)}> + < +
    • + ) : ( +
    • e.stopPropagation()} + > + < +
    • + )} + {pageArr.map((pageNum) => { + return ( +
    • + {pageNum} +
    • + ); + })} + {pageArr.length < 5 ? ( +
    • e.stopPropagation()} + > + > +
    • + ) : ( +
    • onClickMoveNext(e)}> + > +
    • + )} +
    +
    + + ); +} diff --git a/src/components/Product.jsx b/src/components/Product.jsx index bf8fc702..bcd3a5d8 100644 --- a/src/components/Product.jsx +++ b/src/components/Product.jsx @@ -1,6 +1,6 @@ import ic_heart from '../assets/icons/ic_heart.svg'; -export default function Product({ products, width, height, style }) { +export default function Product({ products, style }) { return ( <>

    {product.name}

    diff --git a/src/pages/items/Items.jsx b/src/pages/items/Items.jsx index e1e560e1..3b5ff1d0 100644 --- a/src/pages/items/Items.jsx +++ b/src/pages/items/Items.jsx @@ -3,6 +3,7 @@ import Product from '../../components/Product'; import '../../styles/items/items.css'; import { requestProductList } from '../../services/itemsApi'; import DropdownList from '../../components/DropdownList'; +import Pagination from '../../components/Pagination'; export default function Items() { /** @@ -15,6 +16,11 @@ export default function Items() { */ const [bestProducts, setBestProducts] = useState([]); + /** + * 현재 페이지 번호 + */ + const [pageNum, setPageNum] = useState(1); + /** * loading */ @@ -55,9 +61,7 @@ export default function Items() {

    베스트 상품

    - {!loading && ( - - )} + {!loading && }
    @@ -67,16 +71,19 @@ export default function Items() { className="items-search" placeholder="검색할 상품을 입력해주세요" /> - +
    - +
    +
    ); diff --git a/src/services/itemsApi.js b/src/services/itemsApi.js index 72c1315a..7b66e576 100644 --- a/src/services/itemsApi.js +++ b/src/services/itemsApi.js @@ -5,8 +5,8 @@ */ const requestProductList = async ( orderBy = 'recent', - page = '1', - pageSize = 50 + page = 1, + pageSize = 10 ) => { const url = new URL('https://panda-market-api.vercel.app/products'); url.searchParams.append('page', page); diff --git a/src/styles/components/pagination.css b/src/styles/components/pagination.css new file mode 100644 index 00000000..93368131 --- /dev/null +++ b/src/styles/components/pagination.css @@ -0,0 +1,32 @@ +.pgn-container { + padding: 40px 0px 40px 0px; + display: flex; + justify-content: center; + align-items: center; +} + +.pgn-ul { + margin: 0; + padding: 0; + list-style: none; +} + +.pgn-ul > li { + display: inline-block; + width: 40px; + height: 40px; + border: 1px solid var(--gray200); + border-radius: 40px; + text-align: center; + padding: 10px; + font-size: 16px; + font-weight: 600; + color: var(--gray600); + cursor: pointer; + margin: 2px; +} + +.pgn-ul .pgn-disabled { + color: var(--gray400); + cursor: default; +} diff --git a/src/styles/items/items.css b/src/styles/items/items.css index 2b156b94..cf7aecf5 100644 --- a/src/styles/items/items.css +++ b/src/styles/items/items.css @@ -1,5 +1,5 @@ .items-container { - height: 1200px; + height: 100vh; } .items-best-container { @@ -66,6 +66,14 @@ .product-img { border-radius: 16px; + width: 282px; + height: 282px; +} + +.product-img-all { + border-radius: 16px; + width: 212px; + height: 212px; } .product-name { From a2e04901a9c9a605a5c3f875f90a6914a5914c3d Mon Sep 17 00:00:00 2001 From: Imhwitae Date: Wed, 30 Jul 2025 14:20:42 +0900 Subject: [PATCH 46/94] =?UTF-8?q?feat:=20pagination=20=EA=B8=B0=EB=8A=A5?= =?UTF-8?q?=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/DropdownList.jsx | 17 ++++++--- src/components/Pagination.jsx | 12 +++---- src/components/Product.jsx | 5 ++- src/layout/Header.jsx | 4 ++- src/pages/items/Items.jsx | 61 +++++++++++++++++++++++---------- 5 files changed, 67 insertions(+), 32 deletions(-) diff --git a/src/components/DropdownList.jsx b/src/components/DropdownList.jsx index 7838cd88..c9eff705 100644 --- a/src/components/DropdownList.jsx +++ b/src/components/DropdownList.jsx @@ -1,7 +1,7 @@ import '../styles/components/dropDownList.css'; -import { useEffect, useState } from 'react'; +import { memo, useEffect, useState } from 'react'; -export default function DropdownList() { +function DropdownList({ changeOrder }) { /** * 드롭다운 리스트 메뉴 */ @@ -24,8 +24,13 @@ export default function DropdownList() { setIsOpen(!isOpen); }; - const onClickChangeOrder = (value) => { - setOrder(value); + /** + * 드롭다운 리스트의 정렬 조건을 변경한다. + * @param {string} value + */ + const onClickChangeOrder = (menu) => { + setOrder(menu.name); + changeOrder(menu.value); onClickOpen(); }; @@ -49,7 +54,7 @@ export default function DropdownList() {
  • onClickChangeOrder(menu.name)} + onClick={() => onClickChangeOrder(menu)} > {menu.name}
  • @@ -61,3 +66,5 @@ export default function DropdownList() { ); } + +export default memo(DropdownList); diff --git a/src/components/Pagination.jsx b/src/components/Pagination.jsx index 1e1fa04a..618ba64c 100644 --- a/src/components/Pagination.jsx +++ b/src/components/Pagination.jsx @@ -1,4 +1,4 @@ -import { useEffect, useState } from 'react'; +import { useState } from 'react'; import '../styles/components/pagination.css'; export default function Pagination({ currentNum, setPageNum, totalCount }) { @@ -9,6 +9,7 @@ export default function Pagination({ currentNum, setPageNum, totalCount }) { /** * 화살표 모양으로 다음 페이지로 이동할 때 이벤트 + * @param {event} e */ const onClickMoveNext = (e) => { e.stopPropagation(); @@ -34,6 +35,7 @@ export default function Pagination({ currentNum, setPageNum, totalCount }) { /** * 화살표 모양으로 이전 페이지로 이동할 때 이벤트 + * @param {event} e */ const onClickMovePrev = (e) => { e.stopPropagation(); @@ -46,10 +48,6 @@ export default function Pagination({ currentNum, setPageNum, totalCount }) { } }; - useEffect(() => { - console.log(pageArr); - }, [pageArr]); - return ( <>
    @@ -60,7 +58,7 @@ export default function Pagination({ currentNum, setPageNum, totalCount }) { }} > {currentNum !== 1 ? ( -
  • onClickMovePrev(e)}> +
  • <
  • ) : ( @@ -94,7 +92,7 @@ export default function Pagination({ currentNum, setPageNum, totalCount }) { > ) : ( -
  • onClickMoveNext(e)}> +
  • >
  • )} diff --git a/src/components/Product.jsx b/src/components/Product.jsx index bcd3a5d8..be536947 100644 --- a/src/components/Product.jsx +++ b/src/components/Product.jsx @@ -1,6 +1,7 @@ +import { memo } from 'react'; import ic_heart from '../assets/icons/ic_heart.svg'; -export default function Product({ products, style }) { +function Product({ products, style }) { return ( <>
    ); } + +export default memo(Product); diff --git a/src/layout/Header.jsx b/src/layout/Header.jsx index 07f25cac..06357c47 100644 --- a/src/layout/Header.jsx +++ b/src/layout/Header.jsx @@ -38,7 +38,9 @@ export default function Header() { - isActive ? 'header-menu-text active' : 'header-menu-text' + isActive + ? 'header-menu-text header-active' + : 'header-menu-text' } > 중고마켓 diff --git a/src/pages/items/Items.jsx b/src/pages/items/Items.jsx index 3b5ff1d0..a1f18de1 100644 --- a/src/pages/items/Items.jsx +++ b/src/pages/items/Items.jsx @@ -1,4 +1,4 @@ -import { useEffect, useState } from 'react'; +import { useCallback, useEffect, useState } from 'react'; import Product from '../../components/Product'; import '../../styles/items/items.css'; import { requestProductList } from '../../services/itemsApi'; @@ -21,39 +21,64 @@ export default function Items() { */ const [pageNum, setPageNum] = useState(1); + /** + * 정렬 조건 + */ + const [order, setOrder] = useState('recent'); + + /** + * 페이지에 보여줄 컨텐츠의 개수 + */ + // const [contentNum, setContentNum] = useState(10); + /** * loading */ const [loading, setLoading] = useState(true); /** - * 전체 상품 목록과 베스트 상품 목록을 가져온다. + * 베스트 상품 목록을 가져온다. */ - const getProducts = async () => { + const getBestProducts = async () => { try { - setLoading(true); - const productList = await requestProductList(); const { list: bestList } = await requestProductList('favorite', 1, 4); + if (!bestList) { + throw new Error('베스트 상품 목록 데이터를 불러오지 못했습니다.'); + } + setBestProducts(bestList); + } catch (e) { + console.error(e); + } + }; + + /** + * 전체 상품 목록을 가져온다. + */ + const getProducts = async (order, page) => { + let pageSize = + products.totalCount - page * 10 < 10 + ? products.totalCount - page * 10 + : 10; + + try { + const productList = await requestProductList(order, page, pageSize); if (!productList) { throw new Error('상품목록 데이터를 불러오지 못했습니다.'); } setProducts(productList); - - if (!bestList) { - throw new Error('베스트 상품 목록 데이터를 불러오지 못했습니다.'); - } - setBestProducts(bestList); } catch (e) { console.error(e); - } finally { - setLoading(false); } }; useEffect(() => { - getProducts(); - console.log(products); + getProducts(order, pageNum); + setLoading(false); + }, [order, pageNum]); + + useEffect(() => { + getBestProducts(); }, []); return ( @@ -61,7 +86,7 @@ export default function Items() {

    베스트 상품

    - {!loading && } +
    @@ -74,15 +99,15 @@ export default function Items() { - +
    From 6f87bed4d5781957c4568c5b44d5f7f947aedce6 Mon Sep 17 00:00:00 2001 From: Imhwitae Date: Wed, 30 Jul 2025 23:42:06 +0900 Subject: [PATCH 47/94] =?UTF-8?q?feat:=20=EC=BB=A4=EC=8A=A4=ED=85=80=20?= =?UTF-8?q?=ED=9B=85=EC=9D=84=20=EC=82=AC=EC=9A=A9=ED=95=98=EC=97=AC=20?= =?UTF-8?q?=EB=B0=98=EC=9D=91=ED=98=95=20=EC=9E=91=EC=97=85=20=EC=B2=98?= =?UTF-8?q?=EB=A6=AC=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/assets/icons/ic_sort.svg | 6 ++ src/components/Pagination.jsx | 9 ++- src/hooks/useMediaQuery.jsx | 31 +++++++++ src/pages/items/Items.jsx | 77 ++++++++++++++-------- src/styles/components/dropDownList.css | 20 ++++++ src/styles/items/items.css | 88 ++++++++++++++++++++++++-- src/styles/layout/header.css | 4 +- 7 files changed, 200 insertions(+), 35 deletions(-) create mode 100644 src/assets/icons/ic_sort.svg create mode 100644 src/hooks/useMediaQuery.jsx diff --git a/src/assets/icons/ic_sort.svg b/src/assets/icons/ic_sort.svg new file mode 100644 index 00000000..657b44f9 --- /dev/null +++ b/src/assets/icons/ic_sort.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/src/components/Pagination.jsx b/src/components/Pagination.jsx index 618ba64c..eab75a48 100644 --- a/src/components/Pagination.jsx +++ b/src/components/Pagination.jsx @@ -1,7 +1,12 @@ import { useState } from 'react'; import '../styles/components/pagination.css'; -export default function Pagination({ currentNum, setPageNum, totalCount }) { +export default function Pagination({ + currentNum, + setPageNum, + totalCount, + contentNum, +}) { /** * 페이지 번호를 표시할 배열 */ @@ -16,7 +21,7 @@ export default function Pagination({ currentNum, setPageNum, totalCount }) { setPageNum(currentNum + 1); if (!(currentNum % 5)) { - if (totalCount - currentNum * 10 > 50) { + if (totalCount - currentNum * contentNum > 50) { setPageArr((prevState) => { return prevState.map((el) => el + 5); }); diff --git a/src/hooks/useMediaQuery.jsx b/src/hooks/useMediaQuery.jsx new file mode 100644 index 00000000..09c74579 --- /dev/null +++ b/src/hooks/useMediaQuery.jsx @@ -0,0 +1,31 @@ +import { useEffect, useState } from 'react'; + +const getMatches = (query) => { + return window.matchMedia(query).matches; +}; + +/** + * mediaQuery에 반응하여 데이터를 반환한다. + */ +export default function useMediaQuery(query) { + /** + * 반환할 데이터를 담아둘 state + */ + const [isMatch, setIsMatch] = useState(() => getMatches(query)); + + useEffect(() => { + const media = window.matchMedia(query); + + const handleChange = (e) => { + setIsMatch(e.matches); + }; + + media.addEventListener('change', handleChange); + + return () => { + media.removeEventListener('change', handleChange); + }; + }, [query]); + + return isMatch; +} diff --git a/src/pages/items/Items.jsx b/src/pages/items/Items.jsx index a1f18de1..946163c7 100644 --- a/src/pages/items/Items.jsx +++ b/src/pages/items/Items.jsx @@ -1,18 +1,34 @@ -import { useCallback, useEffect, useState } from 'react'; +import { useEffect, useLayoutEffect, useState } from 'react'; import Product from '../../components/Product'; import '../../styles/items/items.css'; import { requestProductList } from '../../services/itemsApi'; import DropdownList from '../../components/DropdownList'; import Pagination from '../../components/Pagination'; +import useMediaQuery from '../../hooks/useMediaQuery'; export default function Items() { + /** + * tablet 뷰포트인지 확인 + */ + const isTablet = useMediaQuery('(max-width: 1200px)'); + + /** + * mobile 뷰포트인지 확인 + */ + const isMobile = useMediaQuery('(max-width: 768px)'); + + /** + * 뷰포트별로 표시할 아이템 개수 + */ + const [itemCounts, setItemsCounts] = useState({ best: 4, all: 10 }); + /** * 전체 상품 목록 */ const [products, setProducts] = useState({}); /** - * 베스트 상풍 목록 + * 베스트 상품 목록 */ const [bestProducts, setBestProducts] = useState([]); @@ -27,41 +43,33 @@ export default function Items() { const [order, setOrder] = useState('recent'); /** - * 페이지에 보여줄 컨텐츠의 개수 - */ - // const [contentNum, setContentNum] = useState(10); - - /** - * loading + * isLoading */ - const [loading, setLoading] = useState(true); + const [isLoading, setisLoading] = useState(true); /** * 베스트 상품 목록을 가져온다. */ - const getBestProducts = async () => { + const getBestProducts = async (count) => { try { - const { list: bestList } = await requestProductList('favorite', 1, 4); + const { list: bestList } = await requestProductList('favorite', 1, count); if (!bestList) { throw new Error('베스트 상품 목록 데이터를 불러오지 못했습니다.'); } setBestProducts(bestList); } catch (e) { console.error(e); + } finally { + setisLoading(false); } }; /** * 전체 상품 목록을 가져온다. */ - const getProducts = async (order, page) => { - let pageSize = - products.totalCount - page * 10 < 10 - ? products.totalCount - page * 10 - : 10; - + const getProducts = async (order, page, count) => { try { - const productList = await requestProductList(order, page, pageSize); + const productList = await requestProductList(order, page, count); if (!productList) { throw new Error('상품목록 데이터를 불러오지 못했습니다.'); @@ -69,24 +77,39 @@ export default function Items() { setProducts(productList); } catch (e) { console.error(e); + } finally { + setisLoading(false); } }; useEffect(() => { - getProducts(order, pageNum); - setLoading(false); - }, [order, pageNum]); + /** + * 현재 뷰포트에 맞추어 count를 담을 객체 + */ + let currentItemCounts; - useEffect(() => { - getBestProducts(); - }, []); + if (isMobile) { + // 모바일 뷰 + currentItemCounts = { best: 1, all: 4 }; + } else if (isTablet) { + // 태블릿 뷰 + currentItemCounts = { best: 2, all: 6 }; + } else { + // 데스크탑 뷰 + currentItemCounts = { best: 4, all: 10 }; + } + + setItemsCounts(currentItemCounts); + getProducts(order, pageNum, currentItemCounts.all); + getBestProducts(currentItemCounts.best); + }, [isTablet, isMobile, order, pageNum]); return ( <>

    베스트 상품

    - + {!isLoading && }
    @@ -101,13 +124,13 @@ export default function Items() {
    - + {!isLoading && }
    diff --git a/src/styles/components/dropDownList.css b/src/styles/components/dropDownList.css index c51e932d..f4a7b31a 100644 --- a/src/styles/components/dropDownList.css +++ b/src/styles/components/dropDownList.css @@ -60,3 +60,23 @@ border: none; border-radius: 12px; } + +@media (max-width: 768px) { + .dropdown-container { + width: 42px; + left: 91px; + } + + .dropdown-btn { + width: 42px; + text-indent: -9999px; + background-image: url('../../assets/icons/ic_sort.svg'); + background-position: center; + background-repeat: no-repeat; + } + + .dropdown-box { + left: 100%; + transform: translate(-100%); + } +} diff --git a/src/styles/items/items.css b/src/styles/items/items.css index cf7aecf5..bd6a7a69 100644 --- a/src/styles/items/items.css +++ b/src/styles/items/items.css @@ -56,12 +56,13 @@ .product-container { display: grid; - grid-template-columns: repeat(4, 1fr); + grid-template-columns: repeat(4, 282px); + gap: 24px; } .product-all { grid-template-columns: repeat(5, 1fr); - gap: 35px; + gap: 21px; } .product-img { @@ -72,8 +73,8 @@ .product-img-all { border-radius: 16px; - width: 212px; - height: 212px; + width: 221px; + height: 221px; } .product-name { @@ -96,3 +97,82 @@ margin-left: 5px; color: var(--gray600); } + +/* tablet */ +@media (max-width: 1200px) { + .items-best-container { + width: 696px; + /* margin: 0px 10px 0px 10px; */ + justify-content: center; + } + + .items-list-container { + width: 696px; + } + + .items-search { + width: 242px; + } + + .product-container { + grid-template-columns: repeat(2, 1fr); + } + + .product-all { + display: grid; + grid-template-columns: repeat(3, 1fr); + grid-template-rows: repeat(2, 1fr); + gap: 15px; + } + + .product-img { + border-radius: 16px; + width: 343px; + height: 343px; + } +} + +/* mobile */ +@media (max-width: 768px) { + .items-best-container { + width: 344px; + } + + .items-list-container { + width: 344px; + } + + .items-menus { + display: grid; + grid-template-columns: 211px 133px; + row-gap: 5px; + margin-bottom: 10px; + } + + .title-text { + margin: 0; + grid-row: 1 / 2; + grid-column: 1 / 2; + } + + .items-search { + width: 288px; + grid-row: 2 / 3; + /* grid-column: 2 / 3; */ + } + + .items-add-btn { + margin: 0; + grid-row: 1 / 2; + } + + .product-all { + grid-template-columns: repeat(2, 168px); + gap: 10px; + } + + .product-img-all { + width: 168px; + height: 168px; + } +} diff --git a/src/styles/layout/header.css b/src/styles/layout/header.css index fdb828f3..965958bb 100644 --- a/src/styles/layout/header.css +++ b/src/styles/layout/header.css @@ -75,14 +75,14 @@ header { } /* tablet */ -@media (max-width: 1199px) { +@media (max-width: 1200px) { .logo { padding: 10px 24px; } } /* mobile */ -@media (max-width: 767px) { +@media (max-width: 768px) { .logo { padding: 10px 16px; } From 28dd6937db7d9fe73f863c5f52240d851e883635 Mon Sep 17 00:00:00 2001 From: Imhwitae Date: Thu, 31 Jul 2025 14:25:34 +0900 Subject: [PATCH 48/94] =?UTF-8?q?fix:=20pagination=20=EB=A1=9C=EC=A7=81=20?= =?UTF-8?q?=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/Pagination.jsx | 60 ++++++++++++++++++++--------------- src/pages/items/Items.jsx | 2 +- 2 files changed, 36 insertions(+), 26 deletions(-) diff --git a/src/components/Pagination.jsx b/src/components/Pagination.jsx index eab75a48..7a847245 100644 --- a/src/components/Pagination.jsx +++ b/src/components/Pagination.jsx @@ -1,4 +1,4 @@ -import { useState } from 'react'; +import { useEffect, useState } from 'react'; import '../styles/components/pagination.css'; export default function Pagination({ @@ -10,7 +10,40 @@ export default function Pagination({ /** * 페이지 번호를 표시할 배열 */ - const [pageArr, setPageArr] = useState([1, 2, 3, 4, 5]); + const [pageArr, setPageArr] = useState([]); + + /** + * 페이지의 총 개수 + */ + const totalPageCount = Math.ceil(totalCount / contentNum); + + /** + * 보여질 페이지 그룹 + */ + const pageGroup = Math.ceil(currentNum / 5); + + /** + * 페이지 그룹별 첫 번째 번호 + */ + const pageFirstNum = (pageGroup - 1) * 5 + 1; + + /** + * 페이지 그룹별 마지막 번호 + */ + const pageLastNum = + pageGroup * 5 > totalPageCount ? totalPageCount : pageGroup * 5; + + useEffect(() => { + let pages = []; + + for (let i = pageFirstNum; i <= pageLastNum; i++) { + pages.push(i); + } + + setPageArr(pages); + + console.log(pages); + }, [pageGroup, contentNum]); /** * 화살표 모양으로 다음 페이지로 이동할 때 이벤트 @@ -19,23 +52,6 @@ export default function Pagination({ const onClickMoveNext = (e) => { e.stopPropagation(); setPageNum(currentNum + 1); - - if (!(currentNum % 5)) { - if (totalCount - currentNum * contentNum > 50) { - setPageArr((prevState) => { - return prevState.map((el) => el + 5); - }); - } else { - setPageArr((prevState) => { - return Array.from( - { - length: (totalCount - currentNum * 10) % 5, - }, - (_, idx) => prevState[idx] + 5 - ); - }); - } - } }; /** @@ -45,12 +61,6 @@ export default function Pagination({ const onClickMovePrev = (e) => { e.stopPropagation(); setPageNum(currentNum - 1); - - if (currentNum % 5 === 1) { - setPageArr( - Array.from({ length: 5 }, (_, idx) => currentNum - 1 - (5 - (idx + 1))) - ); - } }; return ( diff --git a/src/pages/items/Items.jsx b/src/pages/items/Items.jsx index 946163c7..f62d41d2 100644 --- a/src/pages/items/Items.jsx +++ b/src/pages/items/Items.jsx @@ -130,7 +130,7 @@ export default function Items() { currentNum={pageNum} setPageNum={setPageNum} totalCount={products.totalCount} - // contentNum={media.allItmesCount} + contentNum={itemCounts.all} />
    From 5a3741d72dc8d3b6b284a65546731174f14fe8f7 Mon Sep 17 00:00:00 2001 From: Imhwitae Date: Thu, 31 Jul 2025 14:27:48 +0900 Subject: [PATCH 49/94] =?UTF-8?q?fix:=20pagination=20=EB=B2=84=ED=8A=BC=20?= =?UTF-8?q?=EB=A1=9C=EC=A7=81=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/Pagination.jsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/Pagination.jsx b/src/components/Pagination.jsx index 7a847245..aa4a59e7 100644 --- a/src/components/Pagination.jsx +++ b/src/components/Pagination.jsx @@ -99,7 +99,7 @@ export default function Pagination({ ); })} - {pageArr.length < 5 ? ( + {totalPageCount === currentNum ? (
  • e.stopPropagation()} From a562fe0a0826f5081ecba0ddb00e8018a6a4eb90 Mon Sep 17 00:00:00 2001 From: Imhwitae Date: Mon, 4 Aug 2025 11:59:22 +0900 Subject: [PATCH 50/94] =?UTF-8?q?fix:=20=EC=BD=94=EB=93=9C=EB=A6=AC?= =?UTF-8?q?=EB=B7=B0=20=EA=B0=9C=EC=84=A0=20=EC=82=AC=ED=95=AD=20=EB=B0=98?= =?UTF-8?q?=EC=98=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/DropdownList.jsx | 18 ++++++++--------- src/components/Pagination.jsx | 2 -- src/hooks/useMediaQuery.jsx | 9 +++++---- src/pages/auth/Signup.jsx | 14 ++++++++++--- src/pages/items/Items.jsx | 35 +++++++++++++++++++++++++-------- src/services/itemsApi.js | 12 ++++------- 6 files changed, 56 insertions(+), 34 deletions(-) diff --git a/src/components/DropdownList.jsx b/src/components/DropdownList.jsx index c9eff705..9d0d1b84 100644 --- a/src/components/DropdownList.jsx +++ b/src/components/DropdownList.jsx @@ -1,15 +1,15 @@ import '../styles/components/dropDownList.css'; import { memo, useEffect, useState } from 'react'; -function DropdownList({ changeOrder }) { - /** - * 드롭다운 리스트 메뉴 - */ - const orderList = [ - { name: '최신순', value: 'recent' }, - { name: '좋아요순', value: 'favorite' }, - ]; +/** + * 드롭다운 리스트 메뉴 + */ +const orderList = [ + { name: '최신순', value: 'recent' }, + { name: '좋아요순', value: 'favorite' }, +]; +function DropdownList({ changeOrder }) { const [order, setOrder] = useState(orderList[0].name); /** @@ -21,7 +21,7 @@ function DropdownList({ changeOrder }) { * 드롭다운 리스트 열림/닫힘 이벤트 */ const onClickOpen = () => { - setIsOpen(!isOpen); + setIsOpen((prevState) => !prevState); }; /** diff --git a/src/components/Pagination.jsx b/src/components/Pagination.jsx index aa4a59e7..50fb094d 100644 --- a/src/components/Pagination.jsx +++ b/src/components/Pagination.jsx @@ -41,8 +41,6 @@ export default function Pagination({ } setPageArr(pages); - - console.log(pages); }, [pageGroup, contentNum]); /** diff --git a/src/hooks/useMediaQuery.jsx b/src/hooks/useMediaQuery.jsx index 09c74579..65806367 100644 --- a/src/hooks/useMediaQuery.jsx +++ b/src/hooks/useMediaQuery.jsx @@ -11,15 +11,16 @@ export default function useMediaQuery(query) { /** * 반환할 데이터를 담아둘 state */ + const [isMatch, setIsMatch] = useState(() => getMatches(query)); + const handleChange = (e) => { + setIsMatch(e.matches); + }; + useEffect(() => { const media = window.matchMedia(query); - const handleChange = (e) => { - setIsMatch(e.matches); - }; - media.addEventListener('change', handleChange); return () => { diff --git a/src/pages/auth/Signup.jsx b/src/pages/auth/Signup.jsx index 024f5f3b..eea9e1d8 100644 --- a/src/pages/auth/Signup.jsx +++ b/src/pages/auth/Signup.jsx @@ -32,15 +32,23 @@ export default function Signup() { pw: '', }); + const onValid = (data) => { + console.log('✅ 유효성 검사 성공! 데이터:', data); + setSignupForm(data); + }; + /** * React-Hook-Form 사용 객체 선언 */ const { register, - formState: { errors }, + formState: { errors, isValid }, handleSubmit, getValues, - } = useForm({ mode: 'onBlur' }); + } = useForm({ + mode: 'onBlur', + }); + console.log(isValid); return ( <> @@ -52,7 +60,7 @@ export default function Signup() {
  • -
    +
    From 3cb423033a0f51767cf27de24b3447db124828b6 Mon Sep 17 00:00:00 2001 From: Imhwitae Date: Tue, 5 Aug 2025 21:42:29 +0900 Subject: [PATCH 52/94] =?UTF-8?q?feat:=20=EC=83=81=ED=92=88=20=EB=93=B1?= =?UTF-8?q?=EB=A1=9D=20=ED=8E=98=EC=9D=B4=EC=A7=80=20UI=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80,=20styled=20component=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- package-lock.json | 143 +++++++++++++++++++++++++++++++++-- package.json | 3 +- src/assets/icons/ic_X.svg | 5 ++ src/assets/icons/ic_plus.svg | 4 + src/components/ImgInput.jsx | 104 +++++++++++++++++++++++++ src/pages/items/AddItems.jsx | 105 ++++++++++++++++++++++++- src/styles/commonStyles.js | 15 ++++ 7 files changed, 372 insertions(+), 7 deletions(-) create mode 100644 src/assets/icons/ic_X.svg create mode 100644 src/assets/icons/ic_plus.svg create mode 100644 src/components/ImgInput.jsx create mode 100644 src/styles/commonStyles.js diff --git a/package-lock.json b/package-lock.json index b1c04feb..ab8993f0 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11,7 +11,8 @@ "react": "^18.2.0", "react-dom": "^18.2.0", "react-hook-form": "^7.60.0", - "react-router": "^7.6.3" + "react-router": "^7.6.3", + "styled-components": "^6.1.19" }, "devDependencies": { "@types/react": "^18.2.66", @@ -320,6 +321,27 @@ "node": ">=6.9.0" } }, + "node_modules/@emotion/is-prop-valid": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/@emotion/is-prop-valid/-/is-prop-valid-1.2.2.tgz", + "integrity": "sha512-uNsoYd37AFmaCdXlg6EYD1KaPOaRWRByMCYzbKUX4+hhMfrxdVSelShywL4JVaAeM/eHUOSprYBQls+/neX3pw==", + "license": "MIT", + "dependencies": { + "@emotion/memoize": "^0.8.1" + } + }, + "node_modules/@emotion/memoize": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/@emotion/memoize/-/memoize-0.8.1.tgz", + "integrity": "sha512-W2P2c/VRW1/1tLox0mVUalvnWXxavmv/Oum2aPsRcoDJuob75FC3Y8FbpfLwUegRcxINtGUMPq0tFCvYNTBXNA==", + "license": "MIT" + }, + "node_modules/@emotion/unitless": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/@emotion/unitless/-/unitless-0.8.1.tgz", + "integrity": "sha512-KOEGMu6dmJZtpadb476IsZBclKvILjopjUii3V+7MnXIQCYh8W3NgNcgwo21n9LXZX6EDIKvqfjYxXebDwxKmQ==", + "license": "MIT" + }, "node_modules/@esbuild/aix-ppc64": { "version": "0.21.5", "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.21.5.tgz", @@ -1256,6 +1278,12 @@ "@types/react": "^18.0.0" } }, + "node_modules/@types/stylis": { + "version": "4.2.5", + "resolved": "https://registry.npmjs.org/@types/stylis/-/stylis-4.2.5.tgz", + "integrity": "sha512-1Xve+NMN7FWjY14vLoY5tL3BVEQ/n42YLwaqJIPYhotZ9uBHt87VceMwWQpzmdEt2TNXIorIFG+YeCUUW7RInw==", + "license": "MIT" + }, "node_modules/@ungap/structured-clone": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.3.0.tgz", @@ -1632,6 +1660,15 @@ "node": ">=6" } }, + "node_modules/camelize": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/camelize/-/camelize-1.0.1.tgz", + "integrity": "sha512-dU+Tx2fsypxTgtLoE36npi3UqcjSSMNYfkqgmoEhtZrraP5VWq0K7FkWVTYa8eMPtnU/G2txVsfdCJTn9uzpuQ==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/caniuse-lite": { "version": "1.0.30001727", "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001727.tgz", @@ -1728,11 +1765,30 @@ "node": ">= 8" } }, + "node_modules/css-color-keywords": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/css-color-keywords/-/css-color-keywords-1.0.0.tgz", + "integrity": "sha512-FyyrDHZKEjXDpNJYvVsV960FiqQyXc/LlYmsxl2BcdMb2WPx0OGRVgTg55rPSyLSNMqP52R9r8geSp7apN3Ofg==", + "license": "ISC", + "engines": { + "node": ">=4" + } + }, + "node_modules/css-to-react-native": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/css-to-react-native/-/css-to-react-native-3.2.0.tgz", + "integrity": "sha512-e8RKaLXMOFii+02mOlqwjbD00KSEKqblnpO9e++1aXS1fPQOpS1YoqdVHBqPjHNoxeF2mimzVqawm2KCbEdtHQ==", + "license": "MIT", + "dependencies": { + "camelize": "^1.0.0", + "css-color-keywords": "^1.0.0", + "postcss-value-parser": "^4.0.2" + } + }, "node_modules/csstype": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==", - "dev": true, "license": "MIT" }, "node_modules/data-view-buffer": { @@ -3434,7 +3490,6 @@ "version": "3.3.11", "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz", "integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==", - "dev": true, "funding": [ { "type": "github", @@ -3703,7 +3758,6 @@ "version": "1.1.1", "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", - "dev": true, "license": "ISC" }, "node_modules/possible-typed-array-names": { @@ -3745,6 +3799,12 @@ "node": "^10 || ^12 || >=14" } }, + "node_modules/postcss-value-parser": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", + "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", + "license": "MIT" + }, "node_modules/prelude-ls": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", @@ -4171,6 +4231,12 @@ "node": ">= 0.4" } }, + "node_modules/shallowequal": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/shallowequal/-/shallowequal-1.1.0.tgz", + "integrity": "sha512-y0m1JoUZSlPAjXVtPPW70aZWfIL/dSP7AFkRnniLCrK/8MDKog3TySTBmckD+RObVxH0v4Tox67+F14PdED2oQ==", + "license": "MIT" + }, "node_modules/shebang-command": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", @@ -4274,7 +4340,6 @@ "version": "1.2.1", "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", - "dev": true, "license": "BSD-3-Clause", "engines": { "node": ">=0.10.0" @@ -4418,6 +4483,68 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/styled-components": { + "version": "6.1.19", + "resolved": "https://registry.npmjs.org/styled-components/-/styled-components-6.1.19.tgz", + "integrity": "sha512-1v/e3Dl1BknC37cXMhwGomhO8AkYmN41CqyX9xhUDxry1ns3BFQy2lLDRQXJRdVVWB9OHemv/53xaStimvWyuA==", + "license": "MIT", + "dependencies": { + "@emotion/is-prop-valid": "1.2.2", + "@emotion/unitless": "0.8.1", + "@types/stylis": "4.2.5", + "css-to-react-native": "3.2.0", + "csstype": "3.1.3", + "postcss": "8.4.49", + "shallowequal": "1.1.0", + "stylis": "4.3.2", + "tslib": "2.6.2" + }, + "engines": { + "node": ">= 16" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/styled-components" + }, + "peerDependencies": { + "react": ">= 16.8.0", + "react-dom": ">= 16.8.0" + } + }, + "node_modules/styled-components/node_modules/postcss": { + "version": "8.4.49", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.49.tgz", + "integrity": "sha512-OCVPnIObs4N29kxTjzLfUryOkvZEq+pf8jTF0lg8E7uETuWHA+v7j3c/xJmiqpX450191LlmZfUKkXxkTry7nA==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "nanoid": "^3.3.7", + "picocolors": "^1.1.1", + "source-map-js": "^1.2.1" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/stylis": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/stylis/-/stylis-4.3.2.tgz", + "integrity": "sha512-bhtUjWd/z6ltJiQwg0dUfxEJ+W+jdqQd8TbWLWyeIJHlnsqmGLRFFd8e5mA0AZi/zx90smXRlN66YMTcaSFifg==", + "license": "MIT" + }, "node_modules/supports-color": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", @@ -4451,6 +4578,12 @@ "dev": true, "license": "MIT" }, + "node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==", + "license": "0BSD" + }, "node_modules/type-check": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", diff --git a/package.json b/package.json index d12f9467..27c32455 100644 --- a/package.json +++ b/package.json @@ -13,7 +13,8 @@ "react": "^18.2.0", "react-dom": "^18.2.0", "react-hook-form": "^7.60.0", - "react-router": "^7.6.3" + "react-router": "^7.6.3", + "styled-components": "^6.1.19" }, "devDependencies": { "@types/react": "^18.2.66", diff --git a/src/assets/icons/ic_X.svg b/src/assets/icons/ic_X.svg new file mode 100644 index 00000000..f6674f7f --- /dev/null +++ b/src/assets/icons/ic_X.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/src/assets/icons/ic_plus.svg b/src/assets/icons/ic_plus.svg new file mode 100644 index 00000000..5bb9abf5 --- /dev/null +++ b/src/assets/icons/ic_plus.svg @@ -0,0 +1,4 @@ + + + + diff --git a/src/components/ImgInput.jsx b/src/components/ImgInput.jsx new file mode 100644 index 00000000..b7355114 --- /dev/null +++ b/src/components/ImgInput.jsx @@ -0,0 +1,104 @@ +import { memo, useRef, useState } from 'react'; +import styled from 'styled-components'; +import { palette } from '../styles/commonStyles'; +import icPlus from '../assets/icons/ic_plus.svg'; +import icX from '../assets/icons/ic_X.svg'; + +/** + * input 태그를 감싸는 label + */ +const ImgUpload = styled.label` + width: 282px; + height: 282px; + color: ${palette.gray400}; + background-color: ${palette.gray100}; + background-image: url(${icPlus}); + background-repeat: no-repeat; + background-position: center 90px; + border: none; + border-radius: 12px; + cursor: pointer; + display: inline-block; + padding-top: 160px; + text-align: center; +`; + +/** + * 이미지 미리보기를 표출 + */ +const ProductPreviewImg = styled.img` + width: 282px; + height: 282px; + border-radius: 12px; + margin-left: 30px; + position: relative; +`; + +/** + * 이미지를 삭제할 버튼 + */ +const DeleteButton = styled.button` + width: 22px; + height: 24px; + border-radius: 999px; + border: none; + background-color: ${palette.gray400}; + background-image: url(${icX}); + background-repeat: no-repeat; + background-position: center; + position: absolute; + z-index: 8888; + transform: translate(-150%, 50%); +`; + +/** + * 이미지 등록 버튼을 표출하는 컴포넌트 + * @returns + */ +const ImgInput = () => { + /** + * 미리보기 이미지 문자열을 담는다. + */ + const [imgPreviews, setImgPreviews] = useState(); + const inputRef = useRef(); + + /** + * 업로드한 이미지의 정보를 URL 문자열로 변환 + * @param {event} e + */ + const onChangeUploadImg = (e) => { + const previewImg = e.target.files[0]; + const imgLink = URL.createObjectURL(previewImg); + setImgPreviews(imgLink); + }; + + const onClickDeleteImg = (e) => { + e.preventDefault(); + inputRef.current.value = ''; + setImgPreviews(''); + }; + + return ( + <> +
    + 이미지 등록 + +
    + {imgPreviews && ( +
    + + +
    + )} + + ); +}; + +export default memo(ImgInput); diff --git a/src/pages/items/AddItems.jsx b/src/pages/items/AddItems.jsx index f9234145..bab2854f 100644 --- a/src/pages/items/AddItems.jsx +++ b/src/pages/items/AddItems.jsx @@ -1 +1,104 @@ -export default function AddItems() {} +import styled from 'styled-components'; +import ImgInput from '../../components/ImgInput'; +import { palette } from '../../styles/commonStyles'; + +const ItemContainer = styled.div` + width: 1200px; + display: flex; + flex-direction: column; + margin: 0px auto; + margin-bottom: 20px; +`; + +const ItemTitleBox = styled.div` + width: 1200px; + display: flex; + justify-content: space-between; + align-items: center; + margin: 20px auto; +`; + +const ItemImgBox = styled(ItemTitleBox)` + justify-content: start; + margin: 0 auto; +`; + +/** + * 페이지 타이틀 + * sub 옵션으로 서브 타이트롤 변환 + */ +const PageTitle = styled.h1` + font-size: ${({ sub }) => (sub ? `18px` : `20px`)}; + font-weight: 700; +`; + +/** + * 등록 버튼 + */ +const SubmitButton = styled.button` + width: 74px; + height: 42px; + border: none; + border-radius: 8px; + background-color: #9ca3af; + color: white; + font-size: 16px; + font-weight: 600; +`; + +/** + * 상품 정보 입력 input + */ +const TextInput = styled.input` + height: ${({ wide }) => (wide ? `282px` : `56px`)}; + border: none; + border-radius: 12px; + background-color: ${palette.gray100}; + padding: 20px; + font-size: 16px; + color: ${palette.gray400}; + position: relative; + + ${({ wide }) => + wide ? `&::placeholder {position: absolute; top: 20px;}` : ``} +`; + +export default function AddItems() { + return ( + <> +
    + + 상품 등록하기 + 등록 + + + + 상품 이미지 + + + + + + + 상품명 + + + + + 상품 소개 + + + + + 판매 가격 + + + + + 태그 + + +
    + + ); +} diff --git a/src/styles/commonStyles.js b/src/styles/commonStyles.js new file mode 100644 index 00000000..e06d8262 --- /dev/null +++ b/src/styles/commonStyles.js @@ -0,0 +1,15 @@ +import styled from 'styled-components'; + +export const palette = { + gray900: '#111827', + gray800: '#1f2937', + gray700: '#374151', + gray600: '#4b5563', + gray500: '#6b7280', + gray400: '#9ca3af', + gray200: '#e5e7eb', + gray100: '#f3f4f6', + gray50: '#f9fafb', + blue: '#3692ff', + menu: '#4b5563', +}; From 3ecc116f01ac667eeeca20842f125731ffb7eb80 Mon Sep 17 00:00:00 2001 From: Imhwitae Date: Tue, 5 Aug 2025 22:25:55 +0900 Subject: [PATCH 53/94] =?UTF-8?q?feat:=20=ED=95=B4=EC=8B=9C=ED=83=9C?= =?UTF-8?q?=EA=B7=B8=20=EC=BB=B4=ED=8F=AC=EB=84=8C=ED=8A=B8=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/HashTag.jsx | 42 +++++++++++++++++++++++++ src/components/ImgInput.jsx | 2 +- src/pages/items/AddItems.jsx | 59 ++++++++++++++++++++---------------- 3 files changed, 76 insertions(+), 27 deletions(-) create mode 100644 src/components/HashTag.jsx diff --git a/src/components/HashTag.jsx b/src/components/HashTag.jsx new file mode 100644 index 00000000..d1927f60 --- /dev/null +++ b/src/components/HashTag.jsx @@ -0,0 +1,42 @@ +import styled from 'styled-components'; +import { palette } from '../styles/commonStyles'; +import { DeleteButton } from './ImgInput'; + +const ItmesTag = styled.div` + width: 110px; + height: 36px; + border: none; + background-color: ${palette.gray100}; + font-size: 16px; + border-radius: 999px; + display: flex; + justify-content: space-evenly; + align-items: center; + padding: 5px; + margin-right: 10px; +`; + +const ItemsTagDeleteButton = styled(DeleteButton)` + position: relative; + z-index: 0; + transform: none; +`; + +/** + * 태그 컴포넌트 + * @returns + */ +const HashTag = ({ children }) => { + return ( + <> +
    + + {children} + + +
    + + ); +}; + +export default HashTag; diff --git a/src/components/ImgInput.jsx b/src/components/ImgInput.jsx index b7355114..28da5d79 100644 --- a/src/components/ImgInput.jsx +++ b/src/components/ImgInput.jsx @@ -37,7 +37,7 @@ const ProductPreviewImg = styled.img` /** * 이미지를 삭제할 버튼 */ -const DeleteButton = styled.button` +export const DeleteButton = styled.button` width: 22px; height: 24px; border-radius: 999px; diff --git a/src/pages/items/AddItems.jsx b/src/pages/items/AddItems.jsx index bab2854f..017f76c0 100644 --- a/src/pages/items/AddItems.jsx +++ b/src/pages/items/AddItems.jsx @@ -1,6 +1,7 @@ import styled from 'styled-components'; import ImgInput from '../../components/ImgInput'; import { palette } from '../../styles/commonStyles'; +import HashTag from '../../components/HashTag'; const ItemContainer = styled.div` width: 1200px; @@ -67,37 +68,43 @@ export default function AddItems() { return ( <>
    - - 상품 등록하기 - 등록 - + + + 상품 등록하기 + 등록 + - - 상품 이미지 - - - - + + 상품 이미지 + + + + - - 상품명 - - + + 상품명 + + - - 상품 소개 - - + + 상품 소개 + + - - 판매 가격 - - + + 판매 가격 + + - - 태그 - - + + 태그 + +
    + #티셔츠 + #티셔츠 +
    +
    +
    ); From 78904878a82e2d0541ee771c7599758380423a05 Mon Sep 17 00:00:00 2001 From: Imhwitae Date: Wed, 6 Aug 2025 23:19:43 +0900 Subject: [PATCH 54/94] =?UTF-8?q?feat:=20=ED=83=9C=EA=B7=B8=20UI=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80,=20form=20=EB=82=B4=EC=9A=A9=20=ED=99=95?= =?UTF-8?q?=EC=9D=B8=ED=95=98=EC=97=AC=20=EB=93=B1=EB=A1=9D=20=EB=B2=84?= =?UTF-8?q?=ED=8A=BC=20=ED=99=9C=EC=84=B1=ED=99=94=20=EA=B8=B0=EB=8A=A5=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .eslintrc.cjs | 2 +- src/components/HashTag.jsx | 42 ---------- src/components/ImgInput.jsx | 32 ++++--- src/pages/items/AddItems.jsx | 157 ++++++++++++++++++++++++++++++----- src/styles/commonStyles.js | 41 ++++++--- 5 files changed, 189 insertions(+), 85 deletions(-) delete mode 100644 src/components/HashTag.jsx diff --git a/.eslintrc.cjs b/.eslintrc.cjs index 3e212e1d..3dca2b7a 100644 --- a/.eslintrc.cjs +++ b/.eslintrc.cjs @@ -18,4 +18,4 @@ module.exports = { { allowConstantExport: true }, ], }, -} +}; diff --git a/src/components/HashTag.jsx b/src/components/HashTag.jsx deleted file mode 100644 index d1927f60..00000000 --- a/src/components/HashTag.jsx +++ /dev/null @@ -1,42 +0,0 @@ -import styled from 'styled-components'; -import { palette } from '../styles/commonStyles'; -import { DeleteButton } from './ImgInput'; - -const ItmesTag = styled.div` - width: 110px; - height: 36px; - border: none; - background-color: ${palette.gray100}; - font-size: 16px; - border-radius: 999px; - display: flex; - justify-content: space-evenly; - align-items: center; - padding: 5px; - margin-right: 10px; -`; - -const ItemsTagDeleteButton = styled(DeleteButton)` - position: relative; - z-index: 0; - transform: none; -`; - -/** - * 태그 컴포넌트 - * @returns - */ -const HashTag = ({ children }) => { - return ( - <> -
    - - {children} - - -
    - - ); -}; - -export default HashTag; diff --git a/src/components/ImgInput.jsx b/src/components/ImgInput.jsx index 28da5d79..3d7c6fdc 100644 --- a/src/components/ImgInput.jsx +++ b/src/components/ImgInput.jsx @@ -1,8 +1,8 @@ -import { memo, useRef, useState } from 'react'; -import styled from 'styled-components'; -import { palette } from '../styles/commonStyles'; -import icPlus from '../assets/icons/ic_plus.svg'; -import icX from '../assets/icons/ic_X.svg'; +import { memo, useRef, useState } from "react"; +import styled from "styled-components"; +import { palette } from "../styles/commonStyles"; +import icPlus from "../assets/icons/ic_plus.svg"; +import icX from "../assets/icons/ic_X.svg"; /** * input 태그를 감싸는 label @@ -53,13 +53,12 @@ export const DeleteButton = styled.button` /** * 이미지 등록 버튼을 표출하는 컴포넌트 - * @returns */ -const ImgInput = () => { +const ImgInput = ({ isUpload, setIsUpload }) => { /** * 미리보기 이미지 문자열을 담는다. */ - const [imgPreviews, setImgPreviews] = useState(); + const [imgPreviews, setImgPreviews] = useState(""); const inputRef = useRef(); /** @@ -67,15 +66,25 @@ const ImgInput = () => { * @param {event} e */ const onChangeUploadImg = (e) => { + if (imgPreviews !== "") { + setIsUpload(true); + return; + } + const previewImg = e.target.files[0]; const imgLink = URL.createObjectURL(previewImg); setImgPreviews(imgLink); }; + /** + * 미리보기 이미지를 지우는 함수 + * @param {Event} e + */ const onClickDeleteImg = (e) => { e.preventDefault(); - inputRef.current.value = ''; - setImgPreviews(''); + inputRef.current.value = ""; + setImgPreviews(""); + setIsUpload(false); }; return ( @@ -88,7 +97,8 @@ const ImgInput = () => { accept="image/*" onChange={onChangeUploadImg} ref={inputRef} - style={{ display: 'none' }} + style={{ display: "none" }} + disabled={isUpload} />
    {imgPreviews && ( diff --git a/src/pages/items/AddItems.jsx b/src/pages/items/AddItems.jsx index 017f76c0..fef84ae7 100644 --- a/src/pages/items/AddItems.jsx +++ b/src/pages/items/AddItems.jsx @@ -1,7 +1,8 @@ -import styled from 'styled-components'; -import ImgInput from '../../components/ImgInput'; -import { palette } from '../../styles/commonStyles'; -import HashTag from '../../components/HashTag'; +import styled from "styled-components"; +import ImgInput, { DeleteButton } from "../../components/ImgInput"; +import { ItemsTag, palette } from "../../styles/commonStyles"; +import { useCallback, useEffect, useRef, useState } from "react"; +import { useFieldArray, useForm } from "react-hook-form"; const ItemContainer = styled.div` width: 1200px; @@ -41,7 +42,8 @@ const SubmitButton = styled.button` height: 42px; border: none; border-radius: 8px; - background-color: #9ca3af; + background-color: ${({ isValid }) => + isValid ? `${palette.blue}` : `${palette.gray400}`}; color: white; font-size: 16px; font-weight: 600; @@ -51,57 +53,174 @@ const SubmitButton = styled.button` * 상품 정보 입력 input */ const TextInput = styled.input` - height: ${({ wide }) => (wide ? `282px` : `56px`)}; + height: 56px; border: none; border-radius: 12px; background-color: ${palette.gray100}; padding: 20px; font-size: 16px; - color: ${palette.gray400}; position: relative; + &::placeholder { + color: ${palette.gray400}; + } +`; + +/** + * 상품 소개 입력 textarea + */ +const TextArea = styled.textarea` + height: 282px; + border: none; + border-radius: 12px; + background-color: ${palette.gray100}; + padding: 20px; + font-size: 16px; + position: relative; + font-family: "Pretendard-Regular"; + &::placeholder { + color: ${palette.gray400}; + } +`; - ${({ wide }) => - wide ? `&::placeholder {position: absolute; top: 20px;}` : ``} +const ItemsTagDeleteButton = styled(DeleteButton)` + position: relative; + z-index: 0; + transform: none; `; +/** + * 상품 등록 페이지 컴포넌트 + */ export default function AddItems() { + /** + * 이미지가 등록되어있는지 여부를 확인하는 state + */ + const [isUpload, setIsUpload] = useState(false); + + const { + register, + handleSubmit, + control, + formState: { error, isValid }, + } = useForm({ + mode: "onChange", + defaultValues: { productName: "", description: "", price: "" }, + }); + + const { fields, append, remove } = useFieldArray({ + control, + name: "tags", + rules: { + required: true, + }, + }); + + /** + * 입력받은 가격을 원화 형식으로 변환하는 함수 + * @param {React.ChangeEvent} e + */ + const onChangePrice = (e) => { + console.log(e.target.value); + + let rawPrice = e.target.value.replace(/[^0-9]/g, ""); + + if (rawPrice === "") { + e.target.value = ""; + return; + } + + let formattedPrice = Number(rawPrice).toLocaleString("ko-KR"); + e.target.value = formattedPrice; + }; + + /** + * Enter키를 입력으로 태그를 form에 등록하고 태그 입력 창을 비우는 만드는 함수 + * @param {Event} e + */ + const onKeyDownAppendTag = (e) => { + if (e.key === "Enter" && e.target.value !== "") { + append({ value: e.target.value }); + e.target.value = ""; + } + }; + + const onSubmit = (e) => { + e.preventDefault; + }; + return ( <>
    -
    + 상품 등록하기 - 등록 + 등록 상품 이미지 - + + {isUpload && ( +

    + *이미지 등록은 최대 1개까지 가능합니다. +

    + )}
    상품명 - + 상품 소개 - + 판매 가격 - + onChangePrice(e), + })} + /> 태그 - -
    - #티셔츠 - #티셔츠 + +
    + {fields.map((tag, idx) => { + return ( + + {`#${tag.value}`} + remove(idx)} + > + + ); + })}
    diff --git a/src/styles/commonStyles.js b/src/styles/commonStyles.js index e06d8262..bb58912d 100644 --- a/src/styles/commonStyles.js +++ b/src/styles/commonStyles.js @@ -1,15 +1,32 @@ -import styled from 'styled-components'; +import styled from "styled-components"; export const palette = { - gray900: '#111827', - gray800: '#1f2937', - gray700: '#374151', - gray600: '#4b5563', - gray500: '#6b7280', - gray400: '#9ca3af', - gray200: '#e5e7eb', - gray100: '#f3f4f6', - gray50: '#f9fafb', - blue: '#3692ff', - menu: '#4b5563', + gray900: "#111827", + gray800: "#1f2937", + gray700: "#374151", + gray600: "#4b5563", + gray500: "#6b7280", + gray400: "#9ca3af", + gray200: "#e5e7eb", + gray100: "#f3f4f6", + gray50: "#f9fafb", + blue: "#3692ff", + menu: "#4b5563", }; + +/** + * 태그 지우기 버튼 div + */ +export const ItemsTag = styled.div` + gap: 10px; + height: 36px; + border: none; + background-color: ${palette.gray100}; + font-size: 16px; + border-radius: 999px; + display: flex; + justify-content: space-evenly; + align-items: center; + padding: 15px; + margin-right: 10px; +`; From ff81ffd1d44f3e5eb7a58ddc74266be78fb3ddd9 Mon Sep 17 00:00:00 2001 From: Imhwitae Date: Thu, 7 Aug 2025 15:51:13 +0900 Subject: [PATCH 55/94] =?UTF-8?q?feat:=20=EB=B0=98=EC=9D=91=ED=98=95=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80,=20=EC=9D=B4=EB=AF=B8=EC=A7=80=20=EB=93=B1?= =?UTF-8?q?=EB=A1=9D=20=EC=97=90=EB=9F=AC=EB=A9=94=EC=8B=9C=EC=A7=80=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/ImgInput.jsx | 24 +++++++++++++++++++++++- src/pages/items/AddItems.jsx | 26 ++++++++++++++++++++++++-- 2 files changed, 47 insertions(+), 3 deletions(-) diff --git a/src/components/ImgInput.jsx b/src/components/ImgInput.jsx index 3d7c6fdc..a701471c 100644 --- a/src/components/ImgInput.jsx +++ b/src/components/ImgInput.jsx @@ -21,6 +21,13 @@ const ImgUpload = styled.label` display: inline-block; padding-top: 160px; text-align: center; + + @media (max-width: 1200px) { + width: 168px; + height: 168px; + background-position: center 40px; + padding-top: 100px; + } `; /** @@ -32,6 +39,12 @@ const ProductPreviewImg = styled.img` border-radius: 12px; margin-left: 30px; position: relative; + + @media (max-width: 1200px) { + width: 168px; + height: 168px; + margin-left: 10px; + } `; /** @@ -67,7 +80,6 @@ const ImgInput = ({ isUpload, setIsUpload }) => { */ const onChangeUploadImg = (e) => { if (imgPreviews !== "") { - setIsUpload(true); return; } @@ -87,6 +99,15 @@ const ImgInput = ({ isUpload, setIsUpload }) => { setIsUpload(false); }; + /** + * 이미 등록된 이미지가 있을 때 업로드 상태를 true로 변경하는 함수 + */ + const onClickCheckImg = () => { + if (imgPreviews !== "") { + setIsUpload(true); + } + }; + return ( <>
    @@ -95,6 +116,7 @@ const ImgInput = ({ isUpload, setIsUpload }) => { id="imgUpload" type="file" accept="image/*" + onClick={onClickCheckImg} onChange={onChangeUploadImg} ref={inputRef} style={{ display: "none" }} diff --git a/src/pages/items/AddItems.jsx b/src/pages/items/AddItems.jsx index fef84ae7..1e061161 100644 --- a/src/pages/items/AddItems.jsx +++ b/src/pages/items/AddItems.jsx @@ -1,7 +1,7 @@ import styled from "styled-components"; import ImgInput, { DeleteButton } from "../../components/ImgInput"; import { ItemsTag, palette } from "../../styles/commonStyles"; -import { useCallback, useEffect, useRef, useState } from "react"; +import { useState } from "react"; import { useFieldArray, useForm } from "react-hook-form"; const ItemContainer = styled.div` @@ -10,6 +10,14 @@ const ItemContainer = styled.div` flex-direction: column; margin: 0px auto; margin-bottom: 20px; + + @media (max-width: 1200px) { + width: 696px; + } + + @media (max-width: 768px) { + width: 346px; + } `; const ItemTitleBox = styled.div` @@ -18,6 +26,14 @@ const ItemTitleBox = styled.div` justify-content: space-between; align-items: center; margin: 20px auto; + + @media (max-width: 1200px) { + width: 696px; + } + + @media (max-width: 768px) { + width: 346px; + } `; const ItemImgBox = styled(ItemTitleBox)` @@ -210,7 +226,13 @@ export default function AddItems() { name="tags" onKeyDown={onKeyDownAppendTag} /> -
    +
    {fields.map((tag, idx) => { return ( From d7a1f59590d27690d16502b7ad534f2c836faee6 Mon Sep 17 00:00:00 2001 From: Imhwitae Date: Thu, 7 Aug 2025 17:17:46 +0900 Subject: [PATCH 56/94] =?UTF-8?q?fix:=20=ED=83=9C=EA=B7=B8=20=ED=95=9C?= =?UTF-8?q?=EA=B8=80=20=EC=9E=85=EB=A0=A5=ED=9B=84=20=EB=93=B1=EB=A1=9D?= =?UTF-8?q?=EC=8B=9C=20=EB=91=90=20=EB=B2=88=20=EC=9E=85=EB=A0=A5=EB=90=98?= =?UTF-8?q?=EB=8A=94=20=ED=98=84=EC=83=81=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/App.jsx | 20 +++++----- src/layout/Header.jsx | 20 +++++----- src/pages/items/{AddItems.jsx => AddItem.jsx} | 23 ++++++----- src/pages/items/Items.jsx | 38 +++++++++---------- 4 files changed, 53 insertions(+), 48 deletions(-) rename src/pages/items/{AddItems.jsx => AddItem.jsx} (93%) diff --git a/src/App.jsx b/src/App.jsx index 9acf5420..3c14e592 100644 --- a/src/App.jsx +++ b/src/App.jsx @@ -1,12 +1,12 @@ -import { Route, Routes } from 'react-router'; -import Home from './pages/Home'; -import Login from './pages/auth/Login'; -import MainLayout from './layout/MainLayout'; -import Signup from './pages/auth/Signup'; -import AuthLayout from './layout/AuthLayout'; -import ItemsLayout from './layout/ItemsLayout'; -import Items from './pages/items/Items'; -import AddItems from './pages/items/AddItems'; +import { Route, Routes } from "react-router"; +import Home from "./pages/Home"; +import Login from "./pages/auth/Login"; +import MainLayout from "./layout/MainLayout"; +import Signup from "./pages/auth/Signup"; +import AuthLayout from "./layout/AuthLayout"; +import ItemsLayout from "./layout/ItemsLayout"; +import Items from "./pages/items/Items"; +import AddItem from "./pages/items/AddItem"; function App() { return ( @@ -26,7 +26,7 @@ function App() { {/* 중고 마켓 */} }> } /> - } /> + } /> diff --git a/src/layout/Header.jsx b/src/layout/Header.jsx index 06357c47..1300f215 100644 --- a/src/layout/Header.jsx +++ b/src/layout/Header.jsx @@ -1,6 +1,6 @@ -import '../styles/layout/header.css'; -import ic_profile from '../assets/icons/ic_profile.svg'; -import { Link, NavLink, useLocation } from 'react-router'; +import "../styles/layout/header.css"; +import ic_profile from "../assets/icons/ic_profile.svg"; +import { Link, NavLink, useLocation } from "react-router"; /** * 헤더 @@ -20,15 +20,15 @@ export default function Header() {
    - {location.pathname !== '/' ? ( + {location.pathname !== "/" ? (
    • isActive - ? 'header-menu-text header-active' - : 'header-menu-text' + ? "header-menu-text header-active" + : "header-menu-text" } > 자유게시판 @@ -38,9 +38,9 @@ export default function Header() { - isActive - ? 'header-menu-text header-active' - : 'header-menu-text' + isActive || location.pathname === "/additem" + ? "header-menu-text header-active" + : "header-menu-text" } > 중고마켓 @@ -49,7 +49,7 @@ export default function Header() {
    ) : null} - {location.pathname !== '/' ? ( + {location.pathname !== "/" ? ( 프로필_아이콘 ) : (
    - {!isLoading && } + {!isLoading && }
    Date: Thu, 7 Aug 2025 22:07:54 +0900 Subject: [PATCH 57/94] =?UTF-8?q?feat:=20=EC=95=84=EC=9D=B4=ED=85=9C=20?= =?UTF-8?q?=EC=83=81=EC=84=B8=ED=8E=98=EC=9D=B4=EC=A7=80=20=EB=9D=BC?= =?UTF-8?q?=EC=9A=B0=ED=8C=85=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/App.jsx | 2 ++ src/components/Product.jsx | 47 +++++++++++++++++++--------------- src/pages/items/ItemDetail.jsx | 11 ++++++++ 3 files changed, 40 insertions(+), 20 deletions(-) create mode 100644 src/pages/items/ItemDetail.jsx diff --git a/src/App.jsx b/src/App.jsx index 3c14e592..54629dbc 100644 --- a/src/App.jsx +++ b/src/App.jsx @@ -7,6 +7,7 @@ import AuthLayout from "./layout/AuthLayout"; import ItemsLayout from "./layout/ItemsLayout"; import Items from "./pages/items/Items"; import AddItem from "./pages/items/AddItem"; +import ItemDetail from "./pages/items/ItemDetail"; function App() { return ( @@ -27,6 +28,7 @@ function App() { }> } /> } /> + } /> diff --git a/src/components/Product.jsx b/src/components/Product.jsx index be536947..ededf8ba 100644 --- a/src/components/Product.jsx +++ b/src/components/Product.jsx @@ -1,35 +1,42 @@ -import { memo } from 'react'; -import ic_heart from '../assets/icons/ic_heart.svg'; +import { memo } from "react"; +import ic_heart from "../assets/icons/ic_heart.svg"; +import { Link } from "react-router"; function Product({ products, style }) { return ( <>
    {products && products.map((product) => { return ( -
    - -

    {product.name}

    -

    - {product.price - .toString() - .replace(/\B(?=(\d{3})+(?!\d))/g, ',') + '원'} -

    -
    - 하트_아이콘 - - {product.favoriteCount} - + +
    + +

    {product.name}

    +

    + {product.price + .toString() + .replace(/\B(?=(\d{3})+(?!\d))/g, ",") + "원"} +

    +
    + 하트_아이콘 + + {product.favoriteCount} + +
    -
    + ); })}
    diff --git a/src/pages/items/ItemDetail.jsx b/src/pages/items/ItemDetail.jsx new file mode 100644 index 00000000..fca86dca --- /dev/null +++ b/src/pages/items/ItemDetail.jsx @@ -0,0 +1,11 @@ +import { useParams } from "react-router"; + +export default function ItemDetail() { + const params = useParams(); + + return ( + <> +
    + + ); +} From db26af844ef5c7c58b3f21c51d1329a774d11682 Mon Sep 17 00:00:00 2001 From: Imhwitae Date: Thu, 7 Aug 2025 22:38:30 +0900 Subject: [PATCH 58/94] =?UTF-8?q?docs:=20README=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 154 ++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 149 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index f768e33f..e8b281de 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,152 @@ -# React + Vite +# 판다 마켓 - 중고 거래 플랫폼 -This template provides a minimal setup to get React working in Vite with HMR and some ESLint rules. +## 미션 3 요구사항 -Currently, two official plugins are available: +### 기본 -- [@vitejs/plugin-react](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react/README.md) uses [Babel](https://babeljs.io/) for Fast Refresh -- [@vitejs/plugin-react-swc](https://github.com/vitejs/vite-plugin-react-swc) uses [SWC](https://swc.rs/) for Fast Refresh +- [x] 랜딩 페이지의 url path는 루트(‘/’) 입니다. +- [x] title은 “판다마켓”으로 설정해 주세요. +- [x] 화면의 너비가 1920px 이상이면 하늘색 배경색은 너비를 꽉 채우도록 채워지고, 내부 요소들의 위치는 고정되고, 여백만 커지도록 해주세요. +- [x] 화면의 너비가 1920px 보다 작아질 때, “판다마켓” 로고의 왼쪽 여백 200px“로그인" 버튼의 오른쪽 여백 200px이 유지되고, 화면의 너비가 작아질수록 두 요소간 거리가 가까워지도록 해주세요. +- [x] 클릭으로 기능이 동작해야 하는 경우, 사용자가 클릭할 수 있는 요소임을 알 수 있도록 cursor: pointer를 설정해 주세요. +- [x] “판다마켓” 클릭 시 루트 페이지(‘/’)로 이동시켜주세요. +- [x] “구경하러 가기" 클릭 시 (“/items”)페이지로 이동시켜주세요.(빈 페이지) +- [x] “로그인”버튼 클릭 시 로그인 페이지(‘/login’)로 이동합니다 +- [x] “구경하러가기”버튼 클릭 시(’/items’)로 이동합니다 +- [x] 페이스북, 트위터, 유튜브, 인스타그램 아이콘은 클릭 시 각각의 홈페이지로 새로운 창이 열리면서 이동 합니다 +- [x] “Privacy Policy”, “FAQ”는 클릭 시 각각 아래 페이지로 이동합니다- Privacy 페이지(‘/privacy’) - FAQ 페이지(‘/faq’) + +--- + +- [x] 아래로 스크롤 해도 상단 네비게이션 바(Global Navigation Bar)가 최상단에 고정됩니다. +- [x] “판다마켓" 클릭 시 루트 페이지(“/”)로 이동합니다. (새로고침) +- [x] 로그인 페이지, 회원가입 페이지 모두 로고 위 상단 여백이 동일합니다. +- [x] SNS 아이콘들은 클릭시 각각 아래 페이지로 이동합니다.- “https://www.google.com/”, “https://www.kakaocorp.com/page/” +- [x] “회원 가입”버튼 클릭 시 “/signup” 페이지로 이동합니다. + +--- + +- [x] 브라우저에 현재 보이는 화면의 영역(viewport) 너비를 기준으로 분기되는 반응형 디자인을 적용합니다.- PC: 1200px 이상- Tablet: 768px 이상 ~ 1199px 이하- Mobile: 375px 이상 ~ 767px 이하\* 375px 미만 사이즈의 디자인은 고려하지 않습니다 +- [x] Tablet 사이즈로 작아질 때 “판다마켓” 로고의 왼쪽에 여백 24px, “로그인” 버튼 오른쪽 여백 24px을 유지할 수 있도록 “판다마켓” 로고와 “로그인" 버튼의 간격이 가까워집니다. +- [x] Mobile 사이즈로 작아질 때 “판다마켓” 로고의 왼쪽에 여백 16px, “로그인” 버튼 오른쪽 여백 16px을 유지할 수 있도록 “판다마켓” 로고와 “로그인" 버튼의 간격이 가까워집니다. +- [x] Tablet 사이즈에서 내부 디자인은 PC사이즈와 동일합니다. +- [x] Mobile 사이즈에서 좌우 여백 16px 제외하고 내부 요소들이 너비를 모두 차지합니다. +- [x] Mobile 사이즈에서 내부 요소들의 너비는 기기의 너비가 커지는 만큼 커지지만 400px을 넘지 않습니다. +- [x] Mobile 사이즈에서 좌우 여백 16px 제외하고 내부 요소들이 너비를 모두 차지합니다. +- [x] Mobile 사이즈에서 내부 요소들의 너비는 기기의 너비가 커지는 만큼 커지지만 400px을 넘지 않습니다. + +### 심화 + +- [x] 사용자의 브라우저가 크고 작아짐에 따라 페이지의 요소간 간격, 요소의 크기, font-size 등 모든 크기와 관련된 값이 크고 작아지도록 설정해 보세요.(설정값은 자유입니다) + +--- + +- [x] palette에 있는 color값들을 css 변수로 등록하고 사용합니다. + +--- + +- [x] 페이스북, 카카오톡, 디스코드, 트위터 등 SNS에서 Linkbrary 랜딩 페이지(“/”) 공유 시 좌측 예시와 같은 미리보기를 볼 수 있도록 랜딩 페이지 메타 태그를 설정해 주세요. +- [x] 미리보기에서 제목은 “판다 마켓”, 설명은 “일상의 모든 물건을 거래해보세요”로 설정합니다. +- [x] 주소와 이미지는 자유롭게 설정하세요. + +## 주요 변경사항 + +- Netlify에서 로고 이미지가 보이게 수정했습니다. + +## 스크린샷 + +**메인화면** +| PC | Tablet | Mobile | +| :-: | :----: | :----: | +|![pc_main](https://github.com/user-attachments/assets/ab4254e0-c732-49b6-8eb3-becf313e4a92)|![tablet_main](https://github.com/user-attachments/assets/28e8b861-bf77-47b1-9f60-93267f592650)|![mobile_main](https://github.com/user-attachments/assets/fe76d76f-9b93-4403-8205-ec875e364f7f)| + +
    + +**로그인 화면** +| PC | Mobile | +| :-: | :----: | +|![pc_login](https://github.com/user-attachments/assets/aa9ff9df-8eff-4f13-a7e4-e946ad8fe48f)|![mobile_login](https://github.com/user-attachments/assets/8e1662fb-4544-48ce-a791-40e3e5ce0e28)| + +
    + +**회원가입 화면** +| PC | Mobile | +| :-: | :----: | +|![join_pc](https://github.com/user-attachments/assets/52788e32-a174-4441-abe1-957bc36094e7)|![join_mobile](https://github.com/user-attachments/assets/6222a188-d431-433c-959a-07c052ff61a5)| + +## 멘토에게 + +- 저는 CSS를 작성할 때 대부분의 단위를 `px`로 사용했는데, `rem`, `vw`와 같은 단위를 사용하는 것이 더 나은지 궁금합니다 + > 답변 + > [px vs rem vs em 접근성과 관련된 아티클](https://www.joshwcomeau.com/css/surprising-truth-about-pixels-and-accessibility/) + +
    + +## 미션 5 요구사항 + +### 기본 + +- [x] 중고마켓 페이지 주소는 "/items" 입니다. +- [x] 페이지 주소가 "/items" 일 때 상단 네비게이션 바의 "중고마켓" 버튼의 색상은 "3692FF" 입니다. +- [x] 상단 네비게이션 바는 이전 미션에서 구현한 랜딩 페이지와 동일한 스타일로 만들어주세요 +- [x] 전체 상품에서 드롭다운으로 "최신순" 또는 "좋아요순"을 선택해서 정렬할 수 있습니다. +- [ ] "상품 등록하기" 버튼을 누르면 “/additem” 로 이동합니다 ( 빈 페이지 ) +- [x] 미디어 쿼리를 사용하여 반응형 view 마다 물품 개수를 다르게 보여줍니다 (서버로 요청하는 값은 동일) +- 베스트 상품 + - Desktop : 4개 보이기 + - Tablet : 2개 보이기 + - Mobile : 1개 보이기 +- 전체 상품 + - Desktop : 10개 보이기 + - Tablet : 6개 보이기 + - Mobile : 4개 보이기 + +### 심화 + +- [x] 페이지 네이션 기능을 구현합니다. +- [x] 반응형으로 보여지는 물품들의 개수를 다르게 설정할때 서버에 보내는 pageSize값을 적절하게 설정합니다. + +## 주요 변경사항 + +- 스프린트 미션 1부터 4까지의 내용을 React로 변경했습니다. + > form 변경 내용 + > (React-Hook-form을 이용해 유효성 검사 해보기)[https://velog.io/@nudge0613/React-Hook-Form%EC%9D%84-%EC%9D%B4%EC%9A%A9%ED%95%B4-%ED%9A%8C%EC%9B%90%EA%B0%80%EC%9E%85-%EC%9C%A0%ED%9A%A8%EC%84%B1-%EA%B2%80%EC%82%AC-%ED%95%98%EA%B8%B0] + +## 스크린샷 + +| PC | Tablet | Mobile | +| :-------------------------------------------------------------------------------------------------------------------------------------------------: | :-----------------------------------------------------------------------------------------------------------------------------------------------------: | :----------------------------------------------------------------------------------------------------------------------------------------------------: | +| localhost_5173_items | localhost_5173_items (1) | localhost_5173_items (2) | + +
    + +## 미션 6 요구사항 + +### 기본 + +- [x] 상품 등록 페이지 주소는 “/additem” 입니다. +- [x] 페이지 주소가 “/additem” 일때 상단네비게이션바의 '중고마켓' 버튼의 색상은 “3692FF”입니다. +- [x] 상품 이미지는 최대 한개 업로드가 가능합니다. +- [x] 각 input의 placeholder 값을 정확히 입력해주세요. +- [x] 이미지를 제외하고 input 에 모든 값을 입력하면 ‘등록' 버튼이 활성화 됩니다. +- [ ] API를 통한 상품 등록은 추후 미션에서 적용합니다. + +### 심화 + +- [x] 이미지 안의 X 버튼을 누르면 이미지가 삭제됩니다. +- [x] 추가된 태그 안의 X 버튼을 누르면 해당 태그는 삭제됩니다. + +## 주요 변경사항 + +- styled component를 통해 스타일링 + +## 스크린샷 + +| PC | Tablet | Mobile | +| :---------------------------------------------------------------------------------------------------------------------------------------------------: | :-------------------------------------------------------------------------------------------------------------------------------------------------------: | :------------------------------------------------------------------------------------------------------------------------------------------------------: | +| localhost_5173_additem | localhost_5173_additem (1) | localhost_5173_additem (2) | + +## 멘토에게 + +- styled component를 사용해서 스타일링을 했는데 한 컴포넌트의 코드가 너무 길어지는 느낌입니다. + 스타일은 따로 빼놓는게 나을까요? From d9fbfe42f0473db9f18db3ee005fffcccae4517c Mon Sep 17 00:00:00 2001 From: Imhwitae Date: Thu, 7 Aug 2025 22:39:49 +0900 Subject: [PATCH 59/94] =?UTF-8?q?docs:=20README=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index e8b281de..3d6cf6d0 100644 --- a/README.md +++ b/README.md @@ -49,11 +49,11 @@ - [x] 미리보기에서 제목은 “판다 마켓”, 설명은 “일상의 모든 물건을 거래해보세요”로 설정합니다. - [x] 주소와 이미지는 자유롭게 설정하세요. -## 주요 변경사항 +### 주요 변경사항 - Netlify에서 로고 이미지가 보이게 수정했습니다. -## 스크린샷 +### 스크린샷 **메인화면** | PC | Tablet | Mobile | @@ -74,7 +74,7 @@ | :-: | :----: | |![join_pc](https://github.com/user-attachments/assets/52788e32-a174-4441-abe1-957bc36094e7)|![join_mobile](https://github.com/user-attachments/assets/6222a188-d431-433c-959a-07c052ff61a5)| -## 멘토에게 +### 멘토에게 - 저는 CSS를 작성할 때 대부분의 단위를 `px`로 사용했는데, `rem`, `vw`와 같은 단위를 사용하는 것이 더 나은지 궁금합니다 > 답변 @@ -106,13 +106,13 @@ - [x] 페이지 네이션 기능을 구현합니다. - [x] 반응형으로 보여지는 물품들의 개수를 다르게 설정할때 서버에 보내는 pageSize값을 적절하게 설정합니다. -## 주요 변경사항 +### 주요 변경사항 - 스프린트 미션 1부터 4까지의 내용을 React로 변경했습니다. > form 변경 내용 > (React-Hook-form을 이용해 유효성 검사 해보기)[https://velog.io/@nudge0613/React-Hook-Form%EC%9D%84-%EC%9D%B4%EC%9A%A9%ED%95%B4-%ED%9A%8C%EC%9B%90%EA%B0%80%EC%9E%85-%EC%9C%A0%ED%9A%A8%EC%84%B1-%EA%B2%80%EC%82%AC-%ED%95%98%EA%B8%B0] -## 스크린샷 +### 스크린샷 | PC | Tablet | Mobile | | :-------------------------------------------------------------------------------------------------------------------------------------------------: | :-----------------------------------------------------------------------------------------------------------------------------------------------------: | :----------------------------------------------------------------------------------------------------------------------------------------------------: | @@ -136,17 +136,17 @@ - [x] 이미지 안의 X 버튼을 누르면 이미지가 삭제됩니다. - [x] 추가된 태그 안의 X 버튼을 누르면 해당 태그는 삭제됩니다. -## 주요 변경사항 +### 주요 변경사항 - styled component를 통해 스타일링 -## 스크린샷 +### 스크린샷 | PC | Tablet | Mobile | | :---------------------------------------------------------------------------------------------------------------------------------------------------: | :-------------------------------------------------------------------------------------------------------------------------------------------------------: | :------------------------------------------------------------------------------------------------------------------------------------------------------: | | localhost_5173_additem | localhost_5173_additem (1) | localhost_5173_additem (2) | -## 멘토에게 +### 멘토에게 - styled component를 사용해서 스타일링을 했는데 한 컴포넌트의 코드가 너무 길어지는 느낌입니다. 스타일은 따로 빼놓는게 나을까요? From b1ca77f7d2c68c33ebbc2e2d2cc41ffb0192559c Mon Sep 17 00:00:00 2001 From: Imhwitae Date: Thu, 7 Aug 2025 22:40:56 +0900 Subject: [PATCH 60/94] =?UTF-8?q?docs:=20README=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/README.md b/README.md index 3d6cf6d0..9155bef7 100644 --- a/README.md +++ b/README.md @@ -109,8 +109,7 @@ ### 주요 변경사항 - 스프린트 미션 1부터 4까지의 내용을 React로 변경했습니다. - > form 변경 내용 - > (React-Hook-form을 이용해 유효성 검사 해보기)[https://velog.io/@nudge0613/React-Hook-Form%EC%9D%84-%EC%9D%B4%EC%9A%A9%ED%95%B4-%ED%9A%8C%EC%9B%90%EA%B0%80%EC%9E%85-%EC%9C%A0%ED%9A%A8%EC%84%B1-%EA%B2%80%EC%82%AC-%ED%95%98%EA%B8%B0] + > form 변경 내용: [React-Hook-form을 이용해 유효성 검사 해보기](https://velog.io/@nudge0613/React-Hook-Form%EC%9D%84-%EC%9D%B4%EC%9A%A9%ED%95%B4-%ED%9A%8C%EC%9B%90%EA%B0%80%EC%9E%85-%EC%9C%A0%ED%9A%A8%EC%84%B1-%EA%B2%80%EC%82%AC-%ED%95%98%EA%B8%B0) ### 스크린샷 From 7209459ad29391e95966e70c09107ecd33f3b82a Mon Sep 17 00:00:00 2001 From: Imhwitae Date: Fri, 8 Aug 2025 17:14:07 +0900 Subject: [PATCH 61/94] =?UTF-8?q?feat:=20=EC=83=81=ED=92=88=20=EC=83=81?= =?UTF-8?q?=EC=84=B8=20=EC=A0=95=EB=B3=B4,=20=EB=AC=B8=EC=9D=98=20?= =?UTF-8?q?=ED=95=98=EA=B8=B0=20textarea=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 2 + src/assets/icons/ic_heart_active_large.svg | 3 + src/assets/icons/ic_heart_inactive_large.svg | 3 + src/components/Product.jsx | 1 + src/pages/items/ItemDetail.jsx | 135 ++++++++++++++++++- src/services/itemsApi.js | 34 +++-- src/styles/commonStyles.js | 5 + src/styles/items/ItemDetailStyle.js | 113 ++++++++++++++++ 8 files changed, 285 insertions(+), 11 deletions(-) create mode 100644 src/assets/icons/ic_heart_active_large.svg create mode 100644 src/assets/icons/ic_heart_inactive_large.svg create mode 100644 src/styles/items/ItemDetailStyle.js diff --git a/README.md b/README.md index 9155bef7..5d919827 100644 --- a/README.md +++ b/README.md @@ -149,3 +149,5 @@ - styled component를 사용해서 스타일링을 했는데 한 컴포넌트의 코드가 너무 길어지는 느낌입니다. 스타일은 따로 빼놓는게 나을까요? + +Copyright 2025 코드잇 Inc. All rights reserved. diff --git a/src/assets/icons/ic_heart_active_large.svg b/src/assets/icons/ic_heart_active_large.svg new file mode 100644 index 00000000..aff4192d --- /dev/null +++ b/src/assets/icons/ic_heart_active_large.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/assets/icons/ic_heart_inactive_large.svg b/src/assets/icons/ic_heart_inactive_large.svg new file mode 100644 index 00000000..72f720d5 --- /dev/null +++ b/src/assets/icons/ic_heart_inactive_large.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/components/Product.jsx b/src/components/Product.jsx index ededf8ba..467d1e1c 100644 --- a/src/components/Product.jsx +++ b/src/components/Product.jsx @@ -16,6 +16,7 @@ function Product({ products, style }) {
    diff --git a/src/pages/items/ItemDetail.jsx b/src/pages/items/ItemDetail.jsx index fca86dca..c4383aea 100644 --- a/src/pages/items/ItemDetail.jsx +++ b/src/pages/items/ItemDetail.jsx @@ -1,11 +1,140 @@ -import { useParams } from "react-router"; +import { useLocation, useParams } from "react-router"; +import { requestProductDetail } from "../../services/itemsApi"; +import { useEffect, useState } from "react"; +import { + Heart, + HeartCount, + InquirySubmitButton, + InquiryTextArea, + ProductDate, + ProductImg, + ProductInfoBox, + ProductOwnerName, + ProductPrice, + ProductSubTitle, + ProductTextArea, + ProductTextBox, + ProductTitle, +} from "../../styles/items/ItemDetailStyle"; +import { ItemsTag, palette, ProfileImg } from "../../styles/commonStyles"; +import icProfile from "../../assets/icons/ic_profile.svg"; +import icHeartInactive from "../../assets/icons/ic_heart_inactive_large.svg"; +import icHeartActive from "../../assets/icons/ic_heart_active_large.svg"; export default function ItemDetail() { - const params = useParams(); + /** + * 상품의 id + */ + const { productId } = useParams(); + + const { state } = useLocation(); + + /** + * loading + */ + const [isLoading, setIsLoading] = useState(false); + + /** + * 상품 상세 정보를 받을 state + */ + const [productDetail, setProductDetail] = useState({}); + + /** + * 상품의 상세 정보를 받아온다. + * @param {string} id + */ + const getProductDetail = async (id) => { + try { + setIsLoading(true); + const data = await requestProductDetail(id); + if (!data) { + throw new Error("상품 정보를 불러오지 못했습니다."); + } + console.log(data); + + setProductDetail(data); + } catch (e) { + console.error(e); + } finally { + setIsLoading(false); + } + }; + + useEffect(() => { + getProductDetail(productId); + }, []); return ( <> -
    +
    + + + +
    +
    + {state.name} +
    + + {state.price.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",") + + "원"} + +
    +
    + 상품 소개 + {state.description} +
    +
    + 상품 태그 +
    + {state.tags.map((tag) => { + return {`#${tag}`}; + })} +
    +
    +
    + +
    + + {!isLoading && productDetail.ownerNickname} + + + {state.updatedAt.slice(0, 10).replaceAll("-", ". ")} + +
    +
    + + {!isLoading && productDetail.isFavorite ? ( + 좋아요 이미지 + ) : ( + 좋아요 이미지 + )} + {state.favoriteCount} + +
    +
    +
    +
    +
    +

    + 문의하기 +

    + + 등록 +
    +
    ); } diff --git a/src/services/itemsApi.js b/src/services/itemsApi.js index 50de8d16..1ae2fe45 100644 --- a/src/services/itemsApi.js +++ b/src/services/itemsApi.js @@ -3,20 +3,38 @@ * @param {string} orderBy * @returns {object} */ -const requestProductList = async (querys) => { - const url = new URL('https://panda-market-api.vercel.app/products'); - url.searchParams.append('page', querys.page); - url.searchParams.append('pageSize', querys.pageSize); - url.searchParams.append('orderBy', querys.orderBy); +export const requestProductList = async (querys) => { + const url = new URL("https://panda-market-api.vercel.app/products"); + url.searchParams.append("page", querys.page); + url.searchParams.append("pageSize", querys.pageSize); + url.searchParams.append("orderBy", querys.orderBy); const response = await fetch(url, { - method: 'get', + method: "get", headers: { - 'Content-Type': 'application/json', + "Content-Type": "application/json", }, }); return response.json(); }; -export { requestProductList }; +/** + * 상품의 상세 정보를 요청한다. + * @param {string} productId + * @returns {json} response + */ +export const requestProductDetail = async (productId) => { + const url = new URL( + `https://panda-market-api.vercel.app/products/${productId}` + ); + + const response = await fetch(url, { + method: "get", + headers: { + "Content-Type": "application/json", + }, + }); + + return response.json(); +}; diff --git a/src/styles/commonStyles.js b/src/styles/commonStyles.js index bb58912d..c9399260 100644 --- a/src/styles/commonStyles.js +++ b/src/styles/commonStyles.js @@ -30,3 +30,8 @@ export const ItemsTag = styled.div` padding: 15px; margin-right: 10px; `; + +export const ProfileImg = styled.img` + width: 40px; + height: 40px; +`; diff --git a/src/styles/items/ItemDetailStyle.js b/src/styles/items/ItemDetailStyle.js new file mode 100644 index 00000000..bbbc5ed0 --- /dev/null +++ b/src/styles/items/ItemDetailStyle.js @@ -0,0 +1,113 @@ +import styled from "styled-components"; +import { ItemsTag, palette } from "../commonStyles"; + +export const ProductInfoBox = styled.div` + display: flex; + margin-top: 20px; + border-bottom: 1px solid ${palette.gray200}; + padding-bottom: 40px; +`; + +export const ProductTextBox = styled.div` + display: flex; + flex-direction: column; + width: 100%; +`; + +export const ProductImg = styled.img` + width: 486px; + height: 486px; + border-radius: 16px; + border: none; + margin-right: 20px; +`; + +export const ProductTitle = styled.h1` + font-size: 24px; + font-weight: 600; + margin: 0; +`; + +export const ProductPrice = styled.p` + font-size: 40px; + font-weight: 600; + margin: 20px 0px 10px; +`; + +export const ProductSubTitle = styled.p` + font-size: 16px; + font-weight: 600; + color: ${palette.gray600}; + margin: 20px 0px; +`; + +export const ProductTextArea = styled.p` + font-size: 16px; + font-weight: 400; + width: 100%; + color: ${palette.gray600}; + margin: 0; +`; + +export const ProductOwnerName = styled.p` + font-size: 14px; + font-weight: 500; + margin: 0px 0px 10px 0px; + color: ${palette.gray600}; +`; + +export const ProductDate = styled.p` + font-size: 14px; + font-weight: 400; + color: ${palette.gray400}; + margin: 0; +`; + +export const Heart = styled.div` + border: 1px solid ${palette.gray200}; + border-radius: 35px; + background-color: white; + display: flex; + justify-content: space-between; + column-gap: 5px; + padding: 2px 10px; + align-items: center; +`; + +export const HeartCount = styled.p` + font-size: 16px; + font-weight: 500; + color: ${palette.gray500}; + margin: 0; +`; + +export const InquiryTextArea = styled.textarea` + background-color: ${palette.gray100}; + height: 104px; + width: 100%; + border: none; + border-radius: 12px; + resize: none; + font-family: Pretendard-Reqular; + padding: 20px; + font-size: 16px; + font-weight: 400; + margin-bottom: 10px; + &::placeholder { + color: ${palette.gray400}; + } +`; + +export const InquirySubmitButton = styled.button` + width: 74px; + height: 42px; + border: none; + color: white; + padding: 10px; + border-radius: 8px; + font-size: 16px; + font-weight: 600; + background-color: ${({ isActive }) => + isActive ? `${palette.blue}` : `${palette.gray400}`}; + float: right; +`; From 43f3aca6a4cd1db944ab35e322494605689cd839 Mon Sep 17 00:00:00 2001 From: Imhwitae Date: Fri, 8 Aug 2025 17:40:26 +0900 Subject: [PATCH 62/94] =?UTF-8?q?rename:=20=EB=AC=B8=EC=9D=98=EC=82=AC?= =?UTF-8?q?=ED=95=AD=20=EC=BB=B4=ED=8F=AC=EB=84=8C=ED=8A=B8=20=EB=B6=84?= =?UTF-8?q?=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/Inquiry.jsx | 32 ++++++++++++++++++++ src/pages/items/ItemDetail.jsx | 21 ++++--------- src/styles/components/InquiryDetailStyles.js | 0 src/styles/items/ItemDetailStyle.js | 10 ++++++ 4 files changed, 48 insertions(+), 15 deletions(-) create mode 100644 src/components/Inquiry.jsx create mode 100644 src/styles/components/InquiryDetailStyles.js diff --git a/src/components/Inquiry.jsx b/src/components/Inquiry.jsx new file mode 100644 index 00000000..9bbceb01 --- /dev/null +++ b/src/components/Inquiry.jsx @@ -0,0 +1,32 @@ +import { useState } from "react"; +import { palette } from "../styles/commonStyles"; +import { + InquirySubmitButton, + InquiryTextArea, +} from "../styles/items/ItemDetailStyle"; + +export default function Inquiry() { + const [isActive, setIsActive] = useState(false); + + return ( + <> +

    + 문의하기 +

    + { + e.target.value !== "" ? setIsActive(true) : setIsActive(false); + }} + placeholder="개인정보를 공유 및 요청하거나, 명예 훼손, 무단 광고, 불법 정보 유포시 모니터링 후 삭제될 수 있으며, 이에 대한 민형사상 책임은 게시자에게 있습니다." + > + 등록 + + ); +} diff --git a/src/pages/items/ItemDetail.jsx b/src/pages/items/ItemDetail.jsx index c4383aea..9a39c9d6 100644 --- a/src/pages/items/ItemDetail.jsx +++ b/src/pages/items/ItemDetail.jsx @@ -4,8 +4,6 @@ import { useEffect, useState } from "react"; import { Heart, HeartCount, - InquirySubmitButton, - InquiryTextArea, ProductDate, ProductImg, ProductInfoBox, @@ -20,6 +18,7 @@ import { ItemsTag, palette, ProfileImg } from "../../styles/commonStyles"; import icProfile from "../../assets/icons/ic_profile.svg"; import icHeartInactive from "../../assets/icons/ic_heart_inactive_large.svg"; import icHeartActive from "../../assets/icons/ic_heart_active_large.svg"; +import Inquiry from "../../components/Inquiry"; export default function ItemDetail() { /** @@ -27,6 +26,9 @@ export default function ItemDetail() { */ const { productId } = useParams(); + /** + * 목록에서 가져온 상품 정보 + */ const { state } = useLocation(); /** @@ -120,19 +122,8 @@ export default function ItemDetail() {
    -
    -

    - 문의하기 -

    - - 등록 +
    +
    diff --git a/src/styles/components/InquiryDetailStyles.js b/src/styles/components/InquiryDetailStyles.js new file mode 100644 index 00000000..e69de29b diff --git a/src/styles/items/ItemDetailStyle.js b/src/styles/items/ItemDetailStyle.js index bbbc5ed0..8c736402 100644 --- a/src/styles/items/ItemDetailStyle.js +++ b/src/styles/items/ItemDetailStyle.js @@ -110,4 +110,14 @@ export const InquirySubmitButton = styled.button` background-color: ${({ isActive }) => isActive ? `${palette.blue}` : `${palette.gray400}`}; float: right; + + &:hover { + background-color: ${({ isActive }) => + isActive ? `#1967d6` : `${palette.gray400}`}; + } + + &:active { + background-color: ${({ isActive }) => + isActive ? `#1251aa` : `${palette.gray400}`}; + } `; From 28dbbfcf30df732b850329a9fef023556be535e9 Mon Sep 17 00:00:00 2001 From: Imhwitae Date: Fri, 8 Aug 2025 20:39:09 +0900 Subject: [PATCH 63/94] =?UTF-8?q?feat:=20=EB=AC=B8=EC=9D=98=20=EB=AA=A9?= =?UTF-8?q?=EB=A1=9D=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/Inquiry.jsx | 94 +++++++++++++++----- src/pages/items/ItemDetail.jsx | 5 +- src/services/itemsApi.js | 16 ++++ src/styles/components/InquiryDetailStyles.js | 0 src/styles/components/InquiryStyles.js | 78 ++++++++++++++++ src/styles/items/ItemDetailStyle.js | 41 --------- src/util/formatTimeAgo.js | 37 ++++++++ 7 files changed, 206 insertions(+), 65 deletions(-) delete mode 100644 src/styles/components/InquiryDetailStyles.js create mode 100644 src/styles/components/InquiryStyles.js create mode 100644 src/util/formatTimeAgo.js diff --git a/src/components/Inquiry.jsx b/src/components/Inquiry.jsx index 9bbceb01..f38666de 100644 --- a/src/components/Inquiry.jsx +++ b/src/components/Inquiry.jsx @@ -1,32 +1,86 @@ -import { useState } from "react"; +import { useEffect, useState } from "react"; import { palette } from "../styles/commonStyles"; import { + InquiryContent, + InquiryDate, + InquiryProfileImg, InquirySubmitButton, InquiryTextArea, -} from "../styles/items/ItemDetailStyle"; + InquiryTitle, + InquiryWriter, +} from "../styles/components/InquiryStyles"; +import { requestInquiryLists } from "../services/itemsApi"; +import icProfile from "../assets/icons/ic_profile.svg"; +import { formatTimeAgo } from "../util/formatTimeAgo"; -export default function Inquiry() { +export default function Inquiry({ id }) { + /** + * 버튼 활성화 state + */ const [isActive, setIsActive] = useState(false); + /** + * loading + */ + const [isLoading, setIsLoading] = useState(false); + + /** + * 문의내역을 담을 state + */ + const [inQuiryLists, setInquiryLists] = useState({}); + + const getInquiryLists = async (productId) => { + try { + setIsLoading(true); + const lists = await requestInquiryLists(productId); + if (!lists) { + throw new Error("문의 목록을 받아오지 못했습니다."); + } + + setInquiryLists(lists); + } catch (e) { + console.error(e); + } finally { + setIsLoading(false); + } + }; + + useEffect(() => { + getInquiryLists(id); + }, []); + return ( <> -

    - 문의하기 -

    - { - e.target.value !== "" ? setIsActive(true) : setIsActive(false); - }} - placeholder="개인정보를 공유 및 요청하거나, 명예 훼손, 무단 광고, 불법 정보 유포시 모니터링 후 삭제될 수 있으며, 이에 대한 민형사상 책임은 게시자에게 있습니다." - > - 등록 +
    + 문의하기 + { + e.target.value !== "" ? setIsActive(true) : setIsActive(false); + }} + placeholder="개인정보를 공유 및 요청하거나, 명예 훼손, 무단 광고, 불법 정보 유포시 모니터링 후 삭제될 수 있으며, 이에 대한 민형사상 책임은 게시자에게 있습니다." + > + 등록 +
    + {!isLoading && + inQuiryLists.list?.map((el) => { + return ( +
    +
    + {el.content} +
    +
    + +
    + {el.writer.nickname} + {formatTimeAgo(el.updatedAt)} +
    +
    +
    + ); + })} ); } diff --git a/src/pages/items/ItemDetail.jsx b/src/pages/items/ItemDetail.jsx index 9a39c9d6..28ebe707 100644 --- a/src/pages/items/ItemDetail.jsx +++ b/src/pages/items/ItemDetail.jsx @@ -52,7 +52,6 @@ export default function ItemDetail() { if (!data) { throw new Error("상품 정보를 불러오지 못했습니다."); } - console.log(data); setProductDetail(data); } catch (e) { @@ -122,9 +121,7 @@ export default function ItemDetail() {
    -
    - -
    +
    ); diff --git a/src/services/itemsApi.js b/src/services/itemsApi.js index 1ae2fe45..6e7c4f49 100644 --- a/src/services/itemsApi.js +++ b/src/services/itemsApi.js @@ -38,3 +38,19 @@ export const requestProductDetail = async (productId) => { return response.json(); }; + +export const requestInquiryLists = async (productId) => { + const url = new URL( + `https://panda-market-api.vercel.app/products/${productId}/comments` + ); + url.searchParams.append("limit", 3); + + const response = await fetch(url, { + method: "get", + headers: { + "Content-Type": "application/json", + }, + }); + + return response.json(); +}; diff --git a/src/styles/components/InquiryDetailStyles.js b/src/styles/components/InquiryDetailStyles.js deleted file mode 100644 index e69de29b..00000000 diff --git a/src/styles/components/InquiryStyles.js b/src/styles/components/InquiryStyles.js new file mode 100644 index 00000000..1034fda3 --- /dev/null +++ b/src/styles/components/InquiryStyles.js @@ -0,0 +1,78 @@ +import styled from "styled-components"; +import { palette, ProfileImg } from "../commonStyles"; + +export const InquiryTextArea = styled.textarea` + background-color: ${palette.gray100}; + height: 104px; + width: 100%; + border: none; + border-radius: 12px; + resize: none; + font-family: Pretendard-Reqular; + padding: 20px; + font-size: 16px; + font-weight: 400; + margin-bottom: 10px; + &::placeholder { + color: ${palette.gray400}; + } +`; + +export const InquiryTitle = styled.p` + color: ${palette.gray900}; + font-weight: 600; + font-size: 16px; + margin: 40px 0px 10px; + text-align: left; +`; + +export const InquirySubmitButton = styled.button` + width: 74px; + height: 42px; + border: none; + color: white; + padding: 10px; + border-radius: 8px; + font-size: 16px; + font-weight: 600; + background-color: ${({ isActive }) => + isActive ? `${palette.blue}` : `${palette.gray400}`}; + // float: right; + + &:hover { + background-color: ${({ isActive }) => + isActive ? `#1967d6` : `${palette.gray400}`}; + } + + &:active { + background-color: ${({ isActive }) => + isActive ? `#1251aa` : `${palette.gray400}`}; + } +`; + +export const InquiryContent = styled.p` + margin: 0; + color: ${palette.gray800}; + font-size: 14px; + font-weight: 400; +`; + +export const InquiryProfileImg = styled(ProfileImg)` + width: 32px; + height: 32px; +`; + +export const InquiryWriter = styled.p` + margin: 0px 0px 5px; + font-size: 12px; + font-weight: 400; +`; + +export const InquiryDate = styled.p` + margin: 0; + font-size: 12px; + font-weight: 400; + color: ${palette.gray400}; +`; + +export const BackButton = styled.button``; diff --git a/src/styles/items/ItemDetailStyle.js b/src/styles/items/ItemDetailStyle.js index 8c736402..3edfb867 100644 --- a/src/styles/items/ItemDetailStyle.js +++ b/src/styles/items/ItemDetailStyle.js @@ -80,44 +80,3 @@ export const HeartCount = styled.p` color: ${palette.gray500}; margin: 0; `; - -export const InquiryTextArea = styled.textarea` - background-color: ${palette.gray100}; - height: 104px; - width: 100%; - border: none; - border-radius: 12px; - resize: none; - font-family: Pretendard-Reqular; - padding: 20px; - font-size: 16px; - font-weight: 400; - margin-bottom: 10px; - &::placeholder { - color: ${palette.gray400}; - } -`; - -export const InquirySubmitButton = styled.button` - width: 74px; - height: 42px; - border: none; - color: white; - padding: 10px; - border-radius: 8px; - font-size: 16px; - font-weight: 600; - background-color: ${({ isActive }) => - isActive ? `${palette.blue}` : `${palette.gray400}`}; - float: right; - - &:hover { - background-color: ${({ isActive }) => - isActive ? `#1967d6` : `${palette.gray400}`}; - } - - &:active { - background-color: ${({ isActive }) => - isActive ? `#1251aa` : `${palette.gray400}`}; - } -`; diff --git a/src/util/formatTimeAgo.js b/src/util/formatTimeAgo.js new file mode 100644 index 00000000..71c60d4d --- /dev/null +++ b/src/util/formatTimeAgo.js @@ -0,0 +1,37 @@ +/** + * DateTime을 방금전, n분, 일, 월, 년전 형태로 출력한다. + * @param {string} dateString + * @returns {string} + */ +export const formatTimeAgo = (dateString) => { + const now = new Date(); + const past = new Date(dateString); + const diffInMs = now.getTime() - past.getTime(); + + // 시간 단위(밀리초) + const msInSecond = 1000; + const msInMinute = msInSecond * 60; + const msInHour = msInMinute * 60; + const msInDay = msInHour * 24; + const msInMonth = msInDay * 30; // 간단한 계산을 위해 30일로 가정 + const msInYear = msInDay * 365; // 간단한 계산을 위해 365일로 가정 + + if (diffInMs >= msInYear) { + const years = Math.floor(diffInMs / msInYear); + return `${years}년 전`; + } else if (diffInMs >= msInMonth) { + const months = Math.floor(diffInMs / msInMonth); + return `${months}달 전`; + } else if (diffInMs >= msInDay) { + const days = Math.floor(diffInMs / msInDay); + return `${days}일 전`; + } else if (diffInMs >= msInHour) { + const hours = Math.floor(diffInMs / msInHour); + return `${hours}시간 전`; + } else if (diffInMs >= msInMinute) { + const minutes = Math.floor(diffInMs / msInMinute); + return `${minutes}분 전`; + } else { + return "방금 전"; + } +}; From f337c1eb2d2675f0cc6f056bd6612c0b107589e1 Mon Sep 17 00:00:00 2001 From: Imhwitae Date: Sat, 9 Aug 2025 22:11:35 +0900 Subject: [PATCH 64/94] =?UTF-8?q?feat:=20=EB=AC=B8=EC=9D=98=20=EB=82=B4?= =?UTF-8?q?=EC=97=AD=EC=9D=B4=20=EC=97=86=EC=9D=84=20=EB=95=8C=20=EB=B9=88?= =?UTF-8?q?=20=EC=9D=B4=EB=AF=B8=EC=A7=80=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/assets/icons/ic_back.svg | 4 + src/assets/images/img_inquiry_empty_md.png | Bin 0 -> 6244 bytes src/components/Inquiry.jsx | 92 ++++++++++++++++----- src/styles/components/InquiryStyles.js | 16 +++- 4 files changed, 92 insertions(+), 20 deletions(-) create mode 100644 src/assets/icons/ic_back.svg create mode 100644 src/assets/images/img_inquiry_empty_md.png diff --git a/src/assets/icons/ic_back.svg b/src/assets/icons/ic_back.svg new file mode 100644 index 00000000..8db5377e --- /dev/null +++ b/src/assets/icons/ic_back.svg @@ -0,0 +1,4 @@ + + + + diff --git a/src/assets/images/img_inquiry_empty_md.png b/src/assets/images/img_inquiry_empty_md.png new file mode 100644 index 0000000000000000000000000000000000000000..d941b91a58b0035ccf4624d47170d7f1ed541295 GIT binary patch literal 6244 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 SZ~l7<0JPN&)T&kNk^cdsQ_zM0 literal 0 HcmV?d00001 diff --git a/src/components/Inquiry.jsx b/src/components/Inquiry.jsx index f38666de..6afd167f 100644 --- a/src/components/Inquiry.jsx +++ b/src/components/Inquiry.jsx @@ -1,6 +1,7 @@ import { useEffect, useState } from "react"; import { palette } from "../styles/commonStyles"; import { + BackButton, InquiryContent, InquiryDate, InquiryProfileImg, @@ -12,8 +13,12 @@ import { import { requestInquiryLists } from "../services/itemsApi"; import icProfile from "../assets/icons/ic_profile.svg"; import { formatTimeAgo } from "../util/formatTimeAgo"; +import { useNavigate } from "react-router"; +import icBack from "../assets/icons/ic_back.svg"; +import imgEmptyMd from "../assets/images/img_inquiry_empty_md.png"; export default function Inquiry({ id }) { + const navigate = useNavigate(); /** * 버튼 활성화 state */ @@ -29,6 +34,10 @@ export default function Inquiry({ id }) { */ const [inQuiryLists, setInquiryLists] = useState({}); + /** + * 상품의 아이디에 맞는 문의 목록을 불러온다 + * @param {string} productId + */ const getInquiryLists = async (productId) => { try { setIsLoading(true); @@ -36,8 +45,13 @@ export default function Inquiry({ id }) { if (!lists) { throw new Error("문의 목록을 받아오지 못했습니다."); } + console.log(lists.list?.length); - setInquiryLists(lists); + if (lists.list?.length) { + setInquiryLists(lists); + } else { + setInquiryLists(null); + } } catch (e) { console.error(e); } finally { @@ -61,26 +75,66 @@ export default function Inquiry({ id }) { > 등록
    - {!isLoading && - inQuiryLists.list?.map((el) => { - return ( -
    -
    - {el.content} -
    -
    - -
    - {el.writer.nickname} - {formatTimeAgo(el.updatedAt)} + {!isLoading ? ( + inQuiryLists ? ( + inQuiryLists.list?.map((el) => { + return ( +
    +
    + {el.content} +
    +
    + +
    + {el.writer.nickname} + {formatTimeAgo(el.updatedAt)} +
    -
    - ); - })} + ); + }) + ) : ( +
    + 빈 이미지 +

    + 아직 문의가 없어요 +

    +
    + ) + ) : ( +
    로딩중
    + )} +
    + navigate(-1)}> + 목록으로 돌아가기 + 뒤로가기 이미지 + +
    ); } diff --git a/src/styles/components/InquiryStyles.js b/src/styles/components/InquiryStyles.js index 1034fda3..66b2b51c 100644 --- a/src/styles/components/InquiryStyles.js +++ b/src/styles/components/InquiryStyles.js @@ -75,4 +75,18 @@ export const InquiryDate = styled.p` color: ${palette.gray400}; `; -export const BackButton = styled.button``; +export const BackButton = styled.button` + width: 240px; + height: 48px; + border: none; + background-color: ${palette.blue}; + color: white; + padding: 10px; + border-radius: 40px; + font-size: 18px; + font-weight: 600; + justify-content: center; + align-items: center; + display: flex; + gap: 10px; +`; From 44fce53cce879cc518275fa5f31ea11b051bf4f0 Mon Sep 17 00:00:00 2001 From: Imhwitae Date: Thu, 28 Aug 2025 18:27:12 +0900 Subject: [PATCH 65/94] =?UTF-8?q?feat:=20useService=20=EC=BB=A4=EC=8A=A4?= =?UTF-8?q?=ED=85=80=20=ED=9B=85=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/hooks/useMediaQuery.jsx | 6 ++-- src/hooks/useService.jsx | 35 +++++++++++++++++++++ src/pages/items/ItemDetail.jsx | 57 +++++++++------------------------- src/services/itemsApi.js | 8 ++--- 4 files changed, 57 insertions(+), 49 deletions(-) create mode 100644 src/hooks/useService.jsx diff --git a/src/hooks/useMediaQuery.jsx b/src/hooks/useMediaQuery.jsx index 65806367..8196abdc 100644 --- a/src/hooks/useMediaQuery.jsx +++ b/src/hooks/useMediaQuery.jsx @@ -1,4 +1,4 @@ -import { useEffect, useState } from 'react'; +import { useEffect, useState } from "react"; const getMatches = (query) => { return window.matchMedia(query).matches; @@ -21,10 +21,10 @@ export default function useMediaQuery(query) { useEffect(() => { const media = window.matchMedia(query); - media.addEventListener('change', handleChange); + media.addEventListener("change", handleChange); return () => { - media.removeEventListener('change', handleChange); + media.removeEventListener("change", handleChange); }; }, [query]); diff --git a/src/hooks/useService.jsx b/src/hooks/useService.jsx new file mode 100644 index 00000000..2833084d --- /dev/null +++ b/src/hooks/useService.jsx @@ -0,0 +1,35 @@ +import { useEffect, useState } from "react"; + +/** + * 데이터 통신을 위한 공통 커스텀 훅 + * @param {Function} fetchFunction 서버와 직접 통신하는 함수 + * @returns {data: object, isLoading: boolean} + */ +const useService = (fetchFunction) => { + const [isLoading, setIsLoading] = useState(false); + const [data, setData] = useState(); + + useEffect(() => { + const getService = async (getDataFunction) => { + try { + setIsLoading(true); + const response = await getDataFunction(); + + if (!response) { + throw new Error("데이터를 불러오지 못했습니다."); + } + + setData(response); + } catch (error) { + console.log(error); + } finally { + setIsLoading(false); + } + }; + + getService(fetchFunction); + }, []); + + return { data, isLoading }; +}; +export default useService; diff --git a/src/pages/items/ItemDetail.jsx b/src/pages/items/ItemDetail.jsx index 28ebe707..c0232444 100644 --- a/src/pages/items/ItemDetail.jsx +++ b/src/pages/items/ItemDetail.jsx @@ -19,6 +19,7 @@ import icProfile from "../../assets/icons/ic_profile.svg"; import icHeartInactive from "../../assets/icons/ic_heart_inactive_large.svg"; import icHeartActive from "../../assets/icons/ic_heart_active_large.svg"; import Inquiry from "../../components/Inquiry"; +import useService from "../../hooks/useService"; export default function ItemDetail() { /** @@ -29,65 +30,37 @@ export default function ItemDetail() { /** * 목록에서 가져온 상품 정보 */ - const { state } = useLocation(); + const { state: productInfo } = useLocation(); /** - * loading + * 상품 정보 받아오기 */ - const [isLoading, setIsLoading] = useState(false); - - /** - * 상품 상세 정보를 받을 state - */ - const [productDetail, setProductDetail] = useState({}); - - /** - * 상품의 상세 정보를 받아온다. - * @param {string} id - */ - const getProductDetail = async (id) => { - try { - setIsLoading(true); - const data = await requestProductDetail(id); - if (!data) { - throw new Error("상품 정보를 불러오지 못했습니다."); - } - - setProductDetail(data); - } catch (e) { - console.error(e); - } finally { - setIsLoading(false); - } - }; - - useEffect(() => { - getProductDetail(productId); - }, []); + const { data, isLoading } = useService(() => requestProductDetail(productId)); return ( <>
    - +
    - {state.name} + {productInfo.name}
    - {state.price.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",") + - "원"} + {productInfo.price + .toString() + .replace(/\B(?=(\d{3})+(?!\d))/g, ",") + "원"}
    상품 소개 - {state.description} + {productInfo.description}
    상품 태그
    - {state.tags.map((tag) => { + {productInfo.tags.map((tag) => { return {`#${tag}`}; })}
    @@ -102,20 +75,20 @@ export default function ItemDetail() { }} > - {!isLoading && productDetail.ownerNickname} + {!isLoading ? data?.ownerNickname : "..."} - {state.updatedAt.slice(0, 10).replaceAll("-", ". ")} + {productInfo.updatedAt.slice(0, 10).replaceAll("-", ". ")}
    - {!isLoading && productDetail.isFavorite ? ( + {!isLoading && data?.isFavorite ? ( 좋아요 이미지 ) : ( 좋아요 이미지 )} - {state.favoriteCount} + {productInfo.favoriteCount}
    diff --git a/src/services/itemsApi.js b/src/services/itemsApi.js index 6e7c4f49..b153a1f9 100644 --- a/src/services/itemsApi.js +++ b/src/services/itemsApi.js @@ -3,11 +3,11 @@ * @param {string} orderBy * @returns {object} */ -export const requestProductList = async (querys) => { +export const requestProductList = async (query) => { const url = new URL("https://panda-market-api.vercel.app/products"); - url.searchParams.append("page", querys.page); - url.searchParams.append("pageSize", querys.pageSize); - url.searchParams.append("orderBy", querys.orderBy); + url.searchParams.append("page", query.page); + url.searchParams.append("pageSize", query.pageSize); + url.searchParams.append("orderBy", query.orderBy); const response = await fetch(url, { method: "get", From 889ced0d9254e7a951a78a375286d4dbc10b21c6 Mon Sep 17 00:00:00 2001 From: Imhwitae Date: Thu, 28 Aug 2025 20:35:28 +0900 Subject: [PATCH 66/94] =?UTF-8?q?refactor:=20=EC=BB=B4=ED=8F=AC=EB=84=8C?= =?UTF-8?q?=ED=8A=B8=20=EB=B6=84=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/Inquiry.jsx | 46 ++--------- src/hooks/useService.jsx | 1 + .../components/ItemDetail/ProductDetails.jsx | 70 +++++++++++++++++ src/pages/items/ItemDetail.jsx | 77 ++----------------- 4 files changed, 84 insertions(+), 110 deletions(-) create mode 100644 src/pages/components/ItemDetail/ProductDetails.jsx diff --git a/src/components/Inquiry.jsx b/src/components/Inquiry.jsx index 6afd167f..080e3518 100644 --- a/src/components/Inquiry.jsx +++ b/src/components/Inquiry.jsx @@ -1,4 +1,4 @@ -import { useEffect, useState } from "react"; +import { useState } from "react"; import { palette } from "../styles/commonStyles"; import { BackButton, @@ -16,6 +16,7 @@ import { formatTimeAgo } from "../util/formatTimeAgo"; import { useNavigate } from "react-router"; import icBack from "../assets/icons/ic_back.svg"; import imgEmptyMd from "../assets/images/img_inquiry_empty_md.png"; +import useService from "../hooks/useService"; export default function Inquiry({ id }) { const navigate = useNavigate(); @@ -24,44 +25,7 @@ export default function Inquiry({ id }) { */ const [isActive, setIsActive] = useState(false); - /** - * loading - */ - const [isLoading, setIsLoading] = useState(false); - - /** - * 문의내역을 담을 state - */ - const [inQuiryLists, setInquiryLists] = useState({}); - - /** - * 상품의 아이디에 맞는 문의 목록을 불러온다 - * @param {string} productId - */ - const getInquiryLists = async (productId) => { - try { - setIsLoading(true); - const lists = await requestInquiryLists(productId); - if (!lists) { - throw new Error("문의 목록을 받아오지 못했습니다."); - } - console.log(lists.list?.length); - - if (lists.list?.length) { - setInquiryLists(lists); - } else { - setInquiryLists(null); - } - } catch (e) { - console.error(e); - } finally { - setIsLoading(false); - } - }; - - useEffect(() => { - getInquiryLists(id); - }, []); + const { data, isLoading } = useService(() => requestInquiryLists(id)); return ( <> @@ -76,8 +40,8 @@ export default function Inquiry({ id }) { 등록
    {!isLoading ? ( - inQuiryLists ? ( - inQuiryLists.list?.map((el) => { + data ? ( + data.list?.map((el) => { return (
    { return { data, isLoading }; }; + export default useService; diff --git a/src/pages/components/ItemDetail/ProductDetails.jsx b/src/pages/components/ItemDetail/ProductDetails.jsx new file mode 100644 index 00000000..11fa97f3 --- /dev/null +++ b/src/pages/components/ItemDetail/ProductDetails.jsx @@ -0,0 +1,70 @@ +import { ItemsTag, palette, ProfileImg } from "../../../styles/commonStyles"; +import { + Heart, + HeartCount, + ProductDate, + ProductOwnerName, + ProductPrice, + ProductSubTitle, + ProductTextArea, + ProductTextBox, + ProductTitle, +} from "../../../styles/items/ItemDetailStyle"; +import icProfile from "../../../assets/icons/ic_profile.svg"; +import icHeartInactive from "../../../assets/icons/ic_heart_inactive_large.svg"; +import icHeartActive from "../../../assets/icons/ic_heart_active_large.svg"; + +export default function ProductDetails({ data, productInfo, isLoading }) { + return ( + +
    +
    + {productInfo.name} +
    + + {productInfo.price.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",") + + "원"} + +
    +
    + 상품 소개 + {productInfo.description} +
    +
    + 상품 태그 +
    + {productInfo.tags.map((tag) => { + return {`#${tag}`}; + })} +
    +
    +
    + +
    + + {!isLoading ? data?.ownerNickname : "..."} + + + {productInfo.updatedAt.slice(0, 10).replaceAll("-", ". ")} + +
    +
    + + {!isLoading && data?.isFavorite ? ( + 좋아요 이미지 + ) : ( + 좋아요 이미지 + )} + {productInfo.favoriteCount} + +
    +
    +
    + ); +} diff --git a/src/pages/items/ItemDetail.jsx b/src/pages/items/ItemDetail.jsx index c0232444..053bb23b 100644 --- a/src/pages/items/ItemDetail.jsx +++ b/src/pages/items/ItemDetail.jsx @@ -1,25 +1,10 @@ import { useLocation, useParams } from "react-router"; import { requestProductDetail } from "../../services/itemsApi"; -import { useEffect, useState } from "react"; -import { - Heart, - HeartCount, - ProductDate, - ProductImg, - ProductInfoBox, - ProductOwnerName, - ProductPrice, - ProductSubTitle, - ProductTextArea, - ProductTextBox, - ProductTitle, -} from "../../styles/items/ItemDetailStyle"; -import { ItemsTag, palette, ProfileImg } from "../../styles/commonStyles"; -import icProfile from "../../assets/icons/ic_profile.svg"; -import icHeartInactive from "../../assets/icons/ic_heart_inactive_large.svg"; -import icHeartActive from "../../assets/icons/ic_heart_active_large.svg"; +import { ProductImg, ProductInfoBox } from "../../styles/items/ItemDetailStyle"; + import Inquiry from "../../components/Inquiry"; import useService from "../../hooks/useService"; +import ProductDetails from "../components/ItemDetail/ProductDetails"; export default function ItemDetail() { /** @@ -42,57 +27,11 @@ export default function ItemDetail() {
    - -
    -
    - {productInfo.name} -
    - - {productInfo.price - .toString() - .replace(/\B(?=(\d{3})+(?!\d))/g, ",") + "원"} - -
    -
    - 상품 소개 - {productInfo.description} -
    -
    - 상품 태그 -
    - {productInfo.tags.map((tag) => { - return {`#${tag}`}; - })} -
    -
    -
    - -
    - - {!isLoading ? data?.ownerNickname : "..."} - - - {productInfo.updatedAt.slice(0, 10).replaceAll("-", ". ")} - -
    -
    - - {!isLoading && data?.isFavorite ? ( - 좋아요 이미지 - ) : ( - 좋아요 이미지 - )} - {productInfo.favoriteCount} - -
    -
    -
    +
    From 32a29e2eeb4cea6ade75c488dfe078546d6f7f42 Mon Sep 17 00:00:00 2001 From: Imhwitae Date: Thu, 28 Aug 2025 22:06:53 +0900 Subject: [PATCH 67/94] =?UTF-8?q?design:=20=EC=BC=80=EB=B0=A5=20=EB=A9=94?= =?UTF-8?q?=EB=89=B4=20=EB=B0=8F=20=EC=BC=80=EB=B0=A5=20=EB=93=9C=EB=A1=AD?= =?UTF-8?q?=EB=8B=A4=EC=9A=B4=20=EB=A6=AC=EC=8A=A4=ED=8A=B8=20UI=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/Inquiry.jsx | 11 ++++- src/components/kebab/KebabDropdown.jsx | 25 ++++++++++ src/components/kebab/KebabMenu.jsx | 29 ++++++++++++ src/hooks/useCloseDropdown.jsx | 19 ++++++++ src/hooks/useToggle.jsx | 22 +++++++++ src/styles/commonStyles.js | 4 ++ src/styles/components/kebab/kebabStyle.js | 57 +++++++++++++++++++++++ 7 files changed, 166 insertions(+), 1 deletion(-) create mode 100644 src/components/kebab/KebabDropdown.jsx create mode 100644 src/components/kebab/KebabMenu.jsx create mode 100644 src/hooks/useCloseDropdown.jsx create mode 100644 src/hooks/useToggle.jsx create mode 100644 src/styles/components/kebab/kebabStyle.js diff --git a/src/components/Inquiry.jsx b/src/components/Inquiry.jsx index 080e3518..84f8244c 100644 --- a/src/components/Inquiry.jsx +++ b/src/components/Inquiry.jsx @@ -17,6 +17,7 @@ import { useNavigate } from "react-router"; import icBack from "../assets/icons/ic_back.svg"; import imgEmptyMd from "../assets/images/img_inquiry_empty_md.png"; import useService from "../hooks/useService"; +import KebabMenu from "./kebab/KebabMenu"; export default function Inquiry({ id }) { const navigate = useNavigate(); @@ -47,8 +48,16 @@ export default function Inquiry({ id }) { style={{ borderBottom: `1px solid ${palette.gray200}` }} key={el.id} > -
    +
    {el.content} +
    { + const dropdownRef = useRef(null); + useCloseDropdown(dropdownRef, onClickClose); + + return ( + + {menus?.map((menu) => { + return ( + + {menu.name} + + ); + })} + + ); +}; + +export default memo(KebabDropdown); diff --git a/src/components/kebab/KebabMenu.jsx b/src/components/kebab/KebabMenu.jsx new file mode 100644 index 00000000..bd01b11e --- /dev/null +++ b/src/components/kebab/KebabMenu.jsx @@ -0,0 +1,29 @@ +import useToggle from "../../hooks/useToggle"; +import { + KebabIcon, + KebabMenuContainer, +} from "../../styles/components/kebab/kebabStyle"; +import KebabDropdown from "./KebabDropdown"; + +const menus = [ + { id: "update", name: "수정하기" }, + { id: "delete", name: "삭제하기" }, +]; + +/** + * 케밥 메뉴 + */ +export default function KebabMenu() { + const { isOpen, onClickToggle, onClickClose } = useToggle(false); + + return ( + <> + + + + + {isOpen && } + + + ); +} diff --git a/src/hooks/useCloseDropdown.jsx b/src/hooks/useCloseDropdown.jsx new file mode 100644 index 00000000..7d53bf94 --- /dev/null +++ b/src/hooks/useCloseDropdown.jsx @@ -0,0 +1,19 @@ +import { useEffect } from "react"; + +const useCloseDropdown = (ref, callback) => { + useEffect(() => { + const onClickDropdownOutside = (event) => { + if (ref.current && !ref.current.contains(event.target)) { + callback(); + } + }; + + document.addEventListener("mousedown", onClickDropdownOutside); + + return () => { + document.removeEventListener("mousedown", onClickDropdownOutside); + }; + }, []); +}; + +export default useCloseDropdown; diff --git a/src/hooks/useToggle.jsx b/src/hooks/useToggle.jsx new file mode 100644 index 00000000..6fe0d5bf --- /dev/null +++ b/src/hooks/useToggle.jsx @@ -0,0 +1,22 @@ +import { useCallback, useState } from "react"; + +/** + * 토글 커스텀 훅 + * @param {boolean} initialValue 초깃값 + * @returns {isOpen: boolean, onClickToggle: Function} + */ +const useToggle = (initialValue) => { + const [isOpen, setIsOpen] = useState(initialValue); + + const onClickToggle = useCallback(() => { + setIsOpen((prevState) => !prevState); + }, [isOpen]); + + const onClickClose = useCallback(() => { + setIsOpen(false); + }, []); + + return { isOpen, onClickToggle, onClickClose }; +}; + +export default useToggle; diff --git a/src/styles/commonStyles.js b/src/styles/commonStyles.js index c9399260..ce33a4e4 100644 --- a/src/styles/commonStyles.js +++ b/src/styles/commonStyles.js @@ -1,6 +1,9 @@ import styled from "styled-components"; export const palette = { + secondary: { + gray500: "#6B7280", + }, gray900: "#111827", gray800: "#1f2937", gray700: "#374151", @@ -10,6 +13,7 @@ export const palette = { gray200: "#e5e7eb", gray100: "#f3f4f6", gray50: "#f9fafb", + coolGray300: "#D1D5DB", blue: "#3692ff", menu: "#4b5563", }; diff --git a/src/styles/components/kebab/kebabStyle.js b/src/styles/components/kebab/kebabStyle.js new file mode 100644 index 00000000..37c9d153 --- /dev/null +++ b/src/styles/components/kebab/kebabStyle.js @@ -0,0 +1,57 @@ +import styled from "styled-components"; +import { palette } from "../../commonStyles"; + +export const KebabMenuContainer = styled.div` + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; + gap: 2px; + width: 24px; + height: 24px; + cursor: pointer; + position: relative; +`; + +export const KebabIcon = styled.div` + width: 3px; + height: 3px; + background-color: ${palette.gray400}; + border-radius: 99px; +`; + +export const KebabDropdownContainer = styled.div` + width: 139px; + display: flex; + flex-direction: column; + position: absolute; + top: 100%; + right: 7%; + margin-top: 5px; + border: 1px solid ${palette.coolGray300}; + border-radius: 8px; + z-index: 50; + + & > :first-child { + border-top-right-radius: 8px; + border-top-left-radius: 8px; + } + + & > :last-child { + border-bottom-right-radius: 8px; + border-bottom-left-radius: 8px; + } +`; + +export const KebabDropdownButton = styled.button` + background-color: white; + border: none; + font-weight: 400; + font-size: 16px; + color: ${palette.secondary.gray500}; + padding: 16px 0px 12px; + + &:hover { + background-color: ${palette.gray100}; + } +`; From 0663d775df96ff78dcd620193d490c5a7b2c24c1 Mon Sep 17 00:00:00 2001 From: Imhwitae Date: Thu, 28 Aug 2025 22:11:33 +0900 Subject: [PATCH 68/94] =?UTF-8?q?design:=20=EC=A0=9C=ED=92=88=20=EC=A0=9C?= =?UTF-8?q?=EB=AA=A9=EC=97=90=20=EC=BC=80=EB=B0=A5=20=EB=A9=94=EB=89=B4=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/kebab/KebabDropdown.jsx | 5 +++++ src/pages/components/ItemDetail/ProductDetails.jsx | 4 +++- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/src/components/kebab/KebabDropdown.jsx b/src/components/kebab/KebabDropdown.jsx index 6086dfae..1b55f55c 100644 --- a/src/components/kebab/KebabDropdown.jsx +++ b/src/components/kebab/KebabDropdown.jsx @@ -5,6 +5,11 @@ import { } from "../../styles/components/kebab/kebabStyle"; import useCloseDropdown from "../../hooks/useCloseDropdown"; +/** + * 케밥 메뉴 클릭 시 보여지는 드롭다운 + * @param {object[]} menus + * @param {Function} onclickClose + */ const KebabDropdown = ({ menus, onClickClose }) => { const dropdownRef = useRef(null); useCloseDropdown(dropdownRef, onClickClose); diff --git a/src/pages/components/ItemDetail/ProductDetails.jsx b/src/pages/components/ItemDetail/ProductDetails.jsx index 11fa97f3..db34d0ea 100644 --- a/src/pages/components/ItemDetail/ProductDetails.jsx +++ b/src/pages/components/ItemDetail/ProductDetails.jsx @@ -13,13 +13,15 @@ import { import icProfile from "../../../assets/icons/ic_profile.svg"; import icHeartInactive from "../../../assets/icons/ic_heart_inactive_large.svg"; import icHeartActive from "../../../assets/icons/ic_heart_active_large.svg"; +import KebabMenu from "../../../components/kebab/KebabMenu"; export default function ProductDetails({ data, productInfo, isLoading }) { return (
    -
    +
    {productInfo.name} +
    {productInfo.price.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",") + From affa433ffddd6993f1e10e4a34c10633765a35ee Mon Sep 17 00:00:00 2001 From: Imhwitae Date: Fri, 29 Aug 2025 13:46:27 +0900 Subject: [PATCH 69/94] =?UTF-8?q?design:=20=EB=B0=98=EC=9D=91=ED=98=95=20?= =?UTF-8?q?=EB=94=94=EC=9E=90=EC=9D=B8=20=EC=A0=81=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../components/ItemDetail/ProductDetails.jsx | 10 +- src/pages/items/ItemDetail.jsx | 10 +- src/styles/components/InquiryStyles.js | 9 +- src/styles/items/ItemDetailStyle.js | 117 ++++++++++++++++-- 4 files changed, 125 insertions(+), 21 deletions(-) diff --git a/src/pages/components/ItemDetail/ProductDetails.jsx b/src/pages/components/ItemDetail/ProductDetails.jsx index db34d0ea..2f71f78b 100644 --- a/src/pages/components/ItemDetail/ProductDetails.jsx +++ b/src/pages/components/ItemDetail/ProductDetails.jsx @@ -6,6 +6,8 @@ import { ProductOwnerName, ProductPrice, ProductSubTitle, + ProductTagContainer, + ProductTagWrapper, ProductTextArea, ProductTextBox, ProductTitle, @@ -32,14 +34,14 @@ export default function ProductDetails({ data, productInfo, isLoading }) { 상품 소개 {productInfo.description}
    -
    + 상품 태그 -
    + {productInfo.tags.map((tag) => { return {`#${tag}`}; })} -
    -
    + +
    -
    + -
    + ); } diff --git a/src/styles/components/InquiryStyles.js b/src/styles/components/InquiryStyles.js index 66b2b51c..a068764c 100644 --- a/src/styles/components/InquiryStyles.js +++ b/src/styles/components/InquiryStyles.js @@ -10,12 +10,18 @@ export const InquiryTextArea = styled.textarea` resize: none; font-family: Pretendard-Reqular; padding: 20px; - font-size: 16px; + font-size: 14px; font-weight: 400; margin-bottom: 10px; &::placeholder { color: ${palette.gray400}; } + + @media (min-width: 744px) { + font-size: 16px; + line-height: 26px; + letter-spacing: 0%; + } `; export const InquiryTitle = styled.p` @@ -37,7 +43,6 @@ export const InquirySubmitButton = styled.button` font-weight: 600; background-color: ${({ isActive }) => isActive ? `${palette.blue}` : `${palette.gray400}`}; - // float: right; &:hover { background-color: ${({ isActive }) => diff --git a/src/styles/items/ItemDetailStyle.js b/src/styles/items/ItemDetailStyle.js index 3edfb867..906d5609 100644 --- a/src/styles/items/ItemDetailStyle.js +++ b/src/styles/items/ItemDetailStyle.js @@ -1,11 +1,27 @@ import styled from "styled-components"; import { ItemsTag, palette } from "../commonStyles"; +export const ProductDetailContainer = styled.div` + width: 100%; + margin: 0 auto; + max-width: 1200px; + padding: 16px 16px 0px 16px; + + @media (min-width: 744px) { + padding: 24px 24px 0px 24px; + } +`; + export const ProductInfoBox = styled.div` display: flex; margin-top: 20px; border-bottom: 1px solid ${palette.gray200}; padding-bottom: 40px; + flex-direction: column; + + @media (min-width: 744px) { + flex-direction: row; + } `; export const ProductTextBox = styled.div` @@ -15,38 +31,115 @@ export const ProductTextBox = styled.div` `; export const ProductImg = styled.img` - width: 486px; - height: 486px; border-radius: 16px; border: none; - margin-right: 20px; + + @media (min-width: 375px) { + width: 343px; + height: 343px; + margin: 0; + margin-bottom: 16px; + } + + @media (min-width: 744px) { + margin-right: 16px; + } + + @media (min-width: 1200px) { + margin-right: 20px; + width: 486px; + height: 486px; + } `; export const ProductTitle = styled.h1` - font-size: 24px; font-weight: 600; margin: 0; + + @media (min-width: 375px) { + font-size: 16px; + line-height: 26px; + } + + @media (min-width: 744px) { + font-size: 20px; + line-height: 32px; + letter-spacing: 0%; + } + + @media (min-width: 1200px) { + font-size: 24px; + line-height: 32px; + letter-spacing: 0%; + } `; export const ProductPrice = styled.p` - font-size: 40px; font-weight: 600; - margin: 20px 0px 10px; + + @media (min-width: 375px) { + font-size: 24px; + line-height: 32px; + margin: 8px 0px 16px; + } + + @media (min-width: 744px) { + font-size: 32px; + line-height: 42px; + letter-spacing: 0%; + } + + @media (min-width: 1200px) { + font-size: 40px; + line-height: 32px; + letter-spacing: 0%; + margin: 20px 0px 10px; + } `; export const ProductSubTitle = styled.p` - font-size: 16px; - font-weight: 600; color: ${palette.gray600}; - margin: 20px 0px; + + @media (min-width: 375px) { + font-size: 14px; + line-height: 24px; + letter-spacing: 0%; + margin: 16px 0px 8px; + } + + @media (min-width: 1200px) { + font-size: 16px; + font-weight: 600; + margin: 20px 0px; + } `; export const ProductTextArea = styled.p` - font-size: 16px; - font-weight: 400; - width: 100%; color: ${palette.gray600}; + width: 100%; margin: 0; + + @media (min-width: 375px) { + font-size: 16px; + line-height: 26px; + letter-spacing: 0%; + } +`; + +export const ProductTagWrapper = styled.div` + @media (min-width: 375px) { + margin-bottom: 40px; + } + + @media (min-width: 1200px) { + margin-bottom: 100px; + } +`; + +export const ProductTagContainer = styled.div` + display: flex; + flex-wrap: wrap; + row-gap: 10px; `; export const ProductOwnerName = styled.p` From 95059765147a87310ffc9c5c3cd346467c227870 Mon Sep 17 00:00:00 2001 From: Imhwitae Date: Fri, 29 Aug 2025 13:54:31 +0900 Subject: [PATCH 70/94] =?UTF-8?q?design:=20=EB=B2=84=ED=8A=BC=EC=97=90=20h?= =?UTF-8?q?over=20=ED=9A=A8=EA=B3=BC=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/styles/components/InquiryStyles.js | 8 ++++++++ src/styles/items/ItemDetailStyle.js | 6 ++++++ 2 files changed, 14 insertions(+) diff --git a/src/styles/components/InquiryStyles.js b/src/styles/components/InquiryStyles.js index a068764c..5811c5a0 100644 --- a/src/styles/components/InquiryStyles.js +++ b/src/styles/components/InquiryStyles.js @@ -94,4 +94,12 @@ export const BackButton = styled.button` align-items: center; display: flex; gap: 10px; + + &:hover { + background-color: #1967d6; + } + + &:active { + background-color: #1251aa; + } `; diff --git a/src/styles/items/ItemDetailStyle.js b/src/styles/items/ItemDetailStyle.js index 906d5609..9c295cfd 100644 --- a/src/styles/items/ItemDetailStyle.js +++ b/src/styles/items/ItemDetailStyle.js @@ -165,6 +165,12 @@ export const Heart = styled.div` column-gap: 5px; padding: 2px 10px; align-items: center; + transition: transform 0.3s ease; + + &:hover { + cursor: pointer; + transform: scale(1.1); + } `; export const HeartCount = styled.p` From 4c33e07c4383f16c93350db34a0f9aa1c9884f65 Mon Sep 17 00:00:00 2001 From: Imhwitae Date: Fri, 29 Aug 2025 14:35:44 +0900 Subject: [PATCH 71/94] =?UTF-8?q?feat:=20=EB=AC=B8=EC=9D=98=20=EB=93=B1?= =?UTF-8?q?=EB=A1=9D=20API=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/Inquiry.jsx | 31 +++++++++++++++++++++--- src/hooks/useService.jsx | 37 +++++++++++++++-------------- src/services/inquiryApi.js | 48 ++++++++++++++++++++++++++++++++++++++ src/services/itemsApi.js | 16 ------------- 4 files changed, 95 insertions(+), 37 deletions(-) create mode 100644 src/services/inquiryApi.js diff --git a/src/components/Inquiry.jsx b/src/components/Inquiry.jsx index 84f8244c..ea1e8100 100644 --- a/src/components/Inquiry.jsx +++ b/src/components/Inquiry.jsx @@ -10,7 +10,10 @@ import { InquiryTitle, InquiryWriter, } from "../styles/components/InquiryStyles"; -import { requestInquiryLists } from "../services/itemsApi"; +import { + requestInquiryLists, + requestPostInquiry, +} from "../services/inquiryApi"; import icProfile from "../assets/icons/ic_profile.svg"; import { formatTimeAgo } from "../util/formatTimeAgo"; import { useNavigate } from "react-router"; @@ -26,7 +29,23 @@ export default function Inquiry({ id }) { */ const [isActive, setIsActive] = useState(false); - const { data, isLoading } = useService(() => requestInquiryLists(id)); + /** + * 문의 내역을 가져온다. + */ + const { data, isLoading, requestServer } = useService(() => + requestInquiryLists(id) + ); + + const onClickUploadInquiry = (e) => { + let data = { + productId: id, + Inquiry: { + content: e.target.value, + }, + }; + + requestServer(() => requestPostInquiry(data)); + }; return ( <> @@ -38,7 +57,13 @@ export default function Inquiry({ id }) { }} placeholder="개인정보를 공유 및 요청하거나, 명예 훼손, 무단 광고, 불법 정보 유포시 모니터링 후 삭제될 수 있으며, 이에 대한 민형사상 책임은 게시자에게 있습니다." > - 등록 + + 등록 +
    {!isLoading ? ( data ? ( diff --git a/src/hooks/useService.jsx b/src/hooks/useService.jsx index e0347e1d..5b70c40a 100644 --- a/src/hooks/useService.jsx +++ b/src/hooks/useService.jsx @@ -8,29 +8,30 @@ import { useEffect, useState } from "react"; const useService = (fetchFunction) => { const [isLoading, setIsLoading] = useState(false); const [data, setData] = useState(); + const [error, setError] = useState(false); + const requestServer = async (dataFetch) => { + try { + setIsLoading(true); + const response = await dataFetch(); - useEffect(() => { - const getService = async (getDataFunction) => { - try { - setIsLoading(true); - const response = await getDataFunction(); - - if (!response) { - throw new Error("데이터를 불러오지 못했습니다."); - } - - setData(response); - } catch (error) { - console.log(error); - } finally { - setIsLoading(false); + if (!response) { + throw new Error("서버와의 통신에 실패했습니다."); } - }; - getService(fetchFunction); + setData(response); + } catch (error) { + setError(true); + console.log(error); + } finally { + setIsLoading(false); + } + }; + + useEffect(() => { + requestServer(fetchFunction); }, []); - return { data, isLoading }; + return { data, isLoading, error, requestServer }; }; export default useService; diff --git a/src/services/inquiryApi.js b/src/services/inquiryApi.js new file mode 100644 index 00000000..0e05488b --- /dev/null +++ b/src/services/inquiryApi.js @@ -0,0 +1,48 @@ +/** + * 문의 데이터를 가져온다. + * @param {string} productId + */ +export const requestInquiryLists = async (productId) => { + const url = new URL( + `https://panda-market-api.vercel.app/products/${productId}/comments` + ); + url.searchParams.append("limit", 3); + + const response = await fetch(url, { + method: "get", + headers: { + "Content-Type": "application/json", + }, + }); + + return response.json(); +}; + +/** + * 문의 내용을 등록한다. + * @param {object{}} inquiryData 상품 아이디와 문의 내역 객체 + * @returns + */ +export const requestPostInquiry = async (inquiryData) => { + const url = new URL( + `https://panda-market-api.vercel.app/products/${inquiryData.productId}/comments` + ); + + try { + const response = await fetch(url, { + method: "POST", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify(inquiryData.inquiry), + }); + + if (!response.ok) { + alert("데이터를 전송하지 못했습니다. 다시 시도해주세요"); + } + + return response.json(); + } catch (error) { + console.error(error); + } +}; diff --git a/src/services/itemsApi.js b/src/services/itemsApi.js index b153a1f9..8148c414 100644 --- a/src/services/itemsApi.js +++ b/src/services/itemsApi.js @@ -38,19 +38,3 @@ export const requestProductDetail = async (productId) => { return response.json(); }; - -export const requestInquiryLists = async (productId) => { - const url = new URL( - `https://panda-market-api.vercel.app/products/${productId}/comments` - ); - url.searchParams.append("limit", 3); - - const response = await fetch(url, { - method: "get", - headers: { - "Content-Type": "application/json", - }, - }); - - return response.json(); -}; From 27e7a37abb152cb308ac0d4bc80d5b838cb2734d Mon Sep 17 00:00:00 2001 From: Imhwitae Date: Fri, 29 Aug 2025 16:29:59 +0900 Subject: [PATCH 72/94] =?UTF-8?q?refactor:=20=EB=AC=B8=EC=9D=98=20?= =?UTF-8?q?=EC=9E=91=EC=84=B1=20=EC=BB=B4=ED=8F=AC=EB=84=8C=ED=8A=B8=20?= =?UTF-8?q?=EB=B6=84=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/Inquiry.jsx | 40 +++----------------- src/components/InquiryWriteArea.jsx | 57 +++++++++++++++++++++++++++++ src/hooks/usePost.jsx | 9 +++++ src/hooks/useService.jsx | 37 ++++++++++--------- 4 files changed, 90 insertions(+), 53 deletions(-) create mode 100644 src/components/InquiryWriteArea.jsx create mode 100644 src/hooks/usePost.jsx diff --git a/src/components/Inquiry.jsx b/src/components/Inquiry.jsx index ea1e8100..ddde2ace 100644 --- a/src/components/Inquiry.jsx +++ b/src/components/Inquiry.jsx @@ -1,4 +1,3 @@ -import { useState } from "react"; import { palette } from "../styles/commonStyles"; import { BackButton, @@ -21,50 +20,21 @@ import icBack from "../assets/icons/ic_back.svg"; import imgEmptyMd from "../assets/images/img_inquiry_empty_md.png"; import useService from "../hooks/useService"; import KebabMenu from "./kebab/KebabMenu"; +import usePost from "../hooks/usePost"; +import InquiryWriteArea from "./InquiryWriteArea"; export default function Inquiry({ id }) { const navigate = useNavigate(); - /** - * 버튼 활성화 state - */ - const [isActive, setIsActive] = useState(false); /** * 문의 내역을 가져온다. */ - const { data, isLoading, requestServer } = useService(() => - requestInquiryLists(id) - ); - - const onClickUploadInquiry = (e) => { - let data = { - productId: id, - Inquiry: { - content: e.target.value, - }, - }; - - requestServer(() => requestPostInquiry(data)); - }; + const { data, isLoading } = useService(() => requestInquiryLists(id)); return ( <> -
    - 문의하기 - { - e.target.value !== "" ? setIsActive(true) : setIsActive(false); - }} - placeholder="개인정보를 공유 및 요청하거나, 명예 훼손, 무단 광고, 불법 정보 유포시 모니터링 후 삭제될 수 있으며, 이에 대한 민형사상 책임은 게시자에게 있습니다." - > - - 등록 - -
    + 문의하기 + {!isLoading ? ( data ? ( data.list?.map((el) => { diff --git a/src/components/InquiryWriteArea.jsx b/src/components/InquiryWriteArea.jsx new file mode 100644 index 00000000..be264830 --- /dev/null +++ b/src/components/InquiryWriteArea.jsx @@ -0,0 +1,57 @@ +import { useState } from "react"; +import usePost from "../hooks/usePost"; +import { + InquirySubmitButton, + InquiryTextArea, +} from "../styles/components/InquiryStyles"; + +/** + * 문의 내역 작성 공간 + */ +export default function InquiryWriteArea() { + const [isActive, setIsActive] = useState(false); + const [inquiryContent, setInquiryContent] = useState(""); + + const onChangeWrite = (e) => { + if (e.target.value) { + setIsActive(true); + } else { + setIsActive(false); + } + + setInquiryContent(e.target.value); + }; + + const onClickUploadInquiry = () => { + let data = { + productId: id, + Inquiry: { + content: inquiryContent, + }, + }; + + const { data: success } = usePost(requestPostInquiry(data)); + + if (success) { + location.reload(true); + } else { + alert("등록에 실패했습니다."); + } + }; + + return ( +
    + + + 등록 + +
    + ); +} diff --git a/src/hooks/usePost.jsx b/src/hooks/usePost.jsx new file mode 100644 index 00000000..681432e1 --- /dev/null +++ b/src/hooks/usePost.jsx @@ -0,0 +1,9 @@ +import useService from "./useService"; + +const usePost = (postFetching) => { + const { data, isLoading, isError } = useService(() => postFetching); + + return { data, isLoading, isError }; +}; + +export default usePost; diff --git a/src/hooks/useService.jsx b/src/hooks/useService.jsx index 5b70c40a..eb137f8f 100644 --- a/src/hooks/useService.jsx +++ b/src/hooks/useService.jsx @@ -9,29 +9,30 @@ const useService = (fetchFunction) => { const [isLoading, setIsLoading] = useState(false); const [data, setData] = useState(); const [error, setError] = useState(false); - const requestServer = async (dataFetch) => { - try { - setIsLoading(true); - const response = await dataFetch(); - if (!response) { - throw new Error("서버와의 통신에 실패했습니다."); - } + useEffect(() => { + const getService = async (getDataFunction) => { + try { + setIsLoading(true); + const response = await getDataFunction(); - setData(response); - } catch (error) { - setError(true); - console.log(error); - } finally { - setIsLoading(false); - } - }; + if (!response) { + throw new Error("서버와의 통신에 실패했습니다."); + } - useEffect(() => { - requestServer(fetchFunction); + setData(response); + } catch (error) { + setError(true); + console.error(error); + } finally { + setIsLoading(false); + } + }; + + getService(fetchFunction); }, []); - return { data, isLoading, error, requestServer }; + return { data, isLoading, error }; }; export default useService; From bd65187ba9138e8c4230aab1db1e9f7bbc78e82a Mon Sep 17 00:00:00 2001 From: Imhwitae Date: Fri, 29 Aug 2025 17:51:33 +0900 Subject: [PATCH 73/94] =?UTF-8?q?refactor:=20=EC=BB=B4=ED=8F=AC=EB=84=8C?= =?UTF-8?q?=ED=8A=B8=20=EA=B5=AC=EC=A1=B0=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/Inquiry.jsx | 86 ++----------------- .../components/ItemDetail/InquiryList.jsx | 64 ++++++++++++++ src/styles/components/InquiryStyles.js | 7 ++ src/styles/items/ItemDetailStyle.js | 2 +- 4 files changed, 78 insertions(+), 81 deletions(-) create mode 100644 src/pages/components/ItemDetail/InquiryList.jsx diff --git a/src/components/Inquiry.jsx b/src/components/Inquiry.jsx index ddde2ace..f1258fca 100644 --- a/src/components/Inquiry.jsx +++ b/src/components/Inquiry.jsx @@ -1,27 +1,14 @@ -import { palette } from "../styles/commonStyles"; import { BackButton, - InquiryContent, - InquiryDate, - InquiryProfileImg, - InquirySubmitButton, - InquiryTextArea, + BackButtonWrapper, InquiryTitle, - InquiryWriter, } from "../styles/components/InquiryStyles"; -import { - requestInquiryLists, - requestPostInquiry, -} from "../services/inquiryApi"; -import icProfile from "../assets/icons/ic_profile.svg"; -import { formatTimeAgo } from "../util/formatTimeAgo"; +import { requestInquiryLists } from "../services/inquiryApi"; import { useNavigate } from "react-router"; import icBack from "../assets/icons/ic_back.svg"; -import imgEmptyMd from "../assets/images/img_inquiry_empty_md.png"; import useService from "../hooks/useService"; -import KebabMenu from "./kebab/KebabMenu"; -import usePost from "../hooks/usePost"; import InquiryWriteArea from "./InquiryWriteArea"; +import InquiryList from "../pages/components/ItemDetail/InquiryList"; export default function Inquiry({ id }) { const navigate = useNavigate(); @@ -35,74 +22,13 @@ export default function Inquiry({ id }) { <> 문의하기 - {!isLoading ? ( - data ? ( - data.list?.map((el) => { - return ( -
    -
    - {el.content} - -
    -
    - -
    - {el.writer.nickname} - {formatTimeAgo(el.updatedAt)} -
    -
    -
    - ); - }) - ) : ( -
    - 빈 이미지 -

    - 아직 문의가 없어요 -

    -
    - ) - ) : ( -
    로딩중
    - )} -
    + {!isLoading ? :
    로딩중
    } + navigate(-1)}> 목록으로 돌아가기 뒤로가기 이미지 -
    + ); } diff --git a/src/pages/components/ItemDetail/InquiryList.jsx b/src/pages/components/ItemDetail/InquiryList.jsx new file mode 100644 index 00000000..a375b04b --- /dev/null +++ b/src/pages/components/ItemDetail/InquiryList.jsx @@ -0,0 +1,64 @@ +import KebabMenu from "../../../components/kebab/KebabMenu"; +import { palette } from "../../../styles/commonStyles"; +import { + InquiryContent, + InquiryDate, + InquiryProfileImg, + InquiryWriter, +} from "../../../styles/components/InquiryStyles"; +import icProfile from "../../../assets/icons/ic_profile.svg"; +import imgEmptyMd from "../../../assets/images/img_inquiry_empty_md.png"; +import { formatTimeAgo } from "../../../util/formatTimeAgo"; + +const InquiryList = ({ data }) => { + return data ? ( + data.list?.map((el) => { + return ( +
    +
    + {el.content} + +
    +
    + +
    + {el.writer.nickname} + {formatTimeAgo(el.updatedAt)} +
    +
    +
    + ); + }) + ) : ( +
    + 빈 이미지 +

    + 아직 문의가 없어요 +

    +
    + ); +}; + +export default InquiryList; diff --git a/src/styles/components/InquiryStyles.js b/src/styles/components/InquiryStyles.js index 5811c5a0..cac63e29 100644 --- a/src/styles/components/InquiryStyles.js +++ b/src/styles/components/InquiryStyles.js @@ -80,6 +80,13 @@ export const InquiryDate = styled.p` color: ${palette.gray400}; `; +export const BackButtonWrapper = styled.div` + margin: 60px 0px 60px; + text-align: center; + display: flex; + justify-content: center; +`; + export const BackButton = styled.button` width: 240px; height: 48px; diff --git a/src/styles/items/ItemDetailStyle.js b/src/styles/items/ItemDetailStyle.js index 9c295cfd..e20d3ecc 100644 --- a/src/styles/items/ItemDetailStyle.js +++ b/src/styles/items/ItemDetailStyle.js @@ -93,7 +93,7 @@ export const ProductPrice = styled.p` font-size: 40px; line-height: 32px; letter-spacing: 0%; - margin: 20px 0px 10px; + margin: 20px 0px 16px; } `; From f40f57f37bf99ada70838afaab1c5f3b3bf69ea8 Mon Sep 17 00:00:00 2001 From: Imhwitae Date: Fri, 29 Aug 2025 17:58:16 +0900 Subject: [PATCH 74/94] =?UTF-8?q?fix:=20=EB=AC=B8=EC=9D=98=20=EC=97=86?= =?UTF-8?q?=EC=9D=84=20=EB=95=8C=20=EC=9D=B4=EB=AF=B8=EC=A7=80=20=EB=B3=B4?= =?UTF-8?q?=EC=97=AC=EC=A3=BC=EB=8A=94=20=EB=A1=9C=EC=A7=81=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/pages/components/ItemDetail/InquiryList.jsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pages/components/ItemDetail/InquiryList.jsx b/src/pages/components/ItemDetail/InquiryList.jsx index a375b04b..f91de4ef 100644 --- a/src/pages/components/ItemDetail/InquiryList.jsx +++ b/src/pages/components/ItemDetail/InquiryList.jsx @@ -11,7 +11,7 @@ import imgEmptyMd from "../../../assets/images/img_inquiry_empty_md.png"; import { formatTimeAgo } from "../../../util/formatTimeAgo"; const InquiryList = ({ data }) => { - return data ? ( + return data?.length > 0 ? ( data.list?.map((el) => { return (
    Date: Fri, 29 Aug 2025 18:05:40 +0900 Subject: [PATCH 75/94] =?UTF-8?q?docs:=20README=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/README.md b/README.md index 5d919827..6370b2bd 100644 --- a/README.md +++ b/README.md @@ -150,4 +150,40 @@ - styled component를 사용해서 스타일링을 했는데 한 컴포넌트의 코드가 너무 길어지는 느낌입니다. 스타일은 따로 빼놓는게 나을까요? +
    + +## 미션 7 요구사항 + +### 기본 + +- [x] 상품 상세 페이지 주소는 “items/{productId}” 입니다. +- [x] response로 받은 아래의 데이터로 화면을 구현합니다. + - favoriteCount : 하트 개수 + - images : 상품 이미지 + - tags : 상품태그 + - name : 상품 이름 + - description : 상품 설명 +- [x] 목록으로 돌아가기 버튼을 클릭하면 중고마켓 페이지 주소인 "/items"로 이동합니다. +- [x] 문의하기에 내용을 입력하면 등록 버튼의 색상은 “3692FF”로 변합니다. +- [x] response 로 받은 아래의 데이터로 화면을 구현합니다. + - image : 작성자 이미지 + - nickname : 작성자 닉네임 + - content : 작성자가 남긴 문구 + - description : 상품 설명 + - updatedAt : 문의글 마지막 업데이트 시간 + +### 심화 + +- [x] 모든 버튼에 자유롭게 Hover효과를 적용하세요. + +### 주요 변경사항 + +### 스크린샷 + +| PC | Tablet | Mobile | +| :---------------------------------------------------------------------------------------------------------------------------------------------------: | :-------------------------------------------------------------------------------------------------------------------------------------------------------: | :------------------------------------------------------------------------------------------------------------------------------------------------------: | +| localhost_5173_additem | localhost_5173_additem (1) | localhost_5173_additem (2) | + +### 멘토에게 + Copyright 2025 코드잇 Inc. All rights reserved. From 462577536d1ca6388c097b58ac765f3e42518dea Mon Sep 17 00:00:00 2001 From: Imhwitae Date: Fri, 29 Aug 2025 18:11:51 +0900 Subject: [PATCH 76/94] =?UTF-8?q?fix:=20=EB=AC=B8=EC=9D=98=20=EB=82=B4?= =?UTF-8?q?=EC=97=AD=20=ED=91=9C=EC=B6=9C=20=EC=A1=B0=EA=B1=B4=20=EB=B3=80?= =?UTF-8?q?=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/pages/components/ItemDetail/InquiryList.jsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pages/components/ItemDetail/InquiryList.jsx b/src/pages/components/ItemDetail/InquiryList.jsx index f91de4ef..16dfc373 100644 --- a/src/pages/components/ItemDetail/InquiryList.jsx +++ b/src/pages/components/ItemDetail/InquiryList.jsx @@ -11,7 +11,7 @@ import imgEmptyMd from "../../../assets/images/img_inquiry_empty_md.png"; import { formatTimeAgo } from "../../../util/formatTimeAgo"; const InquiryList = ({ data }) => { - return data?.length > 0 ? ( + return data?.list?.length > 0 ? ( data.list?.map((el) => { return (
    Date: Tue, 2 Sep 2025 14:47:45 +0900 Subject: [PATCH 77/94] =?UTF-8?q?fix:=20=EC=BD=94=EB=93=9C=20=EB=A6=AC?= =?UTF-8?q?=EB=B7=B0=20=EB=B0=98=EC=98=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 2 ++ src/components/Inquiry.jsx | 4 ++-- src/components/InquiryWriteArea.jsx | 3 +-- src/hooks/usePost.jsx | 9 --------- src/hooks/useService.jsx | 12 ++++++------ src/pages/items/ItemDetail.jsx | 4 ++-- src/services/inquiryApi.js | 10 ++++------ src/services/itemsApi.js | 8 ++++---- 8 files changed, 21 insertions(+), 31 deletions(-) delete mode 100644 src/hooks/usePost.jsx diff --git a/.gitignore b/.gitignore index a547bf36..cea8a0ba 100644 --- a/.gitignore +++ b/.gitignore @@ -22,3 +22,5 @@ dist-ssr *.njsproj *.sln *.sw? + +*.env \ No newline at end of file diff --git a/src/components/Inquiry.jsx b/src/components/Inquiry.jsx index f1258fca..e669deea 100644 --- a/src/components/Inquiry.jsx +++ b/src/components/Inquiry.jsx @@ -6,7 +6,7 @@ import { import { requestInquiryLists } from "../services/inquiryApi"; import { useNavigate } from "react-router"; import icBack from "../assets/icons/ic_back.svg"; -import useService from "../hooks/useService"; +import useFetch from "../hooks/useService"; import InquiryWriteArea from "./InquiryWriteArea"; import InquiryList from "../pages/components/ItemDetail/InquiryList"; @@ -16,7 +16,7 @@ export default function Inquiry({ id }) { /** * 문의 내역을 가져온다. */ - const { data, isLoading } = useService(() => requestInquiryLists(id)); + const { data, isLoading } = useFetch(() => requestInquiryLists(id)); return ( <> diff --git a/src/components/InquiryWriteArea.jsx b/src/components/InquiryWriteArea.jsx index be264830..66e3d12e 100644 --- a/src/components/InquiryWriteArea.jsx +++ b/src/components/InquiryWriteArea.jsx @@ -1,5 +1,4 @@ import { useState } from "react"; -import usePost from "../hooks/usePost"; import { InquirySubmitButton, InquiryTextArea, @@ -30,7 +29,7 @@ export default function InquiryWriteArea() { }, }; - const { data: success } = usePost(requestPostInquiry(data)); + // const { data: success } = usePost(requestPostInquiry(data)); if (success) { location.reload(true); diff --git a/src/hooks/usePost.jsx b/src/hooks/usePost.jsx deleted file mode 100644 index 681432e1..00000000 --- a/src/hooks/usePost.jsx +++ /dev/null @@ -1,9 +0,0 @@ -import useService from "./useService"; - -const usePost = (postFetching) => { - const { data, isLoading, isError } = useService(() => postFetching); - - return { data, isLoading, isError }; -}; - -export default usePost; diff --git a/src/hooks/useService.jsx b/src/hooks/useService.jsx index eb137f8f..a3943f7f 100644 --- a/src/hooks/useService.jsx +++ b/src/hooks/useService.jsx @@ -3,18 +3,18 @@ import { useEffect, useState } from "react"; /** * 데이터 통신을 위한 공통 커스텀 훅 * @param {Function} fetchFunction 서버와 직접 통신하는 함수 - * @returns {data: object, isLoading: boolean} + * @returns {data: object, isLoading: boolean, error: boolean} */ -const useService = (fetchFunction) => { +const useFetch = (fetchFunction) => { const [isLoading, setIsLoading] = useState(false); const [data, setData] = useState(); const [error, setError] = useState(false); useEffect(() => { - const getService = async (getDataFunction) => { + const fetcher = async (fetching) => { try { setIsLoading(true); - const response = await getDataFunction(); + const response = await fetching(); if (!response) { throw new Error("서버와의 통신에 실패했습니다."); @@ -29,10 +29,10 @@ const useService = (fetchFunction) => { } }; - getService(fetchFunction); + fetcher(fetchFunction); }, []); return { data, isLoading, error }; }; -export default useService; +export default useFetch; diff --git a/src/pages/items/ItemDetail.jsx b/src/pages/items/ItemDetail.jsx index f21deeb3..9e0105fd 100644 --- a/src/pages/items/ItemDetail.jsx +++ b/src/pages/items/ItemDetail.jsx @@ -7,7 +7,7 @@ import { } from "../../styles/items/ItemDetailStyle"; import Inquiry from "../../components/Inquiry"; -import useService from "../../hooks/useService"; +import useFetch from "../../hooks/useService"; import ProductDetails from "../components/ItemDetail/ProductDetails"; export default function ItemDetail() { @@ -24,7 +24,7 @@ export default function ItemDetail() { /** * 상품 정보 받아오기 */ - const { data, isLoading } = useService(() => requestProductDetail(productId)); + const { data, isLoading } = useFetch(() => requestProductDetail(productId)); return ( <> diff --git a/src/services/inquiryApi.js b/src/services/inquiryApi.js index 0e05488b..e22edd35 100644 --- a/src/services/inquiryApi.js +++ b/src/services/inquiryApi.js @@ -1,11 +1,11 @@ +const BASE_URL = import.meta.env.VITE_BASE_URL; + /** * 문의 데이터를 가져온다. * @param {string} productId */ export const requestInquiryLists = async (productId) => { - const url = new URL( - `https://panda-market-api.vercel.app/products/${productId}/comments` - ); + const url = new URL(`${BASE_URL}products/${productId}/comments`); url.searchParams.append("limit", 3); const response = await fetch(url, { @@ -24,9 +24,7 @@ export const requestInquiryLists = async (productId) => { * @returns */ export const requestPostInquiry = async (inquiryData) => { - const url = new URL( - `https://panda-market-api.vercel.app/products/${inquiryData.productId}/comments` - ); + const url = new URL(`${BASE_URL}products/${inquiryData.productId}/comments`); try { const response = await fetch(url, { diff --git a/src/services/itemsApi.js b/src/services/itemsApi.js index 8148c414..2d26357f 100644 --- a/src/services/itemsApi.js +++ b/src/services/itemsApi.js @@ -1,10 +1,12 @@ +const BASE_URL = import.meta.env.VITE_BASE_URL; + /** * 서버에 상품 목록을 요청한다. * @param {string} orderBy * @returns {object} */ export const requestProductList = async (query) => { - const url = new URL("https://panda-market-api.vercel.app/products"); + const url = new URL(`${BASE_URL}products`); url.searchParams.append("page", query.page); url.searchParams.append("pageSize", query.pageSize); url.searchParams.append("orderBy", query.orderBy); @@ -25,9 +27,7 @@ export const requestProductList = async (query) => { * @returns {json} response */ export const requestProductDetail = async (productId) => { - const url = new URL( - `https://panda-market-api.vercel.app/products/${productId}` - ); + const url = new URL(`${BASE_URL}products/${productId}`); const response = await fetch(url, { method: "get", From ec03870e31ba44b69383fe73acdbec9e99ce8b4a Mon Sep 17 00:00:00 2001 From: Imhwitae Date: Tue, 2 Sep 2025 20:16:39 +0900 Subject: [PATCH 78/94] =?UTF-8?q?refactor:=20=EB=A9=94=EC=9D=B8,=20?= =?UTF-8?q?=EB=A1=9C=EA=B7=B8=EC=9D=B8=20=ED=8E=98=EC=9D=B4=EC=A7=80=20?= =?UTF-8?q?=ED=83=80=EC=9E=85=EC=8A=A4=ED=81=AC=EB=A6=BD=ED=8A=B8=20?= =?UTF-8?q?=EC=A0=81=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- index.html | 2 +- package-lock.json | 15 +++ package.json | 1 + src/{App.jsx => App.tsx} | 0 src/layout/{AuthLayout.jsx => AuthLayout.tsx} | 17 ++-- src/layout/{Footer.jsx => Footer.tsx} | 10 +- src/layout/{Header.jsx => Header.tsx} | 0 src/layout/{MainLayout.jsx => MainLayout.tsx} | 6 +- src/main.jsx | 12 --- src/main.tsx | 12 +++ src/pages/{Home.jsx => Home.tsx} | 14 +-- src/pages/auth/{Login.jsx => Login.tsx} | 52 +++++----- src/pages/auth/{Signup.jsx => Signup.tsx} | 94 ++++++++++--------- src/vite-env.d.ts | 1 + tsconfig.json | 25 +++++ tsconfig.node.json | 11 +++ vite.config.js => vite.config.ts | 0 17 files changed, 174 insertions(+), 98 deletions(-) rename src/{App.jsx => App.tsx} (100%) rename src/layout/{AuthLayout.jsx => AuthLayout.tsx} (59%) rename src/layout/{Footer.jsx => Footer.tsx} (88%) rename src/layout/{Header.jsx => Header.tsx} (100%) rename src/layout/{MainLayout.jsx => MainLayout.tsx} (60%) delete mode 100644 src/main.jsx create mode 100644 src/main.tsx rename src/pages/{Home.jsx => Home.tsx} (88%) rename src/pages/auth/{Login.jsx => Login.tsx} (73%) rename src/pages/auth/{Signup.jsx => Signup.tsx} (71%) create mode 100644 src/vite-env.d.ts create mode 100644 tsconfig.json create mode 100644 tsconfig.node.json rename vite.config.js => vite.config.ts (100%) diff --git a/index.html b/index.html index 2cfc72a7..1cacaed7 100644 --- a/index.html +++ b/index.html @@ -17,6 +17,6 @@
    - + diff --git a/package-lock.json b/package-lock.json index ab8993f0..5df50a73 100644 --- a/package-lock.json +++ b/package-lock.json @@ -22,6 +22,7 @@ "eslint-plugin-react": "^7.34.1", "eslint-plugin-react-hooks": "^4.6.0", "eslint-plugin-react-refresh": "^0.4.6", + "typescript": "^5.9.2", "vite": "^5.2.0" } }, @@ -4688,6 +4689,20 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/typescript": { + "version": "5.9.2", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.2.tgz", + "integrity": "sha512-CWBzXQrc/qOkhidw1OzBTQuYRbfyxDXJMVJ1XNwUHGROVmuaeiEm3OslpZ1RV96d7SKKjZKrSJu3+t/xlw3R9A==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, "node_modules/unbox-primitive": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.1.0.tgz", diff --git a/package.json b/package.json index 27c32455..d6271d62 100644 --- a/package.json +++ b/package.json @@ -24,6 +24,7 @@ "eslint-plugin-react": "^7.34.1", "eslint-plugin-react-hooks": "^4.6.0", "eslint-plugin-react-refresh": "^0.4.6", + "typescript": "^5.9.2", "vite": "^5.2.0" } } diff --git a/src/App.jsx b/src/App.tsx similarity index 100% rename from src/App.jsx rename to src/App.tsx diff --git a/src/layout/AuthLayout.jsx b/src/layout/AuthLayout.tsx similarity index 59% rename from src/layout/AuthLayout.jsx rename to src/layout/AuthLayout.tsx index 24bc8e9a..8eee3100 100644 --- a/src/layout/AuthLayout.jsx +++ b/src/layout/AuthLayout.tsx @@ -1,13 +1,18 @@ -import { useState } from 'react'; -import { Outlet } from 'react-router'; -import visibleEye_off from '../assets/icons/eyes_off.png'; -import visibleEye_on from '../assets/icons/eyes_on.png'; +import { useState } from "react"; +import { Outlet } from "react-router"; +import visibleEye_off from "../assets/icons/eyes_off.png"; +import visibleEye_on from "../assets/icons/eyes_on.png"; + +export interface visibleValue { + pw: boolean; + checkPw: boolean; +} export default function AuthLayout() { /** * 비밀번호 보이기 / 가리기 상태 */ - const [visible, setVisible] = useState({ + const [visible, setVisible] = useState({ pw: false, checkPw: false, }); @@ -16,7 +21,7 @@ export default function AuthLayout() { * id 별로 비밀번호 가리기 여부를 변경한다. * @param {string} id */ - const onClickVisible = (id) => { + const onClickVisible = (id: keyof visibleValue) => { setVisible((prevState) => ({ ...prevState, [id]: !visible[id], diff --git a/src/layout/Footer.jsx b/src/layout/Footer.tsx similarity index 88% rename from src/layout/Footer.jsx rename to src/layout/Footer.tsx index fc20dca7..7f4769e7 100644 --- a/src/layout/Footer.jsx +++ b/src/layout/Footer.tsx @@ -1,8 +1,8 @@ -import '../styles/layout/footer.css'; -import ic_facebook from '../assets/icons/ic_facebook.svg'; -import ic_twitter from '../assets/icons/ic_twitter.svg'; -import ic_youtube from '../assets/icons/ic_youtube.svg'; -import ic_instagram from '../assets/icons/ic_instagram.svg'; +import "../styles/layout/footer.css"; +import ic_facebook from "../assets/icons/ic_facebook.svg"; +import ic_twitter from "../assets/icons/ic_twitter.svg"; +import ic_youtube from "../assets/icons/ic_youtube.svg"; +import ic_instagram from "../assets/icons/ic_instagram.svg"; /** * 푸터 diff --git a/src/layout/Header.jsx b/src/layout/Header.tsx similarity index 100% rename from src/layout/Header.jsx rename to src/layout/Header.tsx diff --git a/src/layout/MainLayout.jsx b/src/layout/MainLayout.tsx similarity index 60% rename from src/layout/MainLayout.jsx rename to src/layout/MainLayout.tsx index e0e2f203..481b0a02 100644 --- a/src/layout/MainLayout.jsx +++ b/src/layout/MainLayout.tsx @@ -1,6 +1,6 @@ -import Header from './Header'; -import Footer from './Footer'; -import { Outlet } from 'react-router'; +import Header from "./Header"; +import Footer from "./Footer"; +import { Outlet } from "react-router"; export default function MainLayout() { return ( diff --git a/src/main.jsx b/src/main.jsx deleted file mode 100644 index 37fd47b5..00000000 --- a/src/main.jsx +++ /dev/null @@ -1,12 +0,0 @@ -import React from 'react'; -import ReactDOM from 'react-dom/client'; -import App from './App.jsx'; -import { BrowserRouter } from 'react-router'; - -ReactDOM.createRoot(document.getElementById('root')).render( - - - - - -); diff --git a/src/main.tsx b/src/main.tsx new file mode 100644 index 00000000..54517b0e --- /dev/null +++ b/src/main.tsx @@ -0,0 +1,12 @@ +import React from "react"; +import ReactDOM from "react-dom/client"; +import App from "./App.tsx"; +import { BrowserRouter } from "react-router"; + +ReactDOM.createRoot(document.getElementById("root")!).render( + + + + + +); diff --git a/src/pages/Home.jsx b/src/pages/Home.tsx similarity index 88% rename from src/pages/Home.jsx rename to src/pages/Home.tsx index 576cb6ae..30418411 100644 --- a/src/pages/Home.jsx +++ b/src/pages/Home.tsx @@ -1,10 +1,10 @@ -import '../styles/style.css'; -import home_top from '../assets/images/Img_home_top.png'; -import hot_item from '../assets/images/hot_item.png'; -import search_img from '../assets/images/search.png'; -import register_img from '../assets/images/register.png'; -import home_bottom from '../assets/images/Img_home_bottom.png'; -import { Link } from 'react-router'; +import "../styles/style.css"; +import home_top from "../assets/images/Img_home_top.png"; +import hot_item from "../assets/images/hot_item.png"; +import search_img from "../assets/images/search.png"; +import register_img from "../assets/images/register.png"; +import home_bottom from "../assets/images/Img_home_bottom.png"; +import { Link } from "react-router"; /** * 메인화면 diff --git a/src/pages/auth/Login.jsx b/src/pages/auth/Login.tsx similarity index 73% rename from src/pages/auth/Login.jsx rename to src/pages/auth/Login.tsx index 76dd1b74..24546441 100644 --- a/src/pages/auth/Login.jsx +++ b/src/pages/auth/Login.tsx @@ -1,16 +1,28 @@ -import '../../styles/auth.css'; -import ic_kakao from '../../assets/icons/ic_kakao.png'; -import ic_google from '../../assets/icons/ic_google.png'; -import { Link, useOutletContext } from 'react-router'; -import { useForm } from 'react-hook-form'; -import { useEffect } from 'react'; +import "../../styles/auth.css"; +import ic_kakao from "../../assets/icons/ic_kakao.png"; +import ic_google from "../../assets/icons/ic_google.png"; +import { Link, useOutletContext } from "react-router"; +import { useForm } from "react-hook-form"; +import { SetStateAction, useEffect } from "react"; +import { visibleValue } from "../../layout/AuthLayout"; /** * 로그인 화면 */ export default function Login() { - const { visible, setVisible, onClickVisible, visibleEye_off, visibleEye_on } = - useOutletContext(); + const { + visible, + setVisible, + onClickVisible, + visibleEye_off, + visibleEye_on, + }: { + visible: visibleValue; + setVisible: (prevState: SetStateAction) => void; + onClickVisible: (e: string) => void; + visibleEye_off: string; + visibleEye_on: string; + } = useOutletContext(); /** * 기본적으로 비밀번호 숨김 상태 유지 @@ -28,8 +40,8 @@ export default function Login() { const { register, formState: { errors }, - handleSubmit, - } = useForm({ mode: 'onBlur' }); + // handleSubmit, + } = useForm({ mode: "onBlur" }); return ( <> @@ -40,7 +52,7 @@ export default function Login() {
    -
    +
    { - onClickVisible(e.target.id); + onClickVisible(e.currentTarget.id); }} />
    - {errors.password?.type === 'required' && ( + {errors.password?.type === "required" && (

    비밀번호를 입력해주세요

    )} - {errors.password?.type === 'minLength' && ( + {errors.password?.type === "minLength" && (

    비밀번호를 8자 이상 입력해주세요.

    diff --git a/src/pages/auth/Signup.jsx b/src/pages/auth/Signup.tsx similarity index 71% rename from src/pages/auth/Signup.jsx rename to src/pages/auth/Signup.tsx index eea9e1d8..af4b0c16 100644 --- a/src/pages/auth/Signup.jsx +++ b/src/pages/auth/Signup.tsx @@ -1,16 +1,28 @@ -import { Link, useOutletContext } from 'react-router'; -import '../../styles/auth.css'; -import ic_kakao from '../../assets/icons/ic_kakao.png'; -import ic_google from '../../assets/icons/ic_google.png'; -import { useEffect, useState } from 'react'; -import { useForm } from 'react-hook-form'; +import { Link, useOutletContext } from "react-router"; +import "../../styles/auth.css"; +import ic_kakao from "../../assets/icons/ic_kakao.png"; +import ic_google from "../../assets/icons/ic_google.png"; +import { SetStateAction, useEffect, useState } from "react"; +import { useForm } from "react-hook-form"; +import { visibleValue } from "../../layout/AuthLayout"; /** * 회원가입 화면 */ export default function Signup() { - const { visible, setVisible, onClickVisible, visibleEye_off, visibleEye_on } = - useOutletContext(); + const { + visible, + setVisible, + onClickVisible, + visibleEye_off, + visibleEye_on, + }: { + visible: visibleValue; + setVisible: (prevState: SetStateAction) => void; + onClickVisible: (e: string) => void; + visibleEye_off: string; + visibleEye_on: string; + } = useOutletContext(); /** * 기본적으로 비밀번호 숨김 상태 유지 @@ -26,16 +38,16 @@ export default function Signup() { * 회원가입 양식 정보를 담고 있는 객체 * 이메일, 닉네임, 비밀번호, 비밀번호 확인 */ - const [signupForm, setSignupForm] = useState({ - email: '', - nickname: '', - pw: '', - }); + // const [signupForm, setSignupForm] = useState({ + // email: "", + // nickname: "", + // pw: "", + // }); - const onValid = (data) => { - console.log('✅ 유효성 검사 성공! 데이터:', data); - setSignupForm(data); - }; + // const onValid = (data) => { + // console.log("✅ 유효성 검사 성공! 데이터:", data); + // setSignupForm(data); + // }; /** * React-Hook-Form 사용 객체 선언 @@ -43,10 +55,10 @@ export default function Signup() { const { register, formState: { errors, isValid }, - handleSubmit, + // handleSubmit, getValues, } = useForm({ - mode: 'onBlur', + mode: "onBlur", }); console.log(isValid); @@ -60,7 +72,7 @@ export default function Signup() { - +
    - {errors.nickname?.type === 'required' && ( + {errors.nickname?.type === "required" && (

    닉네임을 입력해주세요

    )} - {errors.nickname?.type === 'maxLength' && ( + {errors.nickname?.type === "maxLength" && (

    닉네임이 너무 깁니다.

    )} @@ -115,12 +125,11 @@ export default function Signup() { { - onClickVisible(e.target.id); + onClickVisible(e.currentTarget.id); }} />
    - {errors.password?.type === 'required' && ( + {errors.password?.type === "required" && (

    비밀번호를 입력해주세요

    )} - {errors.password?.type === 'minLength' && ( + {errors.password?.type === "minLength" && (

    비밀번호를 8자 이상 입력해주세요.

    @@ -151,16 +160,15 @@ export default function Signup() { - getValues('password') === getValues('confirmPassword'), + getValues("password") === getValues("confirmPassword"), })} />
    @@ -169,17 +177,17 @@ export default function Signup() { src={visible.checkPw ? visibleEye_on : visibleEye_off} alt="visible-icon" onClick={(e) => { - onClickVisible(e.target.id); + onClickVisible(e.currentTarget.id); }} />
    - {errors.confirmPassword?.type === 'minLength' && ( + {errors.confirmPassword?.type === "minLength" && (

    비밀번호를 8자 이상 입력해주세요.

    )} - {errors.confirmPassword?.type === 'validate' && ( + {errors.confirmPassword?.type === "validate" && (

    비밀번호가 일치하지 않습니다.

    )} diff --git a/src/vite-env.d.ts b/src/vite-env.d.ts new file mode 100644 index 00000000..11f02fe2 --- /dev/null +++ b/src/vite-env.d.ts @@ -0,0 +1 @@ +/// diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 00000000..a7fc6fbf --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,25 @@ +{ + "compilerOptions": { + "target": "ES2020", + "useDefineForClassFields": true, + "lib": ["ES2020", "DOM", "DOM.Iterable"], + "module": "ESNext", + "skipLibCheck": true, + + /* Bundler mode */ + "moduleResolution": "bundler", + "allowImportingTsExtensions": true, + "resolveJsonModule": true, + "isolatedModules": true, + "noEmit": true, + "jsx": "react-jsx", + + /* Linting */ + "strict": true, + "noUnusedLocals": true, + "noUnusedParameters": true, + "noFallthroughCasesInSwitch": true + }, + "include": ["src"], + "references": [{ "path": "./tsconfig.node.json" }] +} diff --git a/tsconfig.node.json b/tsconfig.node.json new file mode 100644 index 00000000..97ede7ee --- /dev/null +++ b/tsconfig.node.json @@ -0,0 +1,11 @@ +{ + "compilerOptions": { + "composite": true, + "skipLibCheck": true, + "module": "ESNext", + "moduleResolution": "bundler", + "allowSyntheticDefaultImports": true, + "strict": true + }, + "include": ["vite.config.ts"] +} diff --git a/vite.config.js b/vite.config.ts similarity index 100% rename from vite.config.js rename to vite.config.ts From 49cf6d97b3ecc875c2f86d9772eec9777142d13e Mon Sep 17 00:00:00 2001 From: Imhwitae Date: Wed, 10 Sep 2025 16:24:10 +0900 Subject: [PATCH 79/94] =?UTF-8?q?feat:=20=ED=83=80=EC=9E=85=EC=8A=A4?= =?UTF-8?q?=ED=81=AC=EB=A6=BD=ED=8A=B8=20=EC=A0=81=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- package.json | 2 +- src/layout/AuthLayout.tsx | 12 +++++------- src/pages/auth/Login.tsx | 12 +++--------- src/pages/auth/Signup.tsx | 12 +++--------- src/types/authType.ts | 20 ++++++++++++++++++++ tsconfig.json | 1 + 6 files changed, 33 insertions(+), 26 deletions(-) create mode 100644 src/types/authType.ts diff --git a/package.json b/package.json index d6271d62..cbd4e3c1 100644 --- a/package.json +++ b/package.json @@ -5,7 +5,7 @@ "type": "module", "scripts": { "dev": "vite", - "build": "vite build", + "build": "tsc && vite build", "lint": "eslint . --ext js,jsx --report-unused-disable-directives --max-warnings 0", "preview": "vite preview" }, diff --git a/src/layout/AuthLayout.tsx b/src/layout/AuthLayout.tsx index 8eee3100..6f924f9e 100644 --- a/src/layout/AuthLayout.tsx +++ b/src/layout/AuthLayout.tsx @@ -2,17 +2,13 @@ import { useState } from "react"; import { Outlet } from "react-router"; import visibleEye_off from "../assets/icons/eyes_off.png"; import visibleEye_on from "../assets/icons/eyes_on.png"; - -export interface visibleValue { - pw: boolean; - checkPw: boolean; -} +import { isVisibleKey, VisibleValue } from "../types/authType"; export default function AuthLayout() { /** * 비밀번호 보이기 / 가리기 상태 */ - const [visible, setVisible] = useState({ + const [visible, setVisible] = useState({ pw: false, checkPw: false, }); @@ -21,7 +17,9 @@ export default function AuthLayout() { * id 별로 비밀번호 가리기 여부를 변경한다. * @param {string} id */ - const onClickVisible = (id: keyof visibleValue) => { + const onClickVisible = (id: string) => { + if (!isVisibleKey(id)) return; + setVisible((prevState) => ({ ...prevState, [id]: !visible[id], diff --git a/src/pages/auth/Login.tsx b/src/pages/auth/Login.tsx index 24546441..c692a57f 100644 --- a/src/pages/auth/Login.tsx +++ b/src/pages/auth/Login.tsx @@ -3,8 +3,8 @@ import ic_kakao from "../../assets/icons/ic_kakao.png"; import ic_google from "../../assets/icons/ic_google.png"; import { Link, useOutletContext } from "react-router"; import { useForm } from "react-hook-form"; -import { SetStateAction, useEffect } from "react"; -import { visibleValue } from "../../layout/AuthLayout"; +import { useEffect } from "react"; +import { AuthType } from "../../types/authType"; /** * 로그인 화면 @@ -16,13 +16,7 @@ export default function Login() { onClickVisible, visibleEye_off, visibleEye_on, - }: { - visible: visibleValue; - setVisible: (prevState: SetStateAction) => void; - onClickVisible: (e: string) => void; - visibleEye_off: string; - visibleEye_on: string; - } = useOutletContext(); + }: AuthType = useOutletContext(); /** * 기본적으로 비밀번호 숨김 상태 유지 diff --git a/src/pages/auth/Signup.tsx b/src/pages/auth/Signup.tsx index af4b0c16..747b9c93 100644 --- a/src/pages/auth/Signup.tsx +++ b/src/pages/auth/Signup.tsx @@ -2,9 +2,9 @@ import { Link, useOutletContext } from "react-router"; import "../../styles/auth.css"; import ic_kakao from "../../assets/icons/ic_kakao.png"; import ic_google from "../../assets/icons/ic_google.png"; -import { SetStateAction, useEffect, useState } from "react"; +import { useEffect } from "react"; import { useForm } from "react-hook-form"; -import { visibleValue } from "../../layout/AuthLayout"; +import { AuthType } from "../../types/authType"; /** * 회원가입 화면 @@ -16,13 +16,7 @@ export default function Signup() { onClickVisible, visibleEye_off, visibleEye_on, - }: { - visible: visibleValue; - setVisible: (prevState: SetStateAction) => void; - onClickVisible: (e: string) => void; - visibleEye_off: string; - visibleEye_on: string; - } = useOutletContext(); + }: AuthType = useOutletContext(); /** * 기본적으로 비밀번호 숨김 상태 유지 diff --git a/src/types/authType.ts b/src/types/authType.ts new file mode 100644 index 00000000..5898050b --- /dev/null +++ b/src/types/authType.ts @@ -0,0 +1,20 @@ +import { SetStateAction } from "react"; + +export interface VisibleValue { + pw: boolean; + checkPw: boolean; +} + +export type VisibleKey = keyof VisibleValue; + +export interface AuthType { + visible: VisibleValue; + setVisible: (prevState: SetStateAction) => void; + onClickVisible: (e: string) => void; + visibleEye_off: string; + visibleEye_on: string; +} + +export function isVisibleKey(value: string): value is VisibleKey { + return value === "pw" || value === "checkPw"; +} diff --git a/tsconfig.json b/tsconfig.json index a7fc6fbf..33056b8c 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -5,6 +5,7 @@ "lib": ["ES2020", "DOM", "DOM.Iterable"], "module": "ESNext", "skipLibCheck": true, + "outDir": "./transpile", /* Bundler mode */ "moduleResolution": "bundler", From 1d9ff1721cde5d62f503a9d0a9a9b957fda5025d Mon Sep 17 00:00:00 2001 From: Imhwitae Date: Wed, 10 Sep 2025 16:30:37 +0900 Subject: [PATCH 80/94] =?UTF-8?q?feat:=20=ED=9A=8C=EC=9B=90=EA=B0=80?= =?UTF-8?q?=EC=9E=85=20=ED=83=80=EC=9E=85=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/pages/auth/Signup.tsx | 14 +++++++------- src/types/authType.ts | 6 ++++++ 2 files changed, 13 insertions(+), 7 deletions(-) diff --git a/src/pages/auth/Signup.tsx b/src/pages/auth/Signup.tsx index 747b9c93..af91acf5 100644 --- a/src/pages/auth/Signup.tsx +++ b/src/pages/auth/Signup.tsx @@ -2,9 +2,9 @@ import { Link, useOutletContext } from "react-router"; import "../../styles/auth.css"; import ic_kakao from "../../assets/icons/ic_kakao.png"; import ic_google from "../../assets/icons/ic_google.png"; -import { useEffect } from "react"; +import { useEffect, useState } from "react"; import { useForm } from "react-hook-form"; -import { AuthType } from "../../types/authType"; +import { AuthType, SignupType } from "../../types/authType"; /** * 회원가입 화면 @@ -32,11 +32,11 @@ export default function Signup() { * 회원가입 양식 정보를 담고 있는 객체 * 이메일, 닉네임, 비밀번호, 비밀번호 확인 */ - // const [signupForm, setSignupForm] = useState({ - // email: "", - // nickname: "", - // pw: "", - // }); + const [signupForm, setSignupForm] = useState({ + email: "", + nickname: "", + pw: "", + }); // const onValid = (data) => { // console.log("✅ 유효성 검사 성공! 데이터:", data); diff --git a/src/types/authType.ts b/src/types/authType.ts index 5898050b..abbdf2f8 100644 --- a/src/types/authType.ts +++ b/src/types/authType.ts @@ -18,3 +18,9 @@ export interface AuthType { export function isVisibleKey(value: string): value is VisibleKey { return value === "pw" || value === "checkPw"; } + +export interface SignupType { + email: string; + nickname: string; + pw: string; +} From dab7072ba6c13eae0dab579427396b848a77fe8d Mon Sep 17 00:00:00 2001 From: Imhwitae Date: Thu, 11 Sep 2025 20:35:29 +0900 Subject: [PATCH 81/94] =?UTF-8?q?chore:=20Next=20=ED=94=84=EB=A1=9C?= =?UTF-8?q?=EC=A0=9D=ED=8A=B8=20=EC=84=B8=ED=8C=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .eslintrc.cjs | 21 - .gitignore | 59 +- README.md | 199 +- eslint.config.mjs | 25 + index.html | 22 - next.config.ts | 7 + package-lock.json | 3351 +++++++++-------- package.json | 35 +- public/file.svg | 1 + public/globe.svg | 1 + public/next.svg | 1 + public/panda_favicon.svg | 14 - public/vercel.svg | 1 + public/window.svg | 1 + src/App.tsx | 38 - src/app/favicon.ico | Bin 0 -> 25931 bytes src/app/globals.css | 42 + src/app/layout.tsx | 32 + src/app/page.module.css | 167 + src/app/page.tsx | 95 + src/assets/icons/btn_left.png | Bin 1175 -> 0 bytes src/assets/icons/btn_right.png | Bin 1173 -> 0 bytes src/assets/icons/eyes_off.png | Bin 847 -> 0 bytes src/assets/icons/eyes_on.png | Bin 709 -> 0 bytes src/assets/icons/ic_X.svg | 5 - src/assets/icons/ic_arrow_down.svg | 3 - src/assets/icons/ic_back.svg | 4 - src/assets/icons/ic_facebook.svg | 3 - src/assets/icons/ic_google.png | Bin 1589 -> 0 bytes src/assets/icons/ic_heart.svg | 3 - src/assets/icons/ic_heart_active_large.svg | 3 - src/assets/icons/ic_heart_inactive_large.svg | 3 - src/assets/icons/ic_instagram.svg | 3 - src/assets/icons/ic_kakao.png | Bin 1439 -> 0 bytes src/assets/icons/ic_plus.svg | 4 - src/assets/icons/ic_profile.svg | 24 - src/assets/icons/ic_search.svg | 3 - src/assets/icons/ic_sort.svg | 6 - src/assets/icons/ic_twitter.svg | 3 - src/assets/icons/ic_youtube.svg | 10 - src/assets/images/Img_home_bottom.png | Bin 56972 -> 0 bytes src/assets/images/Img_home_top.png | Bin 49603 -> 0 bytes src/assets/images/hot_item.png | Bin 13582 -> 0 bytes src/assets/images/img_inquiry_empty_md.png | Bin 6244 -> 0 bytes src/assets/images/logo_lg.png | Bin 6365 -> 0 bytes src/assets/images/logo_md.png | Bin 3520 -> 0 bytes src/assets/images/logo_sm.png | Bin 2796 -> 0 bytes src/assets/images/logo_typo.png | Bin 1352 -> 0 bytes src/assets/images/meta_tag_img.png | Bin 10058 -> 0 bytes src/assets/images/register.png | Bin 10648 -> 0 bytes src/assets/images/search.png | Bin 17056 -> 0 bytes src/components/DropdownList.jsx | 70 - src/components/ImgInput.jsx | 136 - src/components/Inquiry.jsx | 34 - src/components/InquiryWriteArea.jsx | 56 - src/components/Pagination.jsx | 116 - src/components/Product.jsx | 48 - src/components/kebab/KebabDropdown.jsx | 30 - src/components/kebab/KebabMenu.jsx | 29 - src/hooks/useCloseDropdown.jsx | 19 - src/hooks/useMediaQuery.jsx | 32 - src/hooks/useService.jsx | 38 - src/hooks/useToggle.jsx | 22 - src/layout/AuthLayout.tsx | 42 - src/layout/Footer.tsx | 60 - src/layout/Header.tsx | 64 - src/layout/ItemsLayout.jsx | 13 - src/layout/MainLayout.tsx | 15 - src/main.tsx | 12 - src/pages/Home.tsx | 94 - src/pages/auth/Login.tsx | 134 - src/pages/auth/Signup.tsx | 217 -- .../components/ItemDetail/InquiryList.jsx | 64 - .../components/ItemDetail/ProductDetails.jsx | 74 - src/pages/items/AddItem.jsx | 257 -- src/pages/items/ItemDetail.jsx | 44 - src/pages/items/Items.jsx | 158 - src/services/inquiryApi.js | 46 - src/services/itemsApi.js | 40 - src/styles/auth.css | 159 - src/styles/colors.css | 13 - src/styles/commonStyles.js | 41 - src/styles/components/InquiryStyles.js | 112 - src/styles/components/dropDownList.css | 82 - src/styles/components/kebab/kebabStyle.js | 57 - src/styles/components/pagination.css | 32 - src/styles/items/ItemDetailStyle.js | 181 - src/styles/items/items.css | 178 - src/styles/layout/footer.css | 78 - src/styles/layout/header.css | 106 - src/styles/style.css | 314 -- src/types/authType.ts | 26 - src/util/formatTimeAgo.js | 37 - src/vite-env.d.ts | 1 - tsconfig.json | 37 +- tsconfig.node.json | 11 - vite.config.ts | 7 - 97 files changed, 2347 insertions(+), 5278 deletions(-) delete mode 100644 .eslintrc.cjs create mode 100644 eslint.config.mjs delete mode 100644 index.html create mode 100644 next.config.ts create mode 100644 public/file.svg create mode 100644 public/globe.svg create mode 100644 public/next.svg delete mode 100644 public/panda_favicon.svg create mode 100644 public/vercel.svg create mode 100644 public/window.svg delete mode 100644 src/App.tsx create mode 100644 src/app/favicon.ico create mode 100644 src/app/globals.css create mode 100644 src/app/layout.tsx create mode 100644 src/app/page.module.css create mode 100644 src/app/page.tsx delete mode 100644 src/assets/icons/btn_left.png delete mode 100644 src/assets/icons/btn_right.png delete mode 100644 src/assets/icons/eyes_off.png delete mode 100644 src/assets/icons/eyes_on.png delete mode 100644 src/assets/icons/ic_X.svg delete mode 100644 src/assets/icons/ic_arrow_down.svg delete mode 100644 src/assets/icons/ic_back.svg delete mode 100644 src/assets/icons/ic_facebook.svg delete mode 100644 src/assets/icons/ic_google.png delete mode 100644 src/assets/icons/ic_heart.svg delete mode 100644 src/assets/icons/ic_heart_active_large.svg delete mode 100644 src/assets/icons/ic_heart_inactive_large.svg delete mode 100644 src/assets/icons/ic_instagram.svg delete mode 100644 src/assets/icons/ic_kakao.png delete mode 100644 src/assets/icons/ic_plus.svg delete mode 100644 src/assets/icons/ic_profile.svg delete mode 100644 src/assets/icons/ic_search.svg delete mode 100644 src/assets/icons/ic_sort.svg delete mode 100644 src/assets/icons/ic_twitter.svg delete mode 100644 src/assets/icons/ic_youtube.svg delete mode 100644 src/assets/images/Img_home_bottom.png delete mode 100644 src/assets/images/Img_home_top.png delete mode 100644 src/assets/images/hot_item.png delete mode 100644 src/assets/images/img_inquiry_empty_md.png delete mode 100644 src/assets/images/logo_lg.png delete mode 100644 src/assets/images/logo_md.png delete mode 100644 src/assets/images/logo_sm.png delete mode 100644 src/assets/images/logo_typo.png delete mode 100644 src/assets/images/meta_tag_img.png delete mode 100644 src/assets/images/register.png delete mode 100644 src/assets/images/search.png delete mode 100644 src/components/DropdownList.jsx delete mode 100644 src/components/ImgInput.jsx delete mode 100644 src/components/Inquiry.jsx delete mode 100644 src/components/InquiryWriteArea.jsx delete mode 100644 src/components/Pagination.jsx delete mode 100644 src/components/Product.jsx delete mode 100644 src/components/kebab/KebabDropdown.jsx delete mode 100644 src/components/kebab/KebabMenu.jsx delete mode 100644 src/hooks/useCloseDropdown.jsx delete mode 100644 src/hooks/useMediaQuery.jsx delete mode 100644 src/hooks/useService.jsx delete mode 100644 src/hooks/useToggle.jsx delete mode 100644 src/layout/AuthLayout.tsx delete mode 100644 src/layout/Footer.tsx delete mode 100644 src/layout/Header.tsx delete mode 100644 src/layout/ItemsLayout.jsx delete mode 100644 src/layout/MainLayout.tsx delete mode 100644 src/main.tsx delete mode 100644 src/pages/Home.tsx delete mode 100644 src/pages/auth/Login.tsx delete mode 100644 src/pages/auth/Signup.tsx delete mode 100644 src/pages/components/ItemDetail/InquiryList.jsx delete mode 100644 src/pages/components/ItemDetail/ProductDetails.jsx delete mode 100644 src/pages/items/AddItem.jsx delete mode 100644 src/pages/items/ItemDetail.jsx delete mode 100644 src/pages/items/Items.jsx delete mode 100644 src/services/inquiryApi.js delete mode 100644 src/services/itemsApi.js delete mode 100644 src/styles/auth.css delete mode 100644 src/styles/colors.css delete mode 100644 src/styles/commonStyles.js delete mode 100644 src/styles/components/InquiryStyles.js delete mode 100644 src/styles/components/dropDownList.css delete mode 100644 src/styles/components/kebab/kebabStyle.js delete mode 100644 src/styles/components/pagination.css delete mode 100644 src/styles/items/ItemDetailStyle.js delete mode 100644 src/styles/items/items.css delete mode 100644 src/styles/layout/footer.css delete mode 100644 src/styles/layout/header.css delete mode 100644 src/styles/style.css delete mode 100644 src/types/authType.ts delete mode 100644 src/util/formatTimeAgo.js delete mode 100644 src/vite-env.d.ts delete mode 100644 tsconfig.node.json delete mode 100644 vite.config.ts diff --git a/.eslintrc.cjs b/.eslintrc.cjs deleted file mode 100644 index 3dca2b7a..00000000 --- a/.eslintrc.cjs +++ /dev/null @@ -1,21 +0,0 @@ -module.exports = { - root: true, - env: { browser: true, es2020: true }, - extends: [ - 'eslint:recommended', - 'plugin:react/recommended', - 'plugin:react/jsx-runtime', - 'plugin:react-hooks/recommended', - ], - ignorePatterns: ['dist', '.eslintrc.cjs'], - parserOptions: { ecmaVersion: 'latest', sourceType: 'module' }, - settings: { react: { version: '18.2' } }, - plugins: ['react-refresh'], - rules: { - 'react/jsx-no-target-blank': 'off', - 'react-refresh/only-export-components': [ - 'warn', - { allowConstantExport: true }, - ], - }, -}; diff --git a/.gitignore b/.gitignore index cea8a0ba..5ef6a520 100644 --- a/.gitignore +++ b/.gitignore @@ -1,26 +1,41 @@ -# Logs -logs -*.log +# See https://help.github.com/articles/ignoring-files/ for more about ignoring files. + +# dependencies +/node_modules +/.pnp +.pnp.* +.yarn/* +!.yarn/patches +!.yarn/plugins +!.yarn/releases +!.yarn/versions + +# testing +/coverage + +# next.js +/.next/ +/out/ + +# production +/build + +# misc +.DS_Store +*.pem + +# debug npm-debug.log* yarn-debug.log* yarn-error.log* -pnpm-debug.log* -lerna-debug.log* - -node_modules -dist -dist-ssr -*.local - -# Editor directories and files -.vscode/* -!.vscode/extensions.json -.idea -.DS_Store -*.suo -*.ntvs* -*.njsproj -*.sln -*.sw? +.pnpm-debug.log* + +# env files (can opt-in for committing if needed) +.env* + +# vercel +.vercel -*.env \ No newline at end of file +# typescript +*.tsbuildinfo +next-env.d.ts diff --git a/README.md b/README.md index 6370b2bd..e215bc4c 100644 --- a/README.md +++ b/README.md @@ -1,189 +1,36 @@ -# 판다 마켓 - 중고 거래 플랫폼 +This is a [Next.js](https://nextjs.org) project bootstrapped with [`create-next-app`](https://nextjs.org/docs/app/api-reference/cli/create-next-app). -## 미션 3 요구사항 +## Getting Started -### 기본 +First, run the development server: -- [x] 랜딩 페이지의 url path는 루트(‘/’) 입니다. -- [x] title은 “판다마켓”으로 설정해 주세요. -- [x] 화면의 너비가 1920px 이상이면 하늘색 배경색은 너비를 꽉 채우도록 채워지고, 내부 요소들의 위치는 고정되고, 여백만 커지도록 해주세요. -- [x] 화면의 너비가 1920px 보다 작아질 때, “판다마켓” 로고의 왼쪽 여백 200px“로그인" 버튼의 오른쪽 여백 200px이 유지되고, 화면의 너비가 작아질수록 두 요소간 거리가 가까워지도록 해주세요. -- [x] 클릭으로 기능이 동작해야 하는 경우, 사용자가 클릭할 수 있는 요소임을 알 수 있도록 cursor: pointer를 설정해 주세요. -- [x] “판다마켓” 클릭 시 루트 페이지(‘/’)로 이동시켜주세요. -- [x] “구경하러 가기" 클릭 시 (“/items”)페이지로 이동시켜주세요.(빈 페이지) -- [x] “로그인”버튼 클릭 시 로그인 페이지(‘/login’)로 이동합니다 -- [x] “구경하러가기”버튼 클릭 시(’/items’)로 이동합니다 -- [x] 페이스북, 트위터, 유튜브, 인스타그램 아이콘은 클릭 시 각각의 홈페이지로 새로운 창이 열리면서 이동 합니다 -- [x] “Privacy Policy”, “FAQ”는 클릭 시 각각 아래 페이지로 이동합니다- Privacy 페이지(‘/privacy’) - FAQ 페이지(‘/faq’) +```bash +npm run dev +# or +yarn dev +# or +pnpm dev +# or +bun dev +``` ---- +Open [http://localhost:3000](http://localhost:3000) with your browser to see the result. -- [x] 아래로 스크롤 해도 상단 네비게이션 바(Global Navigation Bar)가 최상단에 고정됩니다. -- [x] “판다마켓" 클릭 시 루트 페이지(“/”)로 이동합니다. (새로고침) -- [x] 로그인 페이지, 회원가입 페이지 모두 로고 위 상단 여백이 동일합니다. -- [x] SNS 아이콘들은 클릭시 각각 아래 페이지로 이동합니다.- “https://www.google.com/”, “https://www.kakaocorp.com/page/” -- [x] “회원 가입”버튼 클릭 시 “/signup” 페이지로 이동합니다. +You can start editing the page by modifying `app/page.tsx`. The page auto-updates as you edit the file. ---- +This project uses [`next/font`](https://nextjs.org/docs/app/building-your-application/optimizing/fonts) to automatically optimize and load [Geist](https://vercel.com/font), a new font family for Vercel. -- [x] 브라우저에 현재 보이는 화면의 영역(viewport) 너비를 기준으로 분기되는 반응형 디자인을 적용합니다.- PC: 1200px 이상- Tablet: 768px 이상 ~ 1199px 이하- Mobile: 375px 이상 ~ 767px 이하\* 375px 미만 사이즈의 디자인은 고려하지 않습니다 -- [x] Tablet 사이즈로 작아질 때 “판다마켓” 로고의 왼쪽에 여백 24px, “로그인” 버튼 오른쪽 여백 24px을 유지할 수 있도록 “판다마켓” 로고와 “로그인" 버튼의 간격이 가까워집니다. -- [x] Mobile 사이즈로 작아질 때 “판다마켓” 로고의 왼쪽에 여백 16px, “로그인” 버튼 오른쪽 여백 16px을 유지할 수 있도록 “판다마켓” 로고와 “로그인" 버튼의 간격이 가까워집니다. -- [x] Tablet 사이즈에서 내부 디자인은 PC사이즈와 동일합니다. -- [x] Mobile 사이즈에서 좌우 여백 16px 제외하고 내부 요소들이 너비를 모두 차지합니다. -- [x] Mobile 사이즈에서 내부 요소들의 너비는 기기의 너비가 커지는 만큼 커지지만 400px을 넘지 않습니다. -- [x] Mobile 사이즈에서 좌우 여백 16px 제외하고 내부 요소들이 너비를 모두 차지합니다. -- [x] Mobile 사이즈에서 내부 요소들의 너비는 기기의 너비가 커지는 만큼 커지지만 400px을 넘지 않습니다. +## Learn More -### 심화 +To learn more about Next.js, take a look at the following resources: -- [x] 사용자의 브라우저가 크고 작아짐에 따라 페이지의 요소간 간격, 요소의 크기, font-size 등 모든 크기와 관련된 값이 크고 작아지도록 설정해 보세요.(설정값은 자유입니다) +- [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API. +- [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial. ---- +You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js) - your feedback and contributions are welcome! -- [x] palette에 있는 color값들을 css 변수로 등록하고 사용합니다. +## Deploy on Vercel ---- +The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme) from the creators of Next.js. -- [x] 페이스북, 카카오톡, 디스코드, 트위터 등 SNS에서 Linkbrary 랜딩 페이지(“/”) 공유 시 좌측 예시와 같은 미리보기를 볼 수 있도록 랜딩 페이지 메타 태그를 설정해 주세요. -- [x] 미리보기에서 제목은 “판다 마켓”, 설명은 “일상의 모든 물건을 거래해보세요”로 설정합니다. -- [x] 주소와 이미지는 자유롭게 설정하세요. - -### 주요 변경사항 - -- Netlify에서 로고 이미지가 보이게 수정했습니다. - -### 스크린샷 - -**메인화면** -| PC | Tablet | Mobile | -| :-: | :----: | :----: | -|![pc_main](https://github.com/user-attachments/assets/ab4254e0-c732-49b6-8eb3-becf313e4a92)|![tablet_main](https://github.com/user-attachments/assets/28e8b861-bf77-47b1-9f60-93267f592650)|![mobile_main](https://github.com/user-attachments/assets/fe76d76f-9b93-4403-8205-ec875e364f7f)| - -
    - -**로그인 화면** -| PC | Mobile | -| :-: | :----: | -|![pc_login](https://github.com/user-attachments/assets/aa9ff9df-8eff-4f13-a7e4-e946ad8fe48f)|![mobile_login](https://github.com/user-attachments/assets/8e1662fb-4544-48ce-a791-40e3e5ce0e28)| - -
    - -**회원가입 화면** -| PC | Mobile | -| :-: | :----: | -|![join_pc](https://github.com/user-attachments/assets/52788e32-a174-4441-abe1-957bc36094e7)|![join_mobile](https://github.com/user-attachments/assets/6222a188-d431-433c-959a-07c052ff61a5)| - -### 멘토에게 - -- 저는 CSS를 작성할 때 대부분의 단위를 `px`로 사용했는데, `rem`, `vw`와 같은 단위를 사용하는 것이 더 나은지 궁금합니다 - > 답변 - > [px vs rem vs em 접근성과 관련된 아티클](https://www.joshwcomeau.com/css/surprising-truth-about-pixels-and-accessibility/) - -
    - -## 미션 5 요구사항 - -### 기본 - -- [x] 중고마켓 페이지 주소는 "/items" 입니다. -- [x] 페이지 주소가 "/items" 일 때 상단 네비게이션 바의 "중고마켓" 버튼의 색상은 "3692FF" 입니다. -- [x] 상단 네비게이션 바는 이전 미션에서 구현한 랜딩 페이지와 동일한 스타일로 만들어주세요 -- [x] 전체 상품에서 드롭다운으로 "최신순" 또는 "좋아요순"을 선택해서 정렬할 수 있습니다. -- [ ] "상품 등록하기" 버튼을 누르면 “/additem” 로 이동합니다 ( 빈 페이지 ) -- [x] 미디어 쿼리를 사용하여 반응형 view 마다 물품 개수를 다르게 보여줍니다 (서버로 요청하는 값은 동일) -- 베스트 상품 - - Desktop : 4개 보이기 - - Tablet : 2개 보이기 - - Mobile : 1개 보이기 -- 전체 상품 - - Desktop : 10개 보이기 - - Tablet : 6개 보이기 - - Mobile : 4개 보이기 - -### 심화 - -- [x] 페이지 네이션 기능을 구현합니다. -- [x] 반응형으로 보여지는 물품들의 개수를 다르게 설정할때 서버에 보내는 pageSize값을 적절하게 설정합니다. - -### 주요 변경사항 - -- 스프린트 미션 1부터 4까지의 내용을 React로 변경했습니다. - > form 변경 내용: [React-Hook-form을 이용해 유효성 검사 해보기](https://velog.io/@nudge0613/React-Hook-Form%EC%9D%84-%EC%9D%B4%EC%9A%A9%ED%95%B4-%ED%9A%8C%EC%9B%90%EA%B0%80%EC%9E%85-%EC%9C%A0%ED%9A%A8%EC%84%B1-%EA%B2%80%EC%82%AC-%ED%95%98%EA%B8%B0) - -### 스크린샷 - -| PC | Tablet | Mobile | -| :-------------------------------------------------------------------------------------------------------------------------------------------------: | :-----------------------------------------------------------------------------------------------------------------------------------------------------: | :----------------------------------------------------------------------------------------------------------------------------------------------------: | -| localhost_5173_items | localhost_5173_items (1) | localhost_5173_items (2) | - -
    - -## 미션 6 요구사항 - -### 기본 - -- [x] 상품 등록 페이지 주소는 “/additem” 입니다. -- [x] 페이지 주소가 “/additem” 일때 상단네비게이션바의 '중고마켓' 버튼의 색상은 “3692FF”입니다. -- [x] 상품 이미지는 최대 한개 업로드가 가능합니다. -- [x] 각 input의 placeholder 값을 정확히 입력해주세요. -- [x] 이미지를 제외하고 input 에 모든 값을 입력하면 ‘등록' 버튼이 활성화 됩니다. -- [ ] API를 통한 상품 등록은 추후 미션에서 적용합니다. - -### 심화 - -- [x] 이미지 안의 X 버튼을 누르면 이미지가 삭제됩니다. -- [x] 추가된 태그 안의 X 버튼을 누르면 해당 태그는 삭제됩니다. - -### 주요 변경사항 - -- styled component를 통해 스타일링 - -### 스크린샷 - -| PC | Tablet | Mobile | -| :---------------------------------------------------------------------------------------------------------------------------------------------------: | :-------------------------------------------------------------------------------------------------------------------------------------------------------: | :------------------------------------------------------------------------------------------------------------------------------------------------------: | -| localhost_5173_additem | localhost_5173_additem (1) | localhost_5173_additem (2) | - -### 멘토에게 - -- styled component를 사용해서 스타일링을 했는데 한 컴포넌트의 코드가 너무 길어지는 느낌입니다. - 스타일은 따로 빼놓는게 나을까요? - -
    - -## 미션 7 요구사항 - -### 기본 - -- [x] 상품 상세 페이지 주소는 “items/{productId}” 입니다. -- [x] response로 받은 아래의 데이터로 화면을 구현합니다. - - favoriteCount : 하트 개수 - - images : 상품 이미지 - - tags : 상품태그 - - name : 상품 이름 - - description : 상품 설명 -- [x] 목록으로 돌아가기 버튼을 클릭하면 중고마켓 페이지 주소인 "/items"로 이동합니다. -- [x] 문의하기에 내용을 입력하면 등록 버튼의 색상은 “3692FF”로 변합니다. -- [x] response 로 받은 아래의 데이터로 화면을 구현합니다. - - image : 작성자 이미지 - - nickname : 작성자 닉네임 - - content : 작성자가 남긴 문구 - - description : 상품 설명 - - updatedAt : 문의글 마지막 업데이트 시간 - -### 심화 - -- [x] 모든 버튼에 자유롭게 Hover효과를 적용하세요. - -### 주요 변경사항 - -### 스크린샷 - -| PC | Tablet | Mobile | -| :---------------------------------------------------------------------------------------------------------------------------------------------------: | :-------------------------------------------------------------------------------------------------------------------------------------------------------: | :------------------------------------------------------------------------------------------------------------------------------------------------------: | -| localhost_5173_additem | localhost_5173_additem (1) | localhost_5173_additem (2) | - -### 멘토에게 - -Copyright 2025 코드잇 Inc. All rights reserved. +Check out our [Next.js deployment documentation](https://nextjs.org/docs/app/building-your-application/deploying) for more details. diff --git a/eslint.config.mjs b/eslint.config.mjs new file mode 100644 index 00000000..719cea2b --- /dev/null +++ b/eslint.config.mjs @@ -0,0 +1,25 @@ +import { dirname } from "path"; +import { fileURLToPath } from "url"; +import { FlatCompat } from "@eslint/eslintrc"; + +const __filename = fileURLToPath(import.meta.url); +const __dirname = dirname(__filename); + +const compat = new FlatCompat({ + baseDirectory: __dirname, +}); + +const eslintConfig = [ + ...compat.extends("next/core-web-vitals", "next/typescript"), + { + ignores: [ + "node_modules/**", + ".next/**", + "out/**", + "build/**", + "next-env.d.ts", + ], + }, +]; + +export default eslintConfig; diff --git a/index.html b/index.html deleted file mode 100644 index 1cacaed7..00000000 --- a/index.html +++ /dev/null @@ -1,22 +0,0 @@ - - - - - - - - - - - - - - - - 판다마켓 - - -
    - - - diff --git a/next.config.ts b/next.config.ts new file mode 100644 index 00000000..e9ffa308 --- /dev/null +++ b/next.config.ts @@ -0,0 +1,7 @@ +import type { NextConfig } from "next"; + +const nextConfig: NextConfig = { + /* config options here */ +}; + +export default nextConfig; diff --git a/package-lock.json b/package-lock.json index 5df50a73..9705f691 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,928 +1,1253 @@ { "name": "panda_market", - "version": "0.0.0", + "version": "0.1.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "panda_market", - "version": "0.0.0", + "version": "0.1.0", "dependencies": { - "react": "^18.2.0", - "react-dom": "^18.2.0", - "react-hook-form": "^7.60.0", - "react-router": "^7.6.3", - "styled-components": "^6.1.19" + "next": "15.5.3", + "react": "19.1.0", + "react-dom": "19.1.0" }, "devDependencies": { - "@types/react": "^18.2.66", - "@types/react-dom": "^18.2.22", - "@vitejs/plugin-react": "^4.2.1", - "eslint": "^8.57.0", - "eslint-plugin-react": "^7.34.1", - "eslint-plugin-react-hooks": "^4.6.0", - "eslint-plugin-react-refresh": "^0.4.6", - "typescript": "^5.9.2", - "vite": "^5.2.0" - } - }, - "node_modules/@ampproject/remapping": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.3.0.tgz", - "integrity": "sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==", + "@eslint/eslintrc": "^3", + "@types/node": "^20", + "@types/react": "^19", + "@types/react-dom": "^19", + "eslint": "^9", + "eslint-config-next": "15.5.3", + "typescript": "^5" + } + }, + "node_modules/@emnapi/core": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.5.0.tgz", + "integrity": "sha512-sbP8GzB1WDzacS8fgNPpHlp6C9VZe+SJP3F90W9rLemaQj2PzIuTEl1qDOYQf58YIpyjViI24y9aPWCjEzY2cg==", "dev": true, - "license": "Apache-2.0", + "license": "MIT", + "optional": true, "dependencies": { - "@jridgewell/gen-mapping": "^0.3.5", - "@jridgewell/trace-mapping": "^0.3.24" - }, - "engines": { - "node": ">=6.0.0" + "@emnapi/wasi-threads": "1.1.0", + "tslib": "^2.4.0" } }, - "node_modules/@babel/code-frame": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.27.1.tgz", - "integrity": "sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg==", - "dev": true, + "node_modules/@emnapi/runtime": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.5.0.tgz", + "integrity": "sha512-97/BJ3iXHww3djw6hYIfErCZFee7qCtrneuLa20UXFCOTCfBM2cvQHjWJ2EG0s0MtdNwInarqCTz35i4wWXHsQ==", "license": "MIT", + "optional": true, "dependencies": { - "@babel/helper-validator-identifier": "^7.27.1", - "js-tokens": "^4.0.0", - "picocolors": "^1.1.1" - }, - "engines": { - "node": ">=6.9.0" + "tslib": "^2.4.0" } }, - "node_modules/@babel/compat-data": { - "version": "7.28.0", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.28.0.tgz", - "integrity": "sha512-60X7qkglvrap8mn1lh2ebxXdZYtUcpd7gsmy9kLaBJ4i/WdY8PqTSdxyA8qraikqKQK5C1KRBKXqznrVapyNaw==", + "node_modules/@emnapi/wasi-threads": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@emnapi/wasi-threads/-/wasi-threads-1.1.0.tgz", + "integrity": "sha512-WI0DdZ8xFSbgMjR1sFsKABJ/C5OnRrjT06JXbZKexJGrDuPTzZdDYfFlsgcCXCyf+suG5QU2e/y1Wo2V/OapLQ==", "dev": true, "license": "MIT", - "engines": { - "node": ">=6.9.0" + "optional": true, + "dependencies": { + "tslib": "^2.4.0" } }, - "node_modules/@babel/core": { - "version": "7.28.0", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.28.0.tgz", - "integrity": "sha512-UlLAnTPrFdNGoFtbSXwcGFQBtQZJCNjaN6hQNP3UPvuNXT1i82N26KL3dZeIpNalWywr9IuQuncaAfUaS1g6sQ==", + "node_modules/@eslint-community/eslint-utils": { + "version": "4.9.0", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.9.0.tgz", + "integrity": "sha512-ayVFHdtZ+hsq1t2Dy24wCmGXGe4q9Gu3smhLYALJrr473ZH27MsnSL+LKUlimp4BWJqMDMLmPpx/Q9R3OAlL4g==", "dev": true, "license": "MIT", "dependencies": { - "@ampproject/remapping": "^2.2.0", - "@babel/code-frame": "^7.27.1", - "@babel/generator": "^7.28.0", - "@babel/helper-compilation-targets": "^7.27.2", - "@babel/helper-module-transforms": "^7.27.3", - "@babel/helpers": "^7.27.6", - "@babel/parser": "^7.28.0", - "@babel/template": "^7.27.2", - "@babel/traverse": "^7.28.0", - "@babel/types": "^7.28.0", - "convert-source-map": "^2.0.0", - "debug": "^4.1.0", - "gensync": "^1.0.0-beta.2", - "json5": "^2.2.3", - "semver": "^6.3.1" + "eslint-visitor-keys": "^3.4.3" }, "engines": { - "node": ">=6.9.0" + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/babel" + "url": "https://opencollective.com/eslint" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" } }, - "node_modules/@babel/generator": { - "version": "7.28.0", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.28.0.tgz", - "integrity": "sha512-lJjzvrbEeWrhB4P3QBsH7tey117PjLZnDbLiQEKjQ/fNJTjuq4HSqgFA+UNSwZT8D7dxxbnuSBMsa1lrWzKlQg==", + "node_modules/@eslint-community/eslint-utils/node_modules/eslint-visitor-keys": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", + "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", "dev": true, - "license": "MIT", - "dependencies": { - "@babel/parser": "^7.28.0", - "@babel/types": "^7.28.0", - "@jridgewell/gen-mapping": "^0.3.12", - "@jridgewell/trace-mapping": "^0.3.28", - "jsesc": "^3.0.2" - }, + "license": "Apache-2.0", "engines": { - "node": ">=6.9.0" + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" } }, - "node_modules/@babel/helper-compilation-targets": { - "version": "7.27.2", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.27.2.tgz", - "integrity": "sha512-2+1thGUUWWjLTYTHZWK1n8Yga0ijBz1XAhUXcKy81rd5g6yh7hGqMp45v7cadSbEHc9G3OTv45SyneRN3ps4DQ==", + "node_modules/@eslint-community/regexpp": { + "version": "4.12.1", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.1.tgz", + "integrity": "sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ==", "dev": true, "license": "MIT", + "engines": { + "node": "^12.0.0 || ^14.0.0 || >=16.0.0" + } + }, + "node_modules/@eslint/config-array": { + "version": "0.21.0", + "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.21.0.tgz", + "integrity": "sha512-ENIdc4iLu0d93HeYirvKmrzshzofPw6VkZRKQGe9Nv46ZnWUzcF1xV01dcvEg/1wXUR61OmmlSfyeyO7EvjLxQ==", + "dev": true, + "license": "Apache-2.0", "dependencies": { - "@babel/compat-data": "^7.27.2", - "@babel/helper-validator-option": "^7.27.1", - "browserslist": "^4.24.0", - "lru-cache": "^5.1.1", - "semver": "^6.3.1" + "@eslint/object-schema": "^2.1.6", + "debug": "^4.3.1", + "minimatch": "^3.1.2" }, "engines": { - "node": ">=6.9.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } }, - "node_modules/@babel/helper-globals": { - "version": "7.28.0", - "resolved": "https://registry.npmjs.org/@babel/helper-globals/-/helper-globals-7.28.0.tgz", - "integrity": "sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw==", + "node_modules/@eslint/config-helpers": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.3.1.tgz", + "integrity": "sha512-xR93k9WhrDYpXHORXpxVL5oHj3Era7wo6k/Wd8/IsQNnZUTzkGS29lyn3nAT05v6ltUuTFVCCYDEGfy2Or/sPA==", "dev": true, - "license": "MIT", + "license": "Apache-2.0", "engines": { - "node": ">=6.9.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } }, - "node_modules/@babel/helper-module-imports": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.27.1.tgz", - "integrity": "sha512-0gSFWUPNXNopqtIPQvlD5WgXYI5GY2kP2cCvoT8kczjbfcfuIljTbcWrulD1CIPIX2gt1wghbDy08yE1p+/r3w==", + "node_modules/@eslint/core": { + "version": "0.15.2", + "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.15.2.tgz", + "integrity": "sha512-78Md3/Rrxh83gCxoUc0EiciuOHsIITzLy53m3d9UyiW8y9Dj2D29FeETqyKA+BRK76tnTp6RXWb3pCay8Oyomg==", "dev": true, - "license": "MIT", + "license": "Apache-2.0", "dependencies": { - "@babel/traverse": "^7.27.1", - "@babel/types": "^7.27.1" + "@types/json-schema": "^7.0.15" }, "engines": { - "node": ">=6.9.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } }, - "node_modules/@babel/helper-module-transforms": { - "version": "7.27.3", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.27.3.tgz", - "integrity": "sha512-dSOvYwvyLsWBeIRyOeHXp5vPj5l1I011r52FM1+r1jCERv+aFXYk4whgQccYEGYxK2H3ZAIA8nuPkQ0HaUo3qg==", + "node_modules/@eslint/eslintrc": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.3.1.tgz", + "integrity": "sha512-gtF186CXhIl1p4pJNGZw8Yc6RlshoePRvE0X91oPGb3vZ8pM3qOS9W9NGPat9LziaBV7XrJWGylNQXkGcnM3IQ==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-module-imports": "^7.27.1", - "@babel/helper-validator-identifier": "^7.27.1", - "@babel/traverse": "^7.27.3" + "ajv": "^6.12.4", + "debug": "^4.3.2", + "espree": "^10.0.1", + "globals": "^14.0.0", + "ignore": "^5.2.0", + "import-fresh": "^3.2.1", + "js-yaml": "^4.1.0", + "minimatch": "^3.1.2", + "strip-json-comments": "^3.1.1" }, "engines": { - "node": ">=6.9.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, - "peerDependencies": { - "@babel/core": "^7.0.0" + "funding": { + "url": "https://opencollective.com/eslint" } }, - "node_modules/@babel/helper-plugin-utils": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.27.1.tgz", - "integrity": "sha512-1gn1Up5YXka3YYAHGKpbideQ5Yjf1tDa9qYcgysz+cNCXukyLl6DjPXhD3VRwSb8c0J9tA4b2+rHEZtc6R0tlw==", + "node_modules/@eslint/js": { + "version": "9.35.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.35.0.tgz", + "integrity": "sha512-30iXE9whjlILfWobBkNerJo+TXYsgVM5ERQwMcMKCHckHflCmf7wXDAHlARoWnh0s1U72WqlbeyE7iAcCzuCPw==", "dev": true, "license": "MIT", "engines": { - "node": ">=6.9.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://eslint.org/donate" } }, - "node_modules/@babel/helper-string-parser": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz", - "integrity": "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==", + "node_modules/@eslint/object-schema": { + "version": "2.1.6", + "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.6.tgz", + "integrity": "sha512-RBMg5FRL0I0gs51M/guSAj5/e14VQ4tpZnQNWwuDT66P14I43ItmPfIZRhO9fUVIPOAQXU47atlywZ/czoqFPA==", "dev": true, - "license": "MIT", + "license": "Apache-2.0", "engines": { - "node": ">=6.9.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } }, - "node_modules/@babel/helper-validator-identifier": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.27.1.tgz", - "integrity": "sha512-D2hP9eA+Sqx1kBZgzxZh0y1trbuU+JoDkiEwqhQ36nodYqJwyEIhPSdMNd7lOm/4io72luTPWH20Yda0xOuUow==", + "node_modules/@eslint/plugin-kit": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.3.5.tgz", + "integrity": "sha512-Z5kJ+wU3oA7MMIqVR9tyZRtjYPr4OC004Q4Rw7pgOKUOKkJfZ3O24nz3WYfGRpMDNmcOi3TwQOmgm7B7Tpii0w==", "dev": true, - "license": "MIT", + "license": "Apache-2.0", + "dependencies": { + "@eslint/core": "^0.15.2", + "levn": "^0.4.1" + }, "engines": { - "node": ">=6.9.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } }, - "node_modules/@babel/helper-validator-option": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.27.1.tgz", - "integrity": "sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg==", + "node_modules/@humanfs/core": { + "version": "0.19.1", + "resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.1.tgz", + "integrity": "sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==", "dev": true, - "license": "MIT", + "license": "Apache-2.0", "engines": { - "node": ">=6.9.0" + "node": ">=18.18.0" } }, - "node_modules/@babel/helpers": { - "version": "7.27.6", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.27.6.tgz", - "integrity": "sha512-muE8Tt8M22638HU31A3CgfSUciwz1fhATfoVai05aPXGor//CdWDCbnlY1yvBPo07njuVOCNGCSp/GTt12lIug==", + "node_modules/@humanfs/node": { + "version": "0.16.7", + "resolved": "https://registry.npmjs.org/@humanfs/node/-/node-0.16.7.tgz", + "integrity": "sha512-/zUx+yOsIrG4Y43Eh2peDeKCxlRt/gET6aHfaKpuq267qXdYDFViVHfMaLyygZOnl0kGWxFIgsBy8QFuTLUXEQ==", "dev": true, - "license": "MIT", + "license": "Apache-2.0", "dependencies": { - "@babel/template": "^7.27.2", - "@babel/types": "^7.27.6" + "@humanfs/core": "^0.19.1", + "@humanwhocodes/retry": "^0.4.0" }, "engines": { - "node": ">=6.9.0" + "node": ">=18.18.0" } }, - "node_modules/@babel/parser": { - "version": "7.28.0", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.28.0.tgz", - "integrity": "sha512-jVZGvOxOuNSsuQuLRTh13nU0AogFlw32w/MT+LV6D3sP5WdbW61E77RnkbaO2dUvmPAYrBDJXGn5gGS6tH4j8g==", + "node_modules/@humanwhocodes/module-importer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", + "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", "dev": true, - "license": "MIT", - "dependencies": { - "@babel/types": "^7.28.0" - }, - "bin": { - "parser": "bin/babel-parser.js" - }, + "license": "Apache-2.0", "engines": { - "node": ">=6.0.0" + "node": ">=12.22" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" } }, - "node_modules/@babel/plugin-transform-react-jsx-self": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-self/-/plugin-transform-react-jsx-self-7.27.1.tgz", - "integrity": "sha512-6UzkCs+ejGdZ5mFFC/OCUrv028ab2fp1znZmCZjAOBKiBK2jXD1O+BPSfX8X2qjJ75fZBMSnQn3Rq2mrBJK2mw==", + "node_modules/@humanwhocodes/retry": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.4.3.tgz", + "integrity": "sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ==", "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" - }, + "license": "Apache-2.0", "engines": { - "node": ">=6.9.0" + "node": ">=18.18" }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" } }, - "node_modules/@babel/plugin-transform-react-jsx-source": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-source/-/plugin-transform-react-jsx-source-7.27.1.tgz", - "integrity": "sha512-zbwoTsBruTeKB9hSq73ha66iFeJHuaFkUbwvqElnygoNbj/jHRsSeokowZFN3CZ64IvEqcmmkVe89OPXc7ldAw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" - }, + "node_modules/@img/sharp-darwin-arm64": { + "version": "0.34.3", + "resolved": "https://registry.npmjs.org/@img/sharp-darwin-arm64/-/sharp-darwin-arm64-0.34.3.tgz", + "integrity": "sha512-ryFMfvxxpQRsgZJqBd4wsttYQbCxsJksrv9Lw/v798JcQ8+w84mBWuXwl+TT0WJ/WrYOLaYpwQXi3sA9nTIaIg==", + "cpu": [ + "arm64" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "darwin" + ], "engines": { - "node": ">=6.9.0" + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/template": { - "version": "7.27.2", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.27.2.tgz", - "integrity": "sha512-LPDZ85aEJyYSd18/DkjNh4/y1ntkE5KwUHWTiqgRxruuZL2F1yuHligVHLvcHY2vMHXttKFpJn6LwfI7cw7ODw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/code-frame": "^7.27.1", - "@babel/parser": "^7.27.2", - "@babel/types": "^7.27.1" + "funding": { + "url": "https://opencollective.com/libvips" }, - "engines": { - "node": ">=6.9.0" + "optionalDependencies": { + "@img/sharp-libvips-darwin-arm64": "1.2.0" } }, - "node_modules/@babel/traverse": { - "version": "7.28.0", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.28.0.tgz", - "integrity": "sha512-mGe7UK5wWyh0bKRfupsUchrQGqvDbZDbKJw+kcRGSmdHVYrv+ltd0pnpDTVpiTqnaBru9iEvA8pz8W46v0Amwg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/code-frame": "^7.27.1", - "@babel/generator": "^7.28.0", - "@babel/helper-globals": "^7.28.0", - "@babel/parser": "^7.28.0", - "@babel/template": "^7.27.2", - "@babel/types": "^7.28.0", - "debug": "^4.3.1" - }, + "node_modules/@img/sharp-darwin-x64": { + "version": "0.34.3", + "resolved": "https://registry.npmjs.org/@img/sharp-darwin-x64/-/sharp-darwin-x64-0.34.3.tgz", + "integrity": "sha512-yHpJYynROAj12TA6qil58hmPmAwxKKC7reUqtGLzsOHfP7/rniNGTL8tjWX6L3CTV4+5P4ypcS7Pp+7OB+8ihA==", + "cpu": [ + "x64" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "darwin" + ], "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/types": { - "version": "7.28.1", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.28.1.tgz", - "integrity": "sha512-x0LvFTekgSX+83TI28Y9wYPUfzrnl2aT5+5QLnO6v7mSJYtEEevuDRN0F0uSHRk1G1IWZC43o00Y0xDDrpBGPQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-string-parser": "^7.27.1", - "@babel/helper-validator-identifier": "^7.27.1" + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" }, - "engines": { - "node": ">=6.9.0" + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-darwin-x64": "1.2.0" } }, - "node_modules/@emotion/is-prop-valid": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/@emotion/is-prop-valid/-/is-prop-valid-1.2.2.tgz", - "integrity": "sha512-uNsoYd37AFmaCdXlg6EYD1KaPOaRWRByMCYzbKUX4+hhMfrxdVSelShywL4JVaAeM/eHUOSprYBQls+/neX3pw==", - "license": "MIT", - "dependencies": { - "@emotion/memoize": "^0.8.1" + "node_modules/@img/sharp-libvips-darwin-arm64": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-arm64/-/sharp-libvips-darwin-arm64-1.2.0.tgz", + "integrity": "sha512-sBZmpwmxqwlqG9ueWFXtockhsxefaV6O84BMOrhtg/YqbTaRdqDE7hxraVE3y6gVM4eExmfzW4a8el9ArLeEiQ==", + "cpu": [ + "arm64" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "darwin" + ], + "funding": { + "url": "https://opencollective.com/libvips" } }, - "node_modules/@emotion/memoize": { - "version": "0.8.1", - "resolved": "https://registry.npmjs.org/@emotion/memoize/-/memoize-0.8.1.tgz", - "integrity": "sha512-W2P2c/VRW1/1tLox0mVUalvnWXxavmv/Oum2aPsRcoDJuob75FC3Y8FbpfLwUegRcxINtGUMPq0tFCvYNTBXNA==", - "license": "MIT" - }, - "node_modules/@emotion/unitless": { - "version": "0.8.1", - "resolved": "https://registry.npmjs.org/@emotion/unitless/-/unitless-0.8.1.tgz", - "integrity": "sha512-KOEGMu6dmJZtpadb476IsZBclKvILjopjUii3V+7MnXIQCYh8W3NgNcgwo21n9LXZX6EDIKvqfjYxXebDwxKmQ==", - "license": "MIT" - }, - "node_modules/@esbuild/aix-ppc64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.21.5.tgz", - "integrity": "sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ==", + "node_modules/@img/sharp-libvips-darwin-x64": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-x64/-/sharp-libvips-darwin-x64-1.2.0.tgz", + "integrity": "sha512-M64XVuL94OgiNHa5/m2YvEQI5q2cl9d/wk0qFTDVXcYzi43lxuiFTftMR1tOnFQovVXNZJ5TURSDK2pNe9Yzqg==", "cpu": [ - "ppc64" + "x64" ], - "dev": true, - "license": "MIT", + "license": "LGPL-3.0-or-later", "optional": true, "os": [ - "aix" + "darwin" ], - "engines": { - "node": ">=12" + "funding": { + "url": "https://opencollective.com/libvips" } }, - "node_modules/@esbuild/android-arm": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.21.5.tgz", - "integrity": "sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg==", + "node_modules/@img/sharp-libvips-linux-arm": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm/-/sharp-libvips-linux-arm-1.2.0.tgz", + "integrity": "sha512-mWd2uWvDtL/nvIzThLq3fr2nnGfyr/XMXlq8ZJ9WMR6PXijHlC3ksp0IpuhK6bougvQrchUAfzRLnbsen0Cqvw==", "cpu": [ "arm" ], - "dev": true, - "license": "MIT", + "license": "LGPL-3.0-or-later", "optional": true, "os": [ - "android" + "linux" ], - "engines": { - "node": ">=12" + "funding": { + "url": "https://opencollective.com/libvips" } }, - "node_modules/@esbuild/android-arm64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.21.5.tgz", - "integrity": "sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A==", + "node_modules/@img/sharp-libvips-linux-arm64": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm64/-/sharp-libvips-linux-arm64-1.2.0.tgz", + "integrity": "sha512-RXwd0CgG+uPRX5YYrkzKyalt2OJYRiJQ8ED/fi1tq9WQW2jsQIn0tqrlR5l5dr/rjqq6AHAxURhj2DVjyQWSOA==", "cpu": [ "arm64" ], - "dev": true, - "license": "MIT", + "license": "LGPL-3.0-or-later", "optional": true, "os": [ - "android" + "linux" ], - "engines": { - "node": ">=12" + "funding": { + "url": "https://opencollective.com/libvips" } }, - "node_modules/@esbuild/android-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.21.5.tgz", - "integrity": "sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA==", + "node_modules/@img/sharp-libvips-linux-ppc64": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-ppc64/-/sharp-libvips-linux-ppc64-1.2.0.tgz", + "integrity": "sha512-Xod/7KaDDHkYu2phxxfeEPXfVXFKx70EAFZ0qyUdOjCcxbjqyJOEUpDe6RIyaunGxT34Anf9ue/wuWOqBW2WcQ==", "cpu": [ - "x64" + "ppc64" ], - "dev": true, - "license": "MIT", + "license": "LGPL-3.0-or-later", "optional": true, "os": [ - "android" + "linux" ], - "engines": { - "node": ">=12" + "funding": { + "url": "https://opencollective.com/libvips" } }, - "node_modules/@esbuild/darwin-arm64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.21.5.tgz", - "integrity": "sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ==", + "node_modules/@img/sharp-libvips-linux-s390x": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-s390x/-/sharp-libvips-linux-s390x-1.2.0.tgz", + "integrity": "sha512-eMKfzDxLGT8mnmPJTNMcjfO33fLiTDsrMlUVcp6b96ETbnJmd4uvZxVJSKPQfS+odwfVaGifhsB07J1LynFehw==", "cpu": [ - "arm64" + "s390x" ], - "dev": true, - "license": "MIT", + "license": "LGPL-3.0-or-later", "optional": true, "os": [ - "darwin" + "linux" ], - "engines": { - "node": ">=12" + "funding": { + "url": "https://opencollective.com/libvips" } }, - "node_modules/@esbuild/darwin-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.21.5.tgz", - "integrity": "sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw==", + "node_modules/@img/sharp-libvips-linux-x64": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-x64/-/sharp-libvips-linux-x64-1.2.0.tgz", + "integrity": "sha512-ZW3FPWIc7K1sH9E3nxIGB3y3dZkpJlMnkk7z5tu1nSkBoCgw2nSRTFHI5pB/3CQaJM0pdzMF3paf9ckKMSE9Tg==", "cpu": [ "x64" ], - "dev": true, - "license": "MIT", + "license": "LGPL-3.0-or-later", "optional": true, "os": [ - "darwin" + "linux" ], - "engines": { - "node": ">=12" + "funding": { + "url": "https://opencollective.com/libvips" } }, - "node_modules/@esbuild/freebsd-arm64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.21.5.tgz", - "integrity": "sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g==", + "node_modules/@img/sharp-libvips-linuxmusl-arm64": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-arm64/-/sharp-libvips-linuxmusl-arm64-1.2.0.tgz", + "integrity": "sha512-UG+LqQJbf5VJ8NWJ5Z3tdIe/HXjuIdo4JeVNADXBFuG7z9zjoegpzzGIyV5zQKi4zaJjnAd2+g2nna8TZvuW9Q==", "cpu": [ "arm64" ], - "dev": true, - "license": "MIT", + "license": "LGPL-3.0-or-later", "optional": true, "os": [ - "freebsd" + "linux" ], - "engines": { - "node": ">=12" + "funding": { + "url": "https://opencollective.com/libvips" } }, - "node_modules/@esbuild/freebsd-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.21.5.tgz", - "integrity": "sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ==", + "node_modules/@img/sharp-libvips-linuxmusl-x64": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-x64/-/sharp-libvips-linuxmusl-x64-1.2.0.tgz", + "integrity": "sha512-SRYOLR7CXPgNze8akZwjoGBoN1ThNZoqpOgfnOxmWsklTGVfJiGJoC/Lod7aNMGA1jSsKWM1+HRX43OP6p9+6Q==", "cpu": [ "x64" ], - "dev": true, - "license": "MIT", + "license": "LGPL-3.0-or-later", "optional": true, "os": [ - "freebsd" + "linux" ], - "engines": { - "node": ">=12" + "funding": { + "url": "https://opencollective.com/libvips" } }, - "node_modules/@esbuild/linux-arm": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.21.5.tgz", - "integrity": "sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA==", + "node_modules/@img/sharp-linux-arm": { + "version": "0.34.3", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm/-/sharp-linux-arm-0.34.3.tgz", + "integrity": "sha512-oBK9l+h6KBN0i3dC8rYntLiVfW8D8wH+NPNT3O/WBHeW0OQWCjfWksLUaPidsrDKpJgXp3G3/hkmhptAW0I3+A==", "cpu": [ "arm" ], - "dev": true, - "license": "MIT", + "license": "Apache-2.0", "optional": true, "os": [ "linux" ], "engines": { - "node": ">=12" + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-arm": "1.2.0" } }, - "node_modules/@esbuild/linux-arm64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.21.5.tgz", - "integrity": "sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q==", + "node_modules/@img/sharp-linux-arm64": { + "version": "0.34.3", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm64/-/sharp-linux-arm64-0.34.3.tgz", + "integrity": "sha512-QdrKe3EvQrqwkDrtuTIjI0bu6YEJHTgEeqdzI3uWJOH6G1O8Nl1iEeVYRGdj1h5I21CqxSvQp1Yv7xeU3ZewbA==", "cpu": [ "arm64" ], - "dev": true, - "license": "MIT", + "license": "Apache-2.0", "optional": true, "os": [ "linux" ], "engines": { - "node": ">=12" + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-arm64": "1.2.0" } }, - "node_modules/@esbuild/linux-ia32": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.21.5.tgz", - "integrity": "sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg==", + "node_modules/@img/sharp-linux-ppc64": { + "version": "0.34.3", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-ppc64/-/sharp-linux-ppc64-0.34.3.tgz", + "integrity": "sha512-GLtbLQMCNC5nxuImPR2+RgrviwKwVql28FWZIW1zWruy6zLgA5/x2ZXk3mxj58X/tszVF69KK0Is83V8YgWhLA==", "cpu": [ - "ia32" + "ppc64" ], - "dev": true, - "license": "MIT", + "license": "Apache-2.0", "optional": true, "os": [ "linux" ], "engines": { - "node": ">=12" + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-ppc64": "1.2.0" } }, - "node_modules/@esbuild/linux-loong64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.21.5.tgz", - "integrity": "sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg==", + "node_modules/@img/sharp-linux-s390x": { + "version": "0.34.3", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-s390x/-/sharp-linux-s390x-0.34.3.tgz", + "integrity": "sha512-3gahT+A6c4cdc2edhsLHmIOXMb17ltffJlxR0aC2VPZfwKoTGZec6u5GrFgdR7ciJSsHT27BD3TIuGcuRT0KmQ==", "cpu": [ - "loong64" + "s390x" ], - "dev": true, - "license": "MIT", + "license": "Apache-2.0", "optional": true, "os": [ "linux" ], "engines": { - "node": ">=12" + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-s390x": "1.2.0" } }, - "node_modules/@esbuild/linux-mips64el": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.21.5.tgz", - "integrity": "sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg==", + "node_modules/@img/sharp-linux-x64": { + "version": "0.34.3", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-x64/-/sharp-linux-x64-0.34.3.tgz", + "integrity": "sha512-8kYso8d806ypnSq3/Ly0QEw90V5ZoHh10yH0HnrzOCr6DKAPI6QVHvwleqMkVQ0m+fc7EH8ah0BB0QPuWY6zJQ==", "cpu": [ - "mips64el" + "x64" ], - "dev": true, - "license": "MIT", + "license": "Apache-2.0", "optional": true, "os": [ "linux" ], "engines": { - "node": ">=12" + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-x64": "1.2.0" } }, - "node_modules/@esbuild/linux-ppc64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.21.5.tgz", - "integrity": "sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w==", + "node_modules/@img/sharp-linuxmusl-arm64": { + "version": "0.34.3", + "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-arm64/-/sharp-linuxmusl-arm64-0.34.3.tgz", + "integrity": "sha512-vAjbHDlr4izEiXM1OTggpCcPg9tn4YriK5vAjowJsHwdBIdx0fYRsURkxLG2RLm9gyBq66gwtWI8Gx0/ov+JKQ==", "cpu": [ - "ppc64" + "arm64" ], - "dev": true, - "license": "MIT", + "license": "Apache-2.0", "optional": true, "os": [ "linux" ], "engines": { - "node": ">=12" + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linuxmusl-arm64": "1.2.0" } }, - "node_modules/@esbuild/linux-riscv64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.21.5.tgz", - "integrity": "sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA==", + "node_modules/@img/sharp-linuxmusl-x64": { + "version": "0.34.3", + "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-x64/-/sharp-linuxmusl-x64-0.34.3.tgz", + "integrity": "sha512-gCWUn9547K5bwvOn9l5XGAEjVTTRji4aPTqLzGXHvIr6bIDZKNTA34seMPgM0WmSf+RYBH411VavCejp3PkOeQ==", "cpu": [ - "riscv64" + "x64" ], - "dev": true, - "license": "MIT", + "license": "Apache-2.0", "optional": true, "os": [ "linux" ], "engines": { - "node": ">=12" + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linuxmusl-x64": "1.2.0" } }, - "node_modules/@esbuild/linux-s390x": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.21.5.tgz", - "integrity": "sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A==", + "node_modules/@img/sharp-wasm32": { + "version": "0.34.3", + "resolved": "https://registry.npmjs.org/@img/sharp-wasm32/-/sharp-wasm32-0.34.3.tgz", + "integrity": "sha512-+CyRcpagHMGteySaWos8IbnXcHgfDn7pO2fiC2slJxvNq9gDipYBN42/RagzctVRKgxATmfqOSulgZv5e1RdMg==", "cpu": [ - "s390x" + "wasm32" + ], + "license": "Apache-2.0 AND LGPL-3.0-or-later AND MIT", + "optional": true, + "dependencies": { + "@emnapi/runtime": "^1.4.4" + }, + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-win32-arm64": { + "version": "0.34.3", + "resolved": "https://registry.npmjs.org/@img/sharp-win32-arm64/-/sharp-win32-arm64-0.34.3.tgz", + "integrity": "sha512-MjnHPnbqMXNC2UgeLJtX4XqoVHHlZNd+nPt1kRPmj63wURegwBhZlApELdtxM2OIZDRv/DFtLcNhVbd1z8GYXQ==", + "cpu": [ + "arm64" + ], + "license": "Apache-2.0 AND LGPL-3.0-or-later", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-win32-ia32": { + "version": "0.34.3", + "resolved": "https://registry.npmjs.org/@img/sharp-win32-ia32/-/sharp-win32-ia32-0.34.3.tgz", + "integrity": "sha512-xuCdhH44WxuXgOM714hn4amodJMZl3OEvf0GVTm0BEyMeA2to+8HEdRPShH0SLYptJY1uBw+SCFP9WVQi1Q/cw==", + "cpu": [ + "ia32" + ], + "license": "Apache-2.0 AND LGPL-3.0-or-later", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-win32-x64": { + "version": "0.34.3", + "resolved": "https://registry.npmjs.org/@img/sharp-win32-x64/-/sharp-win32-x64-0.34.3.tgz", + "integrity": "sha512-OWwz05d++TxzLEv4VnsTz5CmZ6mI6S05sfQGEMrNrQcOEERbX46332IvE7pO/EUiw7jUrrS40z/M7kPyjfl04g==", + "cpu": [ + "x64" + ], + "license": "Apache-2.0 AND LGPL-3.0-or-later", + "optional": true, + "os": [ + "win32" ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@napi-rs/wasm-runtime": { + "version": "0.2.12", + "resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-0.2.12.tgz", + "integrity": "sha512-ZVWUcfwY4E/yPitQJl481FjFo3K22D6qF0DuFH6Y/nbnE11GY5uguDxZMGXPQ8WQ0128MXQD7TnfHyK4oWoIJQ==", "dev": true, "license": "MIT", "optional": true, + "dependencies": { + "@emnapi/core": "^1.4.3", + "@emnapi/runtime": "^1.4.3", + "@tybys/wasm-util": "^0.10.0" + } + }, + "node_modules/@next/env": { + "version": "15.5.3", + "resolved": "https://registry.npmjs.org/@next/env/-/env-15.5.3.tgz", + "integrity": "sha512-RSEDTRqyihYXygx/OJXwvVupfr9m04+0vH8vyy0HfZ7keRto6VX9BbEk0J2PUk0VGy6YhklJUSrgForov5F9pw==", + "license": "MIT" + }, + "node_modules/@next/eslint-plugin-next": { + "version": "15.5.3", + "resolved": "https://registry.npmjs.org/@next/eslint-plugin-next/-/eslint-plugin-next-15.5.3.tgz", + "integrity": "sha512-SdhaKdko6dpsSr0DldkESItVrnPYB1NS2NpShCSX5lc7SSQmLZt5Mug6t2xbiuVWEVDLZSuIAoQyYVBYp0dR5g==", + "dev": true, + "license": "MIT", + "dependencies": { + "fast-glob": "3.3.1" + } + }, + "node_modules/@next/swc-darwin-arm64": { + "version": "15.5.3", + "resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-15.5.3.tgz", + "integrity": "sha512-nzbHQo69+au9wJkGKTU9lP7PXv0d1J5ljFpvb+LnEomLtSbJkbZyEs6sbF3plQmiOB2l9OBtN2tNSvCH1nQ9Jg==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, "os": [ - "linux" + "darwin" ], "engines": { - "node": ">=12" + "node": ">= 10" } }, - "node_modules/@esbuild/linux-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.21.5.tgz", - "integrity": "sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ==", + "node_modules/@next/swc-darwin-x64": { + "version": "15.5.3", + "resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-15.5.3.tgz", + "integrity": "sha512-w83w4SkOOhekJOcA5HBvHyGzgV1W/XvOfpkrxIse4uPWhYTTRwtGEM4v/jiXwNSJvfRvah0H8/uTLBKRXlef8g==", "cpu": [ "x64" ], - "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-linux-arm64-gnu": { + "version": "15.5.3", + "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-15.5.3.tgz", + "integrity": "sha512-+m7pfIs0/yvgVu26ieaKrifV8C8yiLe7jVp9SpcIzg7XmyyNE7toC1fy5IOQozmr6kWl/JONC51osih2RyoXRw==", + "cpu": [ + "arm64" + ], "license": "MIT", "optional": true, "os": [ "linux" ], "engines": { - "node": ">=12" + "node": ">= 10" } }, - "node_modules/@esbuild/netbsd-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.21.5.tgz", - "integrity": "sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg==", + "node_modules/@next/swc-linux-arm64-musl": { + "version": "15.5.3", + "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-15.5.3.tgz", + "integrity": "sha512-u3PEIzuguSenoZviZJahNLgCexGFhso5mxWCrrIMdvpZn6lkME5vc/ADZG8UUk5K1uWRy4hqSFECrON6UKQBbQ==", "cpu": [ - "x64" + "arm64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ - "netbsd" + "linux" ], "engines": { - "node": ">=12" + "node": ">= 10" } }, - "node_modules/@esbuild/openbsd-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.21.5.tgz", - "integrity": "sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow==", + "node_modules/@next/swc-linux-x64-gnu": { + "version": "15.5.3", + "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-15.5.3.tgz", + "integrity": "sha512-lDtOOScYDZxI2BENN9m0pfVPJDSuUkAD1YXSvlJF0DKwZt0WlA7T7o3wrcEr4Q+iHYGzEaVuZcsIbCps4K27sA==", "cpu": [ "x64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ - "openbsd" + "linux" ], "engines": { - "node": ">=12" + "node": ">= 10" } }, - "node_modules/@esbuild/sunos-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.21.5.tgz", - "integrity": "sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg==", + "node_modules/@next/swc-linux-x64-musl": { + "version": "15.5.3", + "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-15.5.3.tgz", + "integrity": "sha512-9vWVUnsx9PrY2NwdVRJ4dUURAQ8Su0sLRPqcCCxtX5zIQUBES12eRVHq6b70bbfaVaxIDGJN2afHui0eDm+cLg==", "cpu": [ "x64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ - "sunos" + "linux" ], "engines": { - "node": ">=12" + "node": ">= 10" } }, - "node_modules/@esbuild/win32-arm64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.21.5.tgz", - "integrity": "sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A==", + "node_modules/@next/swc-win32-arm64-msvc": { + "version": "15.5.3", + "resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-15.5.3.tgz", + "integrity": "sha512-1CU20FZzY9LFQigRi6jM45oJMU3KziA5/sSG+dXeVaTm661snQP6xu3ykGxxwU5sLG3sh14teO/IOEPVsQMRfA==", "cpu": [ "arm64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ "win32" ], "engines": { - "node": ">=12" + "node": ">= 10" } }, - "node_modules/@esbuild/win32-ia32": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.21.5.tgz", - "integrity": "sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA==", + "node_modules/@next/swc-win32-x64-msvc": { + "version": "15.5.3", + "resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-15.5.3.tgz", + "integrity": "sha512-JMoLAq3n3y5tKXPQwCK5c+6tmwkuFDa2XAxz8Wm4+IVthdBZdZGh+lmiLUHg9f9IDwIQpUjp+ysd6OkYTyZRZw==", "cpu": [ - "ia32" + "x64" ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nolyfill/is-core-module": { + "version": "1.0.39", + "resolved": "https://registry.npmjs.org/@nolyfill/is-core-module/-/is-core-module-1.0.39.tgz", + "integrity": "sha512-nn5ozdjYQpUCZlWGuxcJY/KpxkWQs4DcbMCmKojjyrYDEAGy4Ce19NN4v5MduafTwJlbKc99UA8YhSVqq9yPZA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12.4.0" + } + }, + "node_modules/@rtsao/scc": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@rtsao/scc/-/scc-1.1.0.tgz", + "integrity": "sha512-zt6OdqaDoOnJ1ZYsCYGt9YmWzDXl4vQdKTyJev62gFhRGKdx7mcT54V9KIjg+d2wi9EXsPvAPKe7i7WjfVWB8g==", + "dev": true, + "license": "MIT" + }, + "node_modules/@rushstack/eslint-patch": { + "version": "1.12.0", + "resolved": "https://registry.npmjs.org/@rushstack/eslint-patch/-/eslint-patch-1.12.0.tgz", + "integrity": "sha512-5EwMtOqvJMMa3HbmxLlF74e+3/HhwBTMcvt3nqVJgGCozO6hzIPOBlwm8mGVNR9SN2IJpxSnlxczyDjcn7qIyw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@swc/helpers": { + "version": "0.5.15", + "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.15.tgz", + "integrity": "sha512-JQ5TuMi45Owi4/BIMAJBoSQoOJu12oOk/gADqlcUL9JEdHB8vyjUSsxqeNXnmXHjYKMi2WcYtezGEEhqUI/E2g==", + "license": "Apache-2.0", + "dependencies": { + "tslib": "^2.8.0" + } + }, + "node_modules/@tybys/wasm-util": { + "version": "0.10.0", + "resolved": "https://registry.npmjs.org/@tybys/wasm-util/-/wasm-util-0.10.0.tgz", + "integrity": "sha512-VyyPYFlOMNylG45GoAe0xDoLwWuowvf92F9kySqzYh8vmYm7D2u4iUJKa1tOUpS70Ku13ASrOkS4ScXFsTaCNQ==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@types/estree": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz", + "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/json-schema": { + "version": "7.0.15", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", + "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/json5": { + "version": "0.0.29", + "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", + "integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/node": { + "version": "20.19.13", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.19.13.tgz", + "integrity": "sha512-yCAeZl7a0DxgNVteXFHt9+uyFbqXGy/ShC4BlcHkoE0AfGXYv/BUiplV72DjMYXHDBXFjhvr6DD1NiRVfB4j8g==", + "dev": true, + "license": "MIT", + "dependencies": { + "undici-types": "~6.21.0" + } + }, + "node_modules/@types/react": { + "version": "19.1.12", + "resolved": "https://registry.npmjs.org/@types/react/-/react-19.1.12.tgz", + "integrity": "sha512-cMoR+FoAf/Jyq6+Df2/Z41jISvGZZ2eTlnsaJRptmZ76Caldwy1odD4xTr/gNV9VLj0AWgg/nmkevIyUfIIq5w==", + "dev": true, + "license": "MIT", + "dependencies": { + "csstype": "^3.0.2" + } + }, + "node_modules/@types/react-dom": { + "version": "19.1.9", + "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-19.1.9.tgz", + "integrity": "sha512-qXRuZaOsAdXKFyOhRBg6Lqqc0yay13vN7KrIg4L7N4aaHN68ma9OK3NE1BoDFgFOTfM7zg+3/8+2n8rLUH3OKQ==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "@types/react": "^19.0.0" + } + }, + "node_modules/@typescript-eslint/eslint-plugin": { + "version": "8.43.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.43.0.tgz", + "integrity": "sha512-8tg+gt7ENL7KewsKMKDHXR1vm8tt9eMxjJBYINf6swonlWgkYn5NwyIgXpbbDxTNU5DgpDFfj95prcTq2clIQQ==", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "win32" - ], + "dependencies": { + "@eslint-community/regexpp": "^4.10.0", + "@typescript-eslint/scope-manager": "8.43.0", + "@typescript-eslint/type-utils": "8.43.0", + "@typescript-eslint/utils": "8.43.0", + "@typescript-eslint/visitor-keys": "8.43.0", + "graphemer": "^1.4.0", + "ignore": "^7.0.0", + "natural-compare": "^1.4.0", + "ts-api-utils": "^2.1.0" + }, "engines": { - "node": ">=12" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "@typescript-eslint/parser": "^8.43.0", + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <6.0.0" } }, - "node_modules/@esbuild/win32-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.21.5.tgz", - "integrity": "sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw==", - "cpu": [ - "x64" - ], + "node_modules/@typescript-eslint/eslint-plugin/node_modules/ignore": { + "version": "7.0.5", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-7.0.5.tgz", + "integrity": "sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg==", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "win32" - ], "engines": { - "node": ">=12" + "node": ">= 4" } }, - "node_modules/@eslint-community/eslint-utils": { - "version": "4.7.0", - "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.7.0.tgz", - "integrity": "sha512-dyybb3AcajC7uha6CvhdVRJqaKyn7w2YKqKyAN37NKYgZT36w+iRb0Dymmc5qEJ549c/S31cMMSFd75bteCpCw==", + "node_modules/@typescript-eslint/parser": { + "version": "8.43.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.43.0.tgz", + "integrity": "sha512-B7RIQiTsCBBmY+yW4+ILd6mF5h1FUwJsVvpqkrgpszYifetQ2Ke+Z4u6aZh0CblkUGIdR59iYVyXqqZGkZ3aBw==", "dev": true, "license": "MIT", "dependencies": { - "eslint-visitor-keys": "^3.4.3" + "@typescript-eslint/scope-manager": "8.43.0", + "@typescript-eslint/types": "8.43.0", + "@typescript-eslint/typescript-estree": "8.43.0", + "@typescript-eslint/visitor-keys": "8.43.0", + "debug": "^4.3.4" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { - "url": "https://opencollective.com/eslint" + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <6.0.0" } }, - "node_modules/@eslint-community/regexpp": { - "version": "4.12.1", - "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.1.tgz", - "integrity": "sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ==", + "node_modules/@typescript-eslint/project-service": { + "version": "8.43.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.43.0.tgz", + "integrity": "sha512-htB/+D/BIGoNTQYffZw4uM4NzzuolCoaA/BusuSIcC8YjmBYQioew5VUZAYdAETPjeed0hqCaW7EHg+Robq8uw==", "dev": true, "license": "MIT", + "dependencies": { + "@typescript-eslint/tsconfig-utils": "^8.43.0", + "@typescript-eslint/types": "^8.43.0", + "debug": "^4.3.4" + }, "engines": { - "node": "^12.0.0 || ^14.0.0 || >=16.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "typescript": ">=4.8.4 <6.0.0" } }, - "node_modules/@eslint/eslintrc": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.4.tgz", - "integrity": "sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==", + "node_modules/@typescript-eslint/scope-manager": { + "version": "8.43.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.43.0.tgz", + "integrity": "sha512-daSWlQ87ZhsjrbMLvpuuMAt3y4ba57AuvadcR7f3nl8eS3BjRc8L9VLxFLk92RL5xdXOg6IQ+qKjjqNEimGuAg==", "dev": true, "license": "MIT", "dependencies": { - "ajv": "^6.12.4", - "debug": "^4.3.2", - "espree": "^9.6.0", - "globals": "^13.19.0", - "ignore": "^5.2.0", - "import-fresh": "^3.2.1", - "js-yaml": "^4.1.0", - "minimatch": "^3.1.2", - "strip-json-comments": "^3.1.1" + "@typescript-eslint/types": "8.43.0", + "@typescript-eslint/visitor-keys": "8.43.0" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { - "url": "https://opencollective.com/eslint" + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" } }, - "node_modules/@eslint/js": { - "version": "8.57.1", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.57.1.tgz", - "integrity": "sha512-d9zaMRSTIKDLhctzH12MtXvJKSSUhaHcjV+2Z+GK+EEY7XKpP5yR4x+N3TAcHTcu963nIr+TMcCb4DBCYX1z6Q==", + "node_modules/@typescript-eslint/tsconfig-utils": { + "version": "8.43.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.43.0.tgz", + "integrity": "sha512-ALC2prjZcj2YqqL5X/bwWQmHA2em6/94GcbB/KKu5SX3EBDOsqztmmX1kMkvAJHzxk7TazKzJfFiEIagNV3qEA==", "dev": true, "license": "MIT", "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "typescript": ">=4.8.4 <6.0.0" } }, - "node_modules/@humanwhocodes/config-array": { - "version": "0.13.0", - "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.13.0.tgz", - "integrity": "sha512-DZLEEqFWQFiyK6h5YIeynKx7JlvCYWL0cImfSRXZ9l4Sg2efkFGTuFf6vzXjK1cq6IYkU+Eg/JizXw+TD2vRNw==", - "deprecated": "Use @eslint/config-array instead", + "node_modules/@typescript-eslint/type-utils": { + "version": "8.43.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.43.0.tgz", + "integrity": "sha512-qaH1uLBpBuBBuRf8c1mLJ6swOfzCXryhKND04Igr4pckzSEW9JX5Aw9AgW00kwfjWJF0kk0ps9ExKTfvXfw4Qg==", "dev": true, - "license": "Apache-2.0", + "license": "MIT", "dependencies": { - "@humanwhocodes/object-schema": "^2.0.3", - "debug": "^4.3.1", - "minimatch": "^3.0.5" + "@typescript-eslint/types": "8.43.0", + "@typescript-eslint/typescript-estree": "8.43.0", + "@typescript-eslint/utils": "8.43.0", + "debug": "^4.3.4", + "ts-api-utils": "^2.1.0" }, "engines": { - "node": ">=10.10.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <6.0.0" } }, - "node_modules/@humanwhocodes/module-importer": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", - "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", + "node_modules/@typescript-eslint/types": { + "version": "8.43.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.43.0.tgz", + "integrity": "sha512-vQ2FZaxJpydjSZJKiSW/LJsabFFvV7KgLC5DiLhkBcykhQj8iK9BOaDmQt74nnKdLvceM5xmhaTF+pLekrxEkw==", "dev": true, - "license": "Apache-2.0", + "license": "MIT", "engines": { - "node": ">=12.22" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { - "type": "github", - "url": "https://github.com/sponsors/nzakas" + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" } }, - "node_modules/@humanwhocodes/object-schema": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.3.tgz", - "integrity": "sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==", - "deprecated": "Use @eslint/object-schema instead", + "node_modules/@typescript-eslint/typescript-estree": { + "version": "8.43.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.43.0.tgz", + "integrity": "sha512-7Vv6zlAhPb+cvEpP06WXXy/ZByph9iL6BQRBDj4kmBsW98AqEeQHlj/13X+sZOrKSo9/rNKH4Ul4f6EICREFdw==", "dev": true, - "license": "BSD-3-Clause" + "license": "MIT", + "dependencies": { + "@typescript-eslint/project-service": "8.43.0", + "@typescript-eslint/tsconfig-utils": "8.43.0", + "@typescript-eslint/types": "8.43.0", + "@typescript-eslint/visitor-keys": "8.43.0", + "debug": "^4.3.4", + "fast-glob": "^3.3.2", + "is-glob": "^4.0.3", + "minimatch": "^9.0.4", + "semver": "^7.6.0", + "ts-api-utils": "^2.1.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "typescript": ">=4.8.4 <6.0.0" + } }, - "node_modules/@jridgewell/gen-mapping": { - "version": "0.3.12", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.12.tgz", - "integrity": "sha512-OuLGC46TjB5BbN1dH8JULVVZY4WTdkF7tV9Ys6wLL1rubZnCMstOhNHueU5bLCrnRuDhKPDM4g6sw4Bel5Gzqg==", + "node_modules/@typescript-eslint/typescript-estree/node_modules/brace-expansion": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", + "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", "dev": true, "license": "MIT", "dependencies": { - "@jridgewell/sourcemap-codec": "^1.5.0", - "@jridgewell/trace-mapping": "^0.3.24" + "balanced-match": "^1.0.0" } }, - "node_modules/@jridgewell/resolve-uri": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", - "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", + "node_modules/@typescript-eslint/typescript-estree/node_modules/fast-glob": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.3.tgz", + "integrity": "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==", "dev": true, "license": "MIT", + "dependencies": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.8" + }, "engines": { - "node": ">=6.0.0" + "node": ">=8.6.0" } }, - "node_modules/@jridgewell/sourcemap-codec": { - "version": "1.5.4", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.4.tgz", - "integrity": "sha512-VT2+G1VQs/9oz078bLrYbecdZKs912zQlkelYpuf+SXF+QvZDYJlbx/LSx+meSAwdDFnF8FVXW92AVjjkVmgFw==", - "dev": true, - "license": "MIT" - }, - "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.29", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.29.tgz", - "integrity": "sha512-uw6guiW/gcAGPDhLmd77/6lW8QLeiV5RUTsAX46Db6oLhGaVj4lhnPwb184s1bkc8kdVg/+h988dro8GRDpmYQ==", + "node_modules/@typescript-eslint/typescript-estree/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", "dev": true, - "license": "MIT", + "license": "ISC", "dependencies": { - "@jridgewell/resolve-uri": "^3.1.0", - "@jridgewell/sourcemap-codec": "^1.4.14" + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" } }, - "node_modules/@nodelib/fs.scandir": { - "version": "2.1.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", - "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "node_modules/@typescript-eslint/typescript-estree/node_modules/minimatch": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", "dev": true, - "license": "MIT", + "license": "ISC", "dependencies": { - "@nodelib/fs.stat": "2.0.5", - "run-parallel": "^1.1.9" + "brace-expansion": "^2.0.1" }, "engines": { - "node": ">= 8" + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/@nodelib/fs.stat": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", - "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "node_modules/@typescript-eslint/utils": { + "version": "8.43.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.43.0.tgz", + "integrity": "sha512-S1/tEmkUeeswxd0GGcnwuVQPFWo8NzZTOMxCvw8BX7OMxnNae+i8Tm7REQen/SwUIPoPqfKn7EaZ+YLpiB3k9g==", "dev": true, "license": "MIT", + "dependencies": { + "@eslint-community/eslint-utils": "^4.7.0", + "@typescript-eslint/scope-manager": "8.43.0", + "@typescript-eslint/types": "8.43.0", + "@typescript-eslint/typescript-estree": "8.43.0" + }, "engines": { - "node": ">= 8" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <6.0.0" } }, - "node_modules/@nodelib/fs.walk": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", - "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "node_modules/@typescript-eslint/visitor-keys": { + "version": "8.43.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.43.0.tgz", + "integrity": "sha512-T+S1KqRD4sg/bHfLwrpF/K3gQLBM1n7Rp7OjjikjTEssI2YJzQpi5WXoynOaQ93ERIuq3O8RBTOUYDKszUCEHw==", "dev": true, "license": "MIT", "dependencies": { - "@nodelib/fs.scandir": "2.1.5", - "fastq": "^1.6.0" + "@typescript-eslint/types": "8.43.0", + "eslint-visitor-keys": "^4.2.1" }, "engines": { - "node": ">= 8" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" } }, - "node_modules/@rolldown/pluginutils": { - "version": "1.0.0-beta.19", - "resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.0-beta.19.tgz", - "integrity": "sha512-3FL3mnMbPu0muGOCaKAhhFEYmqv9eTfPSJRJmANrCwtgK8VuxpsZDGK+m0LYAGoyO8+0j5uRe4PeyPDK1yA/hA==", - "dev": true, - "license": "MIT" - }, - "node_modules/@rollup/rollup-android-arm-eabi": { - "version": "4.45.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.45.0.tgz", - "integrity": "sha512-2o/FgACbji4tW1dzXOqAV15Eu7DdgbKsF2QKcxfG4xbh5iwU7yr5RRP5/U+0asQliSYv5M4o7BevlGIoSL0LXg==", + "node_modules/@unrs/resolver-binding-android-arm-eabi": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-android-arm-eabi/-/resolver-binding-android-arm-eabi-1.11.1.tgz", + "integrity": "sha512-ppLRUgHVaGRWUx0R0Ut06Mjo9gBaBkg3v/8AxusGLhsIotbBLuRk51rAzqLC8gq6NyyAojEXglNjzf6R948DNw==", "cpu": [ "arm" ], @@ -933,10 +1258,10 @@ "android" ] }, - "node_modules/@rollup/rollup-android-arm64": { - "version": "4.45.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.45.0.tgz", - "integrity": "sha512-PSZ0SvMOjEAxwZeTx32eI/j5xSYtDCRxGu5k9zvzoY77xUNssZM+WV6HYBLROpY5CkXsbQjvz40fBb7WPwDqtQ==", + "node_modules/@unrs/resolver-binding-android-arm64": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-android-arm64/-/resolver-binding-android-arm64-1.11.1.tgz", + "integrity": "sha512-lCxkVtb4wp1v+EoN+HjIG9cIIzPkX5OtM03pQYkG+U5O/wL53LC4QbIeazgiKqluGeVEeBlZahHalCaBvU1a2g==", "cpu": [ "arm64" ], @@ -947,10 +1272,10 @@ "android" ] }, - "node_modules/@rollup/rollup-darwin-arm64": { - "version": "4.45.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.45.0.tgz", - "integrity": "sha512-BA4yPIPssPB2aRAWzmqzQ3y2/KotkLyZukVB7j3psK/U3nVJdceo6qr9pLM2xN6iRP/wKfxEbOb1yrlZH6sYZg==", + "node_modules/@unrs/resolver-binding-darwin-arm64": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-darwin-arm64/-/resolver-binding-darwin-arm64-1.11.1.tgz", + "integrity": "sha512-gPVA1UjRu1Y/IsB/dQEsp2V1pm44Of6+LWvbLc9SDk1c2KhhDRDBUkQCYVWe6f26uJb3fOK8saWMgtX8IrMk3g==", "cpu": [ "arm64" ], @@ -961,10 +1286,10 @@ "darwin" ] }, - "node_modules/@rollup/rollup-darwin-x64": { - "version": "4.45.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.45.0.tgz", - "integrity": "sha512-Pr2o0lvTwsiG4HCr43Zy9xXrHspyMvsvEw4FwKYqhli4FuLE5FjcZzuQ4cfPe0iUFCvSQG6lACI0xj74FDZKRA==", + "node_modules/@unrs/resolver-binding-darwin-x64": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-darwin-x64/-/resolver-binding-darwin-x64-1.11.1.tgz", + "integrity": "sha512-cFzP7rWKd3lZaCsDze07QX1SC24lO8mPty9vdP+YVa3MGdVgPmFc59317b2ioXtgCMKGiCLxJ4HQs62oz6GfRQ==", "cpu": [ "x64" ], @@ -975,24 +1300,10 @@ "darwin" ] }, - "node_modules/@rollup/rollup-freebsd-arm64": { - "version": "4.45.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.45.0.tgz", - "integrity": "sha512-lYE8LkE5h4a/+6VnnLiL14zWMPnx6wNbDG23GcYFpRW1V9hYWHAw9lBZ6ZUIrOaoK7NliF1sdwYGiVmziUF4vA==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ] - }, - "node_modules/@rollup/rollup-freebsd-x64": { - "version": "4.45.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.45.0.tgz", - "integrity": "sha512-PVQWZK9sbzpvqC9Q0GlehNNSVHR+4m7+wET+7FgSnKG3ci5nAMgGmr9mGBXzAuE5SvguCKJ6mHL6vq1JaJ/gvw==", + "node_modules/@unrs/resolver-binding-freebsd-x64": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-freebsd-x64/-/resolver-binding-freebsd-x64-1.11.1.tgz", + "integrity": "sha512-fqtGgak3zX4DCB6PFpsH5+Kmt/8CIi4Bry4rb1ho6Av2QHTREM+47y282Uqiu3ZRF5IQioJQ5qWRV6jduA+iGw==", "cpu": [ "x64" ], @@ -1003,10 +1314,10 @@ "freebsd" ] }, - "node_modules/@rollup/rollup-linux-arm-gnueabihf": { - "version": "4.45.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.45.0.tgz", - "integrity": "sha512-hLrmRl53prCcD+YXTfNvXd776HTxNh8wPAMllusQ+amcQmtgo3V5i/nkhPN6FakW+QVLoUUr2AsbtIRPFU3xIA==", + "node_modules/@unrs/resolver-binding-linux-arm-gnueabihf": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm-gnueabihf/-/resolver-binding-linux-arm-gnueabihf-1.11.1.tgz", + "integrity": "sha512-u92mvlcYtp9MRKmP+ZvMmtPN34+/3lMHlyMj7wXJDeXxuM0Vgzz0+PPJNsro1m3IZPYChIkn944wW8TYgGKFHw==", "cpu": [ "arm" ], @@ -1017,10 +1328,10 @@ "linux" ] }, - "node_modules/@rollup/rollup-linux-arm-musleabihf": { - "version": "4.45.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.45.0.tgz", - "integrity": "sha512-XBKGSYcrkdiRRjl+8XvrUR3AosXU0NvF7VuqMsm7s5nRy+nt58ZMB19Jdp1RdqewLcaYnpk8zeVs/4MlLZEJxw==", + "node_modules/@unrs/resolver-binding-linux-arm-musleabihf": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm-musleabihf/-/resolver-binding-linux-arm-musleabihf-1.11.1.tgz", + "integrity": "sha512-cINaoY2z7LVCrfHkIcmvj7osTOtm6VVT16b5oQdS4beibX2SYBwgYLmqhBjA1t51CarSaBuX5YNsWLjsqfW5Cw==", "cpu": [ "arm" ], @@ -1031,10 +1342,10 @@ "linux" ] }, - "node_modules/@rollup/rollup-linux-arm64-gnu": { - "version": "4.45.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.45.0.tgz", - "integrity": "sha512-fRvZZPUiBz7NztBE/2QnCS5AtqLVhXmUOPj9IHlfGEXkapgImf4W9+FSkL8cWqoAjozyUzqFmSc4zh2ooaeF6g==", + "node_modules/@unrs/resolver-binding-linux-arm64-gnu": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm64-gnu/-/resolver-binding-linux-arm64-gnu-1.11.1.tgz", + "integrity": "sha512-34gw7PjDGB9JgePJEmhEqBhWvCiiWCuXsL9hYphDF7crW7UgI05gyBAi6MF58uGcMOiOqSJ2ybEeCvHcq0BCmQ==", "cpu": [ "arm64" ], @@ -1045,10 +1356,10 @@ "linux" ] }, - "node_modules/@rollup/rollup-linux-arm64-musl": { - "version": "4.45.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.45.0.tgz", - "integrity": "sha512-Btv2WRZOcUGi8XU80XwIvzTg4U6+l6D0V6sZTrZx214nrwxw5nAi8hysaXj/mctyClWgesyuxbeLylCBNauimg==", + "node_modules/@unrs/resolver-binding-linux-arm64-musl": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm64-musl/-/resolver-binding-linux-arm64-musl-1.11.1.tgz", + "integrity": "sha512-RyMIx6Uf53hhOtJDIamSbTskA99sPHS96wxVE/bJtePJJtpdKGXO1wY90oRdXuYOGOTuqjT8ACccMc4K6QmT3w==", "cpu": [ "arm64" ], @@ -1059,12 +1370,12 @@ "linux" ] }, - "node_modules/@rollup/rollup-linux-loongarch64-gnu": { - "version": "4.45.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loongarch64-gnu/-/rollup-linux-loongarch64-gnu-4.45.0.tgz", - "integrity": "sha512-Li0emNnwtUZdLwHjQPBxn4VWztcrw/h7mgLyHiEI5Z0MhpeFGlzaiBHpSNVOMB/xucjXTTcO+dhv469Djr16KA==", + "node_modules/@unrs/resolver-binding-linux-ppc64-gnu": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-ppc64-gnu/-/resolver-binding-linux-ppc64-gnu-1.11.1.tgz", + "integrity": "sha512-D8Vae74A4/a+mZH0FbOkFJL9DSK2R6TFPC9M+jCWYia/q2einCubX10pecpDiTmkJVUH+y8K3BZClycD8nCShA==", "cpu": [ - "loong64" + "ppc64" ], "dev": true, "license": "MIT", @@ -1073,12 +1384,12 @@ "linux" ] }, - "node_modules/@rollup/rollup-linux-powerpc64le-gnu": { - "version": "4.45.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.45.0.tgz", - "integrity": "sha512-sB8+pfkYx2kvpDCfd63d5ScYT0Fz1LO6jIb2zLZvmK9ob2D8DeVqrmBDE0iDK8KlBVmsTNzrjr3G1xV4eUZhSw==", + "node_modules/@unrs/resolver-binding-linux-riscv64-gnu": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-riscv64-gnu/-/resolver-binding-linux-riscv64-gnu-1.11.1.tgz", + "integrity": "sha512-frxL4OrzOWVVsOc96+V3aqTIQl1O2TjgExV4EKgRY09AJ9leZpEg8Ak9phadbuX0BA4k8U5qtvMSQQGGmaJqcQ==", "cpu": [ - "ppc64" + "riscv64" ], "dev": true, "license": "MIT", @@ -1087,10 +1398,10 @@ "linux" ] }, - "node_modules/@rollup/rollup-linux-riscv64-gnu": { - "version": "4.45.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.45.0.tgz", - "integrity": "sha512-5GQ6PFhh7E6jQm70p1aW05G2cap5zMOvO0se5JMecHeAdj5ZhWEHbJ4hiKpfi1nnnEdTauDXxPgXae/mqjow9w==", + "node_modules/@unrs/resolver-binding-linux-riscv64-musl": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-riscv64-musl/-/resolver-binding-linux-riscv64-musl-1.11.1.tgz", + "integrity": "sha512-mJ5vuDaIZ+l/acv01sHoXfpnyrNKOk/3aDoEdLO/Xtn9HuZlDD6jKxHlkN8ZhWyLJsRBxfv9GYM2utQ1SChKew==", "cpu": [ "riscv64" ], @@ -1101,12 +1412,12 @@ "linux" ] }, - "node_modules/@rollup/rollup-linux-riscv64-musl": { - "version": "4.45.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.45.0.tgz", - "integrity": "sha512-N/euLsBd1rekWcuduakTo/dJw6U6sBP3eUq+RXM9RNfPuWTvG2w/WObDkIvJ2KChy6oxZmOSC08Ak2OJA0UiAA==", + "node_modules/@unrs/resolver-binding-linux-s390x-gnu": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-s390x-gnu/-/resolver-binding-linux-s390x-gnu-1.11.1.tgz", + "integrity": "sha512-kELo8ebBVtb9sA7rMe1Cph4QHreByhaZ2QEADd9NzIQsYNQpt9UkM9iqr2lhGr5afh885d/cB5QeTXSbZHTYPg==", "cpu": [ - "riscv64" + "s390x" ], "dev": true, "license": "MIT", @@ -1115,12 +1426,12 @@ "linux" ] }, - "node_modules/@rollup/rollup-linux-s390x-gnu": { - "version": "4.45.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.45.0.tgz", - "integrity": "sha512-2l9sA7d7QdikL0xQwNMO3xURBUNEWyHVHfAsHsUdq+E/pgLTUcCE+gih5PCdmyHmfTDeXUWVhqL0WZzg0nua3g==", + "node_modules/@unrs/resolver-binding-linux-x64-gnu": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-x64-gnu/-/resolver-binding-linux-x64-gnu-1.11.1.tgz", + "integrity": "sha512-C3ZAHugKgovV5YvAMsxhq0gtXuwESUKc5MhEtjBpLoHPLYM+iuwSj3lflFwK3DPm68660rZ7G8BMcwSro7hD5w==", "cpu": [ - "s390x" + "x64" ], "dev": true, "license": "MIT", @@ -1129,10 +1440,10 @@ "linux" ] }, - "node_modules/@rollup/rollup-linux-x64-gnu": { - "version": "4.45.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.45.0.tgz", - "integrity": "sha512-XZdD3fEEQcwG2KrJDdEQu7NrHonPxxaV0/w2HpvINBdcqebz1aL+0vM2WFJq4DeiAVT6F5SUQas65HY5JDqoPw==", + "node_modules/@unrs/resolver-binding-linux-x64-musl": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-x64-musl/-/resolver-binding-linux-x64-musl-1.11.1.tgz", + "integrity": "sha512-rV0YSoyhK2nZ4vEswT/QwqzqQXw5I6CjoaYMOX0TqBlWhojUf8P94mvI7nuJTeaCkkds3QE4+zS8Ko+GdXuZtA==", "cpu": [ "x64" ], @@ -1143,24 +1454,27 @@ "linux" ] }, - "node_modules/@rollup/rollup-linux-x64-musl": { - "version": "4.45.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.45.0.tgz", - "integrity": "sha512-7ayfgvtmmWgKWBkCGg5+xTQ0r5V1owVm67zTrsEY1008L5ro7mCyGYORomARt/OquB9KY7LpxVBZes+oSniAAQ==", + "node_modules/@unrs/resolver-binding-wasm32-wasi": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-wasm32-wasi/-/resolver-binding-wasm32-wasi-1.11.1.tgz", + "integrity": "sha512-5u4RkfxJm+Ng7IWgkzi3qrFOvLvQYnPBmjmZQ8+szTK/b31fQCnleNl1GgEt7nIsZRIf5PLhPwT0WM+q45x/UQ==", "cpu": [ - "x64" + "wasm32" ], "dev": true, "license": "MIT", "optional": true, - "os": [ - "linux" - ] + "dependencies": { + "@napi-rs/wasm-runtime": "^0.2.11" + }, + "engines": { + "node": ">=14.0.0" + } }, - "node_modules/@rollup/rollup-win32-arm64-msvc": { - "version": "4.45.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.45.0.tgz", - "integrity": "sha512-B+IJgcBnE2bm93jEW5kHisqvPITs4ddLOROAcOc/diBgrEiQJJ6Qcjby75rFSmH5eMGrqJryUgJDhrfj942apQ==", + "node_modules/@unrs/resolver-binding-win32-arm64-msvc": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-win32-arm64-msvc/-/resolver-binding-win32-arm64-msvc-1.11.1.tgz", + "integrity": "sha512-nRcz5Il4ln0kMhfL8S3hLkxI85BXs3o8EYoattsJNdsX4YUU89iOkVn7g0VHSRxFuVMdM4Q1jEpIId1Ihim/Uw==", "cpu": [ "arm64" ], @@ -1171,10 +1485,10 @@ "win32" ] }, - "node_modules/@rollup/rollup-win32-ia32-msvc": { - "version": "4.45.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.45.0.tgz", - "integrity": "sha512-+CXwwG66g0/FpWOnP/v1HnrGVSOygK/osUbu3wPRy8ECXjoYKjRAyfxYpDQOfghC5qPJYLPH0oN4MCOjwgdMug==", + "node_modules/@unrs/resolver-binding-win32-ia32-msvc": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-win32-ia32-msvc/-/resolver-binding-win32-ia32-msvc-1.11.1.tgz", + "integrity": "sha512-DCEI6t5i1NmAZp6pFonpD5m7i6aFrpofcp4LA2i8IIq60Jyo28hamKBxNrZcyOwVOZkgsRp9O2sXWBWP8MnvIQ==", "cpu": [ "ia32" ], @@ -1185,10 +1499,10 @@ "win32" ] }, - "node_modules/@rollup/rollup-win32-x64-msvc": { - "version": "4.45.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.45.0.tgz", - "integrity": "sha512-SRf1cytG7wqcHVLrBc9VtPK4pU5wxiB/lNIkNmW2ApKXIg+RpqwHfsaEK+e7eH4A1BpI6BX/aBWXxZCIrJg3uA==", + "node_modules/@unrs/resolver-binding-win32-x64-msvc": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-win32-x64-msvc/-/resolver-binding-win32-x64-msvc-1.11.1.tgz", + "integrity": "sha512-lrW200hZdbfRtztbygyaq/6jP6AKE8qQN2KvPcJ+x7wiD038YtnYtZ82IMNJ69GJibV7bwL3y9FgK+5w/pYt6g==", "cpu": [ "x64" ], @@ -1199,120 +1513,6 @@ "win32" ] }, - "node_modules/@types/babel__core": { - "version": "7.20.5", - "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz", - "integrity": "sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/parser": "^7.20.7", - "@babel/types": "^7.20.7", - "@types/babel__generator": "*", - "@types/babel__template": "*", - "@types/babel__traverse": "*" - } - }, - "node_modules/@types/babel__generator": { - "version": "7.27.0", - "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.27.0.tgz", - "integrity": "sha512-ufFd2Xi92OAVPYsy+P4n7/U7e68fex0+Ee8gSG9KX7eo084CWiQ4sdxktvdl0bOPupXtVJPY19zk6EwWqUQ8lg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/types": "^7.0.0" - } - }, - "node_modules/@types/babel__template": { - "version": "7.4.4", - "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.4.tgz", - "integrity": "sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/parser": "^7.1.0", - "@babel/types": "^7.0.0" - } - }, - "node_modules/@types/babel__traverse": { - "version": "7.20.7", - "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.20.7.tgz", - "integrity": "sha512-dkO5fhS7+/oos4ciWxyEyjWe48zmG6wbCheo/G2ZnHx4fs3EU6YC6UM8rk56gAjNJ9P3MTH2jo5jb92/K6wbng==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/types": "^7.20.7" - } - }, - "node_modules/@types/estree": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz", - "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/prop-types": { - "version": "15.7.15", - "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.15.tgz", - "integrity": "sha512-F6bEyamV9jKGAFBEmlQnesRPGOQqS2+Uwi0Em15xenOxHaf2hv6L8YCVn3rPdPJOiJfPiCnLIRyvwVaqMY3MIw==", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/react": { - "version": "18.3.23", - "resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.23.tgz", - "integrity": "sha512-/LDXMQh55EzZQ0uVAZmKKhfENivEvWz6E+EYzh+/MCjMhNsotd+ZHhBGIjFDTi6+fz0OhQQQLbTgdQIxxCsC0w==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/prop-types": "*", - "csstype": "^3.0.2" - } - }, - "node_modules/@types/react-dom": { - "version": "18.3.7", - "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.3.7.tgz", - "integrity": "sha512-MEe3UeoENYVFXzoXEWsvcpg6ZvlrFNlOQ7EOsvhI3CfAXwzPfO8Qwuxd40nepsYKqyyVQnTdEfv68q91yLcKrQ==", - "dev": true, - "license": "MIT", - "peerDependencies": { - "@types/react": "^18.0.0" - } - }, - "node_modules/@types/stylis": { - "version": "4.2.5", - "resolved": "https://registry.npmjs.org/@types/stylis/-/stylis-4.2.5.tgz", - "integrity": "sha512-1Xve+NMN7FWjY14vLoY5tL3BVEQ/n42YLwaqJIPYhotZ9uBHt87VceMwWQpzmdEt2TNXIorIFG+YeCUUW7RInw==", - "license": "MIT" - }, - "node_modules/@ungap/structured-clone": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.3.0.tgz", - "integrity": "sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g==", - "dev": true, - "license": "ISC" - }, - "node_modules/@vitejs/plugin-react": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/@vitejs/plugin-react/-/plugin-react-4.6.0.tgz", - "integrity": "sha512-5Kgff+m8e2PB+9j51eGHEpn5kUzRKH2Ry0qGoe8ItJg7pqnkPrYPkDQZGgGmTa0EGarHrkjLvOdU3b1fzI8otQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/core": "^7.27.4", - "@babel/plugin-transform-react-jsx-self": "^7.27.1", - "@babel/plugin-transform-react-jsx-source": "^7.27.1", - "@rolldown/pluginutils": "1.0.0-beta.19", - "@types/babel__core": "^7.20.5", - "react-refresh": "^0.17.0" - }, - "engines": { - "node": "^14.18.0 || >=16.0.0" - }, - "peerDependencies": { - "vite": "^4.2.0 || ^5.0.0 || ^6.0.0 || ^7.0.0-beta.0" - } - }, "node_modules/acorn": { "version": "8.15.0", "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz", @@ -1353,16 +1553,6 @@ "url": "https://github.com/sponsors/epoberezkin" } }, - "node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, "node_modules/ansi-styles": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", @@ -1386,6 +1576,16 @@ "dev": true, "license": "Python-2.0" }, + "node_modules/aria-query": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.3.2.tgz", + "integrity": "sha512-COROpnaoap1E2F000S62r6A60uHZnmlvomhfyT2DlTcrY1OrBKn2UhH7qn5wTC9zMvD0AY7csdPSNwKP+7WiQw==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">= 0.4" + } + }, "node_modules/array-buffer-byte-length": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.2.tgz", @@ -1426,19 +1626,41 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/array.prototype.findlast": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/array.prototype.findlast/-/array.prototype.findlast-1.2.5.tgz", - "integrity": "sha512-CVvd6FHg1Z3POpBLxO6E6zr+rSKEQ9L6rZHAaY7lLfhKsWYUBBOuMs0e9o24oopj6H+geRCX0YJ+TJLBK2eHyQ==", + "node_modules/array.prototype.findlast": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/array.prototype.findlast/-/array.prototype.findlast-1.2.5.tgz", + "integrity": "sha512-CVvd6FHg1Z3POpBLxO6E6zr+rSKEQ9L6rZHAaY7lLfhKsWYUBBOuMs0e9o24oopj6H+geRCX0YJ+TJLBK2eHyQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", + "es-shim-unscopables": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array.prototype.findlastindex": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/array.prototype.findlastindex/-/array.prototype.findlastindex-1.2.6.tgz", + "integrity": "sha512-F/TKATkzseUExPlfvmwQKGITM3DGTK+vkAsCZoDc5daVygbJBnjEUCbgkAvVFsgfXfX4YIqZ/27G3k3tdXrTxQ==", "dev": true, "license": "MIT", "dependencies": { - "call-bind": "^1.0.7", + "call-bind": "^1.0.8", + "call-bound": "^1.0.4", "define-properties": "^1.2.1", - "es-abstract": "^1.23.2", + "es-abstract": "^1.23.9", "es-errors": "^1.3.0", - "es-object-atoms": "^1.0.0", - "es-shim-unscopables": "^1.0.2" + "es-object-atoms": "^1.1.1", + "es-shim-unscopables": "^1.1.0" }, "engines": { "node": ">= 0.4" @@ -1524,6 +1746,13 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/ast-types-flow": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/ast-types-flow/-/ast-types-flow-0.0.8.tgz", + "integrity": "sha512-OH/2E5Fg20h2aPrbe+QL8JZQFko0YZaF+j4mnQ7BGhfavO7OpSLa8a0y9sBwomHdSbkhTS8TQNayBfnW5DwbvQ==", + "dev": true, + "license": "MIT" + }, "node_modules/async-function": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/async-function/-/async-function-1.0.0.tgz", @@ -1550,6 +1779,26 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/axe-core": { + "version": "4.10.3", + "resolved": "https://registry.npmjs.org/axe-core/-/axe-core-4.10.3.tgz", + "integrity": "sha512-Xm7bpRXnDSX2YE2YFfBk2FnF0ep6tmG7xPh8iHee8MIcrgq762Nkce856dYtJYLkuIoYZvGfTs/PbZhideTcEg==", + "dev": true, + "license": "MPL-2.0", + "engines": { + "node": ">=4" + } + }, + "node_modules/axobject-query": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-4.1.0.tgz", + "integrity": "sha512-qIj0G9wZbMGNLjLmg1PT6v2mE9AH2zlnADJD/2tC6E00hgmhUOfEB6greHPAfLRSufHqROIUTkw6E+M3lH0PTQ==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">= 0.4" + } + }, "node_modules/balanced-match": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", @@ -1568,37 +1817,17 @@ "concat-map": "0.0.1" } }, - "node_modules/browserslist": { - "version": "4.25.1", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.25.1.tgz", - "integrity": "sha512-KGj0KoOMXLpSNkkEI6Z6mShmQy0bc1I+T7K9N81k4WWMrfz+6fQ6es80B/YLAeRoKvjYE1YSHHOW1qe9xIVzHw==", + "node_modules/braces": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/browserslist" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], "license": "MIT", "dependencies": { - "caniuse-lite": "^1.0.30001726", - "electron-to-chromium": "^1.5.173", - "node-releases": "^2.0.19", - "update-browserslist-db": "^1.1.3" - }, - "bin": { - "browserslist": "cli.js" + "fill-range": "^7.1.1" }, "engines": { - "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" + "node": ">=8" } }, "node_modules/call-bind": { @@ -1661,20 +1890,10 @@ "node": ">=6" } }, - "node_modules/camelize": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/camelize/-/camelize-1.0.1.tgz", - "integrity": "sha512-dU+Tx2fsypxTgtLoE36npi3UqcjSSMNYfkqgmoEhtZrraP5VWq0K7FkWVTYa8eMPtnU/G2txVsfdCJTn9uzpuQ==", - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/caniuse-lite": { - "version": "1.0.30001727", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001727.tgz", - "integrity": "sha512-pB68nIHmbN6L/4C6MH1DokyR3bYqFwjaSs/sWDHGj4CTcFtQUQMuJftVwWkXq7mNWOybD3KhUv3oWHoGxgP14Q==", - "dev": true, + "version": "1.0.30001741", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001741.tgz", + "integrity": "sha512-QGUGitqsc8ARjLdgAfxETDhRbJ0REsP6O3I96TAth/mVjh2cYzN2u+3AzPP3aVSm2FehEItaJw1xd+IGBXWeSw==", "funding": [ { "type": "opencollective", @@ -1708,11 +1927,31 @@ "url": "https://github.com/chalk/chalk?sponsor=1" } }, + "node_modules/client-only": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/client-only/-/client-only-0.0.1.tgz", + "integrity": "sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA==", + "license": "MIT" + }, + "node_modules/color": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/color/-/color-4.2.3.tgz", + "integrity": "sha512-1rXeuUUiGGrykh+CeBdu5Ie7OJwinCgQY0bc7GCRxy5xVHy+moaqkpL/jqQq0MtQOeYcrqEz4abc5f0KtU7W4A==", + "license": "MIT", + "optional": true, + "dependencies": { + "color-convert": "^2.0.1", + "color-string": "^1.9.0" + }, + "engines": { + "node": ">=12.5.0" + } + }, "node_modules/color-convert": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, + "devOptional": true, "license": "MIT", "dependencies": { "color-name": "~1.1.4" @@ -1725,9 +1964,20 @@ "version": "1.1.4", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true, + "devOptional": true, "license": "MIT" }, + "node_modules/color-string": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/color-string/-/color-string-1.9.1.tgz", + "integrity": "sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg==", + "license": "MIT", + "optional": true, + "dependencies": { + "color-name": "^1.0.0", + "simple-swizzle": "^0.2.2" + } + }, "node_modules/concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", @@ -1735,22 +1985,6 @@ "dev": true, "license": "MIT" }, - "node_modules/convert-source-map": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", - "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", - "dev": true, - "license": "MIT" - }, - "node_modules/cookie": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-1.0.2.tgz", - "integrity": "sha512-9Kr/j4O16ISv8zBBhJoi4bXOYNTkFLOqSL3UDB0njXxCXNezjeyVrJyGOWtgfs/q2km1gwBcfH8q1yEGoMYunA==", - "license": "MIT", - "engines": { - "node": ">=18" - } - }, "node_modules/cross-spawn": { "version": "7.0.6", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", @@ -1766,32 +2000,20 @@ "node": ">= 8" } }, - "node_modules/css-color-keywords": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/css-color-keywords/-/css-color-keywords-1.0.0.tgz", - "integrity": "sha512-FyyrDHZKEjXDpNJYvVsV960FiqQyXc/LlYmsxl2BcdMb2WPx0OGRVgTg55rPSyLSNMqP52R9r8geSp7apN3Ofg==", - "license": "ISC", - "engines": { - "node": ">=4" - } - }, - "node_modules/css-to-react-native": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/css-to-react-native/-/css-to-react-native-3.2.0.tgz", - "integrity": "sha512-e8RKaLXMOFii+02mOlqwjbD00KSEKqblnpO9e++1aXS1fPQOpS1YoqdVHBqPjHNoxeF2mimzVqawm2KCbEdtHQ==", - "license": "MIT", - "dependencies": { - "camelize": "^1.0.0", - "css-color-keywords": "^1.0.0", - "postcss-value-parser": "^4.0.2" - } - }, "node_modules/csstype": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==", + "dev": true, "license": "MIT" }, + "node_modules/damerau-levenshtein": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/damerau-levenshtein/-/damerau-levenshtein-1.0.8.tgz", + "integrity": "sha512-sdQSFB7+llfUcQHUQO3+B8ERRj0Oa4w9POWMI/puGtuf7gFywGmkaLCElnudfTiKZV+NvHqL0ifzdrI8Ro7ESA==", + "dev": true, + "license": "BSD-2-Clause" + }, "node_modules/data-view-buffer": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/data-view-buffer/-/data-view-buffer-1.0.2.tgz", @@ -1907,17 +2129,27 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/detect-libc": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.4.tgz", + "integrity": "sha512-3UDv+G9CsCKO1WKMGw9fwq/SWJYbI0c5Y7LU1AXYoDdbhE2AHQ6N6Nb34sG8Fj7T5APy8qXDCKuuIHd1BR0tVA==", + "license": "Apache-2.0", + "optional": true, + "engines": { + "node": ">=8" + } + }, "node_modules/doctrine": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", - "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", + "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", "dev": true, "license": "Apache-2.0", "dependencies": { "esutils": "^2.0.2" }, "engines": { - "node": ">=6.0.0" + "node": ">=0.10.0" } }, "node_modules/dunder-proto": { @@ -1935,12 +2167,12 @@ "node": ">= 0.4" } }, - "node_modules/electron-to-chromium": { - "version": "1.5.183", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.183.tgz", - "integrity": "sha512-vCrDBYjQCAEefWGjlK3EpoSKfKbT10pR4XXPdn65q7snuNOZnthoVpBfZPykmDapOKfoD+MMIPG8ZjKyyc9oHA==", + "node_modules/emoji-regex": { + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", "dev": true, - "license": "ISC" + "license": "MIT" }, "node_modules/es-abstract": { "version": "1.24.0", @@ -2119,55 +2351,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/esbuild": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.21.5.tgz", - "integrity": "sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==", - "dev": true, - "hasInstallScript": true, - "license": "MIT", - "bin": { - "esbuild": "bin/esbuild" - }, - "engines": { - "node": ">=12" - }, - "optionalDependencies": { - "@esbuild/aix-ppc64": "0.21.5", - "@esbuild/android-arm": "0.21.5", - "@esbuild/android-arm64": "0.21.5", - "@esbuild/android-x64": "0.21.5", - "@esbuild/darwin-arm64": "0.21.5", - "@esbuild/darwin-x64": "0.21.5", - "@esbuild/freebsd-arm64": "0.21.5", - "@esbuild/freebsd-x64": "0.21.5", - "@esbuild/linux-arm": "0.21.5", - "@esbuild/linux-arm64": "0.21.5", - "@esbuild/linux-ia32": "0.21.5", - "@esbuild/linux-loong64": "0.21.5", - "@esbuild/linux-mips64el": "0.21.5", - "@esbuild/linux-ppc64": "0.21.5", - "@esbuild/linux-riscv64": "0.21.5", - "@esbuild/linux-s390x": "0.21.5", - "@esbuild/linux-x64": "0.21.5", - "@esbuild/netbsd-x64": "0.21.5", - "@esbuild/openbsd-x64": "0.21.5", - "@esbuild/sunos-x64": "0.21.5", - "@esbuild/win32-arm64": "0.21.5", - "@esbuild/win32-ia32": "0.21.5", - "@esbuild/win32-x64": "0.21.5" - } - }, - "node_modules/escalade": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", - "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, "node_modules/escape-string-regexp": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", @@ -2182,60 +2365,261 @@ } }, "node_modules/eslint": { - "version": "8.57.1", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.57.1.tgz", - "integrity": "sha512-ypowyDxpVSYpkXr9WPv2PAZCtNip1Mv5KTW0SCurXv/9iOpcrH9PaqUElksqEB6pChqHGDRCFTyrZlGhnLNGiA==", - "deprecated": "This version is no longer supported. Please see https://eslint.org/version-support for other options.", + "version": "9.35.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.35.0.tgz", + "integrity": "sha512-QePbBFMJFjgmlE+cXAlbHZbHpdFVS2E/6vzCy7aKlebddvl1vadiC4JFV5u/wqTkNUwEV8WrQi257jf5f06hrg==", "dev": true, "license": "MIT", "dependencies": { - "@eslint-community/eslint-utils": "^4.2.0", - "@eslint-community/regexpp": "^4.6.1", - "@eslint/eslintrc": "^2.1.4", - "@eslint/js": "8.57.1", - "@humanwhocodes/config-array": "^0.13.0", + "@eslint-community/eslint-utils": "^4.8.0", + "@eslint-community/regexpp": "^4.12.1", + "@eslint/config-array": "^0.21.0", + "@eslint/config-helpers": "^0.3.1", + "@eslint/core": "^0.15.2", + "@eslint/eslintrc": "^3.3.1", + "@eslint/js": "9.35.0", + "@eslint/plugin-kit": "^0.3.5", + "@humanfs/node": "^0.16.6", "@humanwhocodes/module-importer": "^1.0.1", - "@nodelib/fs.walk": "^1.2.8", - "@ungap/structured-clone": "^1.2.0", + "@humanwhocodes/retry": "^0.4.2", + "@types/estree": "^1.0.6", + "@types/json-schema": "^7.0.15", "ajv": "^6.12.4", "chalk": "^4.0.0", - "cross-spawn": "^7.0.2", + "cross-spawn": "^7.0.6", "debug": "^4.3.2", - "doctrine": "^3.0.0", "escape-string-regexp": "^4.0.0", - "eslint-scope": "^7.2.2", - "eslint-visitor-keys": "^3.4.3", - "espree": "^9.6.1", - "esquery": "^1.4.2", + "eslint-scope": "^8.4.0", + "eslint-visitor-keys": "^4.2.1", + "espree": "^10.4.0", + "esquery": "^1.5.0", "esutils": "^2.0.2", "fast-deep-equal": "^3.1.3", - "file-entry-cache": "^6.0.1", + "file-entry-cache": "^8.0.0", "find-up": "^5.0.0", "glob-parent": "^6.0.2", - "globals": "^13.19.0", - "graphemer": "^1.4.0", "ignore": "^5.2.0", "imurmurhash": "^0.1.4", "is-glob": "^4.0.0", - "is-path-inside": "^3.0.3", - "js-yaml": "^4.1.0", "json-stable-stringify-without-jsonify": "^1.0.1", - "levn": "^0.4.1", "lodash.merge": "^4.6.2", "minimatch": "^3.1.2", "natural-compare": "^1.4.0", - "optionator": "^0.9.3", - "strip-ansi": "^6.0.1", - "text-table": "^0.2.0" + "optionator": "^0.9.3" }, "bin": { "eslint": "bin/eslint.js" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { - "url": "https://opencollective.com/eslint" + "url": "https://eslint.org/donate" + }, + "peerDependencies": { + "jiti": "*" + }, + "peerDependenciesMeta": { + "jiti": { + "optional": true + } + } + }, + "node_modules/eslint-config-next": { + "version": "15.5.3", + "resolved": "https://registry.npmjs.org/eslint-config-next/-/eslint-config-next-15.5.3.tgz", + "integrity": "sha512-e6j+QhQFOr5pfsc8VJbuTD9xTXJaRvMHYjEeLPA2pFkheNlgPLCkxdvhxhfuM4KGcqSZj2qEnpHisdTVs3BxuQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@next/eslint-plugin-next": "15.5.3", + "@rushstack/eslint-patch": "^1.10.3", + "@typescript-eslint/eslint-plugin": "^5.4.2 || ^6.0.0 || ^7.0.0 || ^8.0.0", + "@typescript-eslint/parser": "^5.4.2 || ^6.0.0 || ^7.0.0 || ^8.0.0", + "eslint-import-resolver-node": "^0.3.6", + "eslint-import-resolver-typescript": "^3.5.2", + "eslint-plugin-import": "^2.31.0", + "eslint-plugin-jsx-a11y": "^6.10.0", + "eslint-plugin-react": "^7.37.0", + "eslint-plugin-react-hooks": "^5.0.0" + }, + "peerDependencies": { + "eslint": "^7.23.0 || ^8.0.0 || ^9.0.0", + "typescript": ">=3.3.1" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/eslint-import-resolver-node": { + "version": "0.3.9", + "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.9.tgz", + "integrity": "sha512-WFj2isz22JahUv+B788TlO3N6zL3nNJGU8CcZbPZvVEkBPaJdCV4vy5wyghty5ROFbCRnm132v8BScu5/1BQ8g==", + "dev": true, + "license": "MIT", + "dependencies": { + "debug": "^3.2.7", + "is-core-module": "^2.13.0", + "resolve": "^1.22.4" + } + }, + "node_modules/eslint-import-resolver-node/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/eslint-import-resolver-typescript": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/eslint-import-resolver-typescript/-/eslint-import-resolver-typescript-3.10.1.tgz", + "integrity": "sha512-A1rHYb06zjMGAxdLSkN2fXPBwuSaQ0iO5M/hdyS0Ajj1VBaRp0sPD3dn1FhME3c/JluGFbwSxyCfqdSbtQLAHQ==", + "dev": true, + "license": "ISC", + "dependencies": { + "@nolyfill/is-core-module": "1.0.39", + "debug": "^4.4.0", + "get-tsconfig": "^4.10.0", + "is-bun-module": "^2.0.0", + "stable-hash": "^0.0.5", + "tinyglobby": "^0.2.13", + "unrs-resolver": "^1.6.2" + }, + "engines": { + "node": "^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint-import-resolver-typescript" + }, + "peerDependencies": { + "eslint": "*", + "eslint-plugin-import": "*", + "eslint-plugin-import-x": "*" + }, + "peerDependenciesMeta": { + "eslint-plugin-import": { + "optional": true + }, + "eslint-plugin-import-x": { + "optional": true + } + } + }, + "node_modules/eslint-module-utils": { + "version": "2.12.1", + "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.12.1.tgz", + "integrity": "sha512-L8jSWTze7K2mTg0vos/RuLRS5soomksDPoJLXIslC7c8Wmut3bx7CPpJijDcBZtxQ5lrbUdM+s0OlNbz0DCDNw==", + "dev": true, + "license": "MIT", + "dependencies": { + "debug": "^3.2.7" + }, + "engines": { + "node": ">=4" + }, + "peerDependenciesMeta": { + "eslint": { + "optional": true + } + } + }, + "node_modules/eslint-module-utils/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/eslint-plugin-import": { + "version": "2.32.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.32.0.tgz", + "integrity": "sha512-whOE1HFo/qJDyX4SnXzP4N6zOWn79WhnCUY/iDR0mPfQZO8wcYE4JClzI2oZrhBnnMUCBCHZhO6VQyoBU95mZA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@rtsao/scc": "^1.1.0", + "array-includes": "^3.1.9", + "array.prototype.findlastindex": "^1.2.6", + "array.prototype.flat": "^1.3.3", + "array.prototype.flatmap": "^1.3.3", + "debug": "^3.2.7", + "doctrine": "^2.1.0", + "eslint-import-resolver-node": "^0.3.9", + "eslint-module-utils": "^2.12.1", + "hasown": "^2.0.2", + "is-core-module": "^2.16.1", + "is-glob": "^4.0.3", + "minimatch": "^3.1.2", + "object.fromentries": "^2.0.8", + "object.groupby": "^1.0.3", + "object.values": "^1.2.1", + "semver": "^6.3.1", + "string.prototype.trimend": "^1.0.9", + "tsconfig-paths": "^3.15.0" + }, + "engines": { + "node": ">=4" + }, + "peerDependencies": { + "eslint": "^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8 || ^9" + } + }, + "node_modules/eslint-plugin-import/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/eslint-plugin-import/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/eslint-plugin-jsx-a11y": { + "version": "6.10.2", + "resolved": "https://registry.npmjs.org/eslint-plugin-jsx-a11y/-/eslint-plugin-jsx-a11y-6.10.2.tgz", + "integrity": "sha512-scB3nz4WmG75pV8+3eRUQOHZlNSUhFNq37xnpgRkCCELU3XMvXAxLk1eqWWyE22Ki4Q01Fnsw9BA3cJHDPgn2Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "aria-query": "^5.3.2", + "array-includes": "^3.1.8", + "array.prototype.flatmap": "^1.3.2", + "ast-types-flow": "^0.0.8", + "axe-core": "^4.10.0", + "axobject-query": "^4.1.0", + "damerau-levenshtein": "^1.0.8", + "emoji-regex": "^9.2.2", + "hasown": "^2.0.2", + "jsx-ast-utils": "^3.3.5", + "language-tags": "^1.0.9", + "minimatch": "^3.1.2", + "object.fromentries": "^2.0.8", + "safe-regex-test": "^1.0.3", + "string.prototype.includes": "^2.0.1" + }, + "engines": { + "node": ">=4.0" + }, + "peerDependencies": { + "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9" } }, "node_modules/eslint-plugin-react": { @@ -2272,45 +2656,50 @@ } }, "node_modules/eslint-plugin-react-hooks": { - "version": "4.6.2", - "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-4.6.2.tgz", - "integrity": "sha512-QzliNJq4GinDBcD8gPB5v0wh6g8q3SUi6EFF0x8N/BL9PoVs0atuGc47ozMRyOWAKdwaZ5OnbOEa3WR+dSGKuQ==", + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-5.2.0.tgz", + "integrity": "sha512-+f15FfK64YQwZdJNELETdn5ibXEUQmW1DZL6KXhNnc2heoy/sg9VJJeT7n8TlMWouzWqSWavFkIhHyIbIAEapg==", "dev": true, "license": "MIT", "engines": { "node": ">=10" }, "peerDependencies": { - "eslint": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0" + "eslint": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0 || ^9.0.0" } }, - "node_modules/eslint-plugin-react-refresh": { - "version": "0.4.20", - "resolved": "https://registry.npmjs.org/eslint-plugin-react-refresh/-/eslint-plugin-react-refresh-0.4.20.tgz", - "integrity": "sha512-XpbHQ2q5gUF8BGOX4dHe+71qoirYMhApEPZ7sfhF/dNnOF1UXnCMGZf79SFTBO7Bz5YEIT4TMieSlJBWhP9WBA==", + "node_modules/eslint-plugin-react/node_modules/resolve": { + "version": "2.0.0-next.5", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-2.0.0-next.5.tgz", + "integrity": "sha512-U7WjGVG9sH8tvjW5SmGbQuui75FiyjAX72HX15DwBBwF9dNiQZRQAg9nnPhYy+TUnE0+VcrttuvNI8oSxZcocA==", "dev": true, "license": "MIT", - "peerDependencies": { - "eslint": ">=8.40" + "dependencies": { + "is-core-module": "^2.13.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/eslint-plugin-react/node_modules/doctrine": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", - "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", + "node_modules/eslint-plugin-react/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", "dev": true, - "license": "Apache-2.0", - "dependencies": { - "esutils": "^2.0.2" - }, - "engines": { - "node": ">=0.10.0" + "license": "ISC", + "bin": { + "semver": "bin/semver.js" } }, "node_modules/eslint-scope": { - "version": "7.2.2", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz", - "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==", + "version": "8.4.0", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.4.0.tgz", + "integrity": "sha512-sNXOfKCn74rt8RICKMvJS7XKV/Xk9kA7DyJr8mJik3S7Cwgy3qlkkmyS2uQB3jiJg6VNdZd/pDBJu0nvG2NlTg==", "dev": true, "license": "BSD-2-Clause", "dependencies": { @@ -2318,38 +2707,38 @@ "estraverse": "^5.2.0" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "url": "https://opencollective.com/eslint" } }, "node_modules/eslint-visitor-keys": { - "version": "3.4.3", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", - "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz", + "integrity": "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==", "dev": true, "license": "Apache-2.0", "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "url": "https://opencollective.com/eslint" } }, "node_modules/espree": { - "version": "9.6.1", - "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz", - "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==", + "version": "10.4.0", + "resolved": "https://registry.npmjs.org/espree/-/espree-10.4.0.tgz", + "integrity": "sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ==", "dev": true, "license": "BSD-2-Clause", "dependencies": { - "acorn": "^8.9.0", + "acorn": "^8.15.0", "acorn-jsx": "^5.3.2", - "eslint-visitor-keys": "^3.4.1" + "eslint-visitor-keys": "^4.2.1" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "url": "https://opencollective.com/eslint" @@ -2408,6 +2797,36 @@ "dev": true, "license": "MIT" }, + "node_modules/fast-glob": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.1.tgz", + "integrity": "sha512-kNFPyjhh5cKjrUltxs+wFx+ZkbRaxxmZ+X0ZU31SOsxCEtP9VPgtq2teZw1DebupL5GmDaNQ6yKMMVcM41iqDg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.4" + }, + "engines": { + "node": ">=8.6.0" + } + }, + "node_modules/fast-glob/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/fast-json-stable-stringify": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", @@ -2433,16 +2852,29 @@ } }, "node_modules/file-entry-cache": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", - "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz", + "integrity": "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "flat-cache": "^4.0.0" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/fill-range": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", "dev": true, "license": "MIT", "dependencies": { - "flat-cache": "^3.0.4" + "to-regex-range": "^5.0.1" }, "engines": { - "node": "^10.12.0 || >=12.0.0" + "node": ">=8" } }, "node_modules/find-up": { @@ -2463,18 +2895,17 @@ } }, "node_modules/flat-cache": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.2.0.tgz", - "integrity": "sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==", + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-4.0.1.tgz", + "integrity": "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==", "dev": true, "license": "MIT", "dependencies": { "flatted": "^3.2.9", - "keyv": "^4.5.3", - "rimraf": "^3.0.2" + "keyv": "^4.5.4" }, "engines": { - "node": "^10.12.0 || >=12.0.0" + "node": ">=16" } }, "node_modules/flatted": { @@ -2500,28 +2931,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", - "dev": true, - "license": "ISC" - }, - "node_modules/fsevents": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", - "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", - "dev": true, - "hasInstallScript": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": "^8.16.0 || ^10.6.0 || >=11.0.0" - } - }, "node_modules/function-bind": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", @@ -2563,16 +2972,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/gensync": { - "version": "1.0.0-beta.2", - "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", - "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6.9.0" - } - }, "node_modules/get-intrinsic": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", @@ -2630,26 +3029,17 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "deprecated": "Glob versions prior to v9 are no longer supported", + "node_modules/get-tsconfig": { + "version": "4.10.1", + "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.10.1.tgz", + "integrity": "sha512-auHyJ4AgMz7vgS8Hp3N6HXSmlMdUyhSUrfBF16w153rxtLIEOE+HGqaBppczZvnHLqQJfiHotCYpNhl0lUROFQ==", "dev": true, - "license": "ISC", + "license": "MIT", "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, - "engines": { - "node": "*" + "resolve-pkg-maps": "^1.0.0" }, "funding": { - "url": "https://github.com/sponsors/isaacs" + "url": "https://github.com/privatenumber/get-tsconfig?sponsor=1" } }, "node_modules/glob-parent": { @@ -2666,16 +3056,13 @@ } }, "node_modules/globals": { - "version": "13.24.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", - "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", + "version": "14.0.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-14.0.0.tgz", + "integrity": "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==", "dev": true, "license": "MIT", - "dependencies": { - "type-fest": "^0.20.2" - }, "engines": { - "node": ">=8" + "node": ">=18" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" @@ -2849,25 +3236,6 @@ "node": ">=0.8.19" } }, - "node_modules/inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", - "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.", - "dev": true, - "license": "ISC", - "dependencies": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "node_modules/inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", - "dev": true, - "license": "ISC" - }, "node_modules/internal-slot": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.1.0.tgz", @@ -2901,6 +3269,13 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/is-arrayish": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.3.2.tgz", + "integrity": "sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==", + "license": "MIT", + "optional": true + }, "node_modules/is-async-function": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/is-async-function/-/is-async-function-2.1.1.tgz", @@ -2954,6 +3329,16 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/is-bun-module": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-bun-module/-/is-bun-module-2.0.0.tgz", + "integrity": "sha512-gNCGbnnnnFAUGKeZ9PdbyeGYJqewpmc2aKHUEMO5nQPWU9lOmv7jcmQIv+qHD8fXW6W7qfuCwX4rY9LNRjXrkQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "semver": "^7.7.1" + } + }, "node_modules/is-callable": { "version": "1.2.7", "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", @@ -3102,6 +3487,16 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.12.0" + } + }, "node_modules/is-number-object": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.1.1.tgz", @@ -3119,16 +3514,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/is-path-inside": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", - "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, "node_modules/is-regex": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.2.1.tgz", @@ -3310,6 +3695,7 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true, "license": "MIT" }, "node_modules/js-yaml": { @@ -3325,19 +3711,6 @@ "js-yaml": "bin/js-yaml.js" } }, - "node_modules/jsesc": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz", - "integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==", - "dev": true, - "license": "MIT", - "bin": { - "jsesc": "bin/jsesc" - }, - "engines": { - "node": ">=6" - } - }, "node_modules/json-buffer": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", @@ -3360,16 +3733,16 @@ "license": "MIT" }, "node_modules/json5": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", - "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz", + "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==", "dev": true, "license": "MIT", + "dependencies": { + "minimist": "^1.2.0" + }, "bin": { "json5": "lib/cli.js" - }, - "engines": { - "node": ">=6" } }, "node_modules/jsx-ast-utils": { @@ -3398,6 +3771,26 @@ "json-buffer": "3.0.1" } }, + "node_modules/language-subtag-registry": { + "version": "0.3.23", + "resolved": "https://registry.npmjs.org/language-subtag-registry/-/language-subtag-registry-0.3.23.tgz", + "integrity": "sha512-0K65Lea881pHotoGEa5gDlMxt3pctLi2RplBb7Ezh4rRdLEOtgi7n4EwK9lamnUCkKBqaeKRVebTq6BAxSkpXQ==", + "dev": true, + "license": "CC0-1.0" + }, + "node_modules/language-tags": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/language-tags/-/language-tags-1.0.9.tgz", + "integrity": "sha512-MbjN408fEndfiQXbFQ1vnd+1NoLDsnQW41410oQBXiyXDMYH5z505juWa4KUE1LqxRC7DgOgZDbKLxHIwm27hA==", + "dev": true, + "license": "MIT", + "dependencies": { + "language-subtag-registry": "^0.3.20" + }, + "engines": { + "node": ">=0.10" + } + }, "node_modules/levn": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", @@ -3439,6 +3832,7 @@ "version": "1.4.0", "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", + "dev": true, "license": "MIT", "dependencies": { "js-tokens": "^3.0.0 || ^4.0.0" @@ -3447,16 +3841,6 @@ "loose-envify": "cli.js" } }, - "node_modules/lru-cache": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", - "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", - "dev": true, - "license": "ISC", - "dependencies": { - "yallist": "^3.0.2" - } - }, "node_modules/math-intrinsics": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", @@ -3467,6 +3851,30 @@ "node": ">= 0.4" } }, + "node_modules/merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 8" + } + }, + "node_modules/micromatch": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", + "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", + "dev": true, + "license": "MIT", + "dependencies": { + "braces": "^3.0.3", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=8.6" + } + }, "node_modules/minimatch": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", @@ -3480,6 +3888,16 @@ "node": "*" } }, + "node_modules/minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/ms": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", @@ -3505,6 +3923,22 @@ "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" } }, + "node_modules/napi-postinstall": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/napi-postinstall/-/napi-postinstall-0.3.3.tgz", + "integrity": "sha512-uTp172LLXSxuSYHv/kou+f6KW3SMppU9ivthaVTXian9sOt3XM/zHYHpRZiLgQoxeWfYUnslNWQHF1+G71xcow==", + "dev": true, + "license": "MIT", + "bin": { + "napi-postinstall": "lib/cli.js" + }, + "engines": { + "node": "^12.20.0 || ^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/napi-postinstall" + } + }, "node_modules/natural-compare": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", @@ -3512,12 +3946,57 @@ "dev": true, "license": "MIT" }, - "node_modules/node-releases": { - "version": "2.0.19", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.19.tgz", - "integrity": "sha512-xxOWJsBKtzAq7DY0J+DTzuz58K8e7sJbdgwkbMWQe8UYB6ekmsQ45q0M/tJDsGaZmbC+l7n57UV8Hl5tHxO9uw==", - "dev": true, - "license": "MIT" + "node_modules/next": { + "version": "15.5.3", + "resolved": "https://registry.npmjs.org/next/-/next-15.5.3.tgz", + "integrity": "sha512-r/liNAx16SQj4D+XH/oI1dlpv9tdKJ6cONYPwwcCC46f2NjpaRWY+EKCzULfgQYV6YKXjHBchff2IZBSlZmJNw==", + "license": "MIT", + "dependencies": { + "@next/env": "15.5.3", + "@swc/helpers": "0.5.15", + "caniuse-lite": "^1.0.30001579", + "postcss": "8.4.31", + "styled-jsx": "5.1.6" + }, + "bin": { + "next": "dist/bin/next" + }, + "engines": { + "node": "^18.18.0 || ^19.8.0 || >= 20.0.0" + }, + "optionalDependencies": { + "@next/swc-darwin-arm64": "15.5.3", + "@next/swc-darwin-x64": "15.5.3", + "@next/swc-linux-arm64-gnu": "15.5.3", + "@next/swc-linux-arm64-musl": "15.5.3", + "@next/swc-linux-x64-gnu": "15.5.3", + "@next/swc-linux-x64-musl": "15.5.3", + "@next/swc-win32-arm64-msvc": "15.5.3", + "@next/swc-win32-x64-msvc": "15.5.3", + "sharp": "^0.34.3" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.1.0", + "@playwright/test": "^1.51.1", + "babel-plugin-react-compiler": "*", + "react": "^18.2.0 || 19.0.0-rc-de68d2f4-20241204 || ^19.0.0", + "react-dom": "^18.2.0 || 19.0.0-rc-de68d2f4-20241204 || ^19.0.0", + "sass": "^1.3.0" + }, + "peerDependenciesMeta": { + "@opentelemetry/api": { + "optional": true + }, + "@playwright/test": { + "optional": true + }, + "babel-plugin-react-compiler": { + "optional": true + }, + "sass": { + "optional": true + } + } }, "node_modules/object-assign": { "version": "4.1.1", @@ -3608,6 +4087,21 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/object.groupby": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/object.groupby/-/object.groupby-1.0.3.tgz", + "integrity": "sha512-+Lhy3TQTuzXI5hevh8sBGqbmurHbbIjAi0Z4S63nthVLmLxfbj4T54a4CfZrXIrt9iP4mVAPYMo/v99taj3wjQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/object.values": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.2.1.tgz", @@ -3627,16 +4121,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", - "dev": true, - "license": "ISC", - "dependencies": { - "wrappy": "1" - } - }, "node_modules/optionator": { "version": "0.9.4", "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", @@ -3728,16 +4212,6 @@ "node": ">=8" } }, - "node_modules/path-is-absolute": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/path-key": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", @@ -3761,6 +4235,19 @@ "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", "license": "ISC" }, + "node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, "node_modules/possible-typed-array-names": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.1.0.tgz", @@ -3772,10 +4259,9 @@ } }, "node_modules/postcss": { - "version": "8.5.6", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.6.tgz", - "integrity": "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==", - "dev": true, + "version": "8.4.31", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.31.tgz", + "integrity": "sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ==", "funding": [ { "type": "opencollective", @@ -3792,20 +4278,14 @@ ], "license": "MIT", "dependencies": { - "nanoid": "^3.3.11", - "picocolors": "^1.1.1", - "source-map-js": "^1.2.1" + "nanoid": "^3.3.6", + "picocolors": "^1.0.0", + "source-map-js": "^1.0.2" }, "engines": { "node": "^10 || ^12 || >=14" } }, - "node_modules/postcss-value-parser": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", - "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", - "license": "MIT" - }, "node_modules/prelude-ls": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", @@ -3850,95 +4330,43 @@ }, { "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "license": "MIT" - }, - "node_modules/react": { - "version": "18.3.1", - "resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz", - "integrity": "sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==", - "license": "MIT", - "dependencies": { - "loose-envify": "^1.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/react-dom": { - "version": "18.3.1", - "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.3.1.tgz", - "integrity": "sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==", - "license": "MIT", - "dependencies": { - "loose-envify": "^1.1.0", - "scheduler": "^0.23.2" - }, - "peerDependencies": { - "react": "^18.3.1" - } - }, - "node_modules/react-hook-form": { - "version": "7.60.0", - "resolved": "https://registry.npmjs.org/react-hook-form/-/react-hook-form-7.60.0.tgz", - "integrity": "sha512-SBrYOvMbDB7cV8ZfNpaiLcgjH/a1c7aK0lK+aNigpf4xWLO8q+o4tcvVurv3c4EOyzn/3dCsYt4GKD42VvJ/+A==", - "license": "MIT", - "engines": { - "node": ">=18.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/react-hook-form" - }, - "peerDependencies": { - "react": "^16.8.0 || ^17 || ^18 || ^19" - } - }, - "node_modules/react-is": { - "version": "16.13.1", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", - "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==", - "dev": true, + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], "license": "MIT" }, - "node_modules/react-refresh": { - "version": "0.17.0", - "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.17.0.tgz", - "integrity": "sha512-z6F7K9bV85EfseRCp2bzrpyQ0Gkw1uLoCel9XBVWPg/TjRj94SkJzUTGfOa4bs7iJvBWtQG0Wq7wnI0syw3EBQ==", - "dev": true, + "node_modules/react": { + "version": "19.1.0", + "resolved": "https://registry.npmjs.org/react/-/react-19.1.0.tgz", + "integrity": "sha512-FS+XFBNvn3GTAWq26joslQgWNoFu08F4kl0J4CgdNKADkdSGXQyTCnKteIAJy96Br6YbpEU1LSzV5dYtjMkMDg==", "license": "MIT", "engines": { "node": ">=0.10.0" } }, - "node_modules/react-router": { - "version": "7.6.3", - "resolved": "https://registry.npmjs.org/react-router/-/react-router-7.6.3.tgz", - "integrity": "sha512-zf45LZp5skDC6I3jDLXQUu0u26jtuP4lEGbc7BbdyxenBN1vJSTA18czM2D+h5qyMBuMrD+9uB+mU37HIoKGRA==", + "node_modules/react-dom": { + "version": "19.1.0", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.1.0.tgz", + "integrity": "sha512-Xs1hdnE+DyKgeHJeJznQmYMIBG3TKIHJJT95Q58nHLSrElKlGQqDTR2HQ9fx5CN/Gk6Vh/kupBTDLU11/nDk/g==", "license": "MIT", "dependencies": { - "cookie": "^1.0.1", - "set-cookie-parser": "^2.6.0" - }, - "engines": { - "node": ">=20.0.0" + "scheduler": "^0.26.0" }, "peerDependencies": { - "react": ">=18", - "react-dom": ">=18" - }, - "peerDependenciesMeta": { - "react-dom": { - "optional": true - } + "react": "^19.1.0" } }, + "node_modules/react-is": { + "version": "16.13.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", + "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==", + "dev": true, + "license": "MIT" + }, "node_modules/reflect.getprototypeof": { "version": "1.0.10", "resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.10.tgz", @@ -3984,19 +4412,22 @@ } }, "node_modules/resolve": { - "version": "2.0.0-next.5", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-2.0.0-next.5.tgz", - "integrity": "sha512-U7WjGVG9sH8tvjW5SmGbQuui75FiyjAX72HX15DwBBwF9dNiQZRQAg9nnPhYy+TUnE0+VcrttuvNI8oSxZcocA==", + "version": "1.22.10", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.10.tgz", + "integrity": "sha512-NPRy+/ncIMeDlTAsuqwKIiferiawhefFJtkNSW0qZJEqMEb+qBt/77B/jGeeek+F0uOeN05CDa6HXbbIgtVX4w==", "dev": true, "license": "MIT", "dependencies": { - "is-core-module": "^2.13.0", + "is-core-module": "^2.16.0", "path-parse": "^1.0.7", "supports-preserve-symlinks-flag": "^1.0.0" }, "bin": { "resolve": "bin/resolve" }, + "engines": { + "node": ">= 0.4" + }, "funding": { "url": "https://github.com/sponsors/ljharb" } @@ -4011,6 +4442,16 @@ "node": ">=4" } }, + "node_modules/resolve-pkg-maps": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz", + "integrity": "sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1" + } + }, "node_modules/reusify": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.1.0.tgz", @@ -4022,63 +4463,6 @@ "node": ">=0.10.0" } }, - "node_modules/rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "deprecated": "Rimraf versions prior to v4 are no longer supported", - "dev": true, - "license": "ISC", - "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/rollup": { - "version": "4.45.0", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.45.0.tgz", - "integrity": "sha512-WLjEcJRIo7i3WDDgOIJqVI2d+lAC3EwvOGy+Xfq6hs+GQuAA4Di/H72xmXkOhrIWFg2PFYSKZYfH0f4vfKXN4A==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/estree": "1.0.8" - }, - "bin": { - "rollup": "dist/bin/rollup" - }, - "engines": { - "node": ">=18.0.0", - "npm": ">=8.0.0" - }, - "optionalDependencies": { - "@rollup/rollup-android-arm-eabi": "4.45.0", - "@rollup/rollup-android-arm64": "4.45.0", - "@rollup/rollup-darwin-arm64": "4.45.0", - "@rollup/rollup-darwin-x64": "4.45.0", - "@rollup/rollup-freebsd-arm64": "4.45.0", - "@rollup/rollup-freebsd-x64": "4.45.0", - "@rollup/rollup-linux-arm-gnueabihf": "4.45.0", - "@rollup/rollup-linux-arm-musleabihf": "4.45.0", - "@rollup/rollup-linux-arm64-gnu": "4.45.0", - "@rollup/rollup-linux-arm64-musl": "4.45.0", - "@rollup/rollup-linux-loongarch64-gnu": "4.45.0", - "@rollup/rollup-linux-powerpc64le-gnu": "4.45.0", - "@rollup/rollup-linux-riscv64-gnu": "4.45.0", - "@rollup/rollup-linux-riscv64-musl": "4.45.0", - "@rollup/rollup-linux-s390x-gnu": "4.45.0", - "@rollup/rollup-linux-x64-gnu": "4.45.0", - "@rollup/rollup-linux-x64-musl": "4.45.0", - "@rollup/rollup-win32-arm64-msvc": "4.45.0", - "@rollup/rollup-win32-ia32-msvc": "4.45.0", - "@rollup/rollup-win32-x64-msvc": "4.45.0", - "fsevents": "~2.3.2" - } - }, "node_modules/run-parallel": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", @@ -4159,30 +4543,24 @@ } }, "node_modules/scheduler": { - "version": "0.23.2", - "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.2.tgz", - "integrity": "sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ==", - "license": "MIT", - "dependencies": { - "loose-envify": "^1.1.0" - } + "version": "0.26.0", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.26.0.tgz", + "integrity": "sha512-NlHwttCI/l5gCPR3D1nNXtWABUmBwvZpEQiD4IXSbIDq8BzLIK/7Ir5gTFSGZDUu37K5cMNp0hFtzO38sC7gWA==", + "license": "MIT" }, "node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true, + "version": "7.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz", + "integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==", + "devOptional": true, "license": "ISC", "bin": { "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" } }, - "node_modules/set-cookie-parser": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/set-cookie-parser/-/set-cookie-parser-2.7.1.tgz", - "integrity": "sha512-IOc8uWeOZgnb3ptbCURJWNjWUPcO3ZnTTdzsurqERrP6nPyv+paC55vJM0LpOlT2ne+Ix+9+CRG1MNLlyZ4GjQ==", - "license": "MIT" - }, "node_modules/set-function-length": { "version": "1.2.2", "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", @@ -4232,11 +4610,48 @@ "node": ">= 0.4" } }, - "node_modules/shallowequal": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/shallowequal/-/shallowequal-1.1.0.tgz", - "integrity": "sha512-y0m1JoUZSlPAjXVtPPW70aZWfIL/dSP7AFkRnniLCrK/8MDKog3TySTBmckD+RObVxH0v4Tox67+F14PdED2oQ==", - "license": "MIT" + "node_modules/sharp": { + "version": "0.34.3", + "resolved": "https://registry.npmjs.org/sharp/-/sharp-0.34.3.tgz", + "integrity": "sha512-eX2IQ6nFohW4DbvHIOLRB3MHFpYqaqvXd3Tp5e/T/dSH83fxaNJQRvDMhASmkNTsNTVF2/OOopzRCt7xokgPfg==", + "hasInstallScript": true, + "license": "Apache-2.0", + "optional": true, + "dependencies": { + "color": "^4.2.3", + "detect-libc": "^2.0.4", + "semver": "^7.7.2" + }, + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-darwin-arm64": "0.34.3", + "@img/sharp-darwin-x64": "0.34.3", + "@img/sharp-libvips-darwin-arm64": "1.2.0", + "@img/sharp-libvips-darwin-x64": "1.2.0", + "@img/sharp-libvips-linux-arm": "1.2.0", + "@img/sharp-libvips-linux-arm64": "1.2.0", + "@img/sharp-libvips-linux-ppc64": "1.2.0", + "@img/sharp-libvips-linux-s390x": "1.2.0", + "@img/sharp-libvips-linux-x64": "1.2.0", + "@img/sharp-libvips-linuxmusl-arm64": "1.2.0", + "@img/sharp-libvips-linuxmusl-x64": "1.2.0", + "@img/sharp-linux-arm": "0.34.3", + "@img/sharp-linux-arm64": "0.34.3", + "@img/sharp-linux-ppc64": "0.34.3", + "@img/sharp-linux-s390x": "0.34.3", + "@img/sharp-linux-x64": "0.34.3", + "@img/sharp-linuxmusl-arm64": "0.34.3", + "@img/sharp-linuxmusl-x64": "0.34.3", + "@img/sharp-wasm32": "0.34.3", + "@img/sharp-win32-arm64": "0.34.3", + "@img/sharp-win32-ia32": "0.34.3", + "@img/sharp-win32-x64": "0.34.3" + } }, "node_modules/shebang-command": { "version": "2.0.0", @@ -4337,6 +4752,16 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/simple-swizzle": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.2.tgz", + "integrity": "sha512-JA//kQgZtbuY83m+xT+tXJkmJncGMTFT+C+g2h2R9uxkYIrE2yy9sgmcLhCnw57/WSD+Eh3J97FPEDFnbXnDUg==", + "license": "MIT", + "optional": true, + "dependencies": { + "is-arrayish": "^0.3.1" + } + }, "node_modules/source-map-js": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", @@ -4346,6 +4771,13 @@ "node": ">=0.10.0" } }, + "node_modules/stable-hash": { + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/stable-hash/-/stable-hash-0.0.5.tgz", + "integrity": "sha512-+L3ccpzibovGXFK+Ap/f8LOS0ahMrHTf3xu7mMLSpEGU0EO9ucaysSylKo9eRDFNhWve/y275iPmIZ4z39a9iA==", + "dev": true, + "license": "MIT" + }, "node_modules/stop-iteration-iterator": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/stop-iteration-iterator/-/stop-iteration-iterator-1.1.0.tgz", @@ -4360,6 +4792,21 @@ "node": ">= 0.4" } }, + "node_modules/string.prototype.includes": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/string.prototype.includes/-/string.prototype.includes-2.0.1.tgz", + "integrity": "sha512-o7+c9bW6zpAdJHTtujeePODAhkuicdAryFsfVKwA+wGw89wJ4GTY484WTucM9hLtDEOpOvI+aHnzqnC5lHp4Rg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.3" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/string.prototype.matchall": { "version": "4.0.12", "resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.12.tgz", @@ -4458,17 +4905,14 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "node_modules/strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==", "dev": true, "license": "MIT", - "dependencies": { - "ansi-regex": "^5.0.1" - }, "engines": { - "node": ">=8" + "node": ">=4" } }, "node_modules/strip-json-comments": { @@ -4484,68 +4928,29 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/styled-components": { - "version": "6.1.19", - "resolved": "https://registry.npmjs.org/styled-components/-/styled-components-6.1.19.tgz", - "integrity": "sha512-1v/e3Dl1BknC37cXMhwGomhO8AkYmN41CqyX9xhUDxry1ns3BFQy2lLDRQXJRdVVWB9OHemv/53xaStimvWyuA==", + "node_modules/styled-jsx": { + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/styled-jsx/-/styled-jsx-5.1.6.tgz", + "integrity": "sha512-qSVyDTeMotdvQYoHWLNGwRFJHC+i+ZvdBRYosOFgC+Wg1vx4frN2/RG/NA7SYqqvKNLf39P2LSRA2pu6n0XYZA==", "license": "MIT", "dependencies": { - "@emotion/is-prop-valid": "1.2.2", - "@emotion/unitless": "0.8.1", - "@types/stylis": "4.2.5", - "css-to-react-native": "3.2.0", - "csstype": "3.1.3", - "postcss": "8.4.49", - "shallowequal": "1.1.0", - "stylis": "4.3.2", - "tslib": "2.6.2" + "client-only": "0.0.1" }, "engines": { - "node": ">= 16" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/styled-components" + "node": ">= 12.0.0" }, "peerDependencies": { - "react": ">= 16.8.0", - "react-dom": ">= 16.8.0" - } - }, - "node_modules/styled-components/node_modules/postcss": { - "version": "8.4.49", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.49.tgz", - "integrity": "sha512-OCVPnIObs4N29kxTjzLfUryOkvZEq+pf8jTF0lg8E7uETuWHA+v7j3c/xJmiqpX450191LlmZfUKkXxkTry7nA==", - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/postcss" + "react": ">= 16.8.0 || 17.x.x || ^18.0.0-0 || ^19.0.0-0" + }, + "peerDependenciesMeta": { + "@babel/core": { + "optional": true }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" + "babel-plugin-macros": { + "optional": true } - ], - "license": "MIT", - "dependencies": { - "nanoid": "^3.3.7", - "picocolors": "^1.1.1", - "source-map-js": "^1.2.1" - }, - "engines": { - "node": "^10 || ^12 || >=14" } }, - "node_modules/stylis": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/stylis/-/stylis-4.3.2.tgz", - "integrity": "sha512-bhtUjWd/z6ltJiQwg0dUfxEJ+W+jdqQd8TbWLWyeIJHlnsqmGLRFFd8e5mA0AZi/zx90smXRlN66YMTcaSFifg==", - "license": "MIT" - }, "node_modules/supports-color": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", @@ -4572,17 +4977,97 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/text-table": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", - "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", + "node_modules/tinyglobby": { + "version": "0.2.15", + "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.15.tgz", + "integrity": "sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==", "dev": true, - "license": "MIT" + "license": "MIT", + "dependencies": { + "fdir": "^6.5.0", + "picomatch": "^4.0.3" + }, + "engines": { + "node": ">=12.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/SuperchupuDev" + } + }, + "node_modules/tinyglobby/node_modules/fdir": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", + "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12.0.0" + }, + "peerDependencies": { + "picomatch": "^3 || ^4" + }, + "peerDependenciesMeta": { + "picomatch": { + "optional": true + } + } + }, + "node_modules/tinyglobby/node_modules/picomatch": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", + "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/ts-api-utils": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.1.0.tgz", + "integrity": "sha512-CUgTZL1irw8u29bzrOD/nH85jqyc74D6SshFgujOIA7osm2Rz7dYH77agkx7H4FBNxDq7Cjf+IjaX/8zwFW+ZQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18.12" + }, + "peerDependencies": { + "typescript": ">=4.8.4" + } + }, + "node_modules/tsconfig-paths": { + "version": "3.15.0", + "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.15.0.tgz", + "integrity": "sha512-2Ac2RgzDe/cn48GvOe3M+o82pEFewD3UPbyoUHHdKasHwJKjds4fLXWf/Ux5kATBKN20oaFGu+jbElp1pos0mg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/json5": "^0.0.29", + "json5": "^1.0.2", + "minimist": "^1.2.6", + "strip-bom": "^3.0.0" + } }, "node_modules/tslib": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", - "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==", + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", "license": "0BSD" }, "node_modules/type-check": { @@ -4598,19 +5083,6 @@ "node": ">= 0.8.0" } }, - "node_modules/type-fest": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", - "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", - "dev": true, - "license": "(MIT OR CC0-1.0)", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/typed-array-buffer": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.3.tgz", @@ -4722,35 +5194,46 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/update-browserslist-db": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.3.tgz", - "integrity": "sha512-UxhIZQ+QInVdunkDAaiazvvT/+fXL5Osr0JZlJulepYu6Jd7qJtDZjlur0emRlT71EN3ScPoE7gvsuIKKNavKw==", + "node_modules/undici-types": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz", + "integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==", "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/browserslist" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], + "license": "MIT" + }, + "node_modules/unrs-resolver": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/unrs-resolver/-/unrs-resolver-1.11.1.tgz", + "integrity": "sha512-bSjt9pjaEBnNiGgc9rUiHGKv5l4/TGzDmYw3RhnkJGtLhbnnA/5qJj7x3dNDCRx/PJxu774LlH8lCOlB4hEfKg==", + "dev": true, + "hasInstallScript": true, "license": "MIT", "dependencies": { - "escalade": "^3.2.0", - "picocolors": "^1.1.1" + "napi-postinstall": "^0.3.0" }, - "bin": { - "update-browserslist-db": "cli.js" + "funding": { + "url": "https://opencollective.com/unrs-resolver" }, - "peerDependencies": { - "browserslist": ">= 4.21.0" + "optionalDependencies": { + "@unrs/resolver-binding-android-arm-eabi": "1.11.1", + "@unrs/resolver-binding-android-arm64": "1.11.1", + "@unrs/resolver-binding-darwin-arm64": "1.11.1", + "@unrs/resolver-binding-darwin-x64": "1.11.1", + "@unrs/resolver-binding-freebsd-x64": "1.11.1", + "@unrs/resolver-binding-linux-arm-gnueabihf": "1.11.1", + "@unrs/resolver-binding-linux-arm-musleabihf": "1.11.1", + "@unrs/resolver-binding-linux-arm64-gnu": "1.11.1", + "@unrs/resolver-binding-linux-arm64-musl": "1.11.1", + "@unrs/resolver-binding-linux-ppc64-gnu": "1.11.1", + "@unrs/resolver-binding-linux-riscv64-gnu": "1.11.1", + "@unrs/resolver-binding-linux-riscv64-musl": "1.11.1", + "@unrs/resolver-binding-linux-s390x-gnu": "1.11.1", + "@unrs/resolver-binding-linux-x64-gnu": "1.11.1", + "@unrs/resolver-binding-linux-x64-musl": "1.11.1", + "@unrs/resolver-binding-wasm32-wasi": "1.11.1", + "@unrs/resolver-binding-win32-arm64-msvc": "1.11.1", + "@unrs/resolver-binding-win32-ia32-msvc": "1.11.1", + "@unrs/resolver-binding-win32-x64-msvc": "1.11.1" } }, "node_modules/uri-js": { @@ -4763,66 +5246,6 @@ "punycode": "^2.1.0" } }, - "node_modules/vite": { - "version": "5.4.19", - "resolved": "https://registry.npmjs.org/vite/-/vite-5.4.19.tgz", - "integrity": "sha512-qO3aKv3HoQC8QKiNSTuUM1l9o/XX3+c+VTgLHbJWHZGeTPVAg2XwazI9UWzoxjIJCGCV2zU60uqMzjeLZuULqA==", - "dev": true, - "license": "MIT", - "dependencies": { - "esbuild": "^0.21.3", - "postcss": "^8.4.43", - "rollup": "^4.20.0" - }, - "bin": { - "vite": "bin/vite.js" - }, - "engines": { - "node": "^18.0.0 || >=20.0.0" - }, - "funding": { - "url": "https://github.com/vitejs/vite?sponsor=1" - }, - "optionalDependencies": { - "fsevents": "~2.3.3" - }, - "peerDependencies": { - "@types/node": "^18.0.0 || >=20.0.0", - "less": "*", - "lightningcss": "^1.21.0", - "sass": "*", - "sass-embedded": "*", - "stylus": "*", - "sugarss": "*", - "terser": "^5.4.0" - }, - "peerDependenciesMeta": { - "@types/node": { - "optional": true - }, - "less": { - "optional": true - }, - "lightningcss": { - "optional": true - }, - "sass": { - "optional": true - }, - "sass-embedded": { - "optional": true - }, - "stylus": { - "optional": true - }, - "sugarss": { - "optional": true - }, - "terser": { - "optional": true - } - } - }, "node_modules/which": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", @@ -4938,20 +5361,6 @@ "node": ">=0.10.0" } }, - "node_modules/wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", - "dev": true, - "license": "ISC" - }, - "node_modules/yallist": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", - "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", - "dev": true, - "license": "ISC" - }, "node_modules/yocto-queue": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", diff --git a/package.json b/package.json index cbd4e3c1..75b55f8c 100644 --- a/package.json +++ b/package.json @@ -1,30 +1,25 @@ { "name": "panda_market", + "version": "0.1.0", "private": true, - "version": "0.0.0", - "type": "module", "scripts": { - "dev": "vite", - "build": "tsc && vite build", - "lint": "eslint . --ext js,jsx --report-unused-disable-directives --max-warnings 0", - "preview": "vite preview" + "dev": "next dev", + "build": "next build", + "start": "next start", + "lint": "eslint" }, "dependencies": { - "react": "^18.2.0", - "react-dom": "^18.2.0", - "react-hook-form": "^7.60.0", - "react-router": "^7.6.3", - "styled-components": "^6.1.19" + "react": "19.1.0", + "react-dom": "19.1.0", + "next": "15.5.3" }, "devDependencies": { - "@types/react": "^18.2.66", - "@types/react-dom": "^18.2.22", - "@vitejs/plugin-react": "^4.2.1", - "eslint": "^8.57.0", - "eslint-plugin-react": "^7.34.1", - "eslint-plugin-react-hooks": "^4.6.0", - "eslint-plugin-react-refresh": "^0.4.6", - "typescript": "^5.9.2", - "vite": "^5.2.0" + "typescript": "^5", + "@types/node": "^20", + "@types/react": "^19", + "@types/react-dom": "^19", + "eslint": "^9", + "eslint-config-next": "15.5.3", + "@eslint/eslintrc": "^3" } } diff --git a/public/file.svg b/public/file.svg new file mode 100644 index 00000000..004145cd --- /dev/null +++ b/public/file.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/public/globe.svg b/public/globe.svg new file mode 100644 index 00000000..567f17b0 --- /dev/null +++ b/public/globe.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/public/next.svg b/public/next.svg new file mode 100644 index 00000000..5174b28c --- /dev/null +++ b/public/next.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/public/panda_favicon.svg b/public/panda_favicon.svg deleted file mode 100644 index 95d41963..00000000 --- a/public/panda_favicon.svg +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - - - - - - - - - diff --git a/public/vercel.svg b/public/vercel.svg new file mode 100644 index 00000000..77053960 --- /dev/null +++ b/public/vercel.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/public/window.svg b/public/window.svg new file mode 100644 index 00000000..b2b2a44f --- /dev/null +++ b/public/window.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/App.tsx b/src/App.tsx deleted file mode 100644 index 54629dbc..00000000 --- a/src/App.tsx +++ /dev/null @@ -1,38 +0,0 @@ -import { Route, Routes } from "react-router"; -import Home from "./pages/Home"; -import Login from "./pages/auth/Login"; -import MainLayout from "./layout/MainLayout"; -import Signup from "./pages/auth/Signup"; -import AuthLayout from "./layout/AuthLayout"; -import ItemsLayout from "./layout/ItemsLayout"; -import Items from "./pages/items/Items"; -import AddItem from "./pages/items/AddItem"; -import ItemDetail from "./pages/items/ItemDetail"; - -function App() { - return ( - <> - - {/* 메인 화면 */} - }> - } /> - - - {/* 로그인, 회원가입 */} - }> - } /> - } /> - - - {/* 중고 마켓 */} - }> - } /> - } /> - } /> - - - - ); -} - -export default App; diff --git a/src/app/favicon.ico b/src/app/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..718d6fea4835ec2d246af9800eddb7ffb276240c GIT binary patch literal 25931 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 LrJugUA?W`A8`#=m literal 0 HcmV?d00001 diff --git a/src/app/globals.css b/src/app/globals.css new file mode 100644 index 00000000..e3734be1 --- /dev/null +++ b/src/app/globals.css @@ -0,0 +1,42 @@ +:root { + --background: #ffffff; + --foreground: #171717; +} + +@media (prefers-color-scheme: dark) { + :root { + --background: #0a0a0a; + --foreground: #ededed; + } +} + +html, +body { + max-width: 100vw; + overflow-x: hidden; +} + +body { + color: var(--foreground); + background: var(--background); + font-family: Arial, Helvetica, sans-serif; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; +} + +* { + box-sizing: border-box; + padding: 0; + margin: 0; +} + +a { + color: inherit; + text-decoration: none; +} + +@media (prefers-color-scheme: dark) { + html { + color-scheme: dark; + } +} diff --git a/src/app/layout.tsx b/src/app/layout.tsx new file mode 100644 index 00000000..42fc323e --- /dev/null +++ b/src/app/layout.tsx @@ -0,0 +1,32 @@ +import type { Metadata } from "next"; +import { Geist, Geist_Mono } from "next/font/google"; +import "./globals.css"; + +const geistSans = Geist({ + variable: "--font-geist-sans", + subsets: ["latin"], +}); + +const geistMono = Geist_Mono({ + variable: "--font-geist-mono", + subsets: ["latin"], +}); + +export const metadata: Metadata = { + title: "Create Next App", + description: "Generated by create next app", +}; + +export default function RootLayout({ + children, +}: Readonly<{ + children: React.ReactNode; +}>) { + return ( + + + {children} + + + ); +} diff --git a/src/app/page.module.css b/src/app/page.module.css new file mode 100644 index 00000000..58c71af9 --- /dev/null +++ b/src/app/page.module.css @@ -0,0 +1,167 @@ +.page { + --gray-rgb: 0, 0, 0; + --gray-alpha-200: rgba(var(--gray-rgb), 0.08); + --gray-alpha-100: rgba(var(--gray-rgb), 0.05); + + --button-primary-hover: #383838; + --button-secondary-hover: #f2f2f2; + + display: grid; + grid-template-rows: 20px 1fr 20px; + align-items: center; + justify-items: center; + min-height: 100svh; + padding: 80px; + gap: 64px; + font-family: var(--font-geist-sans); +} + +@media (prefers-color-scheme: dark) { + .page { + --gray-rgb: 255, 255, 255; + --gray-alpha-200: rgba(var(--gray-rgb), 0.145); + --gray-alpha-100: rgba(var(--gray-rgb), 0.06); + + --button-primary-hover: #ccc; + --button-secondary-hover: #1a1a1a; + } +} + +.main { + display: flex; + flex-direction: column; + gap: 32px; + grid-row-start: 2; +} + +.main ol { + font-family: var(--font-geist-mono); + padding-left: 0; + margin: 0; + font-size: 14px; + line-height: 24px; + letter-spacing: -0.01em; + list-style-position: inside; +} + +.main li:not(:last-of-type) { + margin-bottom: 8px; +} + +.main code { + font-family: inherit; + background: var(--gray-alpha-100); + padding: 2px 4px; + border-radius: 4px; + font-weight: 600; +} + +.ctas { + display: flex; + gap: 16px; +} + +.ctas a { + appearance: none; + border-radius: 128px; + height: 48px; + padding: 0 20px; + border: 1px solid transparent; + transition: + background 0.2s, + color 0.2s, + border-color 0.2s; + cursor: pointer; + display: flex; + align-items: center; + justify-content: center; + font-size: 16px; + line-height: 20px; + font-weight: 500; +} + +a.primary { + background: var(--foreground); + color: var(--background); + gap: 8px; +} + +a.secondary { + border-color: var(--gray-alpha-200); + min-width: 158px; +} + +.footer { + grid-row-start: 3; + display: flex; + gap: 24px; +} + +.footer a { + display: flex; + align-items: center; + gap: 8px; +} + +.footer img { + flex-shrink: 0; +} + +/* Enable hover only on non-touch devices */ +@media (hover: hover) and (pointer: fine) { + a.primary:hover { + background: var(--button-primary-hover); + border-color: transparent; + } + + a.secondary:hover { + background: var(--button-secondary-hover); + border-color: transparent; + } + + .footer a:hover { + text-decoration: underline; + text-underline-offset: 4px; + } +} + +@media (max-width: 600px) { + .page { + padding: 32px; + padding-bottom: 80px; + } + + .main { + align-items: center; + } + + .main ol { + text-align: center; + } + + .ctas { + flex-direction: column; + } + + .ctas a { + font-size: 14px; + height: 40px; + padding: 0 16px; + } + + a.secondary { + min-width: auto; + } + + .footer { + flex-wrap: wrap; + align-items: center; + justify-content: center; + } +} + +@media (prefers-color-scheme: dark) { + .logo { + filter: invert(); + } +} diff --git a/src/app/page.tsx b/src/app/page.tsx new file mode 100644 index 00000000..84af2cb0 --- /dev/null +++ b/src/app/page.tsx @@ -0,0 +1,95 @@ +import Image from "next/image"; +import styles from "./page.module.css"; + +export default function Home() { + return ( +
    +
    + Next.js logo +
      +
    1. + Get started by editing src/app/page.tsx. +
    2. +
    3. Save and see your changes instantly.
    4. +
    + + +
    + +
    + ); +} diff --git a/src/assets/icons/btn_left.png b/src/assets/icons/btn_left.png deleted file mode 100644 index 62bef86ac143f58a2784a28ac295adaac6e71e30..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1175 zcmV;I1Zew-P)bceHFI|l*Xnx-o`N1#oDDQ`C~er+<&y5ovf|6MQhc)>cVi~mAsKS*xlW5U;oY2 zg=8k>Il)udI5xw)qB-@N ztksWhGfn*GI2{|K*ZI!&hCOcxiA%ne&}_S|HxRqy^*A93Avn%v(@TRRB{1->uVr-1 z9e<`RNY-OUSl-&SV3~j<+S!d(2ZnvVK~~f>WWA(mE**|UJ9{mY0yE|5wWx{EjQi`^ z46KUiC$3XDq!4jB%P!X8^oZ${{Bb5zyDr77P#Bu7zEug3?YiX{QNU* zy`O&hRa-I+(TPHAoGIpFk-}EYD>yajaWJMK1;j(kJ6j#&9(Y|zXJ3wJ< zy{WpWwN5YHu6k%uv*4oEIE7hMbDHN53E9D}LbcYIdh|@qW=2Et;h;Y(VLRep-L0EP zFS@ufMn!MbJDB%*?QUvE`1cURsij9_&+OJWiTX7)jOx^Mj02Qr`PjZ^XRVm zXX>pvj$;R4oCw4CgbMsD*3e>s7BHPwbRb|jIg_K_2{vHdyPlh?`8Nhdw5LKOY^uDd zA{2sSif+8pL`P$R?@Qf8$3q{`r7nJaCWqIjvw$rGcw4%t#+n*yn>~!5Hf}eYYKWJk px|9fG(Nn^^XMuv!lLh~V_#epos9jW470>_x002ovPDHLkV1m>9D7XLs diff --git a/src/assets/icons/btn_right.png b/src/assets/icons/btn_right.png deleted file mode 100644 index e7873a2055ace8238ecbd432ad393221d1d0551a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1173 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 diff --git a/src/assets/icons/ic_X.svg b/src/assets/icons/ic_X.svg deleted file mode 100644 index f6674f7f..00000000 --- a/src/assets/icons/ic_X.svg +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/src/assets/icons/ic_arrow_down.svg b/src/assets/icons/ic_arrow_down.svg deleted file mode 100644 index 8308690f..00000000 --- a/src/assets/icons/ic_arrow_down.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/src/assets/icons/ic_back.svg b/src/assets/icons/ic_back.svg deleted file mode 100644 index 8db5377e..00000000 --- a/src/assets/icons/ic_back.svg +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/src/assets/icons/ic_facebook.svg b/src/assets/icons/ic_facebook.svg deleted file mode 100644 index 8491c2f8..00000000 --- a/src/assets/icons/ic_facebook.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/src/assets/icons/ic_google.png b/src/assets/icons/ic_google.png deleted file mode 100644 index 49852a6bd508728700902c9f7fa4208fad04db49..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1589 zcmV-52Fm$~P)?vK#8&or3on!Mk`TRKhiCz2&ABX6b4FB zf*>X>g#FOnureuk#Z^j#oh)*_?M~~CGjncV?|XL7IOEQ)=giE`LJ!NFvoGJ}Iq&zJ z_xs-WC@2G@lu^sF8tAssbrDq*B|2nJXqt!*UbRlLCr~036baKb8;QUwDG`$jV!|Iv zQL=+d@5lRvOINbD(WTurv|SNJiK7xAPsU8sI+U?2Y1xi+TvyUxAaGmm!+m)Sdg$jd zRu~|U@+6jJdlQ!m#~CD^F|Cf2lnp2+$P=&d;5JQCZurD$<+h?!(0Ebbt7UNNh~Tk# zj!eed$8(|>q*AGdjA?eW<|+kV!Hj8lk0udiM9*4Qhbq(tRTZct==}ikjvKl7RI=`+i*WmTQ3{yDpd^(K^X&djigq2LC_4>JLs-axD@c92 z7v`_O!2Z1p6rZxQ>T~C#dc{f@bQSftAuMd$feqOd(e<`G!W?huiDE*8d(l#RcO&`b z=N{?Npw>@A_39@v;qhk>27Cr_Y^TjI^rkFfU%O$vE3YQe|MnZ?)guUl+V?(!vEac_ zeN5|`mOXb0p^+TIdG^W&EuqQQtlbcrEQ3Rxl*($p_gqR+TP8xhX~{2kAal5Fm_0(v zUA1T_w3+t+x(54H7t#k>k^a6FHP3Cp1R`7v6hTK;7t6eR>FsKEpP>hoL;6o7nm58a z)0Z`=x7K6wTkk`=``&_G+ik&2cI!X8iW}jnMFv*P4JJhvf#bMQjT6Sef-o;&C{w#OQ0>BkP0wDw z@vjWn3&Bba!7)X1#&9zWT2#OMkz!I(^t%~YAQ-A*n6pJa7!W~+et0n~!ekvXW zO6>!r<96?UXKEG(&Ys5Ry5XC_?oE+lws-fZapJFQb4{Nbe1VywqKG)ZZk-Y#2-iJ? z{@$OkrGEjASyO;NTCx1j#klY08F}q)nVe6iht@HdEMxZVVH7Fh3YiePuE&{uP|D(t zjo6fYWRUC-w*0&u|0FMr*oVo!`c*2=cK=-h^|iqX^C763sz-wJCa)sn2BfS-@#ySz z`Gk@ev8weYv>g2ezg;*9lU~G(W8%c+)7Wux51u{nCeBftTr@vyASnE*(GXXF((7$P z66a}q{D)}O9QT_!~3p0!VLB@rAV<->k+-_1RUvNYNQUOV92|j(b}mx1 zb(2KA@_xC&dgZaxX|oyS1XqX110CfePRpP5Du+{y6}V{VeX{aDdpW_x;`$`*L67nn zyt^VKiryc*dK{IwxN1Z}K9;R*6!@?x{r@D|9Qv@RD)O7$nr}r2=YpIUO%E1iqFgq} n{dCJI7;QtHHIyin - - diff --git a/src/assets/icons/ic_heart_active_large.svg b/src/assets/icons/ic_heart_active_large.svg deleted file mode 100644 index aff4192d..00000000 --- a/src/assets/icons/ic_heart_active_large.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/src/assets/icons/ic_heart_inactive_large.svg b/src/assets/icons/ic_heart_inactive_large.svg deleted file mode 100644 index 72f720d5..00000000 --- a/src/assets/icons/ic_heart_inactive_large.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/src/assets/icons/ic_instagram.svg b/src/assets/icons/ic_instagram.svg deleted file mode 100644 index c83306f8..00000000 --- a/src/assets/icons/ic_instagram.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/src/assets/icons/ic_kakao.png b/src/assets/icons/ic_kakao.png deleted file mode 100644 index 01ef8b47c25caf6aa325a8259675dbf81cd83e4a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1439 zcmV;Q1z`G#P)XmWS)yj8bQjm3H^2mvm*LjzZ>o+>)gfb)F=k1%hWb8cSpOxEpSM{E?{P5(bhAlg&rQbkpw z6_sbG2^0!8J=yq&Qcw43YpX~*yN6WBTe>e8>Y_-0Hw_H-Qapa1hCT>VKVLTkX$y`7 z-u9aSHGh8dw-b{Dum;vD6#TVeNqZ9iTB7^g<9p;2GiMT8w6$5J zc4BDgJS{A~>o+XN5g;b>Tx|G}gu2^J5=f=?O*9lfOQpD!wzmV79p~igZUhLy&jg@; zsf4=fHE8+!=hZeG;6AI${e$|ZrZ4JtFxaKX4S#e&Upt6I&Q$wD9JcP>dxr)G&$^!R zw-*K2XH*I$Jk<{MI4BfKEa3x+Gr4|#INFGvQ`2widms!94D{-22Z*D%2H}Op7`KCz zXXkYAgu|RS#QX62sMip;ZQ{-E-uXkf*H-s*8xrmBKSLY8yrALXkk?Xl=iU__+e5e5 z<9Bxss`qzX?FI--YOz9c)I2uUM`@P&56jPW78-I%vKDwDkg9b|gD@4Aej}jbx?OzMJeudSAg97RZz z;p+A5*O&BvzLI9w*7lf`)V2&QY*cL1OA8g`n5e?44T;{Ex~T2X4Mc);dS9#Z5!)(4 zjPpQ{K%s&cL_gFDLXbY{g2nqg`o6osbY9p4S@H7O_>a81ob(#?Sz?nmH(yaFfEV~~ z`904uLWrca6>XCbzMQ>mWJj$4;mQxZ1AZ)(O)Gu_>p4I>@D&R{n}H8FdnRRx0_n0t zc>}d13W!L=e_=l$J0VlS@eGjDWghk=?5z(?W|XU)m?qsSFc&r%_xJQNL|Nn7_wt$X z5h>L=83KjM^o?Ilhiffd~zRQV`z!DIoa zqC#;0c4?p^B>BW-!I35qaCesMz+8_!oKPMW71C*h?QC}TlDR`P33i<9IXW{}bMGjM znQOcw4W#Jw&z-13C@XAh)GbZmSoMSf%C<*MVr%;$a<;8LsU->2E%R`i2C{fNIyHzK zo>}iCPxpFFg&8Q>wXQmR9@R+QZg>{XnE0Ac)l8#7E70Dpj~N@21k67+uyn1iz>-jA zvDOa==9WeCp_thxo#sE^fG~B<2`MI;j||!lAM*F86;p!MnREh_YXllmg06D<1?lL2 t - - - diff --git a/src/assets/icons/ic_profile.svg b/src/assets/icons/ic_profile.svg deleted file mode 100644 index 0480454d..00000000 --- a/src/assets/icons/ic_profile.svg +++ /dev/null @@ -1,24 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/assets/icons/ic_search.svg b/src/assets/icons/ic_search.svg deleted file mode 100644 index 52241e6d..00000000 --- a/src/assets/icons/ic_search.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/src/assets/icons/ic_sort.svg b/src/assets/icons/ic_sort.svg deleted file mode 100644 index 657b44f9..00000000 --- a/src/assets/icons/ic_sort.svg +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/src/assets/icons/ic_twitter.svg b/src/assets/icons/ic_twitter.svg deleted file mode 100644 index 14a6069a..00000000 --- a/src/assets/icons/ic_twitter.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/src/assets/icons/ic_youtube.svg b/src/assets/icons/ic_youtube.svg deleted file mode 100644 index 8270b35a..00000000 --- a/src/assets/icons/ic_youtube.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/src/assets/images/Img_home_bottom.png b/src/assets/images/Img_home_bottom.png deleted file mode 100644 index e50348069977f24460713d47b985aa3696562d86..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 56972 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

    q}oi!}$6h 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 P{5@CKe};Tw|Nj30%WT{G diff --git a/src/assets/images/hot_item.png b/src/assets/images/hot_item.png deleted file mode 100644 index 2afef3f35d665c9a37d7dac9362ea17cb635b3cd..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 13582 zcmeIZXEV(GY<^AQELIIV}(f8wvtp zwGrS05N`TQMc@~qqtZJU5Qv!k-wzfjErS{WV!3E3z5-Q@KHULca4lq1Wk8_nXyR*A zJP=4QPgzdpjVBgrg)oLy7ru4m_en?h?Bxp@k{5aJS+Hi6l0ZuWW+XQDRV=nlIV9=N z5k^5>wDSWtF&_Mkbw&(N_dv4`5j3*7j_Wvsgpt73tuN8p|^TzBi5M;#t@XVQ7?Icv#(-5*zWT9$Gf zAH51BkNLNC)b_s%i}H^P`marx~kE;VsEU*|Z8wi}>ZTW7{ueS5?mkcG5T|%`<61BDU zETs!S2op#lR2c~v&S3@1Z~BS`Sai2(W8u`|d;(LCOZgTI^OXG1yFbuNb<{^SqbR92 zwN%-qfi-e#jKKel35?~R!*;utsuQhQn;Bxj{^)D>1ys!jyNP9GYlp6gvp_tH+ySYX z+H}h)#a-@-t>aS2S}(kxuq&=khE3uB5qgOak{#(l8RM&;9uTUcq+jlPt--?_Y+irB zf!tW#1z-P3Ux__vBAYxyi||+@2y}K=hm)^(DkFSX)vTm@6B2pNRKXn z5Cq+9DX&^DfAl5r7i&+C)~Tf!pSxVSKXl0m{MS-Y_dv3il|w(=?g9F&J|J4^vM(fm z3U4^>Gt}~4QBzhyb(7~`=k=m93O;QSG#xBI+sT}owsdgmVcB6GBW@6GjUQO*R6NfJ zqs@v-R8c2o`;4>QpYH&omfkvp-i)@F=af_>D=xMRqta<4XS^bFMfmDU^$%lu?h_(PXuvvDqwQ$($W2=02K3+t?{!9UnL#O+OB`BDR%VAW{7V*B9zZ$ z`2+hSP~RYa;)VsL4w?ZGDTXez9X@@$wPWqr>815s=x0*mNqy2 zB-f?oBpq~L&IDV7dX4oUY%kmPtnkMlmKmc??T;0!B&3u6g7na%zX&Noyw=dfz86^ej|~{ksUDAR?Kq zXR5w`>7BCm4@hl_mCgaBi9Gt8FTT$aOsc*pB5KR?K^zSI0@#7f|G;GZ{~G5^^*c1B&Exp)Mpq}|rraoPZBmXKA}G1>Uy z*H*;Hn01CA=ZvwKJm|in33iN4K{{D|Puyup=r)Q`;f4HQ|Db*rkrciLu$V@uQ#>b9of9lyS?{IyyK% zc}HJO`1{O7QQVKydh@OL$KSMLbx9Imc*Pc;xVxAs4k+8mo{MjvFuP=1SI#pHIf##t zd1d`~T&3-IUVY76Ey!wCn7A6{a!KkIc4n2-Ehd*^uAB&)I&-mj#xugnN1(ddDL&5- z6`0K;`9wmj@+YAYQp8R`uh3+ZMEt$14`}u?pzOxwpqX3c6$k`+R7F81KZ%T|Shjcg za;7umcl>!;c3|-NjZxuUWji#|o?0u?U1T!5d?kH4<23*F6{Op~kLAKBzU--xzcae;&4cQDa@jitxV`#;PYL5F(qXnmoa(8Jxls7|)VA1|lZV3(QxLbjx zSM5rXRKu@7^nV6XlVFqkU#Ic7sozad!SX$_w3>dcBXXMO(OFFGv*_Jk_6w{6?ss|@ z3v@D$T#z=#k?`kdTk0w+WJ)8PQR`TfuYk>Z--R6~tFw7PC<$@NfNecs(>~Bj>0w9zi@15dvb6IG9XNe%RGKi!%}S3!>O9dPCkO52JU;&`T;H z%Rm{sY)fk30+A{>uj}U(T9XsL_1%+fq>SNQ5e(cX{~tU#2tkbGK>S>07>+oZt`Tu@ySoh+bXR|Uk{>>8 z+@>lt2#39E^YhVZV;BuvN6xz73#(V)9- zhsbIkkWqcymBrv@PmwqMKBOfyS=n-Jw4r`~n@M#k8}J@aS^&7>eEovHh8j6JIIcV- z?ZjhVQHHmxRP(nq6d=7irj0sF&u(dwD#okcBzM$NJn`MTYm?Ehtn649ymM{=+{aBd z2#hV0ayR=#Px@WE$^%A<28`o-F^VoiX8Ar{6WqF3Arb zU1s21^Pfitr9ZgebF+2T(&M;RrT4~lo2RX_Z$BYzeoM$g;@$Q7N#H6s=ti&U5lAS< z2SxsyUf&)shLQSZYomB{z5Jm#%CvdZ?HWzPXMgJ6y_dICfH@PJ*1f3h$3vI^CO6OM zfaK>~fi=;&X4wC7%4CXG-k5y)pepUgRLPji2p=AD-%}mF9O?6Et9j%W^I&Hgb0Er9 z@Sc>=-}fK+w_{_}A$qoHl7w^c$zMI=m~ew-EX=cGqcw}q0ZPn`JrN=+RTSB{t6mkS z4$*C6pYf$Za3K6uVI6dtA03DbvHnov9#(2x?DJ0VUd=nV$s2pT6OysL*E8n6o=tlj zqvl{qY)o~--H2)MIOOjv+Gzr9%LAv0LP$P%`<>6B3i#~=6<{DtQpGDwbu`T4sV?Mc!YcYr{^@f7;j z>Ysm#PaY;IWCFs!<_*v`k}pK1M! zS(8lpqR%ghTgXpG%{xUxHvq$zTXc;=zKJoV5zb%m>?hDp8#mAmXvC=JhZ~YRN1WJ=(UEjjkS$Ceu z&K78+x1X;Z8#Loi@a`pv+o8QkM43R@?9bn8g7-Ts% z^|63EvW6j}1h=SdB3G9)c}HO^qW04b;uLB#s;TvWXpAoz{A%`OS!RruCPrtC)Uy*8 zW+eKRtiBtH%Z6iBsr?{>ji#pV4M_;fgpUWNe?6}q~# z7))S0E*S1wAyXj1G^HI+fslZqcz3dDRrBu>SW!z8GaceZ;4nMd^XqM!j|lSt^yt{{ z(=7YmNQe{#+~_?J`vUhhp6?@!`>;2iISJHw<8R7x{7Q>|z6Mt_h`wCEv*VkerG3Nd z+*}5S7*Md5@}_5S^%)T8f_%HO`pwHWGHa3{pjkB6A^{ z)%1BCS194#9aSRa^UJnR`_tSjW97HkyfQ-HAGxwi^625d6rSiLA^L+ne7Nv(p@j}L^Mt}$Ox7|eoOHoys zw!Yg)EuK96ot=3B+tAG8uJi3xX1oW^hy1bXQj7w|@7IYJUBYIs+qUZm5ZW269g24@ z>DpP`ohZTL_TO?cEr6<6z?;(b`ouZ}ifC7QY{R{6PuHBsX{0>z^ac)K8nm9^!(N;> zE(6{o)mw_j$eQb>B5eG&T+_=FryxIiCIQ^|FOoOw>_AuWFd;GfrnRvC{!%dj{eo}q7uy2a`InUJ-(kZsp1arBq#W#ukIYxzq+ z=qr=KoZ#MqZ;ga`MJs!-G#V2_SEDJ0)w#5}g!xhmdk3=GU=nb;LJH*{^EF8`XLoLWgPn^0&x< zS(GPeSAr5{_&vdeR z$LwOQ2%bnM35Yay!Lto33sZa9HjXkeM- z>V0xk7L$k-l74)KB2#4bWO3jaH#vjNd8at;vpzozdOFJfDQ`0&D%(3NeF@SpJJhc~ zccekyI{P5slw+A5x8U+mC?hE^L#)L4-;UCtJCegR37Ju(dtnB|B`#yrm_U=Wbz^!~ zW1&8JM@nZ$l*(XWr*)!zg-~JgP9LRuIYRYie}&5?7NZ~g5@pEDy-6Ox*?&q9+1t{5 zLN0h}8AI4JZ1&(&QlQGY%U%QcwC;d`oP7CWILP^klaD-|?$mpbKGlz_>88pL-v5Hk zwZY2YI=E;h^Fcwh>1SVO@8^Q>?z`3O1!-{-pj2`Ubz#d)-@ zUZ+C*uWIu_vBPWnwzIFg7sZty@svF8Ui(r=<|BFUc;5@x*le#X+a%@s zZk>uf!s7_~LTvD6)f%4!+HaE~t6lMUBhb!!gN)ZRd0sAbaTSH(HAn5EB{>(iIb>_ zS?t?J{ZJt}NtunlQ0bMvGnHu~_1oqCOkVQx+t+k7*Uf52>81+V9h|p2ZW1Z$R}_?l zPFV2QulB9z8C;c@9^xQa!FlC=S_LOjYkYbg^-;CwhXq56Chr}Z>WUOI1|(?05U(Oe zy6Nznciu z%R}PI#6DzYHjt?q@Ncux51Y+^Z1BmXmpp7DY@W+tSaXhP@^4+M^DE;olZ^T7tXU_O zWW02VK|_jxM)}NmtcZ`KVZ{#!pm<&Raxa3hxL|SbO)|be-cvN;!oM^E^2$d*5$^vp z&zRIFmCPW}{1?RM;SAAwpbJv*OaN6$oVe<`E;y)<_mp@Mr+?f76(ufD?;jePpI+yGj<- z@+wNI!R^=8O;7FBH3+Sa%MOw*$tYCUAaFT}FpF!A_C+3YitS>kRR`&%7_BtYRuMlO zNmTC6uKZLjxl+=NoC+A}3TKF>Mn<88$IkotNd@1Xf7axtCJAj3Oq?3R|O5rumB!j_U zUQzEq`2kC#n9!-w==;TVr#RYza#nl^_@y#}{_R)$!bG5tk%-UBdf)ko`_#RY@Pi9X z-Bq(581ODuH=d;6vy*7i4q`p!~0h&ju;N zmIa3;$oPEIPt+umM}J>Hn+4ZGndS~NX|AuVeobQ1QZpz)(y;BJ&@*WIU&He9f$!Vi zB*ZFAne2EVC8_|zS@AmCSsG|i$nVMgb|?%Blpl(~-Aip4Y}^|!12H;$->=HDD)mu+ zE7a+VfNgI$vcYkrTL_^4LHXX+-gu?_B?0ZQfV*I9s+Y58$*$%3+%vmw0HcV1jOqq4 z*ONZKT@)ZP@1x^BObP>Vw-o<}6RQQiOg&CAV^h_l#dFq~j_a@rXu^;HM0^T!tzXYp zpE!Gr8?`qeS0Ldk?*Ny&S>72;0D&fDOajkHp9t)<>eKqbC`nZMqn{=!w0ksTwRg5P zvBqm_%Xku%zbO^)IQ2YCA0BD!o=Hj#=qhfhfdctD1wZS(y;OlvEAxTC#F^gBj;gwP zi5L5J`5gkDYH|3Sr~;a%awBp;VZZ_x17(Wjo(Nrt(I*+fCYz7T8~v2kGFP4~N27V= z+Yi1HZ%$HO+a6k+_qZNmw2xdSu|NvIl1o!vKQC9E^m~yTjoq|nwHWg@A4&bZZI&&q z$j%SgEnvTEDtnvPHQ@}3q5K2xvOam~0!#T9e7ERDM{|+H(<{DrwbAtrs?bx2F}qi3 z>EYE3%3mv!yB?;QjZs;)>aCECWal|Pp!6m_Ma(~rq&F4Sni!Bz1Z1*w`xu)boo^4xb2scNK^=p z{}JOq(R56WI;J2l^#nYS2^kx_M?aKA{GZb>2Bg}ocGI(g{4)VNN!p3;zybl;N?<)H zIpAHMFagBGXC)v|3?3lc?K=$UWDj5iM=ed*wE%D{zy;sr8JiCds7B5tFp-p}7M~o% zC=M|F+4mOUgk}bJy(S(u#s+=-g1~(a6rKO`;AKE32=p-wfK(3(gBVqS!WYONC?4zW zXe62gpCK#&VqXuN{twPxRX$L-wE;#$SD%5TXMt&s`a}XVmTmz4Bvk>vfT&S033LNm z8~t|!m#Gxp*i z6+b{FFn0Y6grEi%mI$N+xFG+shbbnHqhfGCUvUBmbwmvc{;dK6V0J%c10h5J#K$@p z`2TwpIGUiZSOA`BqQn1v@c)2F{%Nc)7=de31+3r100=w4#~Q$D@c*smzX32H1Pt6T z11*Kp&BU?EV>%?J!^>XMkjUHumqlhWdB=cfc>dE5Q~ou-@M1%0nh;?g0n@R`vy~IS zRGwo4ce{-bN>S!`{&f>Qbq{?k_9sh$AqTGqPR+$%m zgaaX{db6iAr-P5N1Bw}K89roN+&+pS{Ig!h@IQ#sWM1`fqwdjTq0}QTY(|LJ_s8qs zkWW;IHy8qnLB|3ex3%m>jG)OLgN(@a)*&fuZLH~Cx1T}TOJ~}r0#EE41fNyu8d>*> z{9V~(2;kgu6)-bG`?%^Iu<-fVIFh_TrENHTD3zEAcN#y8S{wEOGJOLU3%tL>#fH9? zu!!sB(d;dkjqBe#oyi-AYDNA>Bh z^?$d~JwxqFWc^tT9jhn$SCscYjQIgE|J!D{McZI!o0dsY?o7C#WoAm+M|R%I*MUG6 zMkrhdRCGgMw4+oxHF~V`1dk`s)KY(>OUZw-;K3i8_93RH1_$=prDyip(JRrCjkSf17>$d{1~+Q6%42CmXR%;3%O$w%xZs>I$= z0J%I2s0PTI45sc55-GOkD`5t7tzTlHjOAyi;R;EI?)IbJ}WQ#%?QJPR(Z>d_w@GEWLOtiF`#6r1^YUy1a_ENTGU~2ya{@aqu%VK_vU-@T+n#P%;Yr3wy@K=TlUJ3Uz44p<8;^dj-sN`p@aT zPWhV;JFcvdadubq&#Z$N2%z{xIw6J?`0|dm2k3~t^2Qb3#ufMX8r-ug#6zXVH`aH@ zTwWtKMm$1O$h$t;PBsrD+{1C<3o&1t25-kXRnQ?bcZMQ;MDc?*mD}4x zhonls8_GpY$`XbH(6*e3z!!X0NQwCynVl2k^WP!F{fy<1DdJ6G-}Uw`yZ8BLh6X-I zy~l;ZH@{mtBXsz=tEs|BroNpvkKGh6?-)lDp;~QTpu7`+@+}iMGS&A6#;Q_o#GtG( zX}_iJdpzYlr7EnPR+o}uq*ou~d-_4w-g3;l{1oGdyjtC(nvF1TcRj3rdmn;kja9Pg zbs3|JmAcMTAJFZD1?7jKS87txkk`{hFCL`y0XZ`6n&lfN&U_at-p*^OLVfAnx}i&y zgP*sCo@y>KD5OvGz=>_*a4r0~BnR!LS4DyZU(+XtM>&?|;}^XvaLZ@WMFA*PMWr^&7cgaoEj*6-HpZzDE9+twLA1|%S zTgbFRuKIxw>gNGzTih_CxlBQ-nDmShy8OqM90E-uj0od#<%6;-c5KV@#c6`=ur1@P z>uECn{MqEYdx91BA0icicyYbe$_hDb^%R4)>_K5UIQ0Zur+J`CJ$9NI61qUzfKOHuoT^{kRHfnY~nO-37 z<+4Q9Iiy4)J`&o+AZyxW>M_7(HC6v692Xj%|ZC}(|ehP7PnHr1?HkmSV_jN@hO_}u6jyMyuKbj zl=MrqMeOhC^u{>GN+@06<-1s$%8Q|2x8zrt#)@o9!$V9Z<|>*F;x5r7>As&b|GU8? zOIFCjJ9OcnPUeFUADfo!TMeOkc$yKLURwu=+BdI?dykjfw=U<3aF-N%VyD!lc$&UP z%>E6(I`BpuK9XX?tlaqS)p2)w)ypc=*p4jy#(p4IJpmY0)xCh9j$#ZZ z8FkWGdsJ#XSzB2i6$Yo1$?j-2RhLyS@1VU1UYHe9h^OHSBgN#g>XmG4!axvyAcE1a zw+IL%TEr|)bnx2)Evg-Azga~CODy=!o)ImDdb?1)XGJpQ`}Vfmv&ub*LV5JgxEFO z84>m~JZL(3&yvj^TU2jR#b0-5JJC`74j@G#rCJoIcyfdOfWBq>s;_xGKFBokThYD2 z_D;4{h)dbKfvZqe}v=Mz)EFH1X*M}Os#t8_Y_&2+VW zIipW>xu(XeAFxDz%7uTR2I4oacY39tT~+9h)lcrOT087gM~ckZ51J1yD+iN1uaj-E z$eetl0>kS8$8`@ytBK1tWW_WC$uU0S+qa8Kz8!<|iKV`Y*mIkMyUlDdd?2GBv_$^- z1_w-slc>14`)7XVS^8n}*bPRCPG3*m{1r#YH+Xsk+Rz}wXHGz0LhA4P!(@l$Tel0I zyEHRv-b~`0l?!CkP0}wvUwM6;d$h7w4fjy3p4+AZ^FWMUZXTg8YOjm&-C$ur-?<;g z?cG#dkNF;`2lY4Ft}t`(E_z6gcSHcvt9Vc^{Ir!$WQa@AG;J3n$@qpBWfNMqb%#DV z@U3hYANw3m@MMncJ@fvsCC+@&8B3u8eZyG&a$XMlMURe&j+0QtN5(Oi0txcwpcPOGSAC2?*qIQPP}p}fqrPce zyS$4xcbGP+bGQ#I9&nQ%zTv$gE*7F;B=pX6&w+n{SR&EiLODMyzBJ}c?sZ$(`?2`h zI}es0N$-T?0vH=W={??)kQ1h*%#}!pB~+qcuIy$mZ$iH)EEIvZ6N04(NK-)+3JiGh z+NsO-%t#l76@mdc>55V+{j(P@-{qv3eXRSYruH__?>#kOiwcowJ0R25`k^VHv~+wN zUN&tVxIfVmE40}7jyg^yEbCIbRX0FzC*#QtgU|_mjr^4YC17EuO1yY2bISbkI;Y4* zpp`s;51hPQczO^*@Kp=@x4SA)U5c8*9$BD!JM69W5JkKG>PiSFz)J2Zo1fXRD~f?F zqA&;@=>(ivh5#$vZWeRBGSc7f@<*!EZ1FYy=gN?&EZ6DLqt83DI zMU$jYbWACl=(F$?a_iq)vSJ+f8`=hzPe0xc-dGbl${s4^;pkU?XFq9~?zE)gIPXaxPy#;NotH9H`B0JQRG85<)=6 z_X(Tsc#!jNr_-YFam4^ioCmj%Y49n35H>-eYyr2t?3Kbpih6iaFhbB@EoJ@76N=!i zW&zD_7o>F#6v`8e9%%$n{+79)tQr)m1p*H#X4~@Md0)aOJEr=CsV8V zzDpiD=YLqCt7ZMz-`m_)raA(6L;eUwAy{2!a5TO4T8iK}hWAJ84AyYS4bP-I+g$&l z_yQ1UPA7lMZonE>5}&8y6@ExTYB|c=fQU9l4?(I_s5rIlHD@b(g&()D*wJ4Q6QIlWEV6+ro$bqHM?igT zIXqf>t>YP6AoiYxN_q|)XHPNxU3xbjTjm^MmAy)`<(_qq5eJG^PwM?5rs?r6EfHE$ zR9m!)sqiouU=W#?%=s<{o4l7|UStaM$_k0-n;1$c10$mj;La)hRicFl|IkMAlC9i= z38DLN>~xFWfBfbpV5vH~UmQZ()lFQXOT-0moIF{+DaT-fe@J;B7XKkp)4@_hhHe_W zSJ}ZZ@{l^tMPV?ku+Cv>Lkb+55D+^B(dhSg(U|B6n0QeDPiMo-gdFLaoYtkNB}hCG z{y)fKU?(+BMhL9%#3>h!v-8B`N=UN;hkU(C8s^I9nh`Gx>=mqUr9(Ag$)RU6nk3)e zK-LVSxYB;JP)kaL|D)e(3W{Mmv3|iV@l_5>1ltV1QbB z(|jKa#mB4B9z3_CSrm@Re55$!w($bY--tB;owaEg?+DnhV$;?=;EL`U?3Dgfv)cfe zz`_T;if0}HVJsH@`{pxt>R0$R{Z$4k2PI_6)B{F3D`-Hf_x+*z4K8qf%O2-9% z6|kv&p{pwycx<=d5a<6FKvWi1A3I9=KMcAg0E4m?r%y3-c$s2L6qv!0aw~j^Q8?hI zo8iBKVU^;gEHug2Y~8=6&C9rK(Pl(n4fX#CHMtI#|vdJ{oe>B zhC=CzIugyV9q>Er*@{9$bi;xH$zBRC6BPdO&(Cr0cdD5Dn%^isW4W|{YH`hKZfKd? zPY;fMQKO8+Mu3AwwMNI}YSSVYVeZHV+tdqB;6GsOXtIFt500js)}(j~tT{`w-r>VV zkK?TaW+^Q!mkjfk1!Yy@b)YUtJ5t)~NTH1|Narc4b3hn~MyWK;y*^Nv^GVo l$nO_SR;}yz=}fP5bG&IM_PnF8oitnL6p;bIVEb8s0pHX7tY}#A&7cPwBU4!E>R94B6=@D zqMwrJ-OKyo{ReMmzx`%+c6Ro+o&ENek%1-!850=*0HDy;QiK2Fp8o3AvupYHr26Bp{Vj7p>HR|W-e znwi5}79Ih}uhcME?bqz?Z-kvJF9ckt1x-SH+gY-UJ7Sf;;yVJ_1LU8vsO@RXG}5e}*;T2!g^H|ntJo~zo(cQ4 z*}3`^3o3UGyGwg;H2trGj_U)9S44H)eNE`?wC{F!_Sb(}VTVvmpzw z`_+@hgzXy`j19fO`!a=~T71IK)Z3%wzi;>8Mv(1Iu99xMVD z!oSUrld>Vom&b{6MTgq^aJN2Rc5nR494wt?8!y|OW!V>R z0r4&RoXz~8Tk0Y9OB-wFt;dP2?p~!u9B$}yp^WxFwr=5<={2;! zBef{Im`QP&fA6yeDI+jLM^d^puWh|7bT~~+Y^eE;U(c_0dF{i%B%n&*Cp`%ZXC{?Q zjPQu-#_-sz2_Kvf$u>wPv8T$Coo#&@K;BJ%uq=lgF-p60$2fH^{(YjeXmi+O#pOxc zaGzrHwv+Du{y%xrneeDu2dAdY8szAC`lQ9|%uE(H1xIdq`1wJf;eCc~{#F=A?lh@D zb&_E-UV|L8a<;0LF5JbDA2O3etzmh-7DN^^DnZmqKc(MoEZGEED(|bpaxD;=p{(-( z!Hb%I!ovEJ%>gx4Uwv1JqIO1JVYOw9TrfDJ>WLJ0rl2e05lK;)yuZ>D= zli@1`iwZm1;wzP8=LTvF#ORyZPte(c z2Lpd!Tu^QhZ5x(>e zd${Y`Kv%y{UgDG6y5BG+V<&73kWf%i485?SL-$A_;>;dK{CY^v33yg(s&8UL{;BzK z$VK=R?XT*OV0Gs;hB^)G!D=tkVPGF4aXVzG@K;S_7C&r z+P5OsAeWBY9CAYFUHTq)Ww(H(@h_{?B7?c&zffmYtL7-=*{SG9_2#D)GD!uQbyh_P zRa&p@SvYV|{AERGH2Cm;LMjtA8fDtZ76!!p@gdx+y2Rt*))e{HY4TcRlT=x>J?rc1 zmCmwsG8}pY7PtgDY;Hzz^pS^`o2z;TKZL!WWYjDF5yrX@^vwob*J5&OV3iQYqgIIV zcZl5Io7##ff;H|M*gPe*G;bsG5L zVxS<)sPbYsn8z5D+X>gxH!$K<(l9O{d!~DS6};-nACUA6#?cV(0iPi7XF`o=ui_wF zQ!!Bp?J5oq;`wwT;}Y|`+?5>>nlF|-;a0FfGI>A|8j8xw9)3%y`LjzNgrx(TJ7@?H z``4ar9EbAH7C!9MvGYi#$g&!u{UGI>2e-_epIK;U&SEqT*gU?lzQDhq&bmuzQS+r} z>GrU6{^NbM_;e9=c)V6F$AhMzj>k$|TVg;c*f}^rxaZHb(hGhkm){n0dl{xJdd9?~ zvDDGn9uBob?u&i98aS)GKVjPbu%ZI~fsN|%LZfOuJ=})8^|3q|oEKg8ix`~h1>2~Q zkq$kUYmhFD08^}OUh$RMLW5BPWTqdP6Gq`fb{7B1+ye z&kyWhH8d9xCcBP+;Qf+&iLcT7q8amvUneP)1%*-n)}3#Hic1m!!71rfVKUMT%T`MU zk$#|ej7v_b)ZpJ2`fFKg3UYk<{IUS!SZ#tn%Vp&R+cX9R3Sc|ASl(muuYzyYTSgZ6 zVBcf@)-k6VQHz0&IMwm$WXaKvu`su?dvt}74+EE`pX!f>=6>S@n3g!)yMkc&safp# zoam=AAe)#Y&MXtfXclq-VWGAD!0K@X{mPviMp?^q+Hfg2~R|L(IXmh^QG_J z#I64Rqnc(5C#n`1qo`Ch6_^r!H=eznOO6L!Xz?WR#Ql-`iJ|`~)OcMT>%e znBzX?gy?|gG(oM^M0AA8f46tP5^o`^qMzvHnya8IQX%!^xS57_Dna76$8)ibB8eWX zM}_ByIpecZvLLG^IvZYJw=lEkxtpt4yiIDTPFiqc~mIC?hvzV(H+TJ%0 zV2==2_yG6VY2Vcz+Q86+@qCmSy4zkgwE4tqeEOr;=jz|Rq;erD`&Ur}@v$Jp17TS4 zjDFBeVr!sL@pA?%h;K>et1y||cI-H~sS_zB{GbgS`lh-(_?-a~+#JZkB_-0CvTrz) z!^67VaDCJFzP+j8m%<8idUDv@WVuxz11#u~E=33%zj5=s!~4yW>~4pVNIv(PgP$^TF*xlP0Mu%gA+UK zzK}XkGuw!c18mh^o8N!*dD@>uUZw>i&1^)#N)tR|*l<2BN`a~brywS=x1 zv=ai!zab+$l3HgXThY$xEkh7kR~q6gzopT?BI`#a5;R>P%O>1{GNO5%wy!n6x(G-76m z4oT(7hEyh9F*y;;>B2)%Mv@L-fvf#4V!12B8`Pas%&6Tv0fgo-*J83$C#$^Uyk|HC zcOEWPi7U<>D>|$w$dnI7H|InbZ5*bpQQPzp#G8I_AOj+m&f2u^zyyh(&s6P>)>)G{OmQZ< z@9^h2)qn1WyO(GX{6|aFM`BSVGKx9;o>nZQ4WUrc;m+C2Yfw5sUZ+R3% zJPrtpL$88SFH3CA8VA+#f{k`krvQ zj8L|-Q+SCG-xGCU&6@OtgguW7-F@-L0Hh+<;P<+GZ(HukZ-*((47Q1GQvr=5*_gyz z(IE{Sp@gmcTe9ZO`er@9Zyfe=Ux}Gsy_*Y;Li zzL36<`H@#?j9a|{<2J*oY2gLQ3awOI@WaZw_cLnGEP?mlko5 zKPnPr9UP7PTqC0;wvfJoZA6IGx7qOVBG@gL)U=To9;@Dso>Ij1zU| z_aSyOUheI$uZT|JE$l%I*uz@&ozqx1@2=~+-s~7Uxz%GB_`1X=z(5fmZy|y@aXa}d zCT1S`o_2y2TtAxpw3wzNuI`l3#R=R4layoZ_x77RykJ~?-tlE2OnC617UCvxQex(; zaeLpx9BKbK&w#OZ*H+%%R#71+bl+z*#bsoNF^}1iwHOrV%-I^BVgA%#aEK>k?)N4yGJDW8BfI2vx|PyHs6K+!)#$ zCSJL@{z_AAW>iB!GoDZ9ZtDo)dHh@PiEdkrvM$rpnS;rKhhU*(W{HLqmu=z&T8}z4 z`K;&%qruS^;xa%-Z#>mD)M4fR#8MYiaIj-!gL2=a`hp|j0od}*i>1IC_p`03Y04*W zt0{M%5nBt>9w-^TLBRok@DCFBp*iC@hnfl848AX>1I3e;rtx7|Bk=YR;Gw8dO(*_< zGBS=4*)E#!#g@h=GmIZu_9z5es<=US5Vgcs{RNHFVNv(DB9VqvoL|j=d-eE>ijR(C zB+du#POf6@a$FY7R5vXY`ov4 z+7P-4TT`*xLHq=$4b6$T^lMSlxR?0^|R z`Y2Ftp|X2}aQOlMq2`+(vI0LTv^7W?BMGDh; z!}pnFP9mT6%sZ-Q@`aSg6En0^R(8y=ma;{ussBb!)(>f{^-3wBe2Er9+z!9rLn+`Ek>JO1KOk6Qra_Xd& zBj=w=7jiwqe#8=~w=XQP?rbLTSc?QZeF}0|z2ioRog|i(DLFV-YvA8j_dt5v^0`+V z4Z6l}0SeEK-bu0t2nA6g7A}Y5RBcWu{kBfWUoemVuxtTSr2p#F3v17gme_g53JF3E&NN7lD!~VP?Gyyq-#kJlYe!+ zK4wuG=^PoOCFW}u@ly%wQ1A@IU7@KC+~o-sd|n+U!7!nB%=!T!#jF_N8$Sj}tcD+V znWdfFd`ogXE+fl-XF78-Furj(K;Dw;|2!%{zm@7O7#Q#LEa~a;JJk;Dt;+HjVb^$3dP zYuHNa0jUnC^Tt|OH%neK&!U z5e{tZrMbAwXbv-GQLD)dN=jF#LHSV4f+$I5Ee^N7t+G35wBJ4Me$;m%8r638tkTM! zs&wynPh0F-^RuZD9;gpumtL+o!%E0@V09-0CvFd0%o>6JF9rR7ebjnx0j~n=?%3#B SZ~l7<0JPN&)T&kNk^cdsQ_zM0 diff --git a/src/assets/images/logo_lg.png b/src/assets/images/logo_lg.png deleted file mode 100644 index 8b56d8b58e997b70ff274884019c4c6226f5b40a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6365 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 diff --git a/src/assets/images/logo_md.png b/src/assets/images/logo_md.png deleted file mode 100644 index bc9cbe01c60107be72b4402f295ccda31594b348..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3520 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 diff --git a/src/assets/images/register.png b/src/assets/images/register.png deleted file mode 100644 index ef5972b3413d0ddf989af40ee9f049adca3a7135..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 10648 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 diff --git a/src/assets/images/search.png b/src/assets/images/search.png deleted file mode 100644 index a3520522967c972f2e625c9a361ed32ba7ef6fe4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 17056 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 WWfK9PVk`g{L`rYeUzf<61^q8)XLj!Z diff --git a/src/components/DropdownList.jsx b/src/components/DropdownList.jsx deleted file mode 100644 index 9d0d1b84..00000000 --- a/src/components/DropdownList.jsx +++ /dev/null @@ -1,70 +0,0 @@ -import '../styles/components/dropDownList.css'; -import { memo, useEffect, useState } from 'react'; - -/** - * 드롭다운 리스트 메뉴 - */ -const orderList = [ - { name: '최신순', value: 'recent' }, - { name: '좋아요순', value: 'favorite' }, -]; - -function DropdownList({ changeOrder }) { - const [order, setOrder] = useState(orderList[0].name); - - /** - * 드롭다운 리스트의 열림/닫힘 상태 - */ - const [isOpen, setIsOpen] = useState(false); - - /** - * 드롭다운 리스트 열림/닫힘 이벤트 - */ - const onClickOpen = () => { - setIsOpen((prevState) => !prevState); - }; - - /** - * 드롭다운 리스트의 정렬 조건을 변경한다. - * @param {string} value - */ - const onClickChangeOrder = (menu) => { - setOrder(menu.name); - changeOrder(menu.value); - onClickOpen(); - }; - - useEffect(() => { - return () => { - setIsOpen(false); - }; - }, []); - - return ( - <> -

    - - ); -} - -export default memo(DropdownList); diff --git a/src/components/ImgInput.jsx b/src/components/ImgInput.jsx deleted file mode 100644 index a701471c..00000000 --- a/src/components/ImgInput.jsx +++ /dev/null @@ -1,136 +0,0 @@ -import { memo, useRef, useState } from "react"; -import styled from "styled-components"; -import { palette } from "../styles/commonStyles"; -import icPlus from "../assets/icons/ic_plus.svg"; -import icX from "../assets/icons/ic_X.svg"; - -/** - * input 태그를 감싸는 label - */ -const ImgUpload = styled.label` - width: 282px; - height: 282px; - color: ${palette.gray400}; - background-color: ${palette.gray100}; - background-image: url(${icPlus}); - background-repeat: no-repeat; - background-position: center 90px; - border: none; - border-radius: 12px; - cursor: pointer; - display: inline-block; - padding-top: 160px; - text-align: center; - - @media (max-width: 1200px) { - width: 168px; - height: 168px; - background-position: center 40px; - padding-top: 100px; - } -`; - -/** - * 이미지 미리보기를 표출 - */ -const ProductPreviewImg = styled.img` - width: 282px; - height: 282px; - border-radius: 12px; - margin-left: 30px; - position: relative; - - @media (max-width: 1200px) { - width: 168px; - height: 168px; - margin-left: 10px; - } -`; - -/** - * 이미지를 삭제할 버튼 - */ -export const DeleteButton = styled.button` - width: 22px; - height: 24px; - border-radius: 999px; - border: none; - background-color: ${palette.gray400}; - background-image: url(${icX}); - background-repeat: no-repeat; - background-position: center; - position: absolute; - z-index: 8888; - transform: translate(-150%, 50%); -`; - -/** - * 이미지 등록 버튼을 표출하는 컴포넌트 - */ -const ImgInput = ({ isUpload, setIsUpload }) => { - /** - * 미리보기 이미지 문자열을 담는다. - */ - const [imgPreviews, setImgPreviews] = useState(""); - const inputRef = useRef(); - - /** - * 업로드한 이미지의 정보를 URL 문자열로 변환 - * @param {event} e - */ - const onChangeUploadImg = (e) => { - if (imgPreviews !== "") { - return; - } - - const previewImg = e.target.files[0]; - const imgLink = URL.createObjectURL(previewImg); - setImgPreviews(imgLink); - }; - - /** - * 미리보기 이미지를 지우는 함수 - * @param {Event} e - */ - const onClickDeleteImg = (e) => { - e.preventDefault(); - inputRef.current.value = ""; - setImgPreviews(""); - setIsUpload(false); - }; - - /** - * 이미 등록된 이미지가 있을 때 업로드 상태를 true로 변경하는 함수 - */ - const onClickCheckImg = () => { - if (imgPreviews !== "") { - setIsUpload(true); - } - }; - - return ( - <> -
    - 이미지 등록 - -
    - {imgPreviews && ( -
    - - -
    - )} - - ); -}; - -export default memo(ImgInput); diff --git a/src/components/Inquiry.jsx b/src/components/Inquiry.jsx deleted file mode 100644 index e669deea..00000000 --- a/src/components/Inquiry.jsx +++ /dev/null @@ -1,34 +0,0 @@ -import { - BackButton, - BackButtonWrapper, - InquiryTitle, -} from "../styles/components/InquiryStyles"; -import { requestInquiryLists } from "../services/inquiryApi"; -import { useNavigate } from "react-router"; -import icBack from "../assets/icons/ic_back.svg"; -import useFetch from "../hooks/useService"; -import InquiryWriteArea from "./InquiryWriteArea"; -import InquiryList from "../pages/components/ItemDetail/InquiryList"; - -export default function Inquiry({ id }) { - const navigate = useNavigate(); - - /** - * 문의 내역을 가져온다. - */ - const { data, isLoading } = useFetch(() => requestInquiryLists(id)); - - return ( - <> - 문의하기 - - {!isLoading ? :
    로딩중
    } - - navigate(-1)}> - 목록으로 돌아가기 - 뒤로가기 이미지 - - - - ); -} diff --git a/src/components/InquiryWriteArea.jsx b/src/components/InquiryWriteArea.jsx deleted file mode 100644 index 66e3d12e..00000000 --- a/src/components/InquiryWriteArea.jsx +++ /dev/null @@ -1,56 +0,0 @@ -import { useState } from "react"; -import { - InquirySubmitButton, - InquiryTextArea, -} from "../styles/components/InquiryStyles"; - -/** - * 문의 내역 작성 공간 - */ -export default function InquiryWriteArea() { - const [isActive, setIsActive] = useState(false); - const [inquiryContent, setInquiryContent] = useState(""); - - const onChangeWrite = (e) => { - if (e.target.value) { - setIsActive(true); - } else { - setIsActive(false); - } - - setInquiryContent(e.target.value); - }; - - const onClickUploadInquiry = () => { - let data = { - productId: id, - Inquiry: { - content: inquiryContent, - }, - }; - - // const { data: success } = usePost(requestPostInquiry(data)); - - if (success) { - location.reload(true); - } else { - alert("등록에 실패했습니다."); - } - }; - - return ( -
    - - - 등록 - -
    - ); -} diff --git a/src/components/Pagination.jsx b/src/components/Pagination.jsx deleted file mode 100644 index 50fb094d..00000000 --- a/src/components/Pagination.jsx +++ /dev/null @@ -1,116 +0,0 @@ -import { useEffect, useState } from 'react'; -import '../styles/components/pagination.css'; - -export default function Pagination({ - currentNum, - setPageNum, - totalCount, - contentNum, -}) { - /** - * 페이지 번호를 표시할 배열 - */ - const [pageArr, setPageArr] = useState([]); - - /** - * 페이지의 총 개수 - */ - const totalPageCount = Math.ceil(totalCount / contentNum); - - /** - * 보여질 페이지 그룹 - */ - const pageGroup = Math.ceil(currentNum / 5); - - /** - * 페이지 그룹별 첫 번째 번호 - */ - const pageFirstNum = (pageGroup - 1) * 5 + 1; - - /** - * 페이지 그룹별 마지막 번호 - */ - const pageLastNum = - pageGroup * 5 > totalPageCount ? totalPageCount : pageGroup * 5; - - useEffect(() => { - let pages = []; - - for (let i = pageFirstNum; i <= pageLastNum; i++) { - pages.push(i); - } - - setPageArr(pages); - }, [pageGroup, contentNum]); - - /** - * 화살표 모양으로 다음 페이지로 이동할 때 이벤트 - * @param {event} e - */ - const onClickMoveNext = (e) => { - e.stopPropagation(); - setPageNum(currentNum + 1); - }; - - /** - * 화살표 모양으로 이전 페이지로 이동할 때 이벤트 - * @param {event} e - */ - const onClickMovePrev = (e) => { - e.stopPropagation(); - setPageNum(currentNum - 1); - }; - - return ( - <> -
    -
      { - if (e.target.value) setPageNum(e.target.value); - }} - > - {currentNum !== 1 ? ( -
    • - < -
    • - ) : ( -
    • e.stopPropagation()} - > - < -
    • - )} - {pageArr.map((pageNum) => { - return ( -
    • - {pageNum} -
    • - ); - })} - {totalPageCount === currentNum ? ( -
    • e.stopPropagation()} - > - > -
    • - ) : ( -
    • - > -
    • - )} -
    -
    - - ); -} diff --git a/src/components/Product.jsx b/src/components/Product.jsx deleted file mode 100644 index 467d1e1c..00000000 --- a/src/components/Product.jsx +++ /dev/null @@ -1,48 +0,0 @@ -import { memo } from "react"; -import ic_heart from "../assets/icons/ic_heart.svg"; -import { Link } from "react-router"; - -function Product({ products, style }) { - return ( - <> -
    - {products && - products.map((product) => { - return ( - -
    - -

    {product.name}

    -

    - {product.price - .toString() - .replace(/\B(?=(\d{3})+(?!\d))/g, ",") + "원"} -

    -
    - 하트_아이콘 - - {product.favoriteCount} - -
    -
    - - ); - })} -
    - - ); -} - -export default memo(Product); diff --git a/src/components/kebab/KebabDropdown.jsx b/src/components/kebab/KebabDropdown.jsx deleted file mode 100644 index 1b55f55c..00000000 --- a/src/components/kebab/KebabDropdown.jsx +++ /dev/null @@ -1,30 +0,0 @@ -import { memo, useRef } from "react"; -import { - KebabDropdownButton, - KebabDropdownContainer, -} from "../../styles/components/kebab/kebabStyle"; -import useCloseDropdown from "../../hooks/useCloseDropdown"; - -/** - * 케밥 메뉴 클릭 시 보여지는 드롭다운 - * @param {object[]} menus - * @param {Function} onclickClose - */ -const KebabDropdown = ({ menus, onClickClose }) => { - const dropdownRef = useRef(null); - useCloseDropdown(dropdownRef, onClickClose); - - return ( - - {menus?.map((menu) => { - return ( - - {menu.name} - - ); - })} - - ); -}; - -export default memo(KebabDropdown); diff --git a/src/components/kebab/KebabMenu.jsx b/src/components/kebab/KebabMenu.jsx deleted file mode 100644 index bd01b11e..00000000 --- a/src/components/kebab/KebabMenu.jsx +++ /dev/null @@ -1,29 +0,0 @@ -import useToggle from "../../hooks/useToggle"; -import { - KebabIcon, - KebabMenuContainer, -} from "../../styles/components/kebab/kebabStyle"; -import KebabDropdown from "./KebabDropdown"; - -const menus = [ - { id: "update", name: "수정하기" }, - { id: "delete", name: "삭제하기" }, -]; - -/** - * 케밥 메뉴 - */ -export default function KebabMenu() { - const { isOpen, onClickToggle, onClickClose } = useToggle(false); - - return ( - <> - - - - - {isOpen && } - - - ); -} diff --git a/src/hooks/useCloseDropdown.jsx b/src/hooks/useCloseDropdown.jsx deleted file mode 100644 index 7d53bf94..00000000 --- a/src/hooks/useCloseDropdown.jsx +++ /dev/null @@ -1,19 +0,0 @@ -import { useEffect } from "react"; - -const useCloseDropdown = (ref, callback) => { - useEffect(() => { - const onClickDropdownOutside = (event) => { - if (ref.current && !ref.current.contains(event.target)) { - callback(); - } - }; - - document.addEventListener("mousedown", onClickDropdownOutside); - - return () => { - document.removeEventListener("mousedown", onClickDropdownOutside); - }; - }, []); -}; - -export default useCloseDropdown; diff --git a/src/hooks/useMediaQuery.jsx b/src/hooks/useMediaQuery.jsx deleted file mode 100644 index 8196abdc..00000000 --- a/src/hooks/useMediaQuery.jsx +++ /dev/null @@ -1,32 +0,0 @@ -import { useEffect, useState } from "react"; - -const getMatches = (query) => { - return window.matchMedia(query).matches; -}; - -/** - * mediaQuery에 반응하여 데이터를 반환한다. - */ -export default function useMediaQuery(query) { - /** - * 반환할 데이터를 담아둘 state - */ - - const [isMatch, setIsMatch] = useState(() => getMatches(query)); - - const handleChange = (e) => { - setIsMatch(e.matches); - }; - - useEffect(() => { - const media = window.matchMedia(query); - - media.addEventListener("change", handleChange); - - return () => { - media.removeEventListener("change", handleChange); - }; - }, [query]); - - return isMatch; -} diff --git a/src/hooks/useService.jsx b/src/hooks/useService.jsx deleted file mode 100644 index a3943f7f..00000000 --- a/src/hooks/useService.jsx +++ /dev/null @@ -1,38 +0,0 @@ -import { useEffect, useState } from "react"; - -/** - * 데이터 통신을 위한 공통 커스텀 훅 - * @param {Function} fetchFunction 서버와 직접 통신하는 함수 - * @returns {data: object, isLoading: boolean, error: boolean} - */ -const useFetch = (fetchFunction) => { - const [isLoading, setIsLoading] = useState(false); - const [data, setData] = useState(); - const [error, setError] = useState(false); - - useEffect(() => { - const fetcher = async (fetching) => { - try { - setIsLoading(true); - const response = await fetching(); - - if (!response) { - throw new Error("서버와의 통신에 실패했습니다."); - } - - setData(response); - } catch (error) { - setError(true); - console.error(error); - } finally { - setIsLoading(false); - } - }; - - fetcher(fetchFunction); - }, []); - - return { data, isLoading, error }; -}; - -export default useFetch; diff --git a/src/hooks/useToggle.jsx b/src/hooks/useToggle.jsx deleted file mode 100644 index 6fe0d5bf..00000000 --- a/src/hooks/useToggle.jsx +++ /dev/null @@ -1,22 +0,0 @@ -import { useCallback, useState } from "react"; - -/** - * 토글 커스텀 훅 - * @param {boolean} initialValue 초깃값 - * @returns {isOpen: boolean, onClickToggle: Function} - */ -const useToggle = (initialValue) => { - const [isOpen, setIsOpen] = useState(initialValue); - - const onClickToggle = useCallback(() => { - setIsOpen((prevState) => !prevState); - }, [isOpen]); - - const onClickClose = useCallback(() => { - setIsOpen(false); - }, []); - - return { isOpen, onClickToggle, onClickClose }; -}; - -export default useToggle; diff --git a/src/layout/AuthLayout.tsx b/src/layout/AuthLayout.tsx deleted file mode 100644 index 6f924f9e..00000000 --- a/src/layout/AuthLayout.tsx +++ /dev/null @@ -1,42 +0,0 @@ -import { useState } from "react"; -import { Outlet } from "react-router"; -import visibleEye_off from "../assets/icons/eyes_off.png"; -import visibleEye_on from "../assets/icons/eyes_on.png"; -import { isVisibleKey, VisibleValue } from "../types/authType"; - -export default function AuthLayout() { - /** - * 비밀번호 보이기 / 가리기 상태 - */ - const [visible, setVisible] = useState({ - pw: false, - checkPw: false, - }); - - /** - * id 별로 비밀번호 가리기 여부를 변경한다. - * @param {string} id - */ - const onClickVisible = (id: string) => { - if (!isVisibleKey(id)) return; - - setVisible((prevState) => ({ - ...prevState, - [id]: !visible[id], - })); - }; - - return ( -
    - -
    - ); -} diff --git a/src/layout/Footer.tsx b/src/layout/Footer.tsx deleted file mode 100644 index 7f4769e7..00000000 --- a/src/layout/Footer.tsx +++ /dev/null @@ -1,60 +0,0 @@ -import "../styles/layout/footer.css"; -import ic_facebook from "../assets/icons/ic_facebook.svg"; -import ic_twitter from "../assets/icons/ic_twitter.svg"; -import ic_youtube from "../assets/icons/ic_youtube.svg"; -import ic_instagram from "../assets/icons/ic_instagram.svg"; - -/** - * 푸터 - */ -export default function Footer() { - return ( - <> -
    - - ); -} diff --git a/src/layout/Header.tsx b/src/layout/Header.tsx deleted file mode 100644 index 1300f215..00000000 --- a/src/layout/Header.tsx +++ /dev/null @@ -1,64 +0,0 @@ -import "../styles/layout/header.css"; -import ic_profile from "../assets/icons/ic_profile.svg"; -import { Link, NavLink, useLocation } from "react-router"; - -/** - * 헤더 - */ -export default function Header() { - /** - * 현재 주소 가져오기 - */ - const location = useLocation(); - - return ( - <> -
    -
    -
    - -
    - -
    - {location.pathname !== "/" ? ( -
      -
    • - - isActive - ? "header-menu-text header-active" - : "header-menu-text" - } - > - 자유게시판 - -
    • -
    • - - isActive || location.pathname === "/additem" - ? "header-menu-text header-active" - : "header-menu-text" - } - > - 중고마켓 - -
    • -
    - ) : null} - - {location.pathname !== "/" ? ( - 프로필_아이콘 - ) : ( - - )} - -
    -
    - - ); -} diff --git a/src/layout/ItemsLayout.jsx b/src/layout/ItemsLayout.jsx deleted file mode 100644 index 64632871..00000000 --- a/src/layout/ItemsLayout.jsx +++ /dev/null @@ -1,13 +0,0 @@ -import Header from './Header'; -import { Outlet } from 'react-router'; - -export default function ItemsLayout() { - return ( - <> -
    -
    - -
    - - ); -} diff --git a/src/layout/MainLayout.tsx b/src/layout/MainLayout.tsx deleted file mode 100644 index 481b0a02..00000000 --- a/src/layout/MainLayout.tsx +++ /dev/null @@ -1,15 +0,0 @@ -import Header from "./Header"; -import Footer from "./Footer"; -import { Outlet } from "react-router"; - -export default function MainLayout() { - return ( - <> -
    -
    - -
    -
    - - ); -} diff --git a/src/main.tsx b/src/main.tsx deleted file mode 100644 index 54517b0e..00000000 --- a/src/main.tsx +++ /dev/null @@ -1,12 +0,0 @@ -import React from "react"; -import ReactDOM from "react-dom/client"; -import App from "./App.tsx"; -import { BrowserRouter } from "react-router"; - -ReactDOM.createRoot(document.getElementById("root")!).render( - - - - - -); diff --git a/src/pages/Home.tsx b/src/pages/Home.tsx deleted file mode 100644 index 30418411..00000000 --- a/src/pages/Home.tsx +++ /dev/null @@ -1,94 +0,0 @@ -import "../styles/style.css"; -import home_top from "../assets/images/Img_home_top.png"; -import hot_item from "../assets/images/hot_item.png"; -import search_img from "../assets/images/search.png"; -import register_img from "../assets/images/register.png"; -import home_bottom from "../assets/images/Img_home_bottom.png"; -import { Link } from "react-router"; - -/** - * 메인화면 - */ -export default function Home() { - return ( - <> -
    -
    -
    -

    - 일상의 모든 물건을
    - 거래해보세요 -

    - - - -
    - main_img -
    - -
    -
    - hot_item -
    -

    Hot item

    -

    - 인기 상품을
    - 확인해 보세요 -

    -

    - 가장 HOT한 중고거래 물품을
    - 판다 마켓에서 확인해보세요 -

    -
    -
    -
    - -
    -
    -
    -

    Search

    -

    - 구매를 원하는
    - 상품을 검색하세요 -

    -

    - 구매하고 싶은 물품은 검색해서
    - 쉽게 찾아보세요 -

    -
    - search -
    -
    - -
    -
    - register -
    -

    Register

    -

    - 판매를 원하는
    - 상품을 등록하세요 -

    -

    - 어떤 물건이든 판매하고 싶은 상품을
    - 쉽게 등록하세요 -

    -
    -
    -
    - -
    -
    -

    - 믿을 수 있는
    - 판다마켓 중고 거래 -

    -
    - bottom_img -
    -
    - - ); -} diff --git a/src/pages/auth/Login.tsx b/src/pages/auth/Login.tsx deleted file mode 100644 index c692a57f..00000000 --- a/src/pages/auth/Login.tsx +++ /dev/null @@ -1,134 +0,0 @@ -import "../../styles/auth.css"; -import ic_kakao from "../../assets/icons/ic_kakao.png"; -import ic_google from "../../assets/icons/ic_google.png"; -import { Link, useOutletContext } from "react-router"; -import { useForm } from "react-hook-form"; -import { useEffect } from "react"; -import { AuthType } from "../../types/authType"; - -/** - * 로그인 화면 - */ -export default function Login() { - const { - visible, - setVisible, - onClickVisible, - visibleEye_off, - visibleEye_on, - }: AuthType = useOutletContext(); - - /** - * 기본적으로 비밀번호 숨김 상태 유지 - */ - useEffect(() => { - setVisible((prevState) => ({ - ...prevState, - pw: false, - })); - }, []); - - /** - * React-Hook-Form 사용 객체 선언 - */ - const { - register, - formState: { errors }, - // handleSubmit, - } = useForm({ mode: "onBlur" }); - - return ( - <> -
    -
    -
    - -
    - -
    - -
    -
    - - -
    - {errors.email && ( -

    잘못된 이메일입니다.

    - )} - -
    - - -
    - visible-icon { - onClickVisible(e.currentTarget.id); - }} - /> -
    -
    - {errors.password?.type === "required" && ( -

    비밀번호를 입력해주세요

    - )} - {errors.password?.type === "minLength" && ( -

    - 비밀번호를 8자 이상 입력해주세요. -

    - )} -
    - - -
    -

    간편 로그인하기

    - -
    -

    - 판다마켓이 처음이신가요?  회원가입 -

    -
    -
    - - ); -} diff --git a/src/pages/auth/Signup.tsx b/src/pages/auth/Signup.tsx deleted file mode 100644 index af91acf5..00000000 --- a/src/pages/auth/Signup.tsx +++ /dev/null @@ -1,217 +0,0 @@ -import { Link, useOutletContext } from "react-router"; -import "../../styles/auth.css"; -import ic_kakao from "../../assets/icons/ic_kakao.png"; -import ic_google from "../../assets/icons/ic_google.png"; -import { useEffect, useState } from "react"; -import { useForm } from "react-hook-form"; -import { AuthType, SignupType } from "../../types/authType"; - -/** - * 회원가입 화면 - */ -export default function Signup() { - const { - visible, - setVisible, - onClickVisible, - visibleEye_off, - visibleEye_on, - }: AuthType = useOutletContext(); - - /** - * 기본적으로 비밀번호 숨김 상태 유지 - */ - useEffect(() => { - setVisible((prevState) => ({ - ...prevState, - pw: false, - })); - }, []); - - /** - * 회원가입 양식 정보를 담고 있는 객체 - * 이메일, 닉네임, 비밀번호, 비밀번호 확인 - */ - const [signupForm, setSignupForm] = useState({ - email: "", - nickname: "", - pw: "", - }); - - // const onValid = (data) => { - // console.log("✅ 유효성 검사 성공! 데이터:", data); - // setSignupForm(data); - // }; - - /** - * React-Hook-Form 사용 객체 선언 - */ - const { - register, - formState: { errors, isValid }, - // handleSubmit, - getValues, - } = useForm({ - mode: "onBlur", - }); - console.log(isValid); - - return ( - <> -
    -
    -
    - -
    - -
    - -
    -
    -
    - - -
    - {errors.email && ( -

    잘못된 이메일입니다.

    - )} - -
    - - -
    - {errors.nickname?.type === "required" && ( -

    닉네임을 입력해주세요

    - )} - {errors.nickname?.type === "maxLength" && ( -

    닉네임이 너무 깁니다.

    - )} - -
    - - -
    - visible-icon { - onClickVisible(e.currentTarget.id); - }} - /> -
    -
    - {errors.password?.type === "required" && ( -

    비밀번호를 입력해주세요

    - )} - {errors.password?.type === "minLength" && ( -

    - 비밀번호를 8자 이상 입력해주세요. -

    - )} - -
    - - - getValues("password") === getValues("confirmPassword"), - })} - /> -
    - visible-icon { - onClickVisible(e.currentTarget.id); - }} - /> -
    -
    - {errors.confirmPassword?.type === "minLength" && ( -

    - 비밀번호를 8자 이상 입력해주세요. -

    - )} - {errors.confirmPassword?.type === "validate" && ( -

    비밀번호가 일치하지 않습니다.

    - )} -
    - -
    - -
    -

    간편 로그인하기

    - -
    - -

    - 이미 회원이신가요?  로그인 -

    -
    -
    - - ); -} diff --git a/src/pages/components/ItemDetail/InquiryList.jsx b/src/pages/components/ItemDetail/InquiryList.jsx deleted file mode 100644 index 16dfc373..00000000 --- a/src/pages/components/ItemDetail/InquiryList.jsx +++ /dev/null @@ -1,64 +0,0 @@ -import KebabMenu from "../../../components/kebab/KebabMenu"; -import { palette } from "../../../styles/commonStyles"; -import { - InquiryContent, - InquiryDate, - InquiryProfileImg, - InquiryWriter, -} from "../../../styles/components/InquiryStyles"; -import icProfile from "../../../assets/icons/ic_profile.svg"; -import imgEmptyMd from "../../../assets/images/img_inquiry_empty_md.png"; -import { formatTimeAgo } from "../../../util/formatTimeAgo"; - -const InquiryList = ({ data }) => { - return data?.list?.length > 0 ? ( - data.list?.map((el) => { - return ( -
    -
    - {el.content} - -
    -
    - -
    - {el.writer.nickname} - {formatTimeAgo(el.updatedAt)} -
    -
    -
    - ); - }) - ) : ( -
    - 빈 이미지 -

    - 아직 문의가 없어요 -

    -
    - ); -}; - -export default InquiryList; diff --git a/src/pages/components/ItemDetail/ProductDetails.jsx b/src/pages/components/ItemDetail/ProductDetails.jsx deleted file mode 100644 index 2f71f78b..00000000 --- a/src/pages/components/ItemDetail/ProductDetails.jsx +++ /dev/null @@ -1,74 +0,0 @@ -import { ItemsTag, palette, ProfileImg } from "../../../styles/commonStyles"; -import { - Heart, - HeartCount, - ProductDate, - ProductOwnerName, - ProductPrice, - ProductSubTitle, - ProductTagContainer, - ProductTagWrapper, - ProductTextArea, - ProductTextBox, - ProductTitle, -} from "../../../styles/items/ItemDetailStyle"; -import icProfile from "../../../assets/icons/ic_profile.svg"; -import icHeartInactive from "../../../assets/icons/ic_heart_inactive_large.svg"; -import icHeartActive from "../../../assets/icons/ic_heart_active_large.svg"; -import KebabMenu from "../../../components/kebab/KebabMenu"; - -export default function ProductDetails({ data, productInfo, isLoading }) { - return ( - -
    -
    - {productInfo.name} - -
    - - {productInfo.price.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",") + - "원"} - -
    -
    - 상품 소개 - {productInfo.description} -
    - - 상품 태그 - - {productInfo.tags.map((tag) => { - return {`#${tag}`}; - })} - - -
    - -
    - - {!isLoading ? data?.ownerNickname : "..."} - - - {productInfo.updatedAt.slice(0, 10).replaceAll("-", ". ")} - -
    -
    - - {!isLoading && data?.isFavorite ? ( - 좋아요 이미지 - ) : ( - 좋아요 이미지 - )} - {productInfo.favoriteCount} - -
    -
    -
    - ); -} diff --git a/src/pages/items/AddItem.jsx b/src/pages/items/AddItem.jsx deleted file mode 100644 index ca01885a..00000000 --- a/src/pages/items/AddItem.jsx +++ /dev/null @@ -1,257 +0,0 @@ -import styled from "styled-components"; -import ImgInput, { DeleteButton } from "../../components/ImgInput"; -import { ItemsTag, palette } from "../../styles/commonStyles"; -import { useState } from "react"; -import { useFieldArray, useForm } from "react-hook-form"; - -const ItemContainer = styled.div` - width: 1200px; - display: flex; - flex-direction: column; - margin: 0px auto; - margin-bottom: 20px; - - @media (max-width: 1200px) { - width: 696px; - } - - @media (max-width: 768px) { - width: 346px; - } -`; - -const ItemTitleBox = styled.div` - width: 1200px; - display: flex; - justify-content: space-between; - align-items: center; - margin: 20px auto; - - @media (max-width: 1200px) { - width: 696px; - } - - @media (max-width: 768px) { - width: 346px; - } -`; - -const ItemImgBox = styled(ItemTitleBox)` - justify-content: start; - margin: 0 auto; -`; - -/** - * 페이지 타이틀 - * sub 옵션으로 서브 타이트롤 변환 - */ -const PageTitle = styled.h1` - font-size: ${({ sub }) => (sub ? `18px` : `20px`)}; - font-weight: 700; -`; - -/** - * 등록 버튼 - */ -const SubmitButton = styled.button` - width: 74px; - height: 42px; - border: none; - border-radius: 8px; - background-color: ${({ isValid }) => - isValid ? `${palette.blue}` : `${palette.gray400}`}; - color: white; - font-size: 16px; - font-weight: 600; -`; - -/** - * 상품 정보 입력 input - */ -const TextInput = styled.input` - height: 56px; - border: none; - border-radius: 12px; - background-color: ${palette.gray100}; - padding: 20px; - font-size: 16px; - position: relative; - &::placeholder { - color: ${palette.gray400}; - } -`; - -/** - * 상품 소개 입력 textarea - */ -const TextArea = styled.textarea` - height: 282px; - border: none; - border-radius: 12px; - background-color: ${palette.gray100}; - padding: 20px; - font-size: 16px; - position: relative; - font-family: "Pretendard-Regular"; - &::placeholder { - color: ${palette.gray400}; - } -`; - -const ItemsTagDeleteButton = styled(DeleteButton)` - position: relative; - z-index: 0; - transform: none; -`; - -/** - * 상품 등록 페이지 컴포넌트 - */ -export default function AddItem() { - /** - * 이미지가 등록되어있는지 여부를 확인하는 state - */ - const [isUpload, setIsUpload] = useState(false); - - const { - register, - handleSubmit, - control, - formState: { error, isValid }, - } = useForm({ - mode: "onChange", - defaultValues: { productName: "", description: "", price: "" }, - }); - - const { fields, append, remove } = useFieldArray({ - control, - name: "tags", - rules: { - required: true, - }, - }); - - /** - * 입력받은 가격을 원화 형식으로 변환하는 함수 - * @param {React.ChangeEvent} e - */ - const onChangePrice = (e) => { - let rawPrice = e.target.value.replace(/[^0-9]/g, ""); - - if (rawPrice === "") { - e.target.value = ""; - return; - } - - let formattedPrice = Number(rawPrice).toLocaleString("ko-KR"); - e.target.value = formattedPrice; - }; - - /** - * Enter키를 입력으로 태그를 form에 등록하고 태그 입력 창을 비우는 만드는 함수 - * @param {KeyboardEvent} e - */ - const onKeyDownAppendTag = (e) => { - if (e.nativeEvent.isComposing) return; - - if (e.key === "Enter") { - e.preventDefault(); - - if (e.target.value.trim() !== "") { - append({ value: e.target.value }); - e.target.value = ""; - } - } - }; - - const onSubmit = (e) => { - e.preventDefault(); - }; - - return ( - <> -
    -
    - - 상품 등록하기 - 등록 - - - - 상품 이미지 - - - - {isUpload && ( -

    - *이미지 등록은 최대 1개까지 가능합니다. -

    - )} -
    - - - 상품명 - - - - - 상품 소개 - - - - - 판매 가격 - onChangePrice(e), - })} - /> - - - - 태그 - -
    - {fields.map((tag, idx) => { - return ( - - {`#${tag.value}`} - remove(idx)} - > - - ); - })} -
    -
    -
    -
    - - ); -} diff --git a/src/pages/items/ItemDetail.jsx b/src/pages/items/ItemDetail.jsx deleted file mode 100644 index 9e0105fd..00000000 --- a/src/pages/items/ItemDetail.jsx +++ /dev/null @@ -1,44 +0,0 @@ -import { useLocation, useParams } from "react-router"; -import { requestProductDetail } from "../../services/itemsApi"; -import { - ProductDetailContainer, - ProductImg, - ProductInfoBox, -} from "../../styles/items/ItemDetailStyle"; - -import Inquiry from "../../components/Inquiry"; -import useFetch from "../../hooks/useService"; -import ProductDetails from "../components/ItemDetail/ProductDetails"; - -export default function ItemDetail() { - /** - * 상품의 id - */ - const { productId } = useParams(); - - /** - * 목록에서 가져온 상품 정보 - */ - const { state: productInfo } = useLocation(); - - /** - * 상품 정보 받아오기 - */ - const { data, isLoading } = useFetch(() => requestProductDetail(productId)); - - return ( - <> - - - - - - - - - ); -} diff --git a/src/pages/items/Items.jsx b/src/pages/items/Items.jsx deleted file mode 100644 index 10ef71a4..00000000 --- a/src/pages/items/Items.jsx +++ /dev/null @@ -1,158 +0,0 @@ -import { useEffect, useState } from "react"; -import Product from "../../components/Product"; -import "../../styles/items/items.css"; -import { requestProductList } from "../../services/itemsApi"; -import DropdownList from "../../components/DropdownList"; -import Pagination from "../../components/Pagination"; -import useMediaQuery from "../../hooks/useMediaQuery"; -import { Link } from "react-router"; - -export default function Items() { - /** - * tablet 뷰포트인지 확인 - */ - const isTablet = useMediaQuery("(max-width: 1200px)"); - - /** - * mobile 뷰포트인지 확인 - */ - const isMobile = useMediaQuery("(max-width: 768px)"); - - /** - * 뷰포트별로 표시할 아이템 개수 - */ - const [itemCounts, setItemsCounts] = useState({ best: 4, all: 10 }); - - /** - * 전체 상품 목록 - */ - const [products, setProducts] = useState({}); - - /** - * 베스트 상품 목록 - */ - const [bestProducts, setBestProducts] = useState([]); - - /** - * 현재 페이지 번호 - */ - const [pageNum, setPageNum] = useState(1); - - /** - * 정렬 조건 - */ - const [order, setOrder] = useState("recent"); - - /** - * isLoading - */ - const [isLoading, setIsLoading] = useState(true); - - /** - * 베스트 상품 목록을 가져온다. - */ - const getBestProducts = async (querys) => { - const bestQuery = { - page: 1, - pageSize: querys.best, - orderBy: "favorite", - }; - - try { - const { list: bestList } = await requestProductList(bestQuery); - if (!bestList) { - throw new Error("베스트 상품 목록 데이터를 불러오지 못했습니다."); - } - setBestProducts(bestList); - } catch (e) { - console.error(e); - } finally { - setIsLoading(false); - } - }; - - /** - * 전체 상품 목록을 가져온다. - */ - const getProducts = async (querys) => { - querys.pageSize = querys.all; - - try { - const productList = await requestProductList(querys); - if (!productList) { - throw new Error("상품목록 데이터를 불러오지 못했습니다."); - } - setProducts(productList); - } catch (e) { - console.error(e); - } finally { - setIsLoading(false); - } - }; - - useEffect(() => { - /** - * 현재 뷰포트에 맞추어 count를 담을 객체 - */ - let querys = { - orderBy: order, - page: pageNum, - best: 4, - all: 10, - }; - let currentItemCounts; - - if (isMobile) { - // 모바일 뷰 - currentItemCounts = { best: 1, all: 4 }; - querys.best = 1; - querys.all = 4; - } else if (isTablet) { - // 태블릿 뷰 - currentItemCounts = { best: 2, all: 6 }; - querys.best = 2; - querys.all = 6; - } else { - // 데스크탑 뷰 - currentItemCounts = { best: 4, all: 10 }; - querys.best = 4; - querys.all = 10; - } - - setItemsCounts(currentItemCounts); - getProducts(querys); - getBestProducts(querys); - }, [isTablet, isMobile, order, pageNum]); - - return ( - <> -
    -
    -

    베스트 상품

    - {!isLoading && } -
    -
    -
    -

    전체 상품

    - - - -
    - {!isLoading && } -
    - -
    - - ); -} diff --git a/src/services/inquiryApi.js b/src/services/inquiryApi.js deleted file mode 100644 index e22edd35..00000000 --- a/src/services/inquiryApi.js +++ /dev/null @@ -1,46 +0,0 @@ -const BASE_URL = import.meta.env.VITE_BASE_URL; - -/** - * 문의 데이터를 가져온다. - * @param {string} productId - */ -export const requestInquiryLists = async (productId) => { - const url = new URL(`${BASE_URL}products/${productId}/comments`); - url.searchParams.append("limit", 3); - - const response = await fetch(url, { - method: "get", - headers: { - "Content-Type": "application/json", - }, - }); - - return response.json(); -}; - -/** - * 문의 내용을 등록한다. - * @param {object{}} inquiryData 상품 아이디와 문의 내역 객체 - * @returns - */ -export const requestPostInquiry = async (inquiryData) => { - const url = new URL(`${BASE_URL}products/${inquiryData.productId}/comments`); - - try { - const response = await fetch(url, { - method: "POST", - headers: { - "Content-Type": "application/json", - }, - body: JSON.stringify(inquiryData.inquiry), - }); - - if (!response.ok) { - alert("데이터를 전송하지 못했습니다. 다시 시도해주세요"); - } - - return response.json(); - } catch (error) { - console.error(error); - } -}; diff --git a/src/services/itemsApi.js b/src/services/itemsApi.js deleted file mode 100644 index 2d26357f..00000000 --- a/src/services/itemsApi.js +++ /dev/null @@ -1,40 +0,0 @@ -const BASE_URL = import.meta.env.VITE_BASE_URL; - -/** - * 서버에 상품 목록을 요청한다. - * @param {string} orderBy - * @returns {object} - */ -export const requestProductList = async (query) => { - const url = new URL(`${BASE_URL}products`); - url.searchParams.append("page", query.page); - url.searchParams.append("pageSize", query.pageSize); - url.searchParams.append("orderBy", query.orderBy); - - const response = await fetch(url, { - method: "get", - headers: { - "Content-Type": "application/json", - }, - }); - - return response.json(); -}; - -/** - * 상품의 상세 정보를 요청한다. - * @param {string} productId - * @returns {json} response - */ -export const requestProductDetail = async (productId) => { - const url = new URL(`${BASE_URL}products/${productId}`); - - const response = await fetch(url, { - method: "get", - headers: { - "Content-Type": "application/json", - }, - }); - - return response.json(); -}; diff --git a/src/styles/auth.css b/src/styles/auth.css deleted file mode 100644 index 9b750c1d..00000000 --- a/src/styles/auth.css +++ /dev/null @@ -1,159 +0,0 @@ -@font-face { - font-family: 'Pretendard-Regular'; - src: url('https://fastly.jsdelivr.net/gh/Project-Noonnu/noonfonts_2107@1.1/Pretendard-Regular.woff') - format('woff'); - font-weight: 400; - font-style: normal; -} - -.auth-main-container { - display: flex; - justify-content: center; - align-items: center; - margin: 0 auto; - height: 100vh; -} - -.basic-p { - font-size: 18px; - font-weight: 700; -} - -.form-box { - display: flex; - flex-direction: column; - justify-content: center; - align-content: center; -} - -.input-box { - width: 100%; - height: 56px; - border-radius: 12px; - border: none; - background-color: var(--gray100); - padding: 20px; - margin: 10px 0px 0px; - font-size: 16px; - font-weight: 400; -} - -input::placeholder { - color: var(--gray400); -} - -.auth-btn { - width: 100%; - height: 56px; - border: none; - border-radius: 40px; - margin: 20px 0px 20px 0; - background-color: var(--gray400); - color: white; - font-size: 20px; - font-weight: 600; -} - -.btn-active { - background-color: var(--blue); - cursor: pointer; -} - -.container { - display: flex; - flex-direction: column; - justify-content: center; - width: 640px; - height: 618px; - margin: 0 auto; -} - -.auth-logo { - text-align: center; - margin: 0 auto; -} - -.auth-logo-img { - background-image: url('../assets/images/logo_lg.png'); - background-repeat: no-repeat; - width: 396px; - height: 132px; -} - -.email-box, -.nickname-box { - margin-top: 20px; -} - -.pw-box { - position: relative; - display: flex; - flex-direction: column; - margin-top: 20px; -} - -.auth-visible-icon { - width: 25px; - height: 20px; - background-repeat: no-repeat; - position: absolute; - top: 45px; - right: 15px; - cursor: pointer; -} - -.social-login-container { - background-color: #e6f2ff; - display: flex; - justify-content: space-between; - align-items: center; - padding: 10px 20px; - border-radius: 8px; -} - -.social-login-container p { - font-weight: 500; - font-size: 16px; -} - -.sns-icon-box img { - margin: 0 5px; -} - -.link-signup { - display: flex; - justify-content: center; - font-size: 14px; - font-weight: 500; -} - -.link-signup a { - color: var(--blue); -} - -/* 에러 스타일 */ -.auth-err-border { - border: 1px solid #ff0000; -} - -.auth-err-msg { - color: #ff0000; - margin-top: 10px; - font-size: 14px; -} - -/* mobile */ -@media (max-width: 767px) { - .container { - width: 400px; - padding: 0 16px; - margin: 0; - } - - .auth-logo-img { - background-image: url('../assets/images/logo_md.png'); - background-repeat: no-repeat; - width: 198px; - height: 66px; - } -} diff --git a/src/styles/colors.css b/src/styles/colors.css deleted file mode 100644 index a9c156a6..00000000 --- a/src/styles/colors.css +++ /dev/null @@ -1,13 +0,0 @@ -:root { - --gray900: #111827; - --gray800: #1f2937; - --gray700: #374151; - --gray600: #4b5563; - --gray500: #6b7280; - --gray400: #9ca3af; - --gray200: #e5e7eb; - --gray100: #f3f4f6; - --gray50: #f9fafb; - --blue: #3692ff; - --menu: #4b5563; -} diff --git a/src/styles/commonStyles.js b/src/styles/commonStyles.js deleted file mode 100644 index ce33a4e4..00000000 --- a/src/styles/commonStyles.js +++ /dev/null @@ -1,41 +0,0 @@ -import styled from "styled-components"; - -export const palette = { - secondary: { - gray500: "#6B7280", - }, - gray900: "#111827", - gray800: "#1f2937", - gray700: "#374151", - gray600: "#4b5563", - gray500: "#6b7280", - gray400: "#9ca3af", - gray200: "#e5e7eb", - gray100: "#f3f4f6", - gray50: "#f9fafb", - coolGray300: "#D1D5DB", - blue: "#3692ff", - menu: "#4b5563", -}; - -/** - * 태그 지우기 버튼 div - */ -export const ItemsTag = styled.div` - gap: 10px; - height: 36px; - border: none; - background-color: ${palette.gray100}; - font-size: 16px; - border-radius: 999px; - display: flex; - justify-content: space-evenly; - align-items: center; - padding: 15px; - margin-right: 10px; -`; - -export const ProfileImg = styled.img` - width: 40px; - height: 40px; -`; diff --git a/src/styles/components/InquiryStyles.js b/src/styles/components/InquiryStyles.js deleted file mode 100644 index cac63e29..00000000 --- a/src/styles/components/InquiryStyles.js +++ /dev/null @@ -1,112 +0,0 @@ -import styled from "styled-components"; -import { palette, ProfileImg } from "../commonStyles"; - -export const InquiryTextArea = styled.textarea` - background-color: ${palette.gray100}; - height: 104px; - width: 100%; - border: none; - border-radius: 12px; - resize: none; - font-family: Pretendard-Reqular; - padding: 20px; - font-size: 14px; - font-weight: 400; - margin-bottom: 10px; - &::placeholder { - color: ${palette.gray400}; - } - - @media (min-width: 744px) { - font-size: 16px; - line-height: 26px; - letter-spacing: 0%; - } -`; - -export const InquiryTitle = styled.p` - color: ${palette.gray900}; - font-weight: 600; - font-size: 16px; - margin: 40px 0px 10px; - text-align: left; -`; - -export const InquirySubmitButton = styled.button` - width: 74px; - height: 42px; - border: none; - color: white; - padding: 10px; - border-radius: 8px; - font-size: 16px; - font-weight: 600; - background-color: ${({ isActive }) => - isActive ? `${palette.blue}` : `${palette.gray400}`}; - - &:hover { - background-color: ${({ isActive }) => - isActive ? `#1967d6` : `${palette.gray400}`}; - } - - &:active { - background-color: ${({ isActive }) => - isActive ? `#1251aa` : `${palette.gray400}`}; - } -`; - -export const InquiryContent = styled.p` - margin: 0; - color: ${palette.gray800}; - font-size: 14px; - font-weight: 400; -`; - -export const InquiryProfileImg = styled(ProfileImg)` - width: 32px; - height: 32px; -`; - -export const InquiryWriter = styled.p` - margin: 0px 0px 5px; - font-size: 12px; - font-weight: 400; -`; - -export const InquiryDate = styled.p` - margin: 0; - font-size: 12px; - font-weight: 400; - color: ${palette.gray400}; -`; - -export const BackButtonWrapper = styled.div` - margin: 60px 0px 60px; - text-align: center; - display: flex; - justify-content: center; -`; - -export const BackButton = styled.button` - width: 240px; - height: 48px; - border: none; - background-color: ${palette.blue}; - color: white; - padding: 10px; - border-radius: 40px; - font-size: 18px; - font-weight: 600; - justify-content: center; - align-items: center; - display: flex; - gap: 10px; - - &:hover { - background-color: #1967d6; - } - - &:active { - background-color: #1251aa; - } -`; diff --git a/src/styles/components/dropDownList.css b/src/styles/components/dropDownList.css deleted file mode 100644 index f4a7b31a..00000000 --- a/src/styles/components/dropDownList.css +++ /dev/null @@ -1,82 +0,0 @@ -.dropdown-container { - display: flex; - flex-direction: column; - position: relative; -} - -.dropdown-btn { - width: 130px; - height: 42px; - background-color: white; - border: 1px solid var(--gray200); - border-radius: 12px; - text-align: left; - background-image: url('../../assets/icons/ic_arrow_down.svg'); - background-repeat: no-repeat; - background-position: 90px; - padding: 0px 20px 0px 20px; - font-size: 16px; -} - -.dropdown-box { - background-color: white; - border: 1px solid var(--gray200); - border-radius: 12px; - width: 130px; - display: flex; - flex-direction: column; - position: absolute; - top: 100%; - left: 0; - margin-top: 10px; - z-index: 8888; -} - -.dropdown-li { - width: 130px; - padding: 10.5px; - list-style: none; - text-align: center; - border-bottom: 1px solid var(--gray200); - cursor: pointer; -} - -.dropdown-li:hover { - background-color: var(--gray100); -} - -.dropdown-li:active { - background-color: var(--gray200); -} - -.dropdown-li:last-child { - border-bottom: none; -} - -.dropdown-menu-btn { - width: 100%; - height: 42px; - background-color: white; - border: none; - border-radius: 12px; -} - -@media (max-width: 768px) { - .dropdown-container { - width: 42px; - left: 91px; - } - - .dropdown-btn { - width: 42px; - text-indent: -9999px; - background-image: url('../../assets/icons/ic_sort.svg'); - background-position: center; - background-repeat: no-repeat; - } - - .dropdown-box { - left: 100%; - transform: translate(-100%); - } -} diff --git a/src/styles/components/kebab/kebabStyle.js b/src/styles/components/kebab/kebabStyle.js deleted file mode 100644 index 37c9d153..00000000 --- a/src/styles/components/kebab/kebabStyle.js +++ /dev/null @@ -1,57 +0,0 @@ -import styled from "styled-components"; -import { palette } from "../../commonStyles"; - -export const KebabMenuContainer = styled.div` - display: flex; - flex-direction: column; - justify-content: center; - align-items: center; - gap: 2px; - width: 24px; - height: 24px; - cursor: pointer; - position: relative; -`; - -export const KebabIcon = styled.div` - width: 3px; - height: 3px; - background-color: ${palette.gray400}; - border-radius: 99px; -`; - -export const KebabDropdownContainer = styled.div` - width: 139px; - display: flex; - flex-direction: column; - position: absolute; - top: 100%; - right: 7%; - margin-top: 5px; - border: 1px solid ${palette.coolGray300}; - border-radius: 8px; - z-index: 50; - - & > :first-child { - border-top-right-radius: 8px; - border-top-left-radius: 8px; - } - - & > :last-child { - border-bottom-right-radius: 8px; - border-bottom-left-radius: 8px; - } -`; - -export const KebabDropdownButton = styled.button` - background-color: white; - border: none; - font-weight: 400; - font-size: 16px; - color: ${palette.secondary.gray500}; - padding: 16px 0px 12px; - - &:hover { - background-color: ${palette.gray100}; - } -`; diff --git a/src/styles/components/pagination.css b/src/styles/components/pagination.css deleted file mode 100644 index 93368131..00000000 --- a/src/styles/components/pagination.css +++ /dev/null @@ -1,32 +0,0 @@ -.pgn-container { - padding: 40px 0px 40px 0px; - display: flex; - justify-content: center; - align-items: center; -} - -.pgn-ul { - margin: 0; - padding: 0; - list-style: none; -} - -.pgn-ul > li { - display: inline-block; - width: 40px; - height: 40px; - border: 1px solid var(--gray200); - border-radius: 40px; - text-align: center; - padding: 10px; - font-size: 16px; - font-weight: 600; - color: var(--gray600); - cursor: pointer; - margin: 2px; -} - -.pgn-ul .pgn-disabled { - color: var(--gray400); - cursor: default; -} diff --git a/src/styles/items/ItemDetailStyle.js b/src/styles/items/ItemDetailStyle.js deleted file mode 100644 index e20d3ecc..00000000 --- a/src/styles/items/ItemDetailStyle.js +++ /dev/null @@ -1,181 +0,0 @@ -import styled from "styled-components"; -import { ItemsTag, palette } from "../commonStyles"; - -export const ProductDetailContainer = styled.div` - width: 100%; - margin: 0 auto; - max-width: 1200px; - padding: 16px 16px 0px 16px; - - @media (min-width: 744px) { - padding: 24px 24px 0px 24px; - } -`; - -export const ProductInfoBox = styled.div` - display: flex; - margin-top: 20px; - border-bottom: 1px solid ${palette.gray200}; - padding-bottom: 40px; - flex-direction: column; - - @media (min-width: 744px) { - flex-direction: row; - } -`; - -export const ProductTextBox = styled.div` - display: flex; - flex-direction: column; - width: 100%; -`; - -export const ProductImg = styled.img` - border-radius: 16px; - border: none; - - @media (min-width: 375px) { - width: 343px; - height: 343px; - margin: 0; - margin-bottom: 16px; - } - - @media (min-width: 744px) { - margin-right: 16px; - } - - @media (min-width: 1200px) { - margin-right: 20px; - width: 486px; - height: 486px; - } -`; - -export const ProductTitle = styled.h1` - font-weight: 600; - margin: 0; - - @media (min-width: 375px) { - font-size: 16px; - line-height: 26px; - } - - @media (min-width: 744px) { - font-size: 20px; - line-height: 32px; - letter-spacing: 0%; - } - - @media (min-width: 1200px) { - font-size: 24px; - line-height: 32px; - letter-spacing: 0%; - } -`; - -export const ProductPrice = styled.p` - font-weight: 600; - - @media (min-width: 375px) { - font-size: 24px; - line-height: 32px; - margin: 8px 0px 16px; - } - - @media (min-width: 744px) { - font-size: 32px; - line-height: 42px; - letter-spacing: 0%; - } - - @media (min-width: 1200px) { - font-size: 40px; - line-height: 32px; - letter-spacing: 0%; - margin: 20px 0px 16px; - } -`; - -export const ProductSubTitle = styled.p` - color: ${palette.gray600}; - - @media (min-width: 375px) { - font-size: 14px; - line-height: 24px; - letter-spacing: 0%; - margin: 16px 0px 8px; - } - - @media (min-width: 1200px) { - font-size: 16px; - font-weight: 600; - margin: 20px 0px; - } -`; - -export const ProductTextArea = styled.p` - color: ${palette.gray600}; - width: 100%; - margin: 0; - - @media (min-width: 375px) { - font-size: 16px; - line-height: 26px; - letter-spacing: 0%; - } -`; - -export const ProductTagWrapper = styled.div` - @media (min-width: 375px) { - margin-bottom: 40px; - } - - @media (min-width: 1200px) { - margin-bottom: 100px; - } -`; - -export const ProductTagContainer = styled.div` - display: flex; - flex-wrap: wrap; - row-gap: 10px; -`; - -export const ProductOwnerName = styled.p` - font-size: 14px; - font-weight: 500; - margin: 0px 0px 10px 0px; - color: ${palette.gray600}; -`; - -export const ProductDate = styled.p` - font-size: 14px; - font-weight: 400; - color: ${palette.gray400}; - margin: 0; -`; - -export const Heart = styled.div` - border: 1px solid ${palette.gray200}; - border-radius: 35px; - background-color: white; - display: flex; - justify-content: space-between; - column-gap: 5px; - padding: 2px 10px; - align-items: center; - transition: transform 0.3s ease; - - &:hover { - cursor: pointer; - transform: scale(1.1); - } -`; - -export const HeartCount = styled.p` - font-size: 16px; - font-weight: 500; - color: ${palette.gray500}; - margin: 0; -`; diff --git a/src/styles/items/items.css b/src/styles/items/items.css deleted file mode 100644 index bd6a7a69..00000000 --- a/src/styles/items/items.css +++ /dev/null @@ -1,178 +0,0 @@ -.items-container { - height: 100vh; -} - -.items-best-container { - display: flex; - margin: 0 auto; - width: 1200px; - justify-content: flex-start; - flex-direction: column; -} - -.items-title { - margin: 30px 0px 30px 0px; - font-size: 20px; - font-weight: 700; -} - -.items-list-container { - width: 1200px; - margin: 20px auto; - display: flex; - flex-direction: column; -} - -.items-menus { - width: 100%; - display: flex; - flex-direction: row; - align-items: center; -} - -.title-text { - flex-grow: 1; -} - -.items-search { - width: 325px; - height: 42px; - background-color: var(--gray100); - border: none; - border-radius: 12px; - text-align: start; - font-size: 16px; - background-image: url('../../assets/icons/ic_search.svg'); - background-repeat: no-repeat; - background-position: 15px; - padding: 0px 10px 0px 40px; -} - -.items-add-btn { - margin: 0px 10px 0px 10px; - width: 133px; - height: 42px; -} - -.product-container { - display: grid; - grid-template-columns: repeat(4, 282px); - gap: 24px; -} - -.product-all { - grid-template-columns: repeat(5, 1fr); - gap: 21px; -} - -.product-img { - border-radius: 16px; - width: 282px; - height: 282px; -} - -.product-img-all { - border-radius: 16px; - width: 221px; - height: 221px; -} - -.product-name { - font-size: 14px; - font-weight: 500; -} - -.product-price { - font-size: 16px; - font-weight: 700; -} - -.product-favorite-container { - display: flex; - align-items: center; -} - -.product-favorite-count { - font-size: 12px; - margin-left: 5px; - color: var(--gray600); -} - -/* tablet */ -@media (max-width: 1200px) { - .items-best-container { - width: 696px; - /* margin: 0px 10px 0px 10px; */ - justify-content: center; - } - - .items-list-container { - width: 696px; - } - - .items-search { - width: 242px; - } - - .product-container { - grid-template-columns: repeat(2, 1fr); - } - - .product-all { - display: grid; - grid-template-columns: repeat(3, 1fr); - grid-template-rows: repeat(2, 1fr); - gap: 15px; - } - - .product-img { - border-radius: 16px; - width: 343px; - height: 343px; - } -} - -/* mobile */ -@media (max-width: 768px) { - .items-best-container { - width: 344px; - } - - .items-list-container { - width: 344px; - } - - .items-menus { - display: grid; - grid-template-columns: 211px 133px; - row-gap: 5px; - margin-bottom: 10px; - } - - .title-text { - margin: 0; - grid-row: 1 / 2; - grid-column: 1 / 2; - } - - .items-search { - width: 288px; - grid-row: 2 / 3; - /* grid-column: 2 / 3; */ - } - - .items-add-btn { - margin: 0; - grid-row: 1 / 2; - } - - .product-all { - grid-template-columns: repeat(2, 168px); - gap: 10px; - } - - .product-img-all { - width: 168px; - height: 168px; - } -} diff --git a/src/styles/layout/footer.css b/src/styles/layout/footer.css deleted file mode 100644 index 7676136c..00000000 --- a/src/styles/layout/footer.css +++ /dev/null @@ -1,78 +0,0 @@ -@font-face { - font-family: 'Pretendard-Regular'; - src: url('https://fastly.jsdelivr.net/gh/Project-Noonnu/noonfonts-2107@1.1/Pretendard-Regular.woff') - format('woff'); - font-weight: 400; - font-style: normal; -} - -.footer-container { - height: 160px; - background-color: var(--gray900); - display: flex; - justify-content: center; -} - -.bottom-content-box { - width: 1110px; - padding-bottom: 60px; - display: flex; - align-items: center; - justify-content: space-between; -} - -.copyright { - color: var(--gray400); - font-size: 16px; - font-weight: 400; -} - -.footer-menu a { - color: var(--gray200); - font-size: 16px; - font-weight: 400; - padding: 15px; -} - -.sns-menu ul { - padding: 0; -} - -.sns-menu ul > li { - list-style: none; - display: inline-block; - padding: 5px; -} - -/* tablet */ -@media (max-width: 1199px) { - .bottom-content-box { - width: 768px; - padding: 0px 0px 60px; - justify-content: space-around; - } -} - -/* mobile */ -@media (max-width: 767px) { - .bottom-content-box { - display: grid; - grid-template-columns: 180px 150px; - justify-content: center; - padding: 0px 10px 0px 20px; - } - - .copyright { - grid-row: 2/3; - padding: 15px; - } - - .privacy { - grid-row: 1/2; - } - - .sns-menu { - grid-column: 2/3; - justify-items: center; - } -} diff --git a/src/styles/layout/header.css b/src/styles/layout/header.css deleted file mode 100644 index 965958bb..00000000 --- a/src/styles/layout/header.css +++ /dev/null @@ -1,106 +0,0 @@ -@font-face { - font-family: 'Pretendard-Regular'; - src: url('https://fastly.jsdelivr.net/gh/Project-Noonnu/noonfonts-2107@1.1/Pretendard-Regular.woff') - format('woff'); - font-weight: 400; - font-style: normal; -} - -header { - top: 0; - height: 70px; - background-color: white; - display: flex; - justify-content: center; - position: sticky; - border-bottom: 1px solid #dfdfdf; - z-index: 9999; -} - -.header-link-text { - text-decoration: none; - color: white; - font-weight: 600; - cursor: pointer; -} - -.logo { - width: 100%; - display: flex; - justify-content: space-between; - padding: 10px 200px; -} - -.logo-img { - background-image: url('../../assets/images/logo_sm.png'); - background-repeat: no-repeat; - width: 198px; - height: 66px; -} - -.header-menu-box { - flex-grow: 4; - padding: 0; -} - -.header-menu { - list-style: none; - align-items: center; - display: inline-block; -} - -.header-menu-text { - font-weight: 600; - font-size: 18px; - color: var(--menu); -} - -.header-active { - color: var(--blue); -} - -.header-menu:first-child ~ li { - padding-left: 30px; -} - -.header-login-btn { - width: 128px; - height: 48px; - background-color: var(--blue); - border: none; - border-radius: 8px; - font-size: 16px; - color: white; - font-weight: 600; -} - -/* tablet */ -@media (max-width: 1200px) { - .logo { - padding: 10px 24px; - } -} - -/* mobile */ -@media (max-width: 768px) { - .logo { - padding: 10px 16px; - } - - .logo-img { - background-image: url('../../assets/images/logo_typo.png'); - background-repeat: no-repeat; - width: 103px; - height: 51px; - margin-right: 10px; - } - - .header-menu:first-child ~ li { - padding-left: 10px; - } - - .header-menu-text { - font-weight: 600; - font-size: 16px; - } -} diff --git a/src/styles/style.css b/src/styles/style.css deleted file mode 100644 index 73d4a693..00000000 --- a/src/styles/style.css +++ /dev/null @@ -1,314 +0,0 @@ -@import url(colors.css); - -* { - box-sizing: border-box; -} - -@font-face { - font-family: 'Pretendard-Regular'; - src: url('https://fastly.jsdelivr.net/gh/Project-Noonnu/noonfonts-2107@1.1/Pretendard-Regular.woff') - format('woff'); - font-weight: 400; - font-style: normal; -} - -body { - margin: 0; -} - -a { - text-decoration: none; - color: white; - font-weight: 600; - cursor: pointer; -} - -.slogan-heading { - color: var(--gray700); - font-weight: 700; - font-size: clamp(16px, 2vw, 40px); -} - -.menu-heading { - color: var(--gray700); - font-weight: 700; - font-size: clamp(16px, 2vw, 40px); -} - -h2 { - font-weight: 500; - font-size: clamp(12px, 1vw, 24px); - color: var(--gray700); -} - -button { - cursor: pointer; -} - -.common-btn { - background-color: var(--blue); - border: none; - border-radius: 8px; - font-size: 16px; - color: white; - font-weight: 600; -} - -.main-container { - display: flex; - justify-content: center; - align-items: center; - margin: 0 auto; - height: 100vh; -} - -.plan-card { - background-color: #cfe5ff; - display: flex; - height: 540px; - justify-content: center; - align-items: end; -} - -.slogan { - display: flex; - flex-direction: column; - margin-bottom: 100px; -} - -.large-btn { - width: 19vw; - max-width: 357px; - height: 56px; - background-color: var(--blue); - border-radius: 40px; - border: none; - font-size: 20px; - color: white; - font-weight: 600; -} - -.btn-hover:hover { - background-color: #1967d6; -} - -.btn-active:active { - background-color: #1251aa; -} - -.main-img { - width: 746px; - height: 340px; -} - -.home-container { - height: 720px; - display: flex; - justify-content: center; - align-items: center; -} - -.content-box { - width: 988px; - height: 444px; - border-radius: 12px; - border: none; - background-color: #fcfcfc; - display: flex; - justify-content: space-around; - align-items: center; -} - -.introduce-img { - width: 579px; - height: 444px; -} - -.keyword { - font-weight: 800; - font-size: 18px; - color: var(--blue); -} - -.sec-introduce { - text-align: right; -} - -.bottom { - background-color: #cfe5ff; - height: 540px; - display: flex; - justify-content: center; - align-items: end; -} - -.bottom-slogan { - padding-bottom: 100px; -} - -/* tablet */ -@media (max-width: 1199px) { - body { - background-color: #fcfcfc; - } - - .slogan-heading { - color: var(--gray700); - font-weight: 700; - font-size: 40px; - } - - .menu-heading { - font-size: 32px; - } - - h2 { - font-weight: 500; - font-size: 18px; - color: var(--gray700); - } - - .plan-card { - background-color: #cfe5ff; - display: flex; - flex-direction: column; - height: 771px; - justify-content: space-between; - align-items: center; - } - - .large-btn { - width: 512px; - height: 56px; - } - - .main-img { - width: 744px; - height: 340px; - } - - .slogan { - align-items: center; - margin-top: 50px; - } - - .only-pc { - display: none; - } - - .home-container { - height: 800px; - } - - .content-box { - display: grid; - width: 768px; - height: 100%; - padding: 20px 0; - } - - .introduce, - .sec-introduce { - padding-bottom: 40px; - } - - .sec-introduce { - grid-row: 2/3; - } - - .keyword { - font-weight: 700; - font-size: 18px; - color: var(--blue); - } - - .introduce-img { - width: 696px; - height: 525.55px; - } - - .bottom { - display: grid; - width: 100%; - height: 1080px; - align-items: end; - } - - .bottom img { - width: 100%; - } - - .bottom-slogan { - text-align: center; - } -} - -/* mobile */ -@media (max-width: 767px) { - .slogan-heading { - font-size: 24px; - } - - .menu-heading { - font-size: 24px; - } - - h2 { - font-size: 16px; - } - - .plan-card { - height: 600px; - } - - .slogan { - margin-top: 80px; - } - - .slogan-heading { - font-size: 32px; - text-align: center; - } - - .large-btn { - width: 240px; - height: 48px; - font-size: 18px; - } - - .main-img { - width: 375px; - height: 175px; - } - - .home-container { - height: 480px; - } - - .content-box { - width: 375px; - } - - .introduce, - .sec-introduce { - width: 344px; - } - - .introduce-img { - width: 344px; - height: 260px; - } - - .bottom { - height: 600px; - width: 100%; - } - - .bottom-slogan { - padding-bottom: 0; - } - - .only-mobile { - display: block; - } -} diff --git a/src/types/authType.ts b/src/types/authType.ts deleted file mode 100644 index abbdf2f8..00000000 --- a/src/types/authType.ts +++ /dev/null @@ -1,26 +0,0 @@ -import { SetStateAction } from "react"; - -export interface VisibleValue { - pw: boolean; - checkPw: boolean; -} - -export type VisibleKey = keyof VisibleValue; - -export interface AuthType { - visible: VisibleValue; - setVisible: (prevState: SetStateAction) => void; - onClickVisible: (e: string) => void; - visibleEye_off: string; - visibleEye_on: string; -} - -export function isVisibleKey(value: string): value is VisibleKey { - return value === "pw" || value === "checkPw"; -} - -export interface SignupType { - email: string; - nickname: string; - pw: string; -} diff --git a/src/util/formatTimeAgo.js b/src/util/formatTimeAgo.js deleted file mode 100644 index 71c60d4d..00000000 --- a/src/util/formatTimeAgo.js +++ /dev/null @@ -1,37 +0,0 @@ -/** - * DateTime을 방금전, n분, 일, 월, 년전 형태로 출력한다. - * @param {string} dateString - * @returns {string} - */ -export const formatTimeAgo = (dateString) => { - const now = new Date(); - const past = new Date(dateString); - const diffInMs = now.getTime() - past.getTime(); - - // 시간 단위(밀리초) - const msInSecond = 1000; - const msInMinute = msInSecond * 60; - const msInHour = msInMinute * 60; - const msInDay = msInHour * 24; - const msInMonth = msInDay * 30; // 간단한 계산을 위해 30일로 가정 - const msInYear = msInDay * 365; // 간단한 계산을 위해 365일로 가정 - - if (diffInMs >= msInYear) { - const years = Math.floor(diffInMs / msInYear); - return `${years}년 전`; - } else if (diffInMs >= msInMonth) { - const months = Math.floor(diffInMs / msInMonth); - return `${months}달 전`; - } else if (diffInMs >= msInDay) { - const days = Math.floor(diffInMs / msInDay); - return `${days}일 전`; - } else if (diffInMs >= msInHour) { - const hours = Math.floor(diffInMs / msInHour); - return `${hours}시간 전`; - } else if (diffInMs >= msInMinute) { - const minutes = Math.floor(diffInMs / msInMinute); - return `${minutes}분 전`; - } else { - return "방금 전"; - } -}; diff --git a/src/vite-env.d.ts b/src/vite-env.d.ts deleted file mode 100644 index 11f02fe2..00000000 --- a/src/vite-env.d.ts +++ /dev/null @@ -1 +0,0 @@ -/// diff --git a/tsconfig.json b/tsconfig.json index 33056b8c..c1334095 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,26 +1,27 @@ { "compilerOptions": { - "target": "ES2020", - "useDefineForClassFields": true, - "lib": ["ES2020", "DOM", "DOM.Iterable"], - "module": "ESNext", + "target": "ES2017", + "lib": ["dom", "dom.iterable", "esnext"], + "allowJs": true, "skipLibCheck": true, - "outDir": "./transpile", - - /* Bundler mode */ + "strict": true, + "noEmit": true, + "esModuleInterop": true, + "module": "esnext", "moduleResolution": "bundler", - "allowImportingTsExtensions": true, "resolveJsonModule": true, "isolatedModules": true, - "noEmit": true, - "jsx": "react-jsx", - - /* Linting */ - "strict": true, - "noUnusedLocals": true, - "noUnusedParameters": true, - "noFallthroughCasesInSwitch": true + "jsx": "preserve", + "incremental": true, + "plugins": [ + { + "name": "next" + } + ], + "paths": { + "@/*": ["./src/*"] + } }, - "include": ["src"], - "references": [{ "path": "./tsconfig.node.json" }] + "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"], + "exclude": ["node_modules"] } diff --git a/tsconfig.node.json b/tsconfig.node.json deleted file mode 100644 index 97ede7ee..00000000 --- a/tsconfig.node.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "compilerOptions": { - "composite": true, - "skipLibCheck": true, - "module": "ESNext", - "moduleResolution": "bundler", - "allowSyntheticDefaultImports": true, - "strict": true - }, - "include": ["vite.config.ts"] -} diff --git a/vite.config.ts b/vite.config.ts deleted file mode 100644 index 5a33944a..00000000 --- a/vite.config.ts +++ /dev/null @@ -1,7 +0,0 @@ -import { defineConfig } from 'vite' -import react from '@vitejs/plugin-react' - -// https://vitejs.dev/config/ -export default defineConfig({ - plugins: [react()], -}) From bfa89f9124d4257e3b4736690746c94a266489a6 Mon Sep 17 00:00:00 2001 From: Imhwitae Date: Mon, 15 Sep 2025 21:36:56 +0900 Subject: [PATCH 82/94] =?UTF-8?q?design:=20=EA=B8=B0=EB=B3=B8=20=EB=94=94?= =?UTF-8?q?=EC=9E=90=EC=9D=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .prettierignore | 1 + public/doit_logo.svg | 17 ++++ public/doit_logo_mobile.svg | 7 ++ src/app/globals.css | 83 +++++++++++------- src/app/layout.tsx | 31 +++---- src/app/page.module.css | 170 +----------------------------------- src/app/page.tsx | 92 +------------------ 7 files changed, 93 insertions(+), 308 deletions(-) create mode 100644 .prettierignore create mode 100644 public/doit_logo.svg create mode 100644 public/doit_logo_mobile.svg diff --git a/.prettierignore b/.prettierignore new file mode 100644 index 00000000..b6072cfe --- /dev/null +++ b/.prettierignore @@ -0,0 +1 @@ +/src/app/globals.css \ No newline at end of file diff --git a/public/doit_logo.svg b/public/doit_logo.svg new file mode 100644 index 00000000..79e3a93a --- /dev/null +++ b/public/doit_logo.svg @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + + + diff --git a/public/doit_logo_mobile.svg b/public/doit_logo_mobile.svg new file mode 100644 index 00000000..4fb80423 --- /dev/null +++ b/public/doit_logo_mobile.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/src/app/globals.css b/src/app/globals.css index e3734be1..c3a28ed9 100644 --- a/src/app/globals.css +++ b/src/app/globals.css @@ -1,42 +1,61 @@ :root { - --background: #ffffff; - --foreground: #171717; + --slate-900: #0f172a; + --slate-800: #1e293b; + --slate-500: #64748b; + --slate-400: #94a3b8; + --slate-300: #cbd5e1; + --slate-200: #e2e8f0; + --slate-100: #f1f5f9; + --violet-600: #7c3aed; + --violet-100: #ede9fe; + --rose-500: #f43f5e; + --lime-300: #bef264; + --amber-800: #92400e; + --background: rgb(248 249 250); } -@media (prefers-color-scheme: dark) { - :root { - --background: #0a0a0a; - --foreground: #ededed; - } +html, body, div, span, applet, object, iframe, +h1, h2, h3, h4, h5, h6, p, blockquote, pre, +a, abbr, acronym, address, big, cite, code, +del, dfn, em, img, ins, kbd, q, s, samp, +small, strike, strong, sub, sup, tt, var, +b, u, i, center, +dl, dt, dd, ol, ul, li, +fieldset, form, label, legend, +table, caption, tbody, tfoot, thead, tr, th, td, +article, aside, canvas, details, embed, +figure, figcaption, footer, header, hgroup, +menu, nav, output, ruby, section, summary, +time, mark, audio, video { + margin: 0; + padding: 0; + border: 0; + font-size: 100%; + font: inherit; + vertical-align: baseline; + font-family: "NanumSquare"; } - -html, -body { - max-width: 100vw; - overflow-x: hidden; +/* HTML5 display-role reset for older browsers */ +article, aside, details, figcaption, figure, +footer, header, hgroup, menu, nav, section { + display: block; } - body { - color: var(--foreground); - background: var(--background); - font-family: Arial, Helvetica, sans-serif; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; + line-height: 1; + background-color: var(--background); } - -* { - box-sizing: border-box; - padding: 0; - margin: 0; +ol, ul { + list-style: none; } - -a { - color: inherit; - text-decoration: none; +blockquote, q { + quotes: none; } - -@media (prefers-color-scheme: dark) { - html { - color-scheme: dark; - } +blockquote:before, blockquote:after, +q:before, q:after { + content: ''; + content: none; +} +table { + border-collapse: collapse; + border-spacing: 0; } diff --git a/src/app/layout.tsx b/src/app/layout.tsx index 42fc323e..e8ff6c62 100644 --- a/src/app/layout.tsx +++ b/src/app/layout.tsx @@ -1,22 +1,6 @@ -import type { Metadata } from "next"; -import { Geist, Geist_Mono } from "next/font/google"; +import Header from "@/components/header/header"; import "./globals.css"; -const geistSans = Geist({ - variable: "--font-geist-sans", - subsets: ["latin"], -}); - -const geistMono = Geist_Mono({ - variable: "--font-geist-mono", - subsets: ["latin"], -}); - -export const metadata: Metadata = { - title: "Create Next App", - description: "Generated by create next app", -}; - export default function RootLayout({ children, }: Readonly<{ @@ -24,8 +8,17 @@ export default function RootLayout({ }>) { return ( - - {children} + + + + +
    +
    +
    +
    {children}
    ); diff --git a/src/app/page.module.css b/src/app/page.module.css index 58c71af9..72844d98 100644 --- a/src/app/page.module.css +++ b/src/app/page.module.css @@ -1,167 +1,5 @@ -.page { - --gray-rgb: 0, 0, 0; - --gray-alpha-200: rgba(var(--gray-rgb), 0.08); - --gray-alpha-100: rgba(var(--gray-rgb), 0.05); - - --button-primary-hover: #383838; - --button-secondary-hover: #f2f2f2; - - display: grid; - grid-template-rows: 20px 1fr 20px; - align-items: center; - justify-items: center; - min-height: 100svh; - padding: 80px; - gap: 64px; - font-family: var(--font-geist-sans); -} - -@media (prefers-color-scheme: dark) { - .page { - --gray-rgb: 255, 255, 255; - --gray-alpha-200: rgba(var(--gray-rgb), 0.145); - --gray-alpha-100: rgba(var(--gray-rgb), 0.06); - - --button-primary-hover: #ccc; - --button-secondary-hover: #1a1a1a; - } -} - -.main { - display: flex; - flex-direction: column; - gap: 32px; - grid-row-start: 2; -} - -.main ol { - font-family: var(--font-geist-mono); - padding-left: 0; - margin: 0; - font-size: 14px; - line-height: 24px; - letter-spacing: -0.01em; - list-style-position: inside; -} - -.main li:not(:last-of-type) { - margin-bottom: 8px; -} - -.main code { - font-family: inherit; - background: var(--gray-alpha-100); - padding: 2px 4px; - border-radius: 4px; - font-weight: 600; -} - -.ctas { - display: flex; - gap: 16px; -} - -.ctas a { - appearance: none; - border-radius: 128px; - height: 48px; - padding: 0 20px; - border: 1px solid transparent; - transition: - background 0.2s, - color 0.2s, - border-color 0.2s; - cursor: pointer; - display: flex; - align-items: center; - justify-content: center; - font-size: 16px; - line-height: 20px; - font-weight: 500; -} - -a.primary { - background: var(--foreground); - color: var(--background); - gap: 8px; -} - -a.secondary { - border-color: var(--gray-alpha-200); - min-width: 158px; -} - -.footer { - grid-row-start: 3; - display: flex; - gap: 24px; -} - -.footer a { - display: flex; - align-items: center; - gap: 8px; -} - -.footer img { - flex-shrink: 0; -} - -/* Enable hover only on non-touch devices */ -@media (hover: hover) and (pointer: fine) { - a.primary:hover { - background: var(--button-primary-hover); - border-color: transparent; - } - - a.secondary:hover { - background: var(--button-secondary-hover); - border-color: transparent; - } - - .footer a:hover { - text-decoration: underline; - text-underline-offset: 4px; - } -} - -@media (max-width: 600px) { - .page { - padding: 32px; - padding-bottom: 80px; - } - - .main { - align-items: center; - } - - .main ol { - text-align: center; - } - - .ctas { - flex-direction: column; - } - - .ctas a { - font-size: 14px; - height: 40px; - padding: 0 16px; - } - - a.secondary { - min-width: auto; - } - - .footer { - flex-wrap: wrap; - align-items: center; - justify-content: center; - } -} - -@media (prefers-color-scheme: dark) { - .logo { - filter: invert(); - } +.title { + font-family: "NanumSquareBold"; + font-weight: 700; + font-size: 24px; } diff --git a/src/app/page.tsx b/src/app/page.tsx index 84af2cb0..27f427fc 100644 --- a/src/app/page.tsx +++ b/src/app/page.tsx @@ -1,95 +1,5 @@ -import Image from "next/image"; import styles from "./page.module.css"; export default function Home() { - return ( -
    -
    - Next.js logo -
      -
    1. - Get started by editing src/app/page.tsx. -
    2. -
    3. Save and see your changes instantly.
    4. -
    - - -
    - -
    - ); + return
    main
    ; } From f93c000ef8f77fca8cf5bd999d06bebaff6edbdf Mon Sep 17 00:00:00 2001 From: Imhwitae Date: Mon, 15 Sep 2025 21:37:18 +0900 Subject: [PATCH 83/94] =?UTF-8?q?design:=20=ED=97=A4=EB=8D=94=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/header/header.module.css | 12 ++++++++++++ src/components/header/header.tsx | 18 ++++++++++++++++++ 2 files changed, 30 insertions(+) create mode 100644 src/components/header/header.module.css create mode 100644 src/components/header/header.tsx diff --git a/src/components/header/header.module.css b/src/components/header/header.module.css new file mode 100644 index 00000000..c5dcb538 --- /dev/null +++ b/src/components/header/header.module.css @@ -0,0 +1,12 @@ +.header_container { + background-color: white; + border-bottom: 1px solid var(--slate-200); + display: flex; + justify-content: center; +} + +.header_box { + width: 1200px; + max-width: 1200px; + padding: 10px 0px; +} diff --git a/src/components/header/header.tsx b/src/components/header/header.tsx new file mode 100644 index 00000000..a50b5395 --- /dev/null +++ b/src/components/header/header.tsx @@ -0,0 +1,18 @@ +import Image from "next/image"; +import styles from "./header.module.css"; + +export default function Header() { + return ( +
    +
    + logo +
    +
    + ); +} From ae43cd8194c25c4f3c9ea5b742e50565a72ebe04 Mon Sep 17 00:00:00 2001 From: Imhwitae Date: Mon, 15 Sep 2025 22:23:24 +0900 Subject: [PATCH 84/94] =?UTF-8?q?design:=20=EC=84=9C=EC=B9=98=EB=B0=94=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- public/plus.svg | 4 ++ src/app/globals.css | 6 ++- src/app/page.tsx | 7 ++- src/components/searchbar/searchbar.module.css | 46 +++++++++++++++++++ src/components/searchbar/searchbar.tsx | 25 ++++++++++ 5 files changed, 86 insertions(+), 2 deletions(-) create mode 100644 public/plus.svg create mode 100644 src/components/searchbar/searchbar.module.css create mode 100644 src/components/searchbar/searchbar.tsx diff --git a/public/plus.svg b/public/plus.svg new file mode 100644 index 00000000..592ad572 --- /dev/null +++ b/public/plus.svg @@ -0,0 +1,4 @@ + + + + diff --git a/src/app/globals.css b/src/app/globals.css index c3a28ed9..41beffcb 100644 --- a/src/app/globals.css +++ b/src/app/globals.css @@ -14,6 +14,10 @@ --background: rgb(248 249 250); } +*{ + font-family: "NanumSquare"; +} + html, body, div, span, applet, object, iframe, h1, h2, h3, h4, h5, h6, p, blockquote, pre, a, abbr, acronym, address, big, cite, code, @@ -33,7 +37,7 @@ time, mark, audio, video { font-size: 100%; font: inherit; vertical-align: baseline; - font-family: "NanumSquare"; + } /* HTML5 display-role reset for older browsers */ article, aside, details, figcaption, figure, diff --git a/src/app/page.tsx b/src/app/page.tsx index 27f427fc..38f59f3b 100644 --- a/src/app/page.tsx +++ b/src/app/page.tsx @@ -1,5 +1,10 @@ +import Searchbar from "@/components/searchbar/searchbar"; import styles from "./page.module.css"; export default function Home() { - return
    main
    ; + return ( +
    + +
    + ); } diff --git a/src/components/searchbar/searchbar.module.css b/src/components/searchbar/searchbar.module.css new file mode 100644 index 00000000..3a8b47da --- /dev/null +++ b/src/components/searchbar/searchbar.module.css @@ -0,0 +1,46 @@ +.searchbar_container { + /* width: 1200px; */ +} + +.searchbar_box { + display: flex; + gap: 16px; + justify-content: center; + margin-top: 24px; + height: 56px; +} + +.searchbar { + width: 964px; + max-width: 964px; + border-radius: 24px; + border: 2px solid var(--slate-900); + background-color: var(--slate-100); + font-size: 16px; + line-height: 100%; + letter-spacing: 0%; + padding: 17px 24px; + box-shadow: 4px 3px; +} + +.searchbar:focus { + outline: none; +} + +.add_btn { + width: 168px; + background-color: var(--slate-200); + border: 2px solid var(--slate-900); + border-radius: 24px; + box-shadow: 4px 3px; + font-size: 16px; + font-family: "NanumSquareBold"; + display: flex; + justify-content: center; + align-items: center; + gap: 4px; +} + +.plus { + color: black; +} diff --git a/src/components/searchbar/searchbar.tsx b/src/components/searchbar/searchbar.tsx new file mode 100644 index 00000000..b210c744 --- /dev/null +++ b/src/components/searchbar/searchbar.tsx @@ -0,0 +1,25 @@ +import Image from "next/image"; +import styles from "./searchbar.module.css"; + +export default function Searchbar() { + return ( +
    +
    + + +
    +
    + ); +} From 436307a42d35eee05cf636f12f2b6a032ff7c520 Mon Sep 17 00:00:00 2001 From: Imhwitae Date: Tue, 16 Sep 2025 20:36:33 +0900 Subject: [PATCH 85/94] =?UTF-8?q?chore:=20mongoose=20=EC=84=A4=EC=B9=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- package-lock.json | 200 +++++++++++++++++++++++++++++++++++++++++++++- package.json | 9 ++- 2 files changed, 202 insertions(+), 7 deletions(-) diff --git a/package-lock.json b/package-lock.json index 9705f691..e823cbe9 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8,6 +8,7 @@ "name": "panda_market", "version": "0.1.0", "dependencies": { + "mongoose": "^8.18.1", "next": "15.5.3", "react": "19.1.0", "react-dom": "19.1.0" @@ -666,6 +667,15 @@ "url": "https://opencollective.com/libvips" } }, + "node_modules/@mongodb-js/saslprep": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@mongodb-js/saslprep/-/saslprep-1.3.0.tgz", + "integrity": "sha512-zlayKCsIjYb7/IdfqxorK5+xUMyi4vOKcFy10wKJYc63NSdKI8mNME+uJqfatkPmOSMMUiojrL58IePKBm3gvQ==", + "license": "MIT", + "dependencies": { + "sparse-bitfield": "^3.0.3" + } + }, "node_modules/@napi-rs/wasm-runtime": { "version": "0.2.12", "resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-0.2.12.tgz", @@ -956,6 +966,21 @@ "@types/react": "^19.0.0" } }, + "node_modules/@types/webidl-conversions": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/@types/webidl-conversions/-/webidl-conversions-7.0.3.tgz", + "integrity": "sha512-CiJJvcRtIgzadHCYXw7dqEnMNRjhGZlYK05Mj9OyktqV8uVT8fD2BFOB7S1uwBE3Kj2Z+4UyPmFw/Ixgw/LAlA==", + "license": "MIT" + }, + "node_modules/@types/whatwg-url": { + "version": "11.0.5", + "resolved": "https://registry.npmjs.org/@types/whatwg-url/-/whatwg-url-11.0.5.tgz", + "integrity": "sha512-coYR071JRaHa+xoEvvYqvnIHaVqaYrLPbsufM9BF63HkwI5Lgmy2QR8Q5K/lYDYo5AK82wOvSOS0UsLTpTG7uQ==", + "license": "MIT", + "dependencies": { + "@types/webidl-conversions": "*" + } + }, "node_modules/@typescript-eslint/eslint-plugin": { "version": "8.43.0", "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.43.0.tgz", @@ -1830,6 +1855,15 @@ "node": ">=8" } }, + "node_modules/bson": { + "version": "6.10.4", + "resolved": "https://registry.npmjs.org/bson/-/bson-6.10.4.tgz", + "integrity": "sha512-WIsKqkSC0ABoBJuT1LEX+2HEvNmNKKgnTAyd0fL8qzK4SH2i9NXg+t08YtdZp/V9IZ33cxe3iV4yM0qg8lMQng==", + "license": "Apache-2.0", + "engines": { + "node": ">=16.20.1" + } + }, "node_modules/call-bind": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.8.tgz", @@ -2072,7 +2106,6 @@ "version": "4.4.1", "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.1.tgz", "integrity": "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==", - "dev": true, "license": "MIT", "dependencies": { "ms": "^2.1.3" @@ -3761,6 +3794,15 @@ "node": ">=4.0" } }, + "node_modules/kareem": { + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/kareem/-/kareem-2.6.3.tgz", + "integrity": "sha512-C3iHfuGUXK2u8/ipq9LfjFfXFxAZMQJJq7vLS45r3D9Y2xQ/m4S8zaR4zMLFWh9AsNPXmcFfUDhTEO8UIC/V6Q==", + "license": "Apache-2.0", + "engines": { + "node": ">=12.0.0" + } + }, "node_modules/keyv": { "version": "4.5.4", "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", @@ -3851,6 +3893,12 @@ "node": ">= 0.4" } }, + "node_modules/memory-pager": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/memory-pager/-/memory-pager-1.5.0.tgz", + "integrity": "sha512-ZS4Bp4r/Zoeq6+NLJpP+0Zzm0pR8whtGPf1XExKLJBAczGMnSi3It14OiNCStjQjM6NU1okjQGSxgEZN8eBYKg==", + "license": "MIT" + }, "node_modules/merge2": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", @@ -3898,11 +3946,109 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/mongodb": { + "version": "6.18.0", + "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-6.18.0.tgz", + "integrity": "sha512-fO5ttN9VC8P0F5fqtQmclAkgXZxbIkYRTUi1j8JO6IYwvamkhtYDilJr35jOPELR49zqCJgXZWwCtW7B+TM8vQ==", + "license": "Apache-2.0", + "dependencies": { + "@mongodb-js/saslprep": "^1.1.9", + "bson": "^6.10.4", + "mongodb-connection-string-url": "^3.0.0" + }, + "engines": { + "node": ">=16.20.1" + }, + "peerDependencies": { + "@aws-sdk/credential-providers": "^3.188.0", + "@mongodb-js/zstd": "^1.1.0 || ^2.0.0", + "gcp-metadata": "^5.2.0", + "kerberos": "^2.0.1", + "mongodb-client-encryption": ">=6.0.0 <7", + "snappy": "^7.2.2", + "socks": "^2.7.1" + }, + "peerDependenciesMeta": { + "@aws-sdk/credential-providers": { + "optional": true + }, + "@mongodb-js/zstd": { + "optional": true + }, + "gcp-metadata": { + "optional": true + }, + "kerberos": { + "optional": true + }, + "mongodb-client-encryption": { + "optional": true + }, + "snappy": { + "optional": true + }, + "socks": { + "optional": true + } + } + }, + "node_modules/mongodb-connection-string-url": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/mongodb-connection-string-url/-/mongodb-connection-string-url-3.0.2.tgz", + "integrity": "sha512-rMO7CGo/9BFwyZABcKAWL8UJwH/Kc2x0g72uhDWzG48URRax5TCIcJ7Rc3RZqffZzO/Gwff/jyKwCU9TN8gehA==", + "license": "Apache-2.0", + "dependencies": { + "@types/whatwg-url": "^11.0.2", + "whatwg-url": "^14.1.0 || ^13.0.0" + } + }, + "node_modules/mongoose": { + "version": "8.18.1", + "resolved": "https://registry.npmjs.org/mongoose/-/mongoose-8.18.1.tgz", + "integrity": "sha512-K0RfrUXXufqNRZZjvAGdyjydB91SnbWxlwFYi5t7zN2DxVWFD3c6puia0/7xfBwZm6RCpYOVdYFlRFpoDWiC+w==", + "license": "MIT", + "dependencies": { + "bson": "^6.10.4", + "kareem": "2.6.3", + "mongodb": "~6.18.0", + "mpath": "0.9.0", + "mquery": "5.0.0", + "ms": "2.1.3", + "sift": "17.1.3" + }, + "engines": { + "node": ">=16.20.1" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mongoose" + } + }, + "node_modules/mpath": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/mpath/-/mpath-0.9.0.tgz", + "integrity": "sha512-ikJRQTk8hw5DEoFVxHG1Gn9T/xcjtdnOKIU1JTmGjZZlg9LST2mBLmcX3/ICIbgJydT2GOc15RnNy5mHmzfSew==", + "license": "MIT", + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/mquery": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/mquery/-/mquery-5.0.0.tgz", + "integrity": "sha512-iQMncpmEK8R8ncT8HJGsGc9Dsp8xcgYMVSbs5jgnm1lFHTZqMJTUWTDx1LBO8+mK3tPNZWFLBghQEIOULSTHZg==", + "license": "MIT", + "dependencies": { + "debug": "4.x" + }, + "engines": { + "node": ">=14.0.0" + } + }, "node_modules/ms": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "dev": true, "license": "MIT" }, "node_modules/nanoid": { @@ -4312,7 +4458,6 @@ "version": "2.3.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", - "dev": true, "license": "MIT", "engines": { "node": ">=6" @@ -4752,6 +4897,12 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/sift": { + "version": "17.1.3", + "resolved": "https://registry.npmjs.org/sift/-/sift-17.1.3.tgz", + "integrity": "sha512-Rtlj66/b0ICeFzYTuNvX/EF1igRbbnGSvEyT79McoZa/DeGhMyC5pWKOEsZKnpkqtSeovd5FL/bjHWC3CIIvCQ==", + "license": "MIT" + }, "node_modules/simple-swizzle": { "version": "0.2.2", "resolved": "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.2.tgz", @@ -4771,6 +4922,15 @@ "node": ">=0.10.0" } }, + "node_modules/sparse-bitfield": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/sparse-bitfield/-/sparse-bitfield-3.0.3.tgz", + "integrity": "sha512-kvzhi7vqKTfkh0PZU+2D2PIllw2ymqJKujUcyPMd9Y75Nv4nPbGJZXNhxsgdQab2BmlDct1YnfQCguEvHr7VsQ==", + "license": "MIT", + "dependencies": { + "memory-pager": "^1.0.2" + } + }, "node_modules/stable-hash": { "version": "0.0.5", "resolved": "https://registry.npmjs.org/stable-hash/-/stable-hash-0.0.5.tgz", @@ -5038,6 +5198,18 @@ "node": ">=8.0" } }, + "node_modules/tr46": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-5.1.1.tgz", + "integrity": "sha512-hdF5ZgjTqgAntKkklYw0R03MG2x/bSzTtkxmIRw/sTNV8YXsCJ1tfLAX23lhxhHJlEf3CRCOCGGWw3vI3GaSPw==", + "license": "MIT", + "dependencies": { + "punycode": "^2.3.1" + }, + "engines": { + "node": ">=18" + } + }, "node_modules/ts-api-utils": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.1.0.tgz", @@ -5246,6 +5418,28 @@ "punycode": "^2.1.0" } }, + "node_modules/webidl-conversions": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz", + "integrity": "sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==", + "license": "BSD-2-Clause", + "engines": { + "node": ">=12" + } + }, + "node_modules/whatwg-url": { + "version": "14.2.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-14.2.0.tgz", + "integrity": "sha512-De72GdQZzNTUBBChsXueQUnPKDkg/5A5zp7pFDuQAj5UFoENpiACU0wlCvzpAGnTkj++ihpKwKyYewn/XNUbKw==", + "license": "MIT", + "dependencies": { + "tr46": "^5.1.0", + "webidl-conversions": "^7.0.0" + }, + "engines": { + "node": ">=18" + } + }, "node_modules/which": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", diff --git a/package.json b/package.json index 75b55f8c..9da21058 100644 --- a/package.json +++ b/package.json @@ -9,17 +9,18 @@ "lint": "eslint" }, "dependencies": { + "mongoose": "^8.18.1", + "next": "15.5.3", "react": "19.1.0", - "react-dom": "19.1.0", - "next": "15.5.3" + "react-dom": "19.1.0" }, "devDependencies": { - "typescript": "^5", + "@eslint/eslintrc": "^3", "@types/node": "^20", "@types/react": "^19", "@types/react-dom": "^19", "eslint": "^9", "eslint-config-next": "15.5.3", - "@eslint/eslintrc": "^3" + "typescript": "^5" } } From f52b9a395c2eb02bbbed1ec3cd7c76b3b7b1437e Mon Sep 17 00:00:00 2001 From: Imhwitae Date: Tue, 16 Sep 2025 22:32:01 +0900 Subject: [PATCH 86/94] =?UTF-8?q?design:=20Todo=20=EC=BB=B4=ED=8F=AC?= =?UTF-8?q?=EB=84=8C=ED=8A=B8=20=EC=A0=9C=EC=9E=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- public/checked.svg | 4 +++ public/done.png | Bin 0 -> 1367 bytes public/file.svg | 1 - public/globe.svg | 1 - public/next.svg | 1 - public/not_check.svg | 3 ++ public/todo.png | Bin 0 -> 1434 bytes public/vercel.svg | 1 - public/window.svg | 1 - src/app/globals.css | 1 + src/app/page.tsx | 6 +++- src/components/searchbar/searchbar.module.css | 10 ++----- src/components/searchbar/searchbar.tsx | 27 +++++++----------- src/components/todo/checkList.module.css | 17 +++++++++++ src/components/todo/checkList.tsx | 12 ++++++++ src/components/todo/todo.module.css | 5 ++++ src/components/todo/todo.tsx | 12 ++++++++ src/mock.ts | 0 18 files changed, 73 insertions(+), 29 deletions(-) create mode 100644 public/checked.svg create mode 100644 public/done.png delete mode 100644 public/file.svg delete mode 100644 public/globe.svg delete mode 100644 public/next.svg create mode 100644 public/not_check.svg create mode 100644 public/todo.png delete mode 100644 public/vercel.svg delete mode 100644 public/window.svg create mode 100644 src/components/todo/checkList.module.css create mode 100644 src/components/todo/checkList.tsx create mode 100644 src/components/todo/todo.module.css create mode 100644 src/components/todo/todo.tsx create mode 100644 src/mock.ts diff --git a/public/checked.svg b/public/checked.svg new file mode 100644 index 00000000..62bc5549 --- /dev/null +++ b/public/checked.svg @@ -0,0 +1,4 @@ + + + + diff --git a/public/done.png b/public/done.png new file mode 100644 index 0000000000000000000000000000000000000000..39d7ff66f8e3b873e051a3230763e35910efad46 GIT binary patch literal 1367 zcmV-d1*rOoP)o2`>B*QhF>olq-?S7203yB8L*bZ8 zh;jo_grQY)0VzEcgg~mBh(97dIHcLOo2;kroAqqHUOT(1dhJS`pR`)licodz$_53q9Q+y5+#$w% znanxQas9+^lM3PcJo>+40S=KSD?DB=CX&{R4iQ2De$e(a5E6wjqaR>FT7ZEf9R_iZ z7Pg5Ht^rlj3=nas8Ry%y>?lk@Pmv}U`21?(s&n4OabzYKv!uxlKGAIrcqu}27HAvF znQG`ht(kC?G({leZZuQU#%0nJ0;jC|Ef&D0oEh0+(7v)shaa%$kztem-xPFuxlSt^ zL28@l_F6PHT9R#7Y5^@?-P*Q(lp~J~(E)CYHsAcc+3|O%e#a^$dHnMC>y#IQFNRut zLui|CEcQ5UsasFrHymw$1ef;YU`sBA8ZRL-$Nb}DOOA+FHaPc~w{PU(fp5j2G zk5LZh^x_6xSlyE4XovOyVnc*ukME>oPwbR^7frxdqb**gt4NsgLJ5F?s6f5)@DBNo zAfj9a7D4**#rs;py5u+H`&ih=hX;4lrL~6a2X$0E1by=Cy6h_njCNHQbugnayO#O= zuUc=jD?@CnsI2IH9>u4x)a5Y(a&~f$v;+vDL^#gJ_znSj>!)ii`$3)KPwr~g;r9!x z*V_6<8;th&tcnBi&~L$1FdPcMA%h?EUf>0|Nj1 zYol#t@BUolzU!1Hklm-doRtKhj*1rdek|AkL7oa{Q#Yir{5$LQ{MN@19}BY|-X|^; zmHns%dn{rz<0GYxbX3_;l0XZ*)*$%GV$#6xAd^a4!1I9P?_nnVNCksMREe+z^KN#0zh!E03#DZ z3X8OJkpq4>GP+SG&GS`XXrBfaVU=Y?7vx?A%mN+)XDrJoo#C_QPbnwVqN&ae6d2Jn zztq}BCQ?-?77K;IN38|*;Qia3HKY9zo<(UVWhhS)DNhlwMaIIdHoltYQchc0kbOi2 zSmTB8+kZ9_Z3Tgz \ No newline at end of file diff --git a/public/globe.svg b/public/globe.svg deleted file mode 100644 index 567f17b0..00000000 --- a/public/globe.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/public/next.svg b/public/next.svg deleted file mode 100644 index 5174b28c..00000000 --- a/public/next.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/public/not_check.svg b/public/not_check.svg new file mode 100644 index 00000000..0e06cb40 --- /dev/null +++ b/public/not_check.svg @@ -0,0 +1,3 @@ + + + diff --git a/public/todo.png b/public/todo.png new file mode 100644 index 0000000000000000000000000000000000000000..7b97262f5eda1dc8eed3c73acc1b91a3ef391063 GIT binary patch literal 1434 zcmV;L1!ek)P)jVkY~na-9aRX#QaFV}p(2N#>ZOOO92zQ>UMW(LXiprFIGXf~RH{l9Qjmzn ztsph!kV=(`?GuMoX?nn?RBV*Cs_eEnc0LTYcX)5?v3KK-*uh@=Fh42T$?n@7<^5;o zy_wl%&>^v%tGe~FcmWuDhjA;6#~_{#f|WwD6(z>61z~eD!Z}<6 zMOR@=yA8#cv&Q&*rs4HQCn;|5V(ACq{4^+f1T)!?$7mF9>O>KO6iP8QT)9DGVH~2+ zki~ObzbQdngu@E6iiUkC(;NmELzEyc!{9V{ha=8Y6)Gw3Jy7%o#=tN}@5ZTI?J1~E z1QdOvJnbkWM4?`yhOK_X^|B5XQ7SWaMW2y6uyP7qdV(gvN&2dUkSs8}EGqe!TBk=m1Qe z^tZHMTFrG_Pq(qO;sq~`U(+1iA@MW|51#xh$|OJ|q$peHoLi6n5{|VKji=D&O}MyA zJjuf+|H0z&|Kk4L=qSwfj}JSXO?J^(3KGeUx_ZvPI}Vq^6W}HquD)xWxfkF`2>D}Y zA}|D}j{2}AAF7_aao?;8qE8$U*Ch{8*u~}NP3s^>Q}3Yr=$WBFSp@2F-~IfL!=8kf zg6yt`>L8Kb1UpFBi@$YniT6(hVDiX8(Nd%Fv=}akZ)e_i*d?BBRE7KU!?*ChF;OP_ zTaW%0WfF#3axAGWEKT@H~m^ z4m?OTxwb(?EtZ@?$5#L3;&OS#A&g>3K?rj6WThpOqt`HAv;);;k5$P(cf>KC%!(uR z4!gj*h(DvXdQy3Ck)T`hcLcRm;#g>;?%G7a77s88rL!lG`0DLLcKaf@ z35k+{0mVP!sXOP}=PvbUkMm6WZYQ#Bj;$%>5W1)Fq1<=f%Zh9`yN!XC>hrX%C?9^ zGE-NNOhWAT?!ec)n1Zd~kB0UKE}gKb(XEe$b`yJkRR>Qgj0+#rjEml*<5Se \ No newline at end of file diff --git a/public/window.svg b/public/window.svg deleted file mode 100644 index b2b2a44f..00000000 --- a/public/window.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/src/app/globals.css b/src/app/globals.css index 41beffcb..32c88866 100644 --- a/src/app/globals.css +++ b/src/app/globals.css @@ -16,6 +16,7 @@ *{ font-family: "NanumSquare"; + box-sizing: border-box; } html, body, div, span, applet, object, iframe, diff --git a/src/app/page.tsx b/src/app/page.tsx index 38f59f3b..81c1ca25 100644 --- a/src/app/page.tsx +++ b/src/app/page.tsx @@ -1,10 +1,14 @@ import Searchbar from "@/components/searchbar/searchbar"; import styles from "./page.module.css"; +import Todo from "@/components/todo/todo"; export default function Home() { return ( -
    +
    +
    + +
    ); } diff --git a/src/components/searchbar/searchbar.module.css b/src/components/searchbar/searchbar.module.css index 3a8b47da..c7883422 100644 --- a/src/components/searchbar/searchbar.module.css +++ b/src/components/searchbar/searchbar.module.css @@ -1,18 +1,14 @@ -.searchbar_container { - /* width: 1200px; */ -} - .searchbar_box { display: flex; gap: 16px; justify-content: center; - margin-top: 24px; + margin: 24px 0px 40px 0px; height: 56px; } .searchbar { - width: 964px; - max-width: 964px; + width: 1016px; + max-width: 1016px; border-radius: 24px; border: 2px solid var(--slate-900); background-color: var(--slate-100); diff --git a/src/components/searchbar/searchbar.tsx b/src/components/searchbar/searchbar.tsx index b210c744..8f95bfb2 100644 --- a/src/components/searchbar/searchbar.tsx +++ b/src/components/searchbar/searchbar.tsx @@ -3,23 +3,18 @@ import styles from "./searchbar.module.css"; export default function Searchbar() { return ( -
    -
    - + + -
    + 추가하기 +
    ); } diff --git a/src/components/todo/checkList.module.css b/src/components/todo/checkList.module.css new file mode 100644 index 00000000..dd3ac730 --- /dev/null +++ b/src/components/todo/checkList.module.css @@ -0,0 +1,17 @@ +.check_list_container { + width: 588px; + max-width: 588px; + height: 50px; + background-color: white; + border-radius: 27px; + border: 2px solid var(--slate-900); + display: flex; + align-items: center; + gap: 16px; + padding: 9px 12px; +} + +.check_list_text { + font-size: 16px; + letter-spacing: 0%; +} diff --git a/src/components/todo/checkList.tsx b/src/components/todo/checkList.tsx new file mode 100644 index 00000000..f37bb45c --- /dev/null +++ b/src/components/todo/checkList.tsx @@ -0,0 +1,12 @@ +import Image from "next/image"; +import styles from "./checkList.module.css"; +import notCheck from "../../../public/not_check.svg"; + +export default function CheckList() { + return ( +
    + 체크안됨 +

    비타민 챙겨먹기

    +
    + ); +} diff --git a/src/components/todo/todo.module.css b/src/components/todo/todo.module.css new file mode 100644 index 00000000..8cb8b1f5 --- /dev/null +++ b/src/components/todo/todo.module.css @@ -0,0 +1,5 @@ +.todo_container { + display: flex; + flex-direction: column; + gap: 16px; +} diff --git a/src/components/todo/todo.tsx b/src/components/todo/todo.tsx new file mode 100644 index 00000000..bb807ec4 --- /dev/null +++ b/src/components/todo/todo.tsx @@ -0,0 +1,12 @@ +import Image from "next/image"; +import CheckList from "./checkList"; +import styles from "./todo.module.css"; + +export default function Todo() { + return ( +
    + todo 이미지 + +
    + ); +} diff --git a/src/mock.ts b/src/mock.ts new file mode 100644 index 00000000..e69de29b From 07191899efc008a895098ce1879de19f52c413ec Mon Sep 17 00:00:00 2001 From: Imhwitae Date: Wed, 17 Sep 2025 12:01:40 +0900 Subject: [PATCH 87/94] =?UTF-8?q?design:=20=EC=B2=B4=ED=81=AC=EB=A6=AC?= =?UTF-8?q?=EC=8A=A4=ED=8A=B8=20=EC=99=84=EB=A3=8C=20=EC=83=81=ED=83=9C=20?= =?UTF-8?q?=EB=94=94=EC=9E=90=EC=9D=B8=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- package-lock.json | 200 +---------------------- package.json | 1 - src/components/todo/checkList.module.css | 12 +- src/components/todo/checkList.tsx | 27 ++- src/components/todo/todo.tsx | 12 +- src/mock.ts | 17 ++ 6 files changed, 62 insertions(+), 207 deletions(-) diff --git a/package-lock.json b/package-lock.json index e823cbe9..9705f691 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8,7 +8,6 @@ "name": "panda_market", "version": "0.1.0", "dependencies": { - "mongoose": "^8.18.1", "next": "15.5.3", "react": "19.1.0", "react-dom": "19.1.0" @@ -667,15 +666,6 @@ "url": "https://opencollective.com/libvips" } }, - "node_modules/@mongodb-js/saslprep": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/@mongodb-js/saslprep/-/saslprep-1.3.0.tgz", - "integrity": "sha512-zlayKCsIjYb7/IdfqxorK5+xUMyi4vOKcFy10wKJYc63NSdKI8mNME+uJqfatkPmOSMMUiojrL58IePKBm3gvQ==", - "license": "MIT", - "dependencies": { - "sparse-bitfield": "^3.0.3" - } - }, "node_modules/@napi-rs/wasm-runtime": { "version": "0.2.12", "resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-0.2.12.tgz", @@ -966,21 +956,6 @@ "@types/react": "^19.0.0" } }, - "node_modules/@types/webidl-conversions": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/@types/webidl-conversions/-/webidl-conversions-7.0.3.tgz", - "integrity": "sha512-CiJJvcRtIgzadHCYXw7dqEnMNRjhGZlYK05Mj9OyktqV8uVT8fD2BFOB7S1uwBE3Kj2Z+4UyPmFw/Ixgw/LAlA==", - "license": "MIT" - }, - "node_modules/@types/whatwg-url": { - "version": "11.0.5", - "resolved": "https://registry.npmjs.org/@types/whatwg-url/-/whatwg-url-11.0.5.tgz", - "integrity": "sha512-coYR071JRaHa+xoEvvYqvnIHaVqaYrLPbsufM9BF63HkwI5Lgmy2QR8Q5K/lYDYo5AK82wOvSOS0UsLTpTG7uQ==", - "license": "MIT", - "dependencies": { - "@types/webidl-conversions": "*" - } - }, "node_modules/@typescript-eslint/eslint-plugin": { "version": "8.43.0", "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.43.0.tgz", @@ -1855,15 +1830,6 @@ "node": ">=8" } }, - "node_modules/bson": { - "version": "6.10.4", - "resolved": "https://registry.npmjs.org/bson/-/bson-6.10.4.tgz", - "integrity": "sha512-WIsKqkSC0ABoBJuT1LEX+2HEvNmNKKgnTAyd0fL8qzK4SH2i9NXg+t08YtdZp/V9IZ33cxe3iV4yM0qg8lMQng==", - "license": "Apache-2.0", - "engines": { - "node": ">=16.20.1" - } - }, "node_modules/call-bind": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.8.tgz", @@ -2106,6 +2072,7 @@ "version": "4.4.1", "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.1.tgz", "integrity": "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==", + "dev": true, "license": "MIT", "dependencies": { "ms": "^2.1.3" @@ -3794,15 +3761,6 @@ "node": ">=4.0" } }, - "node_modules/kareem": { - "version": "2.6.3", - "resolved": "https://registry.npmjs.org/kareem/-/kareem-2.6.3.tgz", - "integrity": "sha512-C3iHfuGUXK2u8/ipq9LfjFfXFxAZMQJJq7vLS45r3D9Y2xQ/m4S8zaR4zMLFWh9AsNPXmcFfUDhTEO8UIC/V6Q==", - "license": "Apache-2.0", - "engines": { - "node": ">=12.0.0" - } - }, "node_modules/keyv": { "version": "4.5.4", "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", @@ -3893,12 +3851,6 @@ "node": ">= 0.4" } }, - "node_modules/memory-pager": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/memory-pager/-/memory-pager-1.5.0.tgz", - "integrity": "sha512-ZS4Bp4r/Zoeq6+NLJpP+0Zzm0pR8whtGPf1XExKLJBAczGMnSi3It14OiNCStjQjM6NU1okjQGSxgEZN8eBYKg==", - "license": "MIT" - }, "node_modules/merge2": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", @@ -3946,109 +3898,11 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/mongodb": { - "version": "6.18.0", - "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-6.18.0.tgz", - "integrity": "sha512-fO5ttN9VC8P0F5fqtQmclAkgXZxbIkYRTUi1j8JO6IYwvamkhtYDilJr35jOPELR49zqCJgXZWwCtW7B+TM8vQ==", - "license": "Apache-2.0", - "dependencies": { - "@mongodb-js/saslprep": "^1.1.9", - "bson": "^6.10.4", - "mongodb-connection-string-url": "^3.0.0" - }, - "engines": { - "node": ">=16.20.1" - }, - "peerDependencies": { - "@aws-sdk/credential-providers": "^3.188.0", - "@mongodb-js/zstd": "^1.1.0 || ^2.0.0", - "gcp-metadata": "^5.2.0", - "kerberos": "^2.0.1", - "mongodb-client-encryption": ">=6.0.0 <7", - "snappy": "^7.2.2", - "socks": "^2.7.1" - }, - "peerDependenciesMeta": { - "@aws-sdk/credential-providers": { - "optional": true - }, - "@mongodb-js/zstd": { - "optional": true - }, - "gcp-metadata": { - "optional": true - }, - "kerberos": { - "optional": true - }, - "mongodb-client-encryption": { - "optional": true - }, - "snappy": { - "optional": true - }, - "socks": { - "optional": true - } - } - }, - "node_modules/mongodb-connection-string-url": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/mongodb-connection-string-url/-/mongodb-connection-string-url-3.0.2.tgz", - "integrity": "sha512-rMO7CGo/9BFwyZABcKAWL8UJwH/Kc2x0g72uhDWzG48URRax5TCIcJ7Rc3RZqffZzO/Gwff/jyKwCU9TN8gehA==", - "license": "Apache-2.0", - "dependencies": { - "@types/whatwg-url": "^11.0.2", - "whatwg-url": "^14.1.0 || ^13.0.0" - } - }, - "node_modules/mongoose": { - "version": "8.18.1", - "resolved": "https://registry.npmjs.org/mongoose/-/mongoose-8.18.1.tgz", - "integrity": "sha512-K0RfrUXXufqNRZZjvAGdyjydB91SnbWxlwFYi5t7zN2DxVWFD3c6puia0/7xfBwZm6RCpYOVdYFlRFpoDWiC+w==", - "license": "MIT", - "dependencies": { - "bson": "^6.10.4", - "kareem": "2.6.3", - "mongodb": "~6.18.0", - "mpath": "0.9.0", - "mquery": "5.0.0", - "ms": "2.1.3", - "sift": "17.1.3" - }, - "engines": { - "node": ">=16.20.1" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/mongoose" - } - }, - "node_modules/mpath": { - "version": "0.9.0", - "resolved": "https://registry.npmjs.org/mpath/-/mpath-0.9.0.tgz", - "integrity": "sha512-ikJRQTk8hw5DEoFVxHG1Gn9T/xcjtdnOKIU1JTmGjZZlg9LST2mBLmcX3/ICIbgJydT2GOc15RnNy5mHmzfSew==", - "license": "MIT", - "engines": { - "node": ">=4.0.0" - } - }, - "node_modules/mquery": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/mquery/-/mquery-5.0.0.tgz", - "integrity": "sha512-iQMncpmEK8R8ncT8HJGsGc9Dsp8xcgYMVSbs5jgnm1lFHTZqMJTUWTDx1LBO8+mK3tPNZWFLBghQEIOULSTHZg==", - "license": "MIT", - "dependencies": { - "debug": "4.x" - }, - "engines": { - "node": ">=14.0.0" - } - }, "node_modules/ms": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true, "license": "MIT" }, "node_modules/nanoid": { @@ -4458,6 +4312,7 @@ "version": "2.3.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", + "dev": true, "license": "MIT", "engines": { "node": ">=6" @@ -4897,12 +4752,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/sift": { - "version": "17.1.3", - "resolved": "https://registry.npmjs.org/sift/-/sift-17.1.3.tgz", - "integrity": "sha512-Rtlj66/b0ICeFzYTuNvX/EF1igRbbnGSvEyT79McoZa/DeGhMyC5pWKOEsZKnpkqtSeovd5FL/bjHWC3CIIvCQ==", - "license": "MIT" - }, "node_modules/simple-swizzle": { "version": "0.2.2", "resolved": "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.2.tgz", @@ -4922,15 +4771,6 @@ "node": ">=0.10.0" } }, - "node_modules/sparse-bitfield": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/sparse-bitfield/-/sparse-bitfield-3.0.3.tgz", - "integrity": "sha512-kvzhi7vqKTfkh0PZU+2D2PIllw2ymqJKujUcyPMd9Y75Nv4nPbGJZXNhxsgdQab2BmlDct1YnfQCguEvHr7VsQ==", - "license": "MIT", - "dependencies": { - "memory-pager": "^1.0.2" - } - }, "node_modules/stable-hash": { "version": "0.0.5", "resolved": "https://registry.npmjs.org/stable-hash/-/stable-hash-0.0.5.tgz", @@ -5198,18 +5038,6 @@ "node": ">=8.0" } }, - "node_modules/tr46": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-5.1.1.tgz", - "integrity": "sha512-hdF5ZgjTqgAntKkklYw0R03MG2x/bSzTtkxmIRw/sTNV8YXsCJ1tfLAX23lhxhHJlEf3CRCOCGGWw3vI3GaSPw==", - "license": "MIT", - "dependencies": { - "punycode": "^2.3.1" - }, - "engines": { - "node": ">=18" - } - }, "node_modules/ts-api-utils": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.1.0.tgz", @@ -5418,28 +5246,6 @@ "punycode": "^2.1.0" } }, - "node_modules/webidl-conversions": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz", - "integrity": "sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==", - "license": "BSD-2-Clause", - "engines": { - "node": ">=12" - } - }, - "node_modules/whatwg-url": { - "version": "14.2.0", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-14.2.0.tgz", - "integrity": "sha512-De72GdQZzNTUBBChsXueQUnPKDkg/5A5zp7pFDuQAj5UFoENpiACU0wlCvzpAGnTkj++ihpKwKyYewn/XNUbKw==", - "license": "MIT", - "dependencies": { - "tr46": "^5.1.0", - "webidl-conversions": "^7.0.0" - }, - "engines": { - "node": ">=18" - } - }, "node_modules/which": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", diff --git a/package.json b/package.json index 9da21058..9c07d34a 100644 --- a/package.json +++ b/package.json @@ -9,7 +9,6 @@ "lint": "eslint" }, "dependencies": { - "mongoose": "^8.18.1", "next": "15.5.3", "react": "19.1.0", "react-dom": "19.1.0" diff --git a/src/components/todo/checkList.module.css b/src/components/todo/checkList.module.css index dd3ac730..020dd125 100644 --- a/src/components/todo/checkList.module.css +++ b/src/components/todo/checkList.module.css @@ -9,9 +9,15 @@ align-items: center; gap: 16px; padding: 9px 12px; -} - -.check_list_text { font-size: 16px; letter-spacing: 0%; } + +.checked { + background-color: var(--violet-100); + text-decoration: line-through; +} + +.check_btn { + cursor: pointer; +} diff --git a/src/components/todo/checkList.tsx b/src/components/todo/checkList.tsx index f37bb45c..7b830e62 100644 --- a/src/components/todo/checkList.tsx +++ b/src/components/todo/checkList.tsx @@ -1,12 +1,31 @@ import Image from "next/image"; import styles from "./checkList.module.css"; import notCheck from "../../../public/not_check.svg"; +import checkedIcon from "../../../public/checked.svg"; -export default function CheckList() { +export default function CheckList({ + name, + isCompleted, +}: { + name: string; + isCompleted: boolean; +}) { return ( -
    - 체크안됨 -

    비타민 챙겨먹기

    +
    + {isCompleted +

    {name}

    ); } diff --git a/src/components/todo/todo.tsx b/src/components/todo/todo.tsx index bb807ec4..489c1155 100644 --- a/src/components/todo/todo.tsx +++ b/src/components/todo/todo.tsx @@ -1,12 +1,20 @@ import Image from "next/image"; import CheckList from "./checkList"; import styles from "./todo.module.css"; +import todoImg from "../../../public/todo.png"; +import { todoData } from "@/mock"; export default function Todo() { return (
    - todo 이미지 - + todo 이미지 + {todoData.map((todo) => ( + + ))}
    ); } diff --git a/src/mock.ts b/src/mock.ts index e69de29b..6d553719 100644 --- a/src/mock.ts +++ b/src/mock.ts @@ -0,0 +1,17 @@ +export const todoData = [ + { + isCompleted: true, + name: "비타민 챙겨먹기", + id: 1, + }, + { + isCompleted: false, + name: "맥주 마시기", + id: 2, + }, + { + isCompleted: false, + name: "운동하기", + id: 3, + }, +]; From ed4030a3a2f8a0004c9b32e725cac57d52fc1aa0 Mon Sep 17 00:00:00 2001 From: Imhwitae Date: Wed, 17 Sep 2025 15:00:19 +0900 Subject: [PATCH 88/94] =?UTF-8?q?feat:=20=ED=88=AC=EB=91=90=EB=A6=AC?= =?UTF-8?q?=EC=8A=A4=ED=8A=B8=20=EB=8D=B0=EC=9D=B4=ED=84=B0=20=EC=9A=94?= =?UTF-8?q?=EC=B2=AD=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/app/page.module.css | 7 ++- src/app/page.tsx | 6 +-- src/components/todo/todo.module.css | 5 -- src/components/todo/todo.tsx | 20 -------- src/components/todo/todoList.module.css | 13 +++++ src/components/todo/todoList.tsx | 64 +++++++++++++++++++++++++ src/mock.ts | 17 ------- src/types.ts | 10 ++++ 8 files changed, 93 insertions(+), 49 deletions(-) delete mode 100644 src/components/todo/todo.module.css delete mode 100644 src/components/todo/todo.tsx create mode 100644 src/components/todo/todoList.module.css create mode 100644 src/components/todo/todoList.tsx delete mode 100644 src/mock.ts create mode 100644 src/types.ts diff --git a/src/app/page.module.css b/src/app/page.module.css index 72844d98..5009d986 100644 --- a/src/app/page.module.css +++ b/src/app/page.module.css @@ -1,5 +1,4 @@ -.title { - font-family: "NanumSquareBold"; - font-weight: 700; - font-size: 24px; +.list_container { + display: flex; + justify-content: center; } diff --git a/src/app/page.tsx b/src/app/page.tsx index 81c1ca25..df5cdabc 100644 --- a/src/app/page.tsx +++ b/src/app/page.tsx @@ -1,13 +1,13 @@ import Searchbar from "@/components/searchbar/searchbar"; import styles from "./page.module.css"; -import Todo from "@/components/todo/todo"; +import TodoList from "@/components/todo/todoList"; export default function Home() { return (
    -
    - +
    +
    ); diff --git a/src/components/todo/todo.module.css b/src/components/todo/todo.module.css deleted file mode 100644 index 8cb8b1f5..00000000 --- a/src/components/todo/todo.module.css +++ /dev/null @@ -1,5 +0,0 @@ -.todo_container { - display: flex; - flex-direction: column; - gap: 16px; -} diff --git a/src/components/todo/todo.tsx b/src/components/todo/todo.tsx deleted file mode 100644 index 489c1155..00000000 --- a/src/components/todo/todo.tsx +++ /dev/null @@ -1,20 +0,0 @@ -import Image from "next/image"; -import CheckList from "./checkList"; -import styles from "./todo.module.css"; -import todoImg from "../../../public/todo.png"; -import { todoData } from "@/mock"; - -export default function Todo() { - return ( -
    - todo 이미지 - {todoData.map((todo) => ( - - ))} -
    - ); -} diff --git a/src/components/todo/todoList.module.css b/src/components/todo/todoList.module.css new file mode 100644 index 00000000..1e8b8595 --- /dev/null +++ b/src/components/todo/todoList.module.css @@ -0,0 +1,13 @@ +.todo_list_container { + width: 1200px; + max-width: 1200px; + display: grid; + grid-template-columns: 1fr 1fr; + gap: 24px; +} + +.todo_list_box { + display: flex; + flex-direction: column; + gap: 16px; +} diff --git a/src/components/todo/todoList.tsx b/src/components/todo/todoList.tsx new file mode 100644 index 00000000..13b35a88 --- /dev/null +++ b/src/components/todo/todoList.tsx @@ -0,0 +1,64 @@ +import Image from "next/image"; +import CheckList from "./checkList"; +import styles from "./todoList.module.css"; +import todoImg from "../../../public/todo.png"; +import doneImg from "../../../public/done.png"; +import { SeparatedTodos, TodoData } from "@/types"; + +async function getAllTodoList() { + const response = await fetch( + `${process.env.NEXT_API_URL}/fe-18-sprint9/items` + ); + + if (!response.ok) console.error(response.statusText); + + const todoList: TodoData[] = await response.json(); + const separatedTodos = todoList.reduce( + (acc, todo) => { + if (todo.isCompleted) { + acc.completed.push(todo); + } else { + acc.incomplete.push(todo); + } + return acc; + }, + { + completed: [], + incomplete: [], + } + ); + + return separatedTodos; +} + +export default async function TodoList() { + const separatedTodos = await getAllTodoList(); + + return ( + <> +
    +
    + todo 이미지 + {separatedTodos.incomplete.map((todo) => ( + + ))} +
    + +
    + done 이미지 + {separatedTodos.completed.map((todo) => ( + + ))} +
    +
    + + ); +} diff --git a/src/mock.ts b/src/mock.ts deleted file mode 100644 index 6d553719..00000000 --- a/src/mock.ts +++ /dev/null @@ -1,17 +0,0 @@ -export const todoData = [ - { - isCompleted: true, - name: "비타민 챙겨먹기", - id: 1, - }, - { - isCompleted: false, - name: "맥주 마시기", - id: 2, - }, - { - isCompleted: false, - name: "운동하기", - id: 3, - }, -]; diff --git a/src/types.ts b/src/types.ts new file mode 100644 index 00000000..a433d698 --- /dev/null +++ b/src/types.ts @@ -0,0 +1,10 @@ +export interface TodoData { + id: number; + name: string; + isCompleted: boolean; +} + +export interface SeparatedTodos { + completed: TodoData[]; + incomplete: TodoData[]; +} From 82872c5b5eea5a1c4d93e34e77ad007f4d1b6145 Mon Sep 17 00:00:00 2001 From: Imhwitae Date: Wed, 17 Sep 2025 15:11:25 +0900 Subject: [PATCH 89/94] =?UTF-8?q?rename:=20=EC=BB=B4=ED=8F=AC=EB=84=8C?= =?UTF-8?q?=ED=8A=B8=20=EC=9D=B4=EB=A6=84=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/app/page.tsx | 4 ++-- src/components/{searchbar => addTask}/searchbar.module.css | 0 .../{searchbar/searchbar.tsx => addTask/taskbar.tsx} | 6 +++++- src/components/todo/todoList.tsx | 3 ++- 4 files changed, 9 insertions(+), 4 deletions(-) rename src/components/{searchbar => addTask}/searchbar.module.css (100%) rename src/components/{searchbar/searchbar.tsx => addTask/taskbar.tsx} (86%) diff --git a/src/app/page.tsx b/src/app/page.tsx index df5cdabc..de24b361 100644 --- a/src/app/page.tsx +++ b/src/app/page.tsx @@ -1,11 +1,11 @@ -import Searchbar from "@/components/searchbar/searchbar"; +import Taskbar from "@/components/addTask/taskbar"; import styles from "./page.module.css"; import TodoList from "@/components/todo/todoList"; export default function Home() { return (
    - +
    diff --git a/src/components/searchbar/searchbar.module.css b/src/components/addTask/searchbar.module.css similarity index 100% rename from src/components/searchbar/searchbar.module.css rename to src/components/addTask/searchbar.module.css diff --git a/src/components/searchbar/searchbar.tsx b/src/components/addTask/taskbar.tsx similarity index 86% rename from src/components/searchbar/searchbar.tsx rename to src/components/addTask/taskbar.tsx index 8f95bfb2..486dae75 100644 --- a/src/components/searchbar/searchbar.tsx +++ b/src/components/addTask/taskbar.tsx @@ -1,7 +1,11 @@ +"use client"; + import Image from "next/image"; import styles from "./searchbar.module.css"; -export default function Searchbar() { +export default function Taskbar() { + // const onChangeTask + return (
    diff --git a/src/components/todo/todoList.tsx b/src/components/todo/todoList.tsx index 13b35a88..421cbe07 100644 --- a/src/components/todo/todoList.tsx +++ b/src/components/todo/todoList.tsx @@ -7,7 +7,8 @@ import { SeparatedTodos, TodoData } from "@/types"; async function getAllTodoList() { const response = await fetch( - `${process.env.NEXT_API_URL}/fe-18-sprint9/items` + `${process.env.NEXT_API_URL}/fe-18-sprint9/items`, + { next: { tags: [`todo`] } } ); if (!response.ok) console.error(response.statusText); From eff48bd022ce249ff6984999baf774ce854247f7 Mon Sep 17 00:00:00 2001 From: Imhwitae Date: Wed, 17 Sep 2025 16:50:47 +0900 Subject: [PATCH 90/94] =?UTF-8?q?refactor:=20=ED=88=AC=EB=91=90=EB=A6=AC?= =?UTF-8?q?=EC=8A=A4=ED=8A=B8=20=EB=A6=AC=ED=8C=A9=ED=86=A0=EB=A7=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- public/empty_done.png | Bin 0 -> 4523 bytes public/empty_todo.png | Bin 0 -> 7362 bytes public/plus_white.svg | 4 ++ ...earchbar.module.css => taskbar.module.css} | 13 ++--- src/components/addTask/taskbar.tsx | 45 +++++++++++------ ...kList.module.css => check-list.module.css} | 0 .../todo/{checkList.tsx => check-list.tsx} | 2 +- src/components/todo/empty-img.module.css | 14 ++++++ src/components/todo/todo-section.tsx | 32 ++++++++++++ src/components/todo/todoList.tsx | 47 +++++++++++------- src/types.ts | 11 ++++ 11 files changed, 129 insertions(+), 39 deletions(-) create mode 100644 public/empty_done.png create mode 100644 public/empty_todo.png create mode 100644 public/plus_white.svg rename src/components/addTask/{searchbar.module.css => taskbar.module.css} (80%) rename src/components/todo/{checkList.module.css => check-list.module.css} (100%) rename src/components/todo/{checkList.tsx => check-list.tsx} (93%) create mode 100644 src/components/todo/empty-img.module.css create mode 100644 src/components/todo/todo-section.tsx diff --git a/public/empty_done.png b/public/empty_done.png new file mode 100644 index 0000000000000000000000000000000000000000..d476d7e3a660dd51a67dc95711db0317f0398b64 GIT binary patch literal 4523 zcmbVwhf@Fv$$`v<;v-kaImyXT&ry}8+&+r1A@4YeuB*~kF^0Hv;uh7n%x<7JMN7~dNz zi7nt2nTL+KHvj;p|4)E`>|7Q+2=q46RtMA$b8O-#g!YdN9svOLiQp?35dc7|rmOMD z#2>her8Ht6U?ka}5=X%s>P>Wa*+hVzpdVzs1*kK^pMqaPKr8gqD!?;BbUx~k>{mV@ z3<{R7`Z(PKW_i-}kDdQHY0*g5=HA$?*^C#(D}nlpC#V1VoO$sc|8LDhgH|nJXLm9- zFhMpIL%l4)as+cMYBW$l03dEVoWIc)Ri`Hq=-%0LamBT!v^1j#FD-gCsvdFo)BPAP zm{nIfhdP{xncVwgO?(O2(|M1lBKHxT#~<^ynJi>}1E$$N%eNSYr}z`qSW_LgRz;73 z2+kt2M5T*pY)Jo9{0J=DK)UDP>>D2|L;xV86wmCE`s$0J`g}ltE#YIE!oK7|=(Z@H zi&Y~q9?bMhg^)@T#*=j1)?9lRnUwwK{WjD3nIR8~M!KeQ0c9dSlEaFpvptw}yDq0Z zl|F(D)(eA3S=i^z+Aqr$o1q&Bgi$;(_tAiqfZfYRC!JHYLl}>P-dpQjo+aov>%j4i zzLmEVB--((VoF)5fx@ACT$7hI)hEOtibt_7u`}mQ@}1zap?9jYe^mAJVjumoiG>8i z@q2$>8apSO)Y~HwN#@>Sm-(r1n}L*&CA^Oo%^RQnmEd`VPYz=R}CZ*z-%Sc{|B(5n|-?HcqYqcoi`h)Js* zfkwk6wuuP$doAJHc=@$$9{vPiheF4tE25L{YO0V^bFIJEnoqGOxY<>f_EAaClSFnd zJ3qRH^T}My2@2{yi^$I|Gc_&zDGBw($4o!FPZ4aHlVfV?!zBG(i>A=DpjkH7cP))C z{_u?Opd{;;k4N-ev9eqoj#e){9~w+hGkKwUJ`RDA(G808xsC63k)@Vvls?bx8TK~}8C+lVEJ@Gb?VC@PK@4o^N@UbsT&6ukhJ;qghg~P*M-_i<k=Vo^ztX4R0_bKN9-i z^d?-m-5gZ}DOZc%;mGSe*;)3EkFy$)RMm36s<0$H+j^JMrp`BC*K5rF%UzqS!9+7o zpJQI?+*MFzJETwga>R@$kAsIQkqPgm;qFg|Li`! zFwF#vLl1L^UHjvD3#k*$%4uCchuWmT5?Fh~esT+|sS z29{RPNl>t1^r|K#A2bW>QPeMOTx!3qKnEeozfi2vtHr#25Vzw{!UIK|Y57?oIhvjG z`4{%WL?FC0g)Xo$7r&jZ#q6d9xoJvOrl<#ZLwH1~u zZyjwL!0k*afUoUCCN8Jedi@RC{@lo{R1(&y0%a>HfHQ0xH>QTD))PNYuB;RVTnjy@ z)M52<3fCZ4o;FxAXO;*CM(UcemWhfJSmg0xjQ*rcMFM{Gu;T%=m=ZH*+q7I9fPi8q zEg><+bSlHh*Sso?%pLSuv7HaV%3didKCU@b963b{OFzSMuQ~^iI8@llqX+kf z0crli$GQen4RB^GkUxzBJftfStT9Q8JEzIRP&vIi{^H&-MvisZ4_oRRQ!ou7cM-f@ z52L(Q2dIp0WsNK`&J#`l!sH}ervqwDf*01epzsx$@`Ss+K*jj>b5&8Rdu5hZLatKJ z--K}u2By#5ah{E6aW0ZMG6wC#Im6zqf88^cm?v%xX!S}1%!yh#?Ajr{>iqaLG32&t z;9yke(h59%3YY+nhN*!cF0EAYSaI!(pKKi$t0cC#rwQBdAQ^|SS;bkKAOpt6Jm1c% z5m@HttfmI@0-xd~ldia}-pA^VA)+6N8BC9rR>^P#VpIv++b4$`z2?%onfW45H>1qk zA3T`W`(0PD@OO1vK{L6?vo&x&w@S03Gjg0P%Ex2E|A~Uo)y4?Be$f;-eW{A^Cg_S=4&=%Ql0 zi?_3tlfCJn(}(xoxF5^uRdf4^GVUPPmlr}?PnsIs7dHK7zvj)VDh-5G`Mkvq8_Zr# zZaOcp-_@_pm%{}+A|mj2z=82w71GVlAo%n&=tx@b(w>`NP4HHU{jYtQ>D5b5l{+3z z3d&uDx6(I%FB@v}{Xo*?SyPrK#V*Vyri1=@|AxFB!|4}{saSXqh7!ncXPbki6z6!c z3s3XqDmq`x(VBqg=$7H>jjy~UL{78fZ}Xv8zw&FG$8l$h`h8WGS~j1fD+X?JT3f-% z1$ubUWZ7kJ)T&Mr0=pIy#b~ieRuL2#p`6wIYwYfC-3V&Sd-W8ur~uZ{a7z?$q2#ac zs1zJrYq7LQEjONRO#=@~i}-OtY$tXGxLxVP+#_y8fvGH(EIA}Z2rMd#i0%m4W64Pr zsOKoxBfIId+MBs=l*?`pNRJ9 zI1x8K!G{=Phof|Nvk&J`pY)ycPhM#`*;6Bd4<+EDRX7tpc~pGj9L{CIKS_7j!ESz# zmx68Md}kv0nbUUq#|D|^5kx~|chN*eDjkxfd1?1ny^MqED3YNvCH}lbKlpKVkcZEq z#d=5wBBQKKb*(A<`?=ntiKmk+mY9DAKpiUY*E=uaKEsXEO(JRAy#2SfY7Vp7ow47R z9W+ZJCqskFDBHGr(PFG6n8gH`MFoSvH#+BEUUD)@fi22*zdD8=)u~|Z+Wb3ZHX3JY zI=;Ghocz^`0Anh}CDM(+p3A^_rOz41;?P;12^X|wp6vRh-zCn`ZSs>(5I6m<(>gP9 zi*CSK#NqgUk5f8LXEtZQMNw+$S0=?Gn$tHVmCJuRPgj(?Lw0YUht@U*8USXTrU4m3 z0##zGNsP~a&c~KFL3G;DV_cn54*o>4w-J0*Cl^L9KfGmprNpa0P-WOax%X=GTnKXX zLX3gz{|p|(=DYiiyf$9M|s+H9x4pxuNHb!VDPi*T_o#n`oi z80XZFb0(`SOy%j^V8;=H4L7Bw!q-U#tnc&zj+o8iV0{<3X0Qf0-9kO4krQ3SVBo^s zj=h0}yo6HK0{Mj}fnxW^#64oO$~L5?)d0FiB9lW`AYeJ#J3S7`rRD0V^YJsZFtrGb zCFUDXDm0P1-&jcG#>Y2qaR3o(d0%fQEg!?w3KmYXe}U9~Ou;u;dd%n$))8$M&YBxY zT9Wm~uqg?uM0m#Z7+mIB6Cf^!-OTNzULaw!gFgBrkUGnQQr3B#8x{1b%7Tv73f(Of zG&y&05i*g^te2C@L)c19=DEmqldZ58<;ZN_uO_3o)_0IvP=G5*x0`Asig-Z~gC=x5 z_O?;VT&6Y+%D9)}rA?MnOk?EOcS<4=*K3afKNTM}cVka-Ia#96=ac zdN7ofYau$=hJ=0c#6Yd#@1moiM4Qj#e5^?xdNW1u5|7$P3*wYCu6!KpC%hGk(RUD* z{Pvk#9prUtaBYTAk7!xsAHw^u%M6zsGc246lsWIRn46ii{^QM(CG^+7)ASP(`gc~> zSzi`lxX?$+T
    l29V7WSG1cR4H=FmQp#APDm)va~XAPP<5IX0Qh+|+T#7YI_Z>K z&^dQ3hkvV}%;(v$NUJ!hNBHs(jYgWj#p-+2f4j@v4|HR%gpQZ5gpnk)TzwFJ1jDV2 zlcq_+S>E%;m6skb@tHLTzP{M4J0&agXib|im)dAdUawCR_Y`=>zWRPaTf|=T)GGk+ z&=g;R?s#Xku{x0XI`hAT-q|#^mF;4ZHf<29mA^+QZ)X%{Z0KZfOHeo&0ozDk`%!jJ z)h4Z4LZk`#ZyZ^XTHmVK@TfULle!XF>>yD?*Bu#ZO7ux9^r=kss3C}OIt;BzdNSyK z+eRDSeAv!xU3Hi1&|?Xh)|hvOu~>>t47c}C zt@*w{aJIPPmCBB0`P_}N>F6<{U~iJt2$A*z0EEDSphy4#Aq9|_lm$dVBT2}@Z9^)l zhN7{7!+B8u9|8;#I_Os2JAo0)7`Iub&UT#AJZPk`;`50DRH%JYG<3Y~dAC@=4(V-m zqxHT*-jj(N%&<1wcIgW6m`M8WH0fw-q+Blbev0&(2SpZx9(20K5W^yJU@VW!-`%KJ z#Ye29xRMPJ2?*jT5fC{2;U;?E0eiH;Ww+s8V<$Sv#AUqYF`xbJ6P`{j7AjCKJfb9J z%0<4$+pE;eF6$@5cjxy@For;V&jB+%ah4CHOETXbXcj$%kE4T`@oUN4DBG`COvs@n zX&tRr1R!xhC~&1)_&^!4&jyob>0uj>$s=hpen7pO<^gd;>YGch|B$4nUXlU*Z@(;1 ag*Vi@>G@uv&|LoiY;-jZHEPvu!v6=^6Mta< literal 0 HcmV?d00001 diff --git a/public/empty_todo.png b/public/empty_todo.png new file mode 100644 index 0000000000000000000000000000000000000000..d792da72073867c97924ac35924d88ccf2e881c9 GIT binary patch literal 7362 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 + + + diff --git a/src/components/addTask/searchbar.module.css b/src/components/addTask/taskbar.module.css similarity index 80% rename from src/components/addTask/searchbar.module.css rename to src/components/addTask/taskbar.module.css index c7883422..972a3daa 100644 --- a/src/components/addTask/searchbar.module.css +++ b/src/components/addTask/taskbar.module.css @@ -1,4 +1,4 @@ -.searchbar_box { +.taskbar_box { display: flex; gap: 16px; justify-content: center; @@ -6,7 +6,7 @@ height: 56px; } -.searchbar { +.taskbar { width: 1016px; max-width: 1016px; border-radius: 24px; @@ -19,7 +19,7 @@ box-shadow: 4px 3px; } -.searchbar:focus { +.taskbar:focus { outline: none; } @@ -28,7 +28,7 @@ background-color: var(--slate-200); border: 2px solid var(--slate-900); border-radius: 24px; - box-shadow: 4px 3px; + box-shadow: 4px 3px var(--slate-900); font-size: 16px; font-family: "NanumSquareBold"; display: flex; @@ -37,6 +37,7 @@ gap: 4px; } -.plus { - color: black; +.writing_task { + background-color: var(--violet-600); + color: white; } diff --git a/src/components/addTask/taskbar.tsx b/src/components/addTask/taskbar.tsx index 486dae75..58ff1072 100644 --- a/src/components/addTask/taskbar.tsx +++ b/src/components/addTask/taskbar.tsx @@ -1,24 +1,41 @@ "use client"; import Image from "next/image"; -import styles from "./searchbar.module.css"; +import styles from "./taskbar.module.css"; +import { ChangeEvent, useState } from "react"; +import plus from "../../../public/plus.svg"; +import plusWhite from "../../../public/plus_white.svg"; export default function Taskbar() { - // const onChangeTask + const [task, setTask] = useState(""); + const onChangeTask = (e: ChangeEvent) => { + setTask(e.target.value); + }; return ( -
    - - -
    + +
    + ); } diff --git a/src/components/todo/checkList.module.css b/src/components/todo/check-list.module.css similarity index 100% rename from src/components/todo/checkList.module.css rename to src/components/todo/check-list.module.css diff --git a/src/components/todo/checkList.tsx b/src/components/todo/check-list.tsx similarity index 93% rename from src/components/todo/checkList.tsx rename to src/components/todo/check-list.tsx index 7b830e62..64b32a84 100644 --- a/src/components/todo/checkList.tsx +++ b/src/components/todo/check-list.tsx @@ -1,5 +1,5 @@ import Image from "next/image"; -import styles from "./checkList.module.css"; +import styles from "./check-list.module.css"; import notCheck from "../../../public/not_check.svg"; import checkedIcon from "../../../public/checked.svg"; diff --git a/src/components/todo/empty-img.module.css b/src/components/todo/empty-img.module.css new file mode 100644 index 00000000..9410f6ec --- /dev/null +++ b/src/components/todo/empty-img.module.css @@ -0,0 +1,14 @@ +.empty { + display: flex; + align-items: center; + flex-direction: column; + gap: 24px; +} + +.empty_msg { + font-family: "NanumSquareBold"; + font-size: 16px; + letter-spacing: 0%; + color: var(--slate-400); + text-align: center; +} diff --git a/src/components/todo/todo-section.tsx b/src/components/todo/todo-section.tsx new file mode 100644 index 00000000..53ecae21 --- /dev/null +++ b/src/components/todo/todo-section.tsx @@ -0,0 +1,32 @@ +import { TodoSectionProps } from "@/types"; +import Image, { StaticImageData } from "next/image"; +import CheckList from "./check-list"; +import styles from "./empty-img.module.css"; + +export default function TodoSection({ + img, + imgAlt, + list, + emptyImg, + emptyMsg, +}: TodoSectionProps) { + return ( + <> + {imgAlt} + {list.length > 0 ? ( + list.map((todo) => ( + + )) + ) : ( +
    + 리스트 없음 +

    {emptyMsg}

    +
    + )} + + ); +} diff --git a/src/components/todo/todoList.tsx b/src/components/todo/todoList.tsx index 421cbe07..f348a978 100644 --- a/src/components/todo/todoList.tsx +++ b/src/components/todo/todoList.tsx @@ -1,9 +1,10 @@ -import Image from "next/image"; -import CheckList from "./checkList"; import styles from "./todoList.module.css"; import todoImg from "../../../public/todo.png"; import doneImg from "../../../public/done.png"; import { SeparatedTodos, TodoData } from "@/types"; +import emptyTodo from "../../../public/empty_todo.png"; +import emptyDone from "../../../public/empty_done.png"; +import TodoSection from "./todo-section"; async function getAllTodoList() { const response = await fetch( @@ -39,25 +40,35 @@ export default async function TodoList() { <>
    - todo 이미지 - {separatedTodos.incomplete.map((todo) => ( - - ))} + + 할 일이 없어요. +
    + TODO를 새롭게 추가해주세요! + + } + />
    - done 이미지 - {separatedTodos.completed.map((todo) => ( - - ))} + + 아직 다 한 일이 없어요. +
    + 해야 할 일을 체크해보세요! + + } + />
    diff --git a/src/types.ts b/src/types.ts index a433d698..f43e158e 100644 --- a/src/types.ts +++ b/src/types.ts @@ -1,3 +1,6 @@ +import { StaticImageData } from "next/image"; +import { ReactNode } from "react"; + export interface TodoData { id: number; name: string; @@ -8,3 +11,11 @@ export interface SeparatedTodos { completed: TodoData[]; incomplete: TodoData[]; } + +export interface TodoSectionProps { + img: StaticImageData; + list: TodoData[]; + emptyImg: StaticImageData; + imgAlt: string; + emptyMsg: ReactNode; +} From ec1ba8a11786c2ab45b6e51de7c54bcc49d35201 Mon Sep 17 00:00:00 2001 From: Imhwitae Date: Thu, 18 Sep 2025 14:32:25 +0900 Subject: [PATCH 91/94] =?UTF-8?q?feat:=20=ED=97=A4=EB=8D=94=20=EB=A1=9C?= =?UTF-8?q?=EA=B3=A0=EC=97=90=20=EB=A7=81=ED=81=AC=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/header/header.tsx | 17 ++++++++++------- src/components/todo/todo-section.tsx | 2 +- src/components/todo/todoList.tsx | 2 +- 3 files changed, 12 insertions(+), 9 deletions(-) diff --git a/src/components/header/header.tsx b/src/components/header/header.tsx index a50b5395..d7070424 100644 --- a/src/components/header/header.tsx +++ b/src/components/header/header.tsx @@ -1,17 +1,20 @@ import Image from "next/image"; import styles from "./header.module.css"; +import Link from "next/link"; export default function Header() { return (
    - logo + + logo +
    ); diff --git a/src/components/todo/todo-section.tsx b/src/components/todo/todo-section.tsx index 53ecae21..7c035348 100644 --- a/src/components/todo/todo-section.tsx +++ b/src/components/todo/todo-section.tsx @@ -1,5 +1,5 @@ import { TodoSectionProps } from "@/types"; -import Image, { StaticImageData } from "next/image"; +import Image from "next/image"; import CheckList from "./check-list"; import styles from "./empty-img.module.css"; diff --git a/src/components/todo/todoList.tsx b/src/components/todo/todoList.tsx index f348a978..5da79e9a 100644 --- a/src/components/todo/todoList.tsx +++ b/src/components/todo/todoList.tsx @@ -9,7 +9,7 @@ import TodoSection from "./todo-section"; async function getAllTodoList() { const response = await fetch( `${process.env.NEXT_API_URL}/fe-18-sprint9/items`, - { next: { tags: [`todo`] } } + { next: { tags: ["todo"] } } ); if (!response.ok) console.error(response.statusText); From a773bafcdeaf0102cc296616c1974786889f20ac Mon Sep 17 00:00:00 2001 From: Imhwitae Date: Thu, 18 Sep 2025 16:14:56 +0900 Subject: [PATCH 92/94] =?UTF-8?q?feat:=20=ED=95=A0=20=EC=9D=BC=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80=ED=95=98=EA=B8=B0=20=EA=B8=B0=EB=8A=A5=20=EA=B0=9C?= =?UTF-8?q?=EB=B0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/actions/add-task.action.ts | 31 +++++++++++++++++++++++ src/components/addTask/taskbar.module.css | 1 + src/components/addTask/taskbar.tsx | 19 +++++++++++--- src/components/todo/todoList.tsx | 7 +++-- src/types.ts | 5 ++++ 5 files changed, 56 insertions(+), 7 deletions(-) create mode 100644 src/actions/add-task.action.ts diff --git a/src/actions/add-task.action.ts b/src/actions/add-task.action.ts new file mode 100644 index 00000000..f45391d0 --- /dev/null +++ b/src/actions/add-task.action.ts @@ -0,0 +1,31 @@ +"use server"; + +import { ActionState } from "@/types"; +import { revalidateTag } from "next/cache"; + +export default async function addTaskAction( + prevData: ActionState, + formData: FormData +): Promise { + const name = formData.get("name")?.toString(); + + if (!name) return { status: false, error: "할 일을 입력해주세요" }; + + try { + const response = await fetch(`${process.env.NEXT_API_URL}/items`, { + method: "POST", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify({ name }), + }); + + if (!response.ok) return { status: false, error: response.statusText }; + + revalidateTag("todo"); + + return { status: true, error: "" }; + } catch (error) { + return { status: true, error: `할 일 등록에 실패했습니다. ${error}` }; + } +} diff --git a/src/components/addTask/taskbar.module.css b/src/components/addTask/taskbar.module.css index 972a3daa..5e1d7d09 100644 --- a/src/components/addTask/taskbar.module.css +++ b/src/components/addTask/taskbar.module.css @@ -35,6 +35,7 @@ justify-content: center; align-items: center; gap: 4px; + cursor: pointer; } .writing_task { diff --git a/src/components/addTask/taskbar.tsx b/src/components/addTask/taskbar.tsx index 58ff1072..80909522 100644 --- a/src/components/addTask/taskbar.tsx +++ b/src/components/addTask/taskbar.tsx @@ -2,20 +2,32 @@ import Image from "next/image"; import styles from "./taskbar.module.css"; -import { ChangeEvent, useState } from "react"; +import { ChangeEvent, useActionState, useEffect, useState } from "react"; import plus from "../../../public/plus.svg"; import plusWhite from "../../../public/plus_white.svg"; +import addTaskAction from "@/actions/add-task.action"; export default function Taskbar() { const [task, setTask] = useState(""); + const [state, formAction, isPending] = useActionState(addTaskAction, { + status: true, + error: "", + }); + const onChangeTask = (e: ChangeEvent) => { setTask(e.target.value); }; + useEffect(() => { + if (state && !state.status) alert(state.error); + setTask(""); + }, [state]); + return ( -
    +
    추가이미지 + />{" "} 추가하기
    diff --git a/src/components/todo/todoList.tsx b/src/components/todo/todoList.tsx index 5da79e9a..6f6d9c59 100644 --- a/src/components/todo/todoList.tsx +++ b/src/components/todo/todoList.tsx @@ -7,10 +7,9 @@ import emptyDone from "../../../public/empty_done.png"; import TodoSection from "./todo-section"; async function getAllTodoList() { - const response = await fetch( - `${process.env.NEXT_API_URL}/fe-18-sprint9/items`, - { next: { tags: ["todo"] } } - ); + const response = await fetch(`${process.env.NEXT_API_URL}/items`, { + next: { tags: ["todo"] }, + }); if (!response.ok) console.error(response.statusText); diff --git a/src/types.ts b/src/types.ts index f43e158e..36096b9e 100644 --- a/src/types.ts +++ b/src/types.ts @@ -19,3 +19,8 @@ export interface TodoSectionProps { imgAlt: string; emptyMsg: ReactNode; } + +export interface ActionState { + status: boolean; + error: string; +} From 925b61d3a35c7fc3ea18734f73521751d1ad5aec Mon Sep 17 00:00:00 2001 From: Imhwitae Date: Thu, 18 Sep 2025 16:40:41 +0900 Subject: [PATCH 93/94] =?UTF-8?q?design:=20=EB=A1=9C=EB=94=A9=EC=8A=A4?= =?UTF-8?q?=ED=94=BC=EB=84=88=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/addTask/taskbar.module.css | 1 + src/components/addTask/taskbar.tsx | 21 ++++++++++------ src/components/loading/spinner.module.css | 29 +++++++++++++++++++++++ src/components/loading/spinner.tsx | 24 +++++++++++++++++++ src/components/todo/check-list.tsx | 4 ++++ src/components/todo/todo-section.tsx | 8 +------ 6 files changed, 73 insertions(+), 14 deletions(-) create mode 100644 src/components/loading/spinner.module.css create mode 100644 src/components/loading/spinner.tsx diff --git a/src/components/addTask/taskbar.module.css b/src/components/addTask/taskbar.module.css index 5e1d7d09..7bab8b1d 100644 --- a/src/components/addTask/taskbar.module.css +++ b/src/components/addTask/taskbar.module.css @@ -26,6 +26,7 @@ .add_btn { width: 168px; background-color: var(--slate-200); + color: var(--slate-900); border: 2px solid var(--slate-900); border-radius: 24px; box-shadow: 4px 3px var(--slate-900); diff --git a/src/components/addTask/taskbar.tsx b/src/components/addTask/taskbar.tsx index 80909522..e4b0b2d7 100644 --- a/src/components/addTask/taskbar.tsx +++ b/src/components/addTask/taskbar.tsx @@ -6,6 +6,7 @@ import { ChangeEvent, useActionState, useEffect, useState } from "react"; import plus from "../../../public/plus.svg"; import plusWhite from "../../../public/plus_white.svg"; import addTaskAction from "@/actions/add-task.action"; +import Spinner from "../loading/spinner"; export default function Taskbar() { const [task, setTask] = useState(""); @@ -40,13 +41,19 @@ export default function Taskbar() { } disabled={isPending ? true : false} > - 추가이미지{" "} - 추가하기 + {task && isPending ? ( + + ) : ( + <> + 추가이미지 + 추가하기 + + )}
    diff --git a/src/components/loading/spinner.module.css b/src/components/loading/spinner.module.css new file mode 100644 index 00000000..1e8716e7 --- /dev/null +++ b/src/components/loading/spinner.module.css @@ -0,0 +1,29 @@ +.spinnerContainer { + display: flex; + justify-content: center; + align-items: center; + width: 100%; + height: 100%; +} + +.spinner { + /* 원형 모양을 만들기 위해 border-radius를 50%로 설정 */ + border-radius: 50%; + + /* 테두리 두께와 스타일 설정 */ + border-width: 4px; + border-style: solid; + + /* spin이라는 이름의 애니메이션을 1초 동안, 선형으로, 무한 반복 */ + animation: spin 1s linear infinite; +} + +/* 회전 애니메이션 정의 */ +@keyframes spin { + from { + transform: rotate(0deg); + } + to { + transform: rotate(360deg); + } +} diff --git a/src/components/loading/spinner.tsx b/src/components/loading/spinner.tsx new file mode 100644 index 00000000..e7f528c8 --- /dev/null +++ b/src/components/loading/spinner.tsx @@ -0,0 +1,24 @@ +import styles from "./spinner.module.css"; + +/** + * 로딩 스피너 컴포넌트 + * @param {string} size - 스피너의 크기 (e.g., '50px') + * @param {string} color - 스피너의 색상 (e.g., '#007bff') + */ +export default function Spinner({ size = "30px", color = "#7c3aed" }) { + // 인라인 스타일을 사용하여 props로 받은 크기와 색상을 적용 + const spinnerStyle = { + width: size, + height: size, + // 테두리의 기본 색상은 연한 회색으로 설정 + borderColor: "#e0e0e0", + // 회전하는 부분의 색상을 props로 받은 color로 설정 + borderTopColor: color, + }; + + return ( +
    +
    +
    + ); +} diff --git a/src/components/todo/check-list.tsx b/src/components/todo/check-list.tsx index 64b32a84..b5828063 100644 --- a/src/components/todo/check-list.tsx +++ b/src/components/todo/check-list.tsx @@ -1,12 +1,16 @@ +"use client"; + import Image from "next/image"; import styles from "./check-list.module.css"; import notCheck from "../../../public/not_check.svg"; import checkedIcon from "../../../public/checked.svg"; export default function CheckList({ + id, name, isCompleted, }: { + id: number; name: string; isCompleted: boolean; }) { diff --git a/src/components/todo/todo-section.tsx b/src/components/todo/todo-section.tsx index 7c035348..64f55dea 100644 --- a/src/components/todo/todo-section.tsx +++ b/src/components/todo/todo-section.tsx @@ -14,13 +14,7 @@ export default function TodoSection({ <> {imgAlt} {list.length > 0 ? ( - list.map((todo) => ( - - )) + list.map((todo) => ) ) : (
    리스트 없음 From 841ec30a03fb0bac066235066e340e1fb0bf483f Mon Sep 17 00:00:00 2001 From: Imhwitae Date: Thu, 18 Sep 2025 18:26:11 +0900 Subject: [PATCH 94/94] =?UTF-8?q?feat:=20=ED=95=A0=20=EC=9D=BC=20=EC=99=84?= =?UTF-8?q?=EB=A3=8C/=EC=A7=84=ED=96=89=20=EC=A4=91=20=EC=83=81=ED=83=9C?= =?UTF-8?q?=20=EB=B3=80=EA=B2=BD=20=EA=B8=B0=EB=8A=A5=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/actions/add-task.action.ts | 2 +- src/actions/revalidate-todo.action.ts | 7 +++ src/components/todo/check-list.module.css | 14 ++++-- src/components/todo/check-list.tsx | 33 +++++++++++--- src/components/todo/todo-section.tsx | 10 ++++- src/components/todo/todoList.tsx | 2 +- src/hooks/useCompleteTodo.tsx | 53 +++++++++++++++++++++++ src/types.ts | 7 +++ 8 files changed, 113 insertions(+), 15 deletions(-) create mode 100644 src/actions/revalidate-todo.action.ts create mode 100644 src/hooks/useCompleteTodo.tsx diff --git a/src/actions/add-task.action.ts b/src/actions/add-task.action.ts index f45391d0..93decc4c 100644 --- a/src/actions/add-task.action.ts +++ b/src/actions/add-task.action.ts @@ -12,7 +12,7 @@ export default async function addTaskAction( if (!name) return { status: false, error: "할 일을 입력해주세요" }; try { - const response = await fetch(`${process.env.NEXT_API_URL}/items`, { + const response = await fetch(`${process.env.NEXT_PUBLIC_API_URL}/items`, { method: "POST", headers: { "Content-Type": "application/json", diff --git a/src/actions/revalidate-todo.action.ts b/src/actions/revalidate-todo.action.ts new file mode 100644 index 00000000..8ad7e41f --- /dev/null +++ b/src/actions/revalidate-todo.action.ts @@ -0,0 +1,7 @@ +"use server"; + +import { revalidateTag } from "next/cache"; + +export default async function revalidateTodo() { + revalidateTag("todo"); +} diff --git a/src/components/todo/check-list.module.css b/src/components/todo/check-list.module.css index 020dd125..d6fa05d3 100644 --- a/src/components/todo/check-list.module.css +++ b/src/components/todo/check-list.module.css @@ -13,11 +13,17 @@ letter-spacing: 0%; } +.check_list_container > button { + background: none; /* 배경 제거 */ + border: none; /* 테두리 제거 */ + padding: 0; /* 패딩 제거 */ + font: inherit; /* 부모 요소의 폰트 상속 */ + color: inherit; /* 부모 요소의 글자색 상속 */ + cursor: pointer; /* 마우스 커서를 포인터로 설정 */ + outline: inherit; /* focus 시 나타나는 외곽선 상속 */ +} + .checked { background-color: var(--violet-100); text-decoration: line-through; } - -.check_btn { - cursor: pointer; -} diff --git a/src/components/todo/check-list.tsx b/src/components/todo/check-list.tsx index b5828063..f48c5be5 100644 --- a/src/components/todo/check-list.tsx +++ b/src/components/todo/check-list.tsx @@ -4,6 +4,10 @@ import Image from "next/image"; import styles from "./check-list.module.css"; import notCheck from "../../../public/not_check.svg"; import checkedIcon from "../../../public/checked.svg"; +import { useState } from "react"; +import useCompleteTodo from "@/hooks/useCompleteTodo"; +import { TodoDetailData } from "@/types"; +import Spinner from "../loading/spinner"; export default function CheckList({ id, @@ -14,6 +18,12 @@ export default function CheckList({ name: string; isCompleted: boolean; }) { + const [task, setTask] = useState(null); + const { isLoading } = useCompleteTodo(id, task); + const onClickSetTask = () => { + setTask({ name, memo: "", imageUrl: "", isCompleted: !isCompleted }); + }; + return (
    - {isCompleted +

    {name}

    ); diff --git a/src/components/todo/todo-section.tsx b/src/components/todo/todo-section.tsx index 64f55dea..e098fa7f 100644 --- a/src/components/todo/todo-section.tsx +++ b/src/components/todo/todo-section.tsx @@ -12,12 +12,18 @@ export default function TodoSection({ }: TodoSectionProps) { return ( <> - {imgAlt} + {imgAlt} {list.length > 0 ? ( list.map((todo) => ) ) : (
    - 리스트 없음 + 리스트 없음

    {emptyMsg}

    )} diff --git a/src/components/todo/todoList.tsx b/src/components/todo/todoList.tsx index 6f6d9c59..891873df 100644 --- a/src/components/todo/todoList.tsx +++ b/src/components/todo/todoList.tsx @@ -7,7 +7,7 @@ import emptyDone from "../../../public/empty_done.png"; import TodoSection from "./todo-section"; async function getAllTodoList() { - const response = await fetch(`${process.env.NEXT_API_URL}/items`, { + const response = await fetch(`${process.env.NEXT_PUBLIC_API_URL}/items`, { next: { tags: ["todo"] }, }); diff --git a/src/hooks/useCompleteTodo.tsx b/src/hooks/useCompleteTodo.tsx new file mode 100644 index 00000000..9d04c54e --- /dev/null +++ b/src/hooks/useCompleteTodo.tsx @@ -0,0 +1,53 @@ +import revalidateTodo from "@/actions/revalidate-todo.action"; +import { TodoDetailData } from "@/types"; +import { useEffect, useState } from "react"; + +export default function useCompleteTodo( + id: number, + todoData: TodoDetailData | null +) { + const [isLoading, setIsLoading] = useState(false); + const [error, setError] = useState(false); + + const onClickComplete = async (taskId: number, data: TodoDetailData) => { + setIsLoading(true); + + try { + const response = await fetch( + `${process.env.NEXT_PUBLIC_API_URL}/items/${taskId}`, + { + method: "PATCH", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify(data), + } + ); + + if (!response.ok) { + alert(`완료하지 못했습니다`); + setError(true); + return; + } + + revalidateTodo(); + } catch (error) { + alert("완료하지 못했습니다"); + setError(true); + } finally { + setIsLoading(false); + } + }; + + useEffect(() => { + if (!todoData) return; + + onClickComplete(id, todoData); + }, [id, todoData]); + + return { + isLoading, + error, + onClickComplete, + }; +} diff --git a/src/types.ts b/src/types.ts index 36096b9e..97413ff2 100644 --- a/src/types.ts +++ b/src/types.ts @@ -7,6 +7,13 @@ export interface TodoData { isCompleted: boolean; } +export interface TodoDetailData { + name: string; + isCompleted: boolean; + memo: string; + imageUrl: string; +} + export interface SeparatedTodos { completed: TodoData[]; incomplete: TodoData[];