From 0c99697a6f3973aa5f4f177a8220b1fc3b402e55 Mon Sep 17 00:00:00 2001 From: Hyungi Ahn Date: Mon, 20 Oct 2025 07:22:27 +0900 Subject: [PATCH] =?UTF-8?q?fix:=20=EB=A1=9C=EA=B7=B8=EC=9D=B8=20=ED=9B=84?= =?UTF-8?q?=20=EC=82=AC=EC=9A=A9=EC=9E=90=20=EC=97=AD=ED=95=A0=20=EC=9D=B8?= =?UTF-8?q?=EC=8B=9D=20=EB=AC=B8=EC=A0=9C=20=ED=95=B4=EA=B2=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - AuthContext를 통한 통합 인증 상태 관리로 변경 - App.jsx와 AuthContext 간 중복 사용자 상태 관리 제거 - SimpleLogin에서 AuthContext의 login 함수 직접 사용 - 로그인 후 사용자 역할이 즉시 올바르게 인식되도록 개선 - 새로고침 없이도 시스템 관리자 권한 정상 표시 변경사항: - App.jsx: AuthProvider 래퍼 추가, 중복 인증 로직 제거 - SimpleLogin.jsx: AuthContext 직접 사용으로 변경 - 사용자 상태 동기화 문제 완전 해결 --- backend/exports/PR-20251014-003.json | 66 +++ backend/exports/PR-20251014-003.xlsx | Bin 0 -> 5556 bytes backend/exports/PR-20251014-004.json | 576 +++++++++++++++++++++++++++ backend/exports/PR-20251014-004.xlsx | Bin 0 -> 5549 bytes frontend/src/App.jsx | 62 +-- frontend/src/SimpleLogin.jsx | 27 +- 6 files changed, 669 insertions(+), 62 deletions(-) create mode 100644 backend/exports/PR-20251014-003.json create mode 100644 backend/exports/PR-20251014-003.xlsx create mode 100644 backend/exports/PR-20251014-004.json create mode 100644 backend/exports/PR-20251014-004.xlsx diff --git a/backend/exports/PR-20251014-003.json b/backend/exports/PR-20251014-003.json new file mode 100644 index 0000000..3e4a76d --- /dev/null +++ b/backend/exports/PR-20251014-003.json @@ -0,0 +1,66 @@ +{ + "request_no": "PR-20251014-003", + "job_no": "테스트용", + "created_at": "2025-10-14T21:40:12.581699", + "materials": [ + { + "material_id": 1, + "description": "HALF NIPPLE, SMLS, SCH 80S, ASTM A312 TP304 SW X NPT", + "category": "FITTING", + "size": "1/2\"", + "material_grade": "ASTM A312 TP304", + "quantity": 3, + "unit": "EA", + "user_requirement": "" + }, + { + "material_id": 3, + "description": "HALF NIPPLE, SMLS, SCH 80S, ASTM A312 TP304 SW X NPT", + "category": "FITTING", + "size": "1/2\"", + "material_grade": "ASTM A312 TP304", + "quantity": 3, + "unit": "EA", + "user_requirement": "" + }, + { + "material_id": 143, + "description": "HALF NIPPLE, SMLS, SCH 160, ASTM A106 B SW * NPT", + "category": "FITTING", + "size": "1\"", + "material_grade": "ASTM A106 B", + "quantity": 2, + "unit": "EA", + "user_requirement": "" + } + ], + "grouped_materials": [ + { + "group_key": "HALF NIPPLE, SMLS, SCH 80S, ASTM A312 TP304 SW X NPT|1/2\"|undefined|ASTM A312 TP304", + "material_ids": [ + 1, + 3 + ], + "description": "HALF NIPPLE, SMLS, SCH 80S, ASTM A312 TP304 SW X NPT", + "category": "FITTING", + "size": "1/2\"", + "material_grade": "ASTM A312 TP304", + "quantity": 3, + "unit": "EA", + "user_requirement": "" + }, + { + "group_key": "HALF NIPPLE, SMLS, SCH 160, ASTM A106 B SW * NPT|1\"|undefined|ASTM A106 B", + "material_ids": [ + 143 + ], + "description": "HALF NIPPLE, SMLS, SCH 160, ASTM A106 B SW * NPT", + "category": "FITTING", + "size": "1\"", + "material_grade": "ASTM A106 B", + "quantity": 2, + "unit": "EA", + "user_requirement": "" + } + ] +} \ No newline at end of file diff --git a/backend/exports/PR-20251014-003.xlsx b/backend/exports/PR-20251014-003.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..5eadfc068d8d4f3417ee5d2ef16a6cf46f192183 GIT binary patch literal 5556 zcmZ`-2Q*x3yBEZ2dknxKh7F>jTaixhL& zy4dKsxwyLXTe-UOc{@33$7>U|3Xm#aX{^sWKl;fe$TWtS@Agv{7fZBN@(e%s*GDJJ zNY4qxHc<8$wX=AMMzp^PB-YrV8KJR{p9{iz`5ak|5PeE8%?#u}FsE8OPfQ(V1&`Kx4Y?DPZU zXD=22K=x06ZCu=-za1`uYwNZN5Jg<|r1)(V($N?2rRV2FgtfDh)^hIFM6W1CJ!lNl zh18JT5RczIJFYArW7i-D$rh0cK6v3X+&BTVU&zdfEV$9N5~j22#&k}4N6{@a0(MVv zY{iU`jC)`Qeb>J9ej6uv!O@nwNVG~Qu+S4^g!839N%yug*L(+vJ^jitBk9$qyRg35 zWa_NjLPXq+kFwjjZ^U?X!(`Y6#6)-j4CTK?$OrtWqWXhhmE1818?KjAuEd)hc<|q?;K$}EBH#w;7YiJCfrZ+|Jgy}qlmY-$fNA=9?<1l;2 zd>S=d%K&q*o&1o&0}~eurs`!z;bY2PgE%Mxi`-Cwy*{#f@5J%*`ShGDba4G1gHVXG z0G$z2(16REB^{H3Z_4ewk4y;E;~Non6MwYohG8{mXnA}0uXN>*3$Dw zD%3>Jw??l0$C%jWzcFVJ+8OTBXDTFr_BGOseL2o4kwbjWld5Welvq$BBrtq_#YQPih zt61K6u=lSC)1p<8bkASfjY#`m;+|xS641lx7_eb>GdHL9)hYmba4eD9T#j z7Nd1TQH9hzdmCnH0_qs{))}cLJ2x&9O_sIn+U$ovADDoXkR_RmW4;}TNhE8&6Ct6I zxmEDY=*C5^dE0&TT4?W+i@LywabZVr{4cdJYKhNs0_OOHcaB!l<@28(v;4`lL3YQTYp!l0Wz8Ei{$H;%?mr(+}*9yDb_G#rZF!IRib7{l>%$s zc}&kw?soh&TL>F|ufZr(JQ|d%Nawt+f2ff=GIWm3^){cY2AWVA4qpHC}lPqGv~Do=Yr60{ZDnb+n32I8F^YU++oe zX29zSMjs}+w4JPf_NHBsoVrmTkYVVw`ek_dY!&^W00rkJ<2uS2G z#o}<%;!H6V<&5O=y6wdLP_orNgB(`cGY73iKVles1lg--dMZ;*sWW(KT;BDXh)joy z5TtICLS3v;uzy>>X_e=G`y+{F72z6CI?cz$mCk26`gI`B8X&e%eWT=CU#K9gc<&o8 z5k43aX$)G>HrpCs&B}i7%j|iY?uEA8yKwDR11?LgS{#@uy$?K^T|9M8mQvTs_W4YP z<)MPjl1hJ*idtw%Z#yaRCOKArO1JV)>`>cc`rwRH!cTid^<0z#<+74ND&Q9pI_4v6 zAd2V;BHX*wZi_oR$xppvCr`m4PGJT@w&T=2N>OMTVK=2O25kH9r`ZX^XBG_l8)=)^ zEj8PGopX3Ou4c@~WU8rURQD0D=I>O!bkFjwYgH+`GMcz^BJ@qtb>`k2j`<2XSg9}& z9S|KIOjc^$)PU4IVat}P_S+3%$~vEzDLk5;C-NUFH7T;?A(PX*<7=%NaPc2v`>`(MB>{^l}uXU@t88nI06@iartGrnK5F!BVrMHIIg+is~R!H zk`96N*UKH^iq`h{?^`j=SpO~{sHZ~9!8iawAPE3K^QVA#xwtvF+d-io?)-l}{;DFW z>4Um60u-HBshn@N^gtZ)Sg6!slC``ddGTr+J2P5%yV=4+Pn-_+8na?2JGzlCB%8NN z)U`sRaDpC?U%r%VZfM<{*vd!k&#g)#ch104l?I#Od+=mvI@{0FI^6a9-xmKc_&nMCT zkkKxqah|#~s!rv6>{64qmfjM{TZnAc&|s*o1iE&JC?^C=upIFMetX!~O24+%!incn z*c*?HnZj8y4lgx}CO*>2*_xGEwJvHnl4hAbi44BP-ob3WDaYK+)WKq%?MM8LG)->> zb`QFWl!_z-9`gVfMsO~tU(_83H=i=`$;~6>B5?tihJez0Olbf-QKs-Xs%rbkZ6@qc zM6u-=0Dlb_`UHrbxIM-j1T#U4RsINTdo{A;XeG#I1?mZ6N@a0;C+@lL{7pvYnXZN2 z(E40S?N#^1X>=>}41BV;x3d582-sel_$!p4c}#7l zkwY0Vm%ibr+rxyMfjEIZ%U0(}vDk`EoyRkDOynz{B|0=zL=ns9q# zYqk+c=)*~cp62vrQ9rX~NQ7Kfrx>%#Eza3t7$TbnSbA-BIsb?#fCHIRTCX!S| zq#WZxfARd7+Z<^Y%?XPAc;tK3S%`vjBYxQJWZR>bL?&Ad%Q&~>d#AbYmqT$8v2aC# z1tGbi__dl}AdB=GuXt|8sZJF<2cRPL!%b`I(Qu-wYT%_}G(<+@JzYkt6W40({BppY zq01BhEw@1i_~a`Yh9TLP`CLBY9?lK;oN=>~t1Qj?LHm#@zqd$8a%jaquzc)5bvS!# z(?1=EWw{M|adz_MQ)P0)%2|3gWkCVoSq!D2rrW$vk-;Xq1U)=Miz5m<%jNE`u^}9@ zOZN)@;b6<-X>d9B109ffyfgoB5n(FMyOyd<+%g;GOi6 z$vAF1=Iu9ve7<-`$EjBPl%_dkAV;Om%(gwFYc2kXy|`$326OEgS2d>Y=7VoBlLnVi z(cbKFlQ!50>T?KLU6vPV{p@2GQbi@vyE~xx_9D*&k4FrcAhGuruo!>VA+=nrAWfMs8z(PcDPOZ!BO0o7A89~&8ys8UL;T?&y(JLrpU2Fpxt!p zv1mEqg9Ddk?y~|TZc$Bn-h7e7p~Ekv;FW#0F5WihiCQi9^ZN$`@QnudYN!_h#Ua-5 z`?gFL4JDJQXTidnSN&fH3C1#WkY$_aZ$y6<_w64tB^IcuxPlMhg<3J5DM;De*`~t% zA{*;!?{8~Y`$HuZGAGSB0!2|HlPdV^E)^%&X5#>b0tPY6T+EGGDDY1%_+7!RU0fV~ zXM?!JVdqu>B9)+`o?B(OPU=c2>35BaqO@^#bH(^j>I>Y@tQI%Yt2ZL5(`6)^YIL>_ z7ZkS*KsiZ3MEUDRQ<1(cY3+dVVEARcNrlzpWZ@*Gjd-qc(Z>}9?}RNSbDm6rpXaf$ z7=N?e_$+@0?5!m!+#?3i$>hZ<^Q6TLPi1M2%*4~YJJvTqxXITYe+&P@4m&U^P`&I^ zxtd@Cy`UmCS6F5yk8)Yt(;`9I8vig`R^Kqyia=x0+Z?LRsbu*XpPE}4H+A;aXF#!x z5c^+U4*YLx<=zDY%{r@9`{y4gSuK`04Bzq7iiFQCt?3F*v}@qh8&RJHRL&}sD}cu= zBXQQ*bF*w{>J$Tn)e=K#c}tv_P9*Ru-?@$&`Hmc1TJ6zndYQ=KZjCo38psWFRPi+f z{=JukHx?VpF`+%fgqikFi2rP-e+K%mt%ZWikh~Be3P*yL0W>9J`PjvLWt7yBp(kV^ z%9W+9TXblEIzxki@nBl>FIyPDNVK2SgGnjSz8!lHv~%+gpiqjQQf1;h1$*2fVu2}u zP-k5Mg=bIy4b6D_Lsz`k174D=yVJ$%qO#?I2@< zGqH$s!}RonPGN8_h>ZWHeL~fGa*%J4+)J~sTZZ+bgKBlfAn==d$c_4{-UwF09@WPV)3QY^F3cYS zHFi}v>)pE09m=Mzin&o$k#`Sxz8f6-2B*YEIP#ExQtz}csKQ>i!|Ls&g*6a8ccNI! zJBruTh{Z4LxEY+yt2X?ZQe-#L>U^%>*)p+SeQC^zfNTnNBWN|palJIAOEIy_RB|cI zc58|wZ0;HH>0=4qW0peCpEo{N^fB&xz2>-p(E0%LFLwMUkVVNIy2O#+Wsq{1t{MxQ z0_Xo%*f0V8>j=g~`2Xr{*U{JYu0L1+AQ-FSpXmQpzplftt3rRnyD`82FB;Kx1J|d5 z{}>1%!28R)G&cU>_zq zV*dG0%3cRw=lS1YevImf0slX&zi#I`mHxIv0s61R($mDnh^cp34i$M@IdJ<)b89f*#qJ+@}QKAGv z)Qlc?a{_uAiHd#(Mv``yp_p0^q5;NjB%001IDe6_xXx;c_868lt#y(qDl z1H|6Y3*zZ5{K(T&D8SuKFGY{EON8>?rS`_0$HQHAQTFkY#lB$8J5s3*s(#VuArFwx zXXWNal3Hl{K`0J?$rx0{Q(&J4pn+7qTXpQs4Gm64XArB>P+%hUv?JtWHC12@9%xbXrqb+=qb5VQ?v1x=w#+iMkI{v#(!)( z4@^cZ_K5yc3~Qi`RxW;iNE7<1m%MCZaYjgsEO)Du`L0i(Nx__UMxvnmTT(?V3pl7QT-o(?b;pP~j_9~OvH&2NMS4iN2&jvb1#;o_IB zQ;bJ&;l|sl8ZV=7#q%aAlL(qSkn~NBOSSbjcfUc!B*zGo-OYtV?tc^W(lU>Ok`MsM z;|2hzvBU(p3HvyK-NAoW(cjc;n_GC#NYgysfei;ZV%$l4q#_#N)ZWg1v+$Qu+xl$L zKv1$x$BqoRrH$B|LZ@W{T<41yLdOvxB6kr?@1*?iEDUkC=ZU6|BA z<0IkDxVXF*Al)!9n&`=lzi8B2(3OAa)={cV3@>pWcKD2$sezWiO@3f7b`-j>nd_8C zl5Alx=ITE;mJ;7nJsd#ZzGo2IT@&9^Iqb9P%*B0C<662w=cJ;(yctAAi&#|}V+Vjd z{U$$+;$>R%p894mPP4SmDO>J>e#pcFfAxI8pL8C*ktw0>m7hv*9dHLVqH7oeQ*KCD z>`EK8Or1pYA`BUca(W|vYDC`r@CA19Gpn_)R6Hm@RCdTUBh0xHr((M`7oC3Yy}nXd zkv^rTGUVANK)iRxVeu%I+v6^^mn^fRN(dT*ftGQKp?6M5HudEk*-SEPtx0F~kvnb{m-cto! zqz-LtC+b~DjytM^j;tZ7!-eGEen1sekd8&HTz6Q`*fCzJ00Ix^L(-;8o@-DQQ{PRXh60`jXU*xis~^g_@@ zG(33|Wou5=GZLUb3J0E>RY|5R*!FG>LVbrOq1S; zjp)pjgb3( zbq5Ph;sN6^@SOyz0u?5YjR!xqUrepSnt7V!ELJvPMLr4w=o2}cHTWQ@xN4)9&i96l zb_AES_F>&8Pkq(_vb&CQX)F!?uUI6{Fjjsm9AzR8vQ(QGRod~~Tk^liN*829n@Ps* zr$V|q4v+Lph4e4_uLiOR2m0#~fLRpw0)Sk$q6e?gFpSimCA zjA}{GYI|ZWH?Jn>mfvZXKhk#p!n03Qo@YJ<3?jVS>J2H6AH1?xp(KnDd}!hKn?McFB0Km9d@6R;N42 zBVUmFa@KlW9!@W>eo*pqk+nY7J2$AQORee>G|74*wjkpcLE7*gr0`r0RWEI0RVx|JDjWcuNVu32jPOVYf6NFVo^ebzw>|O6%8os-0Tj%oI0hmRSvx@@N`ICJ-3V zXGl$^3lcQZtHXc(~wVqHg_O^m^Z{ZSGqSXEQJEziI<=1^xl_Ww5=gQ~CUMKUNwZ8vc4R+{ zn!HdhN}~o}zI=r<@HuO^7tO`|Eaodelsk|vKH-x4XW!5!=&2Y;F|h67V1#`yXoSBh zllq!k5pLy7Oa#4=J)^qocMAN0Ue8EK5s(YdjHaLIy87dL>G67VBw>i^WAx(9j5xz4 zV#!;^9=BM4&K|{zw@#bmBjOkqxx|3buUv#2cDt<5N0h2SQIvcv8<7srf%x{jgDDnN z^tJOB*Pd+Pgl#KZhIHD5Qf9I3PO+f~0Y@yIZ?DG*0#qn8AC(Ze%ho&+EJPTo)`o@? zozg4UU&AfE>pQUUGP72%SoW*u(?ACo4+Z{5w^kQY`+-t3EUkeZI|T(z6~eshAph~% z%dMxudS82}%R_tv4_56r-);PwD;cJqb3WSMnLLq-&ehHKt(b0+t?+z6Tq!5**>UNq zc9x7NudYF(fE*^0?Ow> zHZV3h&O+n5Y(}=Q01Ne7vns(5!Evwqk!t@TsAZ6V8 zIhC_a+xacI*@-a|Ce6~8Ggb%& zpV;l&bSC7yFSkgs?c_5`KNDMFaEygWdFR@#;N&(Um01J!JwBBt`CW>~ z+x`RRivLz@Ghey&F)je`k_-SK|D#xMpFlUT_wQnF&J>w4CPI1ff`?71Avun5+}Q3J z-%T8I=cCRE_dHaZ{k4x~h~Opq)WtYdGQ}bcq=5T8pUb(CnndINL&Vz2VD63QEWXq0 z@)eDoWizu6EhXY@T&y~XA|G3fCP<(i^rDr$-tZL<8q+F2;Maafs7Xul&D7M$5Xf~t zaUVX>GMe1@qIx(!Y&96^@=`}M`&+wsHlnn6UjA!*A=QvnLi2}GyO5nNZ`WyUp%)c; z5)ylkljCwt1oa*yMSkskT&3?OJNxnydEdU`Y>Pk z9`jkltP*&rlG-pqn2)6hC|}8Ur=2`!#EQgJr)d?>w$i{1pH?-Ppd<;ZLb4>LIGnQH za71O3)!?7P$2R>@jmVWkh5r7Q9sO7|Sv{QMmr8<#ymk#!c9%QvTI1qs=)5W9amcn8 zngu%bQl4d4A-0G&@Q#m13o%dfoXi?W$3fVEMSbuam_>SI?Eyvg_@Vkp-u6~V76p#& z565R`C!gQfrMG-L%gUoIE*3gVq&3y?S_~{R-a@`cj?6ORNjjbt@C`QDla4!O`A2_u zb>R0i{x$y{8Jc>$vv_~G#PW{da!$O5$vc6Pr41p5%N(~)h``&nCSVC}!6|?F?BniZ z!9kG4hl{sNJQ|HI3>^_e`D)!(4yf$j^_0iXcOkospIjr>R+S{WJ_I^N)YC~1>rqTof>d2mhKMu1a^fk|7V- zT;kzMC>`^>H*(j};V09-CDN#|nb3)q1|3!=q}aQS7ud~PSm^hfpQhu1D@vvWqXOIL zzCq!NR(-BjjU#P}Un_Zug4&}FG0C4h*`0tomjwlaFbauRe$3vpWo|tpD9dRR$!fqm zS6NgXA@B8k-DpPwlOz8!G(3U+%;HtKqxYaNn6H(R{nV1E*tpE$=g-8mfE zs^-&A!o_ti2fv_6#&hyvRa@s3lDp-f4t}zy7Hg<^3LHX9brbzEU7F2SQM-6wO;*4cSBT|7B(yrIc!41{ep z?GYShk&G<)b0%Jv&tW1G2s?z{6hyy@YlN4hPib&~TwSNRp+TyCkx@_L5l znDGz4fA-QpS^jHZA)xZtpJAznQLO?PUXK^ymJ3zU(#J)f03+_zRd#JNApx2!Eh1*< z%#I@mM`4MC;JZdscc~7Xxcb2#w^#wCcbRF`Ccn~fCI2j0Vh<(N-%v&nIWsRH*>1e+ zP0=+HyncCerhG$Eq5A1_={*XOkSey@>9((nN) zpfI8H^ZJeSu%I%#KQ;d z;bUVQ=n3|=`n{2=)6u^-Qjbm9cV8EAX-}n1p(OsTPSPlpRmrzPJBSbD`RqIGS9Rns zbV_^&)%jS$e7z z#Mj5&Jmmjsd>j;>krd;`PyJr=qjPaR?uHZ2zyPCT3z@Gw&H5`$ijH;?acK`>c%Gof z$Ol@9z0^nN^Mf9?sm+=z=HRN8 zt0l^Rtl+d^!!g#4zYCVD(5s>QZ|DNHL-|J_zY4q>3jYT7Vk0B=oBx#TRq$1v{|)BB qjvKMy|3~##?Oc`8-*(8U{;RMIbqKK2I{<(fdn#aqxY=(30{#b4u(<~S literal 0 HcmV?d00001 diff --git a/frontend/src/App.jsx b/frontend/src/App.jsx index 361bb6a..3162fe4 100644 --- a/frontend/src/App.jsx +++ b/frontend/src/App.jsx @@ -13,15 +13,14 @@ import PurchaseRequestPage from './pages/PurchaseRequestPage'; import SystemLogsPage from './pages/SystemLogsPage'; import LogMonitoringPage from './pages/LogMonitoringPage'; import InactiveProjectsPage from './pages/InactiveProjectsPage'; +import { AuthProvider, useAuth } from './contexts/AuthContext'; import errorLogger from './utils/errorLogger'; import api from './api'; import './App.css'; -function App() { +function AppContent() { // TK-MP BOM Management System v2.0 - Project Selection Dashboard - const [isAuthenticated, setIsAuthenticated] = useState(false); - const [isLoading, setIsLoading] = useState(true); - const [user, setUser] = useState(null); + const { user, isAuthenticated, isLoading, logout } = useAuth(); const [currentPage, setCurrentPage] = useState('dashboard'); const [pageParams, setPageParams] = useState({}); const [selectedProject, setSelectedProject] = useState(null); @@ -177,30 +176,13 @@ function App() { }); }; - // 인증 상태 확인 + // 인증된 사용자의 데이터 로드 useEffect(() => { - const checkAuth = async () => { - try { - const token = localStorage.getItem('access_token'); - if (token) { - api.defaults.headers.common['Authorization'] = `Bearer ${token}`; - const userResponse = await api.get('/auth/me'); - setUser(userResponse.data.user); - setIsAuthenticated(true); - await loadPendingSignups(); - await loadProjects(); // 프로젝트 로드 추가 - } - } catch (error) { - console.error('인증 확인 실패:', error); - localStorage.removeItem('access_token'); - localStorage.removeItem('user_data'); - setIsAuthenticated(false); - } finally { - setIsLoading(false); - } - }; - checkAuth(); - }, []); + if (isAuthenticated && user) { + loadPendingSignups(); + loadProjects(); + } + }, [isAuthenticated, user]); // 페이지 이동 함수 const navigateToPage = (page, params = {}) => { @@ -359,22 +341,11 @@ function App() { } }; - const handleLogout = () => { - localStorage.removeItem('access_token'); - localStorage.removeItem('user_data'); - setIsAuthenticated(false); - setUser(null); + const handleLogout = async () => { + await logout(); setCurrentPage('dashboard'); - window.location.reload(); }; - const handleLoginSuccess = (userData) => { - setIsAuthenticated(true); - setUser(userData); - setIsLoading(false); - loadPendingSignups(); - loadProjects(); - }; return ( @@ -392,7 +363,7 @@ function App() { ) : !isAuthenticated ? ( - + ) : (
{/* 상단 헤더 */} @@ -429,4 +400,13 @@ function App() { ); } +// AuthProvider로 감싸는 래퍼 컴포넌트 +function App() { + return ( + + + + ); +} + export default App; \ No newline at end of file diff --git a/frontend/src/SimpleLogin.jsx b/frontend/src/SimpleLogin.jsx index de626cf..c181928 100644 --- a/frontend/src/SimpleLogin.jsx +++ b/frontend/src/SimpleLogin.jsx @@ -1,7 +1,9 @@ import React, { useState } from 'react'; +import { useAuth } from './contexts/AuthContext'; import api from './api'; -const SimpleLogin = ({ onLoginSuccess }) => { +const SimpleLogin = () => { + const { login } = useAuth(); const [formData, setFormData] = useState({ username: '', password: '' @@ -110,28 +112,11 @@ const SimpleLogin = ({ onLoginSuccess }) => { setError(''); try { - const response = await api.post('/auth/login', formData); - const data = response.data; - - if (data.success) { - // 토큰과 사용자 정보 저장 - localStorage.setItem('access_token', data.access_token); - localStorage.setItem('user_data', JSON.stringify(data.user)); - - setSuccess('로그인 성공! 대시보드로 이동합니다...'); - - // 잠깐 성공 메시지 보여준 후 대시보드로 이동 - setTimeout(() => { - if (onLoginSuccess) { - onLoginSuccess(); - } - }, 1000); - } else { - setError(data.error?.message || '로그인에 실패했습니다.'); - } + await login(formData.username, formData.password); + setSuccess('로그인 성공! 대시보드로 이동합니다...'); } catch (err) { console.error('Login error:', err); - setError(err.response?.data?.message || '서버 연결에 실패했습니다.'); + setError(err.message || '서버 연결에 실패했습니다.'); } finally { setIsLoading(false); }