From 1ea29e5d1ecbd4a66c72db1dc41db45ddd349b70 Mon Sep 17 00:00:00 2001 From: everythingonblack Date: Mon, 7 Jul 2025 10:52:42 +0700 Subject: [PATCH] ok --- public/back.png | Bin 0 -> 6802 bytes public/camera.png | Bin 0 -> 8598 bytes public/send.png | Bin 0 -> 8005 bytes public/upload.png | Bin 0 -> 8670 bytes src/Camera.js | 119 +++++++++----------- src/ChatBot.js | 270 ++++++++++++++++++++++++++++++---------------- 6 files changed, 224 insertions(+), 165 deletions(-) create mode 100644 public/back.png create mode 100644 public/camera.png create mode 100644 public/send.png create mode 100644 public/upload.png diff --git a/public/back.png b/public/back.png new file mode 100644 index 0000000000000000000000000000000000000000..77c050b8bcce3d9c1b64e3e0d1558547f147b10e GIT binary patch literal 6802 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 GkpBWumri;B literal 0 HcmV?d00001 diff --git a/public/camera.png b/public/camera.png new file mode 100644 index 0000000000000000000000000000000000000000..83f5c3af29a48647caf3a0ecb15d3624cc2201f4 GIT binary patch literal 8598 zcmcI~_g_;_u=Ys^ND!4Ky$1q8sz^X;Kw9WckRA}}2m(r%1VKRQNGPESQWa2;CP?T- zL5fIk(u*KfI&Z%BbKgJV{&ddlnVp^8vpf6jGaGH7r*Vynl?niWYiLbXBLD!AUO@mQ z1?gesUF`Uu;1!hY z6(z+GGi6*{m|)r-hRBXW3&lkh=VPfz<=$`{48rZU(22kTp<9HOw-wBq0qUaxdljV&A-2*yp1Wx~-GGlS?+9m(5yY#@5< zDE9wGzF4dfSfffha!cm|Goeq)_%19QRf!OB1!7fws%uObh9+f2$_MojIN1QY-rIFclXW( z(elc|Z5kLZbma9=<|Pdb_yOxM0e$kSpbQ^5#khh6iXeU|z9;MxTTheW*mp%Mu%xZg zjdY(CN3}Waq?-LF^AnZnz%Ofcch-P^{=X*Om`9a#hc;dgjyw)@0Y6|{+0Z)4C~$j9 z)@-@PjGNV-crbLAqjqv~SqE^_?@LTNT>ax-|B#;s^U$xB?qw&Y4dS&XJj3Hb$C51Z zesihoZ)g%S)pxlr^6vC%GyVG_i|+x;9l|qtX}-L<_VO$+l1F9$di% z{km9o0y}T7>8A;CI=jo7@6uvoll<~xD>v3>!L9<>q}hw9)kbuq5~+{%3D8vitc{P6Fh=;vo;Ggk%4?fvm94s*##4|EJ$o*tPao^!i?J1K*CoxWtS zL9AVr**2`-OgL;ZZE`JO`l$o>xgl|imKd8^9v45QwX58B3D6npxFpq|jwUs(_DYIO zQnyvlGoW)0=t+pcpZ3l?hbyyZ$_#rWJUDtjk5o_l*kwc#Cr!14=79wiYxY$i;uKSD z?0@3|?%cI50Vz*!JbBC@nI9yb0}iG$<^N2F+Mmp!u0FbEQi}-;^h2#~u4>%AV^+^( z00X@_It-27gB-?D*@&#IwbEb!JOR{e}la;5bSQMZU5$-*E2U8{6jGdsw z!kSmzDlsWVx{x5&21LE=>3f@aiea4PmR*yEGh7q46adJAZ z{ml5S;>wFH9-W=#KX+S*KKwxZ{mJ!|(x7pvOxG^q8+k@)r(7i*j2*wb-jmYC|0k== zy-AN&MrX(d$9R`Ft`R|zv1R(15ges>E|%bHiB{Tv7C2=A2ahK2KSi@Stmm6{SfWHA zH0Os!vI84ruX{?TVU-mHFTj1KADIluK&m+xvuOR$LqNDq8LI%yfFHB0?yk;)m(>7& zciIJxov92*n`qWH~$sdG}xaDw<(LQx)+?TCw?>|{$Yt6$i_y1}8mO?;tLFd2Ul$OLcdhmCqKWx*# zWdC_mBDr6S?I_;uL9N$cx|g!k5|Tt{!F7!VD+RMDpMnPT)s)Up?}{bb#4d?ocql^g z`@8$6me*zKAt>+8TFnM)y?nBP`PE9*hDs3i=L}K0b-70RiL?FX39k6ojfC*_&OVs9X-ICsw_@&qwZ)!ldX^k*GD7_#XrU3{c zU1mnQBeNF^MUfKQ!4#alE**U>Bb3<7II>o~1zRS!QnFM*IwO$D3ohPM`J>}_ z>o^a2=#y^C8u@8gh?nYwHM^WaOhs??fRxTA-9zC-#^-_qPb|7R&yzmUf#hw5*dlND zVwB3XDOlRwsMiMB*hbqPi^YlTT>?_tl8W1OH@;HD;{0Ko``S$|uwJOF>Q*{j{?hPpyT+2fYl>0VbTiWDOXz}C$ z(frWwKh;z`h}diGy9h>K>EDqGUEFAIW4j9uW|V(dFL1+|^KF6(biRr(0d?Dj3iAQC zi<1WO!z<_i7I)H@{IPQ7KXGMK&)ud>m`oCoE?Lv2WGV0Q4S|CGa;P?)(#>+1JZj0g zNaYVCX%Q*kE6?Td({`brmKIlX`N4K+^kx9gU(AJD)+S$5t%R*nuvY~KvBU;SgTIi} z0|FBec@n)%pdm_-pPi5Ec8$-y2WM45VHgNr9W%UGz@*T`t%q@<#OgNt@L3B)$q;TP zY6-V2e|QWjRmN`nAxB}mW$=LR10Eog`|VB7@%@MS_9I6Nn(-gpATdN%h`)1H3+FUL zqZFjlQtObm1@C3I{>d^1OS?*e<6r~NNh$Jvxd&8eJH^(&?AMli@;OGywUfRY{I5-&d@Wl@9zf}3aIm~br=1ETW3iXz}I zg<8t>AD)we=OEaytoqjFocIgx!K!T9ZVfD~C93vMJq>UZU6D9`<=MF>rlMJA|Ggu` zo^p=ks0ww~@5zIm)oyTgR2n;K3kBHlcHEUVuM`9Z!Y^YJ*l>;1XR;NBO4MV41HIQ)0&mWrcZn7}TtBT+j1p49w+#wLmpf^LKm?Wf;>^jYo`!=fly(ie2 zX|~?7`BB3fx?DwYH6c8~E9rqj+Hbjg>qpoVS1|K{L*LMSx>9+Crr#B&O)iXI_UiCI zAav%9@bfGUuFi=P`tE!-S{ao88N-3Iwm`31%9w1+;S zPyMJCq`Tj{>k``xIuP)etXza)z};QtOc{&LE75f!Vu8aU0*VPU{>5r`=^P+>;%3@` z$_t;sQnAE{dK1<|8*1Tv`nu%gclc7NOx_2D8vg-7)28~Q+lz0kyX?BW5nvf+!_Ewg zSo|7|I7lbbSgicF@a5;&jb-|vLBhqe-vgZ-$1aCFX|7>9fN{&6%h%mY&rM3tk(V?3 z%~yWLOAH8IaA!TPXpLKj%>|OlgK+emYf*J{J%p7O01CDcnHZ zx{T_S8^Wo(>DNKI7bu)9BV@M)&<)0u*FIo!*v_obnH77dk6&#FbmmYSOlh`X_;9G$ z0J~%;E4G3u&?0S}TB$&MGuUMTeoVG3Q7xuDVLEiY=iFH2kpToEC8W{PO3^Y64B3lQ ztNy=2-UsZ-C`=2!vmpfB!j6#;;VeTwfY7;3^;F7~E*S+@+AM9!u6+nz9fTyNy$hkb_GoQ(;4@qgWShrl4R`TTi+zd?vWFNSfNhv#;HjW}~{1- z;x~+XS3$7b|vbpKpla34ft|=k^*x-Yq zFOw3I+Y2)1m83m{YNT|7!HI~HU+;gyu{EZ@7@i$3FHI7dFKQqHX)8t4O&*^I3$1U{ zawRC1BNq3u$)WSZ0_{U{p%> zVhnVhRd&t`g<}~}S)C5iN$cM}?{!wEMea5zU9+)ja{?6{hr8T#Y>XSj)&3}!-2X;$ zHmzl{a6y{U7kz9Ucwe!+V32d-ZMi}Y(oAehnlibG`PK9)NC!sJ%DwgAJwI%0>+0 zQ^@_BJMQLhWJd^*assbEfVV_}`pZfCVBX08U`zNd8Wpm7es@{=QuYP3!RH7LvI!#tXRaa{| z^g?^cZ7bb;B*}U3@;v@(RZM>~>thQEFLeQqxtP~tB_&!Btx2rzKeRZ^Ofy8;%i?rO zh*~%gYTfaWXFJmeJ zs+O;Ehkw+zRf(FKG#c{MW@h^s>!x|4;-m9Gs0ds{{Z88R6xL732VC;bi5n_OOBK#=KU6NmD^mj(@#!8Om z`pQ_J4Vq5Xs`Vh_j=h5iYjPT3k)eyc7z1K@6*9ta=0vlWSY2)A&WIkYU?Ir;1?Slxd?jB=6pDH0M8QpBmO`V8;u-j0g*)deC1^1~;$C0VcFM;W$K z`>bP#!~9LMl$~i)FLZ&Hj!J_phS{IPu-cIFx#gg$<;@HQKsx|3Mt1a-Zz{rvyh3N4 zJ&q@Z6s!Dh3g?-%?!|l0$-fi+!$X|Bxzq}~&G-XFk8-#vJj5?|BmEJ~n~)fpqh5)4 zr|o|z9o9+NQy4Zl&;c=UriebcL!A6`4 zqy3EsIzWVDZoBcL=0a-5uN(M7+OgX4D>8y(-RQi;)VheD+F+js8$MYho`bS z9&kD~p|lYj__<)LGK7t;FC)!k-4;25d&CGO6cY=_w7eI5JmOWAnmK3DeE`qK(tGwvMFJw|#IZoI8+^Q^PQ;T$WXWfK1` z!3lV&cON06<#K3s{Lr}4w+$EMo&k6}h2l6Lf0?~Lc1+;w#Y`Rx0QN71^pu+uRCx!j z>PLwAWV%4TWHTzBdFRHJ&B`6W1?<=Rd$dP}R9iit{}RK{wmzpcgOVWC0qusLi7*ed z@`Uv-s=EnOhi<=MJy-ZAy(4@d{tRL-CAs~bT{^TNjgP0)aP%j*t#}AhJ{oSbLM0s< zo%y2vj|OS<3?ckYwsc?T>%(re(AM|=Y7MF^pngNsMFOdl?yq70q*##w+}ur z-opkwyzmYIrAaTx2e7{-nW}opG*`iwcui2F`_wNh(IK^m<+AbV|9t;W`w1)&darNR z8Qh(IKrU+s@F#vcX~ihL&yGa>*<<2Vn$CH#1eXvE1(GyG}`kP0Q2brqM&yD*|@{ z_Dnov@{etbNi$BTEyY-Ub_z?^;N^+V5guS7q;cYc&?oKtsTDr_Ae0RD9D#W_Qwqnb zNTO8Yb-^`O%zS`Np=-5x_b6YYfkU@FSny8JPjbFm+w!{GUZUQ|frC^no_N&|BF}4R z?!cxYQ^E5qDjSyD0W9cSWQ9~{>ba46E62liWLm*&JW!J7FALhTui)ch$0BY~7>oY#as)spM;v<;^i`H<;*L}Gh?dRe%-mS z9VN{Mn-e+TI#Td;61RZIY{{36X9nD#e?C6dK`C!Mbn69%x`}iPBrV!hAh6g0?CfF`MH`9&P5yhczXpEh zihL3epV&1f2V~6Y>bW}k;8?t)q=nz}ArapGt=~g-<5lh8OM7u6pP{33*6o(~NB;_P zUXjq#%93`{mI?79FX^v!?e{p~<4yfcYY&cCF=_LhEi0nltPW{M&7_TcJ!95=(MH8C z#<<>#`ObVfQq&8nlvN)$n{(^8Byv=VSd|`GqWw6=DNH~Q@KP=6n=1tCQ#S_Z@J5jQ z`8b4~K(doP=-fIGF)b&jR%w_#^GP0TmaOW)e?L^Kdw@Q)JRAqjZKpEt=!7QKi2b}S zHz=oh;>Hv7P|_!&(CCJLstgW9xWU)h^>Wxj9*({4c=#)+n}xYYv8s~Lh0FneiP=xN zbDJaByQyfWWej2OfD<*(=sy1ULFMqoxf3!l_+FLXKy+)_5WyJ|GyCqYaciHx;>&5D zH>raqJceb^+_^CG9tH_811&#`8X_;7`zg7|5N%TNo|%?rugc($k4I->k)-AD^HqAQ z9%3aoLU-pUO!Cicp>t?Vs@2!%zOKGn-)Gqpvgg85mn0auO_dp_#gy#uFhKz~`&1qu zAnkXs-)HOE=6Rd*RTJKeGecT&xY`q(M)59e)Iediy0gS-I1DLq5bIdwI$AycV9Zyn z@8jKnkI}V=sV`N09z4;dN>Wi!%=N18eU}k%$!n)z{s?K{5E6%QsgA69_N!y|tP%8v z;p@NJHxTGg5|q8$cSntXX3%JIid~;`-Z-YVNV>Xi=eQX2Bo$v+b-xOZHJ!H}Kl(-> z?2n6ljvt+~>EWn(2bYz4&9*;J-gL_7cX2Z*dw4DCWH1eiiQ6NNOI2*h)%?5?3>otc zHl)|}f3EFO?eVOwbKd2$8o|`F&}^g>?{;W#^uBnos1-7BNM+NZNdK1>?dSH9YwAo4 zJ==Hh?x^q&Q+@HIb#bBlO_J>6WWFR@cs7`R)@$r;$sHV)x;TxX>)$|aWRzF0= zS4&)b)^N;<#uf;2o$U)iQ2y|-cqH5Nd1Cj5hIf2kcGP13l2#xbi!>0y zB(tq$k<&*rtPb(R{cn-@3Y&|!`IuGgz&>;RWc_~BKTiFCQclvT7Qa8mAsX>H<2LB~)#JN0+Q*w8_!Ri= z4>rxSE7AKmUAiRS!2X7J6@Awf4V{_(Ee`UHd@5$y8i{3x(6lP>dx);Vlm1FN-;*i2 z%qtk?4-uOF>#&rrdb4J*&_gsH3ni94E>*W9cu0w>{0}K(zIXf5%~6r zERkoxnSa>cx!xAwO?Ac>(za02)hu>rxk)*f5@eA0QY{e{yzsI3Y$El=Ot7!N+g#_0 z^p46R^g8tK-f*zuUed78KM{vMPQ$pf?6jvzI!WYk4S)N;4lOS`D4B7OY3m#VjTbyb zHAJz%So?g6gjsRhMG7g^!2*IM#1jATXQh7-Ij08aQr{f0@L7`3n@G5tbr6H11SRz~ zN@3>9Xn>WP0`vZqe52i$Rw4gWEfPRGKKo&8oqzCz68q|dJ{7YaeOT3MGllzu5mKAu zG<7N`!SVi4oYbI%KtzV$AG;En4)=S1M@Z!9A}`7i|8Gf1phZU-(rhx{rv? zKE^b^e@x;tsVKd|zb)H3Y+v7Fy9cDYf%Wwl5^QAzAQ znTB_-6N7jh6iJR?ed*0KZVjESOLzHmpg5=0^}L8x|4VcfS>d2@}Hj!;2+u zf92c)lIgrA)FVhZ;j>vUyY8YbG*3`CB?k(6P(-&mNtoD(7ai;cv$2~szAq8ck1&(F zdXr*wSv?xiQ=F9k_swT`C$LAEb6S4YkHBnYMU}Bg*Z5V#k2!VyZ-8#=s~f+cr-elp z@9D`%#5hQRKl2jVq=UTJkZe1Ue{=ZDxx(Dd&z3-VvaBLZ^YGHnpu^Q5VWbvYYiXj$$ z1uodU0#-*DlN1rruWA@cH1^9_AO*iY!k4Jvu_KO$0p&1qsk_r6q;aNZ1G#D^l!kDa zM+0?781yN1(B@VXZ80nEo+;Ho+gRXeyB)e|B^A!uNXrZdcg=0j{v;GUZ%g{b3d(Iy zU;Mac<((#8H>#ei2>JVE+(l}Z;6e$k%CK;s55P9s24P6>i+gifh`}GFibzsshEiuJ zGC&{Wwb8;+P6_&YoYOeucBvxl$b*gMG{@f9qqS4h?!CtW2D2ahQE zxBI+H;%SHwx7MhC`o}%m5p-tAc+PU#G$;u9uefXHE&9Q>&cszwQDxw2G-g&6qKY&p z(ei??0ov-Rql);MqvXdaeAsARmFU`(>imKaR~^_yujYMV!P)VkT$_yfIRw`D(Bb=x z$w*3!-Ab{AmMjc;HClCoZ;7LTRf0vYff6T7fxpIr!_&;2W>H%(6@)j~YSY%cuP2(u z3r&5{oP<bMmI;AC5S{Pb}29YiiK_z6Qa|Q&YOF{%G0YOrfMrLTF8R?dk zZWwaj`Mvl40r$)ObYic)_gZT|=j^?nCsJScF@%DN0ssIATtn3m06>IW5I{ykxLCd| za`^Ab-SDw8P(Hx24ghR;xT=zokM;Iv?+F(*&rTa=<1Gg95UU6Xt$}JsNY2fB5t>HC zIz~71Orbu`oPv^-+?u7Pd3HQp21;8uDJSUOLFIDnT8IRh-0)5A3rlksfsWZfPW!SB z%8@>G^K%cJ=F)!+^nI$H^As?PK|x>M3D%O3drLDz#sHcGe4q@$;m}IZOP>RIkGrvI)Qk^8a&y z4|m-QBEj(uL@4O-Q>0>6`+2=P4 z;z@I|hW^YCpMz;B&1x;=h{h?=C(gUOLhBTXB$x8=X-!!^^$STrT;DUJnyb=xEpz$_ zR)u?33CkNv;^*dQOC3L)22rFknspE+b93pE$+GboIFUXs7mY;f30Oks%(0?fJ0m2v z&Z@K4>tuU6mMU16Hc|O;FR4LWeYsHSV1uXMK@7KbrHsXh(h`4u$Pau+iu}>nc~D2o zF80k_68O@(-btZ?(r99BBSpp!Ob7iTuQ?6m^w;!mbW@#wf1%(A9-5Hh^gP=$e9F2nmjfbnBkJ4 zOLKeyIMsg$snxjnr`kK2`slrGnA}v}d>P?h{8#BtZyJ1!h zYAfu@n(0IQFTuyXT8+7Q>+DZ!1x%pDpq+$+qSW;#ACdiN|G=^IVO>c@|GRm*s8|KB zL`v>r^aySEad7CvRTo}fzGIQq4C<3;hrq3tVFafB(uZyCttN8knr+S+o73@BElQdW~yt}Jt0G+-e2_SgC zhZ{%Mz7Hk34+%=F**j7A{gZ8Kl-VaJDeF;gv8_lUd(*MhPEGbH#Kb#vb?RNV>-hk6 z9a7|J+8iifS#~$bc9?S`=DvydpvCC7YB@>O$Jd;r{4RhY=Vu$3{tNm0_A@TyFaJwg zl}*|O(nGVr88FO~545p>H$2H1Sp0&gMB@JFX%3-AY;NZAgHyGgfg~k)v&YHxQwn*j4QEX5@Jg#$)-4Mbzvdcd@TiZ=B|85X&#!yd^vrK2 zNjM}H_s{QA#5>6;_z-#I3~O3-NY4G+a6K!f)%UdCcs2#(s|U;!`)#kl9lN~h7btmR*~rV zTAA^Ghy$0z6$B7p%W*$ZTe`BKh zPP8A|ggR2ns46f*9(SfQ)Xk(6fATkRdTTZlqWGpLPeJ38us0@i-HcXj#eC!O!jXRW z5#JNYD2c7$G7p7KW!c&kwWz{AE<^ikoPQP&+}0S9{a&NNEu3K`^mK-+;ptK;rxTWmA^AT^3_n=4~@)|htCcEeIn-1T`xz<5%d!VUFGDAg zP59xG>!WmQW>mESm*QGQ$Xx;`?j$))ADfvWvd_}<9lc`ID|RL!o0)bQxEqD3c(S7n zbh<<70o4OmsdY))OzV{w>K@czwxrd&FJsHZfai2SCar?Q@YQA#U$1~?{0Qt z{2+8^MNl(A6weLsZSVhJdwfN8vqXXG)p(|&E8_c7-8;s#ThpYCduqD9h^JO@2}jAG zPf1UG`%tG{J}LLmXdRskdA)sODvZN3|G{cj@3x_5wf9eaojBIecuDTwCTCRA$isj) zMV60p(pxI3-0KUt0~jVX`q@F_UO=-}L_;e$pu;(#mg|sKS_S(@mg%r|(BCZ<{a~$~ z+-+O3y2%1-{p8;FAbd3=(5d1gx3hj$-E}@L**P<&PZj8P&=M<_ug-RO9ZXvbRq0Zj zdSruDU}RB|9I8)^f9_>6m>0}A?lBQ9G}x5IlbLpZSw(*3G2G9RSLNMleAUK$k7{=G z2>&GD_VjTpWLmJtvL2`ATH=HVl-^|LeN|mK*DQSV^~I-V8a^La!#Q+yr%4h>(d6|Q z-8;P~;ekh0+nP)&A=SqA^!B^*T39U=-uVQjtzlO1{0t8Wahw+IcHDK_*2}Q9t1VF8 z(YIV*db-g%(5v@lg0j!KOv5jv{=H4>RorQMU(^>`BsFK`Yr%0{tJ>8COEX?6X; zQyo7v7jNL~TD1wbGfm5-P&gJuF1-cv@`2?qs1X;-$-33- zJCnGDt&HNw=3hh4as=+M&fA;40b>?$(S;o9g^qbSmZ|$rI1X z(ld6ulRvI(RhEQZ-?NDP1;#wrD`YkBl|JlCOWQV#_%>0?bEUGd#a!~GjHp+yyjD5+ zVzGg#3hT@h4q6z`!ucz+3%I9j62FiWND(+GNQmBVgLbJgoj&H7b#9mJa;4~b!{1w# zDh>gjIwO`5Un!w?A5Ny$Kz(fLR+q|=Lb(lCM=)&3)Fp0~`a7P*9sS6w?Rl+KI0(gg znysuMvgQ{J1weWGIcTO2=bu<;$}iYH$h32F%6sHn#1*Nqz6MTq?DlLDmC8Mh5@vA9 zWVB-!I1%j&2<5NQ-M?Q+vhYEAdZ)Kqbi^25i1so8i=}6Kzo!mvTc7;N)K==Tf=Ol$ zcI_nF1eVjduX*57xVg+^NbE&>8GuZ`1fdz&#jsgRG8yeV8kg||mg~_Yp8aSWqo~qV z5g$Avh@LZ=31IOjmSQn&|5s`+NNjp^QO@5h;eZZ33sS1TJ~C^Eb^5FwecIdcw-~c1JWu zT45raV}Lun`C-c@&3B0DZJt0XprC61=nmbC{s`4_*_KSp-V^hCg^H^!>9EEg8F^Bj zG4@Gh2b>)Y6hO0d$mE5#Ie=$;MlRx?10Oupirk-{*rK~^JHa3Fh{P(8*iO4zoU|k? zS}Zb@9WIh(-sGPy8l<-%6X>cp{q`>XHEbp>w&U$B=3T9y^IZUD^6?h_1TNw3_=FRH z!3zEi>f`{<21h3MFAfhIf8cY;E2FS#gsJOEp}MzLDo3IL3$xayzuR|vL~CX$wfHaW z)@;M|@{Dpr8M&qTQe;sIB&hGK>%=*RU+dE5&}0Smh6bhv?MpBfo@{Fhhx4JX20QLk z!Ql&7+m8wmYI5Z`T{mQuDIBBMR>2T06NX_&*eQ`KI6Wg`m2o!h(6j-&E$L6y?H+az zVLvX;G{Wv1GVQ+BXX9Ll-(H}a7Nvgcsuh*e%>MB7=X`f&SoH+_qsD%1_|Q|_<`Z&g zfjv%X%d8=jBeH>5;F4#!a>EJGM^W&Jx=Gsptk;+nQ(zT5%3m%;f8ma@A5rE!EuyW- zd^@MU>jVX(YEyG)aRWjxxD>Tv5@&lSUvIVAbDk9OWZYtThKWn3PqYuZBM$Hr|6MA% zU)GjNTp1#lp0b*kY^)jFepsh3#QOp*ei3r&*7cD!|FypX7-dcBJuMx=F0{g-C@9q; zZ?p~71Sl)g94#eJz5r{b)=Uljwg9jf+u8=Z||19M=h^?NS8Qc%vXH4U!FcOK8Qg2)mYE*2N+cuGX86IkE>5bvs*RjEYnr%lHQ+D8y- z_ixv4xhDp+Tg=Kx7jc|lAMt+wiX_2l}iGE<$p4U2wG1s1cgXCSHrpRMGI*^xiBEW|0= zot(jfjo#sPIg_`;hyit6<9j#J4*rME~LzO)8 z#8qn_r@~@!*i_XhP^@WCA@SL-H3Ezdq&IBx79(B`vq)80c%PI-D}D65>UiMKjzUsg z#pM#-v-a3AljX;^Bti{K!baU@5q4qZMQmXd_WH6VKtABI_$|(a8QRIxxiAHhVTl|{ zq5pkRJN7oS2PhpOxN*NEYmBE@k?w^VGl=4+-NVT3Y{RLhOb zDol?-l}?}=?xPz+s=j9`Hyahb_ofWFClNeY7}O??SX#XiM9Gr%R4bOmwjg^UI5(?> znsIP(z2!Ukq^hp6_{4MOOI$iwGiY9FXkqOk- zQPh|5L2>oqB+4xC+_t|0#uzu+Ys8Kj!6+Lkd$7Vaq;yKD=2nn9b_~>meUqeATd8D$ zD?5!(pGm2wKJWPy`Qh2@H_%7W01m;Rps>u^o<(-&c4K^e=g!N>6U5P#|4OoTpl$HP z@^40N%j03sy$5B?C`Ob$+s-ZJ*xiwiARB+NDrU*Ol|2M>F5?RelNYbdMye)Xxs4fV zzNHkWB#@Trz(w_2b=e04AyQ3yPF9@HBGn92e-54E$h+B7VlH?pLOE;}{2@<}a5%+O zf=pRiTW!d@Run#Re0dS3T?Kv+$H%vnWYg3uDu;=hbLzZ+WjtU;ot31;XN#G7-H?8N z&dULvaW~~3OnG8I-vfP8evwbY|7&%y>ZsREg_x~B0-}g7ZdSJqpX8IK8b9x_zvrv5 z8p+KdS|~impO1qwMt`Z%6o%?&0J*kqUkN``2YRA|aT|8y_y{xN$6h7y;a+@FA3A zHG2ZjtAZSV-$i139rF8(yfvVHr_p6V)1h$s9=E~a(4ziA-Z;Px3s#tUVR6o>*bGxM z{f)1k0B$vs@GtK7>H2r!L?y$-uD7t7!|@73IIyI_f3f|h^^PFEi?5xk0O+cGpj{40L z`Z&7g9?8~R9M3nir2N3%I&mP?ER*7q1kB2YB~pBCicC!7I?rDAe8%6gI-t2>A$0G* ziJr^o|D=KU@Wds-rDt|a7-bF%t3XQSBB{S-!g_;KmP&}CUe0~rttkQx{pyeQ(Qm8RH#f%S|GYKv5WI2*3YCM- zg5oJGy?Seh1~O=o31^RwZF<%JH#=qtcs+`}l%6N@^_}`(kV3u{H#}d0^@r@s^pEq) zhxnqWt7M7Rh!^8meeq-F+>*eHAmv7Hp0c^^D43Hj+t2wuZu2ok0x#dUf*4fh%grLBL8`P2bZN z@?);e_$^p33xUD!vF0L$%QkIs#*|;3C7m4X6tR~}0#|N5$Hh)zi>c*6z&;g1?L4P^ zuWPbi*Id_c5?Fr7+`E2IC?e~Yy<%N2d;#-D+u?Lq1yr{Qay2d4@^a zyrtmtI#>&}&l7;r!*tH;s}D)$lvI9>Mdudd&b$n<5JjQ{I&To($_cS|p~=P3Q^i4$ zJ}8NdF-vmq7jw&qNxpA?wcS|1(Wm1jI0e{C@w~g8_gc)J!Jo#pIEJL|^y?leTru?q zL0B=RtyE^~;vA!(pPQ8y$R5$n+WyLuxs?~7DU$!#c9nUkXjjcF* zD*mS5892zw=A2?3Qj~A{(l|k?S!kB3iXpLuFHrczVsa`-9cG9|tV}!RH5-s7$ESBG z(d+ag$^>-mbnMx|^~yXVY(D(_?28ZYFNa{nF5e=l^n96Ol{GYp=L%24C{?c$=` zz09BpzX-!zbV=mA_%D@UkkCKRn*LkRzZ&{gA5Y)3PyPTgK>PYK8eF?+P?C*CGA39Z zo~xn}&~jldMA7xZO_S_3Pc!%T?b}?hH?vbc(u(9Cj@3aFE$D)n;n|yUMEO){{DTR^ z+vzX33D{OAs!DJWnSDwttBj?i9QH2wM2mb>S#oijLgYDU{DK+f{FV2Uon>y|7Yrun zG<4%JGA3O69b_8#DYf1w!{~9!@BGg{997slGGIYq^qbcBQoRDS-=wKpwcK2$g4d>b zIFR?G=6``G!hc9)m8a1-zKR3$bfe)@HrOy8ev70yNr0z+tga!oouM63a67II;pnUD zBniO(4t)E;92S!2wy`3FPVkV2=K~h%1i{VLUXjwNJQTx0k+t)Lp}eDru#xl`sTm|& zVO}xHfd?r~kd;hkTpYGwTF^+yC;RL9I|@}SqrC5+%5>lG=Kr^$_0x3=ar`O+$X>x5hPOT>jj!m^q3?+zV=;<&&i*p;T_3MFLwbxrEkoE15NlFM=!z> z*&puCccaQj3Cy-~CFS~tLeiYTx***;<*Ri{-i^k3SAu=Ufi*Y?N!Gf4ycaX^@WWcJ`92hU7#P4NcR4(PRyKn&3n$AiPh0kAtHD{0000HN>x!0068AmGK-3&*{e3Uq~+iwv-H{Lc3|EpJhoyuAJ0INWlU zYs|7Za5*s`)0V49#bO06l{$kIk&b` zD|xomQbRbls+S$3)h?5Zk%KU5a!js6(1LACbMXhYrd=``>4#ejsnXK;Uo`-qEc@4g zLQ?bj!BLCqP2Y+g6Q7s%7qO%HJ`CnDgkjQH=N%O<5|!=@MqfP*u8;550L(SgBpR8) z!|5m5+|u8kCzxaAC(7SXcWVNJT8R?%?BLw9gGLAX`0j$wKlqq+sgLw+!9B0aTq@#a zC6WPLcE)=)1-*AfKjCEq!CFNwQ7^X#s)_nIX}qGg154j2Fzx0 z+q;L=VE^QAREZ3mE^bwtTcF+jsQ!?)X8gbE{85W)mzveNWsC30&kEQ2+n!xSrV=|7 z#njwncdXD!Y}l`B^KB8Po~HU*qk^JC3yep%*zz9h%Zl|_Hyq;gT-^U0bUwdwcI~R0 zRPdMmBs=r&TdFj@hT|gpRu3MY-s*Y*A#5NI;A7g7Pd!cX)kXbIuZ=E#qAG6x-05QF zIJ6%It)>-qNAyghn!2ro&)%yojRjwD$bo&BfggbkDC$gKO4L*ovUR)p5KnbTD{?FByVsUd|PK+U>SVt(Ho5+VKrAAJv$QiYJPNjfm?a`lwLj{uKgn!rVCGL&K56oXvcMAsY?7~ z2p>aOgKCr4SAm$&hn1`@f7wz`Uvpbj=o_-~3xj19UgJ|+-Z0edjX!nkh!W@&6SaP+ zKi=QJIPYbp2EnM`!BLLt&F5zGqL2mT7JF*a{j;g05~lQ7j`Au+1M^)-sVwm9l#yeL zv7UdFOW>#bYA5uXXRbC_7{uT5@QL>-2M z_u&(D)kq6|#B44l!`^<%m3pAfy_Wq*z;oe6W3f*ykaJbd3oc0YO=PP1QNtq8WaBBo zaA7pr)!6g}X<^L30fmU-Sl1&dqz4#9oy7 z^aIrwXGSmbizSj?K4V^Qcbo5IbCLV`2(-(!#f<}+N(`vr8oJ~+eA(R0X!Je<88PDG zqW^R6eL>mF6Q^vzVkT_Iv4PtoF)2;@>hN%soXmCJ(@KW8hH7$Cui^Err>bmVX-*}r#tuM`ih&*D(`MXC7P|Y0VC#QI5+8sbk zJ~m9{I;nX>3hIboof1}I3LhnMA#N51FYVk#S!txwQrE9+-e+KgvDc5up~q&2|M}(n z_vyidO6@YgVqq|*iZSt#z=aQi>D3O2oC3+)86lXNi{-fQcTy znL!F7Xe>O>n&KKvHYx|}FBPK9X`~@sYk!%*!-IPI_3x5Iq7(&0RP~YX2Fqq;Y83&y zEx8Mohm~d>#s%kppZ(?CLtyxTARr071D#C0QVY~P56WwLEORxpv<@YOhq%)(Z>MSK zFPeNvr5LVP1OhToPAFc@lqQLgpcywaWmr0P3|>|+dG&vrfUYLVCt4N9r`wB|S4n)6 zY(Y?aOBQ`F@#DZ`JQOk0q?0ja1^_K7r+DLQ6IJ3zlV2QG0+>ww*1VSRo~59L>)&;I z#F3}?;8$;wyRA$}D4!qsbVhFGBtL}$C5(oi#fNIV&#sJ(BFgG(UjyBs;C0&~uyw}s z%&<9`uTDm6P&E79<8!%OB>1VM3C!VmFXnSsT&+AXNo43PHo#maVMg(G&`CI=Y&Q>w z)b$kq#Uh**+_mg~%3K1q3OnajSOD8Fxl$A{TU#EPp{8y`I4a-(Op1Y_wwz0jS$jV6 z<-Rt|iP~>nREy6SFbCkXy-%SCeA`#;w)nGG_}$^l-f40e2wW_q0*;|(Gw1v~T+>y( z$DwQgw_3f1-oMcfi?7V@T*Cm-#hXPdvKMc9q`RpUe#N<44=p&<7-?4I!VuodrU-N! z-M)V8YyZoC`>!&WwX*5JZ!Vauz%jYUR8Zh5bin5!Bldv0*AG+DClSk86D~D)Vll6{HGtGW5#^m_L*~1}zzP z`OQ0!_x0?1nC=?C`pcN&z;mqlulNUbFtlPpG^$C%F4Q(&itqfU`%OTj(|`6qj9qW# zfSgHG-Y)ZfoRse&_j6x;6mu0?T%idx&Y@9Ur)#Q&X0Cz%s_S`rk$jX^dha7w%5St0zx4o0{bR-H2FF19 zy8dSp;A6^!CbZ_oS5Yvj!@wi$e|e4-z~yEl6TA={LGqaE}9M+Y&4odZg3q& z$hQ;QRBs{7j{bXi{A-Wd(+zc?F(%~=q$as~+kms?(gS5_;m=i63BM6@dYH3No{R5M zy_kULKpaH$V4z)fV#a}vGmDy+HfpKGCs~vQ9=8JIvd2%>h$~|;(@|(a4>P9iF%`DG zSrhRC;hL#+FLGIDMRUtCC_FG-MzCP*C1I(_nPo&AOHDZT+z5j2W8+>s$fN;n z*aViUl~&ldL_&9&woVk(np#*>PTuGQD6)y0j2@WMN5Bflv%T5^<BSO}dm*lqZA@EXsTTLIWcR(<(Q{A_%e!9IJTo$%Ll;!{_)eTDLo5*M2$KpK zO&Qjun+GI7;pzI+mbDgk&aR;xTRNzQ zG+(|$C2y=Zdw8yDBMx5RpMnBly?tpPYaz3htGlSXl#tEDGU=8gj1sclw9zBDk@Og(MUZ1If4#^~ zjyhe~8)AKFlyhcy^YsC2c4XYe_zqRuJDKb| zb!i~1i(~5Mu5-Tf!K~nb#N^uGwWb&py?U<|a&4}p2X5{I0u8`L>%aRu?$_cj-}A1p zF1u#r^>s*;mb5v4un=1OVlQhW5kY^Q5Uxc_wcJr z!2#sxTZzC6>R+9dOlQB(No(0fmA#1D99ZaA9js(fiwo~$*wKV(ckfwWsbM@ zPvlRsX+=tDI@5?l1NYBN$r7Rvpp|nsHZ0?p@kgM-z0iPe-JB_{ zY0OW{ZUM$#N^vLW4I!41b8hSZ6tMgnWaD+^)|0@QrY=lDBRY4#7qp#Z-^IX5&#S!4 z7wESYIXufe*@wr4K-!ifog?2uD)9)$`+4CJs4Nk3S(_2lDXh{oC*F)&hO}bNh}#kQ z)I6hP-@n=V$)xzEY5aj8^wR&?{Zxv8IKFh|H`WqkH~=0V0Q~9gJs)a2UdtvM6PlY=#Rq?tUBTuZ9+ClJLQ_R#@7szC&5HI0 zCpEHueD3Oe+)_M3BD7F;+3T^(tt=h!ja@p-UJUE8)gU@M{dX3qJDPMgQ(h7cJ4>B* z!K6IsZ?kZR@`n+M-Gr3hkNk!-wQoAo9_SV%*e-~n5u`CL}Mur8#lw&8m zvkS}(P;#-oL^%F+Xl?32-H!8oacPeY4GNY zHU7u7f~jJZy;k67l-O}wQ@ESVHwt&1$KB!x5gfaS@486r2w5Oky=D(tvG@G#mV6s&M}=?r^>??yS=6i4lhs+Ye{5loE3d_>zmF@pM*|S1 z48d1rR<?5IZI6NjkEc(`jC5Xw4XE%8Cvd5mN50#E5g}W1IUJ2ky^H% z{Dq%g(~Q$)I*l)zy@LHwdNkfBPDoGkKj3QbQ8tkB@y#$UAW68y4}m0J|)}ncMS>++{6oJF+YCypb~9>*HnH6DeC) zQk%^ zXjq{w7*S3&5y{!(OyCb@o#J#$%(NX4WwQ=KKN60%s!YIt#*H%91oE&JE?hHoWu9cv zB%jBLH=SrjG+E}k@f(jVpjm!}!qe47PT(1MGZ`3p_(iAp(QK+2{}jxuzC=suG}4@6 z=5}oMb}#35Pbc4dU+CAt8v&57GT>U*+xjhLjl8ino^q82-DTyZkmrZjlgT)H>t{n+ zJ}OQ1Dp^*us}NSm0>%&|^8ZwfaWk$a!D!vB@CH0ONu);0vYKAdrf*7HycQK2pTQol zI1|wEe0fTtvV|dnTV80Ppil5ytNz&y}}*F8M0 zx=Tr9B*$~3%@_x(Y3d|I)h9UJ1Y|@MRG6}%)if@6_nG=_W`Rr9%Quuf=U0mnl98Qa z&rqI^nYk%02-RThJI{ILAqH!#1}0MPeww`i=@G_f76^tqSG7{Sq42 zCVjMy|7*hHR>|_G3VgO&e~dHthmL#>@S}VaZ2w2{d&wC$?##oVkOv+^jU_Emk)*^b zdZ)gNzIvWcndjE;zNVP56{wFkID=N`F_k^<4`-`3itS7Yo3GdCMYT&WGYzgb+x=JG z^%Dpm1%cm_Ws5b`z@zM_=}(v}%Z1&^F|jEs%hA#1+*BbSCvhFV(>%(P@#|9Gw%r*{ zire!;hP#OPGm5>&DHpsJ>k-#i(f~LxTDKzL=VYj7eI5P7TIfhay{UcgjG66=P;Q=0 zWN}>(dm+YdIHw*9J~Bf*{wH(zXP@>Mze(#trQ5=7lJhXUf_BsN61M{DRSe+jwJDe< zOSo-n2HMtv)yr5zN8o^M?j#q|g>dRo3nG>O+(0C771&Oj2X`9QQ^^j8!;Brk|J0J* z3I?Ynm5+t&IW#ic#j8iWOAXhh6amvI1(Nn05ywinC=|v;$rdo$4A!)minxca20MpydCQjYASEy`nbsb`L-(%7L1>2_Kw2dok88!pl|TAgz%c*4k9$Og2lo#> z=Sv9yRv7edZ^C|&@G)UG@nmABca|^+t}6I<+WAA5Vyjfq5T^AFIUJD$;PICvMpj3y zF0}aJFkum`0r!cOk!J&;pN9b(Ukm4T(!((ek3l$Zw8pm*%2#vIf=J%ke?3sS0~Dw@ z?0q!W(x_H6IOh;gRk1y5p@qa!U{ zted@)UgR|ikTI*O5OpC~M^?OmtH?14ilnxnL34aehK?3ED?V~j9C`h8xCqW_q~g?t zkN_R=B;(hxEyo;v?xeq5hEL?#l|2QsZ_1c_&-AY^x(A$+KA#gGGQUX@m>S)~ge~U?v9*@p_zdR(tyBq2 zdf+QGQ|m0b9`?SPG>N+;qH7}1qqQ{D{^H|?&>Yupgx+ZwEthBBUt)BX@3xZPB%D!Z z-LA1xM!8B(z)1WDR=5toaUt5)x5bXE77#k^cJB#@tPn-L99Lv-;L|<=^T`6ZReRAp zB)u(sxbdFqWnf9;*I~H$H7a)YwxG~7TNo7lSYdM;oBZ)!>Gk&GK*$oy^WdpFBEp|f z#Z9XAToy9%_t=sl!-pdWhJ=6kT>4jh6o(u~|K>EU3wQXv}>?ArSimW~Z4)Q4Y+O*tHo|tS1{MhEWiB}X{sfe&+tj%^>?$4r-VnJ z;lp9c^Cc1QiEGI87!9UBF8B;d0R9Nh9fmAXj@bqr(^cGOT+u+B9GSBjmrq)7tYtxC zV&b@^^qP^RX~*NA*E0Swk#ZgB&JyD@D!}2I`ppU9$E=>4q3JO_Dv+!ALe|eP=<59> zfUWnYNzO2X48^QB?*;AY6DZ87l?AG~TYm?!DuX;ePnfBZlhjOa$M~pJ;_l+=-7`eP zWqX4IMKhKuv-O}6ua4gKjExs#b0&o6hj2zIHn=u@c;cLdePpEz1vm&B7+C+%BapsO z^nb{e1$<~VV8)>gOiNX)zvsXU2Y$$A1>_6=Nl0CITfI0wWEk81%hpekiWx^&Ef09t zslGwJgopO@{z!@b3RXz9!~evN9rWt1qtH$+EM2b^87t}z4=Z5+4{$f&a9JQKR}TA; z_vL;+T>f;)6U)SkR7zqQ{l~pt9_U1`+H3NPddwmHN-8~sz;+BaNt3XLN3W{wH~NkB z@;PCPsbhMpoL~BBOqkHo>K)U}ej(_C$UNMdNghAarF&}NWP>D}+)OWgzLvKVtDboY z%evdETnnLQp$dEkC6wT$KH@|vr&K+Hc2;0I1jMCl-oiKZ3odmmr?^SOlqWj8ByMWL z!04a+agp3#aE?d6tyD{@+JGZw#7b-~e2c_Yy`Hus!gxj&T_r{=)k!P4M`g}zPKSgc z5f1Zg!`Jcqg_vvK(po>u2R!#-Url(4F*eEAeBq5;yHC8v4tZ7CPBa}PJIAw*g;dms zpQ^(X8qGXvN6wrN_u}-tQy&h*TT z@2&9xZ^%D?@HgK9s&`fEIh*XFc;32Xs$*`#3PlwszbLAMbl*Yo`0)4)0bO3 zTuNYB=8WUTk;vU1B?A>AR-EnH2L6FRBqS;i0B48omj`P6^crXk+6W<6f(iOjjE$GD zfdRs6a11;`kN-oV@ekP6W^UrweRufMX)Lc;yO?+1aCF%~8S2t*NcqRu`~y%f9~}-f zE#0)5$V%j}h-qK)^xxzp=H?b;Jv%%t)6k48{=`i`_-xjzP8sk$*}#3G_=RY-DYlGV zKF#{reEhM*8G-LjH|^Wy$ml(oqnA62S_{5mh1EdqYI^2_^DMt^KERQrUX3l19)wb> zRza9>8|oIjuVl&MQLBeSlV4=+-Q<6#DzIYU%(+l_oIkd;`R3hmz9;3)jyUyp%q!}UT5iMpBXH@7V@=||__fX{BfJs;7+NIM+UVoqGA^ViA+t->ann(9-9Ce;- zQpf7|;Ebf#Hpjp)=*HqM=t&aBC+ao+)^<+X8yKKMsKNf^3SUSBwm(u#y2ObZTeCH# zv+suh7Iu*@OIckZJj#V4kQgfsR;CpuA+8E?pm3SZNF1V{mbR|t7Y%e9Ro;J_!2m^P zg(b_vX3-8Dee^rTpxoH%b8dQ!9fc0|CX6HhDh_79U2Xjy<893XkHt84RA%S|XsRP2 zK+Ghuu7ekC9ZlF%(xv#RB-QIdNm04^cLyh_gn8I}8UwO}Pp zi#ZZlp6Q}`WzP3~U;L%nhytlC*^@*57#hX=gZ35&a<}#at*Su90*?p0u88k#4Z`%*Wrurv(_vNu#t}j6 z5_@4xO2SSZJjzxQkeJCkQWSo)ueVIzBYhtPI`LQ~hSR2l)FTV!Z literal 0 HcmV?d00001 diff --git a/src/Camera.js b/src/Camera.js index dd775aa..a498fbb 100644 --- a/src/Camera.js +++ b/src/Camera.js @@ -5,11 +5,11 @@ const CameraPage = ({ handleClose, handleUploadImage }) => { const [isCameraActive, setIsCameraActive] = useState(true); const [uploading, setUploading] = useState(false); const [isMobile, setIsMobile] = useState(false); + const [isUploadedFile, setIsUploadedFile] = useState(false); // ✅ NEW STATE const videoRef = useRef(null); const canvasRef = useRef(null); const fileInputRef = useRef(null); - // Check if device is mobile useEffect(() => { const checkMobile = () => { setIsMobile(window.innerWidth <= 768); @@ -21,7 +21,6 @@ const CameraPage = ({ handleClose, handleUploadImage }) => { return () => window.removeEventListener('resize', checkMobile); }, []); - // Start the camera when the component mounts useEffect(() => { const startCamera = async () => { try { @@ -37,7 +36,6 @@ const CameraPage = ({ handleClose, handleUploadImage }) => { }; startCamera(); - // Cleanup camera stream when component unmounts return () => { if (videoRef.current && videoRef.current.srcObject) { const tracks = videoRef.current.srcObject.getTracks(); @@ -46,7 +44,6 @@ const CameraPage = ({ handleClose, handleUploadImage }) => { }; }, []); - // Capture the image from the video stream const captureImage = () => { const canvas = canvasRef.current; const video = videoRef.current; @@ -61,10 +58,10 @@ const CameraPage = ({ handleClose, handleUploadImage }) => { const capturedImage = canvas.toDataURL('image/jpeg'); setImage(capturedImage); setIsCameraActive(false); + setIsUploadedFile(false); // ✅ from camera } }; - // Handle image upload from file input const handleFileUpload = e => { const file = e.target.files[0]; if (file) { @@ -72,15 +69,17 @@ const CameraPage = ({ handleClose, handleUploadImage }) => { reader.onloadend = () => { setImage(reader.result); setIsCameraActive(false); + setIsUploadedFile(true); // ✅ from file }; reader.readAsDataURL(file); } }; - // Cancel the image capture or file upload and restart the camera const cancelCapture = () => { setImage(null); setIsCameraActive(true); + setIsUploadedFile(false); // ✅ reset + const startCamera = async () => { try { const stream = await navigator.mediaDevices.getUserMedia({ @@ -96,71 +95,96 @@ const CameraPage = ({ handleClose, handleUploadImage }) => { startCamera(); }; - // Trigger file input click const triggerFileInput = () => { fileInputRef.current?.click(); }; const mainContent = (
- {/* Camera/Image Display Area */}
{isCameraActive && (
- {/* Hidden canvas element for capturing the image */}
); - // Desktop layout with left and right sidebars if (!isMobile) { return (
- {/* Left Sidebar */}
- - {/* Main content */}
{mainContent}
- - {/* Right Sidebar */}
); } - // Mobile layout (full screen) return mainContent; }; @@ -222,7 +238,6 @@ const videoStyle = { const imageStyle = { width: '100%', height: '100%', - objectFit: 'cover', }; const controlsStyle = { @@ -249,23 +264,6 @@ const baseButtonStyle = { transition: 'all 0.2s ease', }; -const captureButtonStyle = { - ...baseButtonStyle, - backgroundColor: '#fff', - color: '#000', -}; - -const uploadButtonStyle = { - ...baseButtonStyle, - backgroundColor: '#4CAF50', - color: '#fff', -}; - -const cancelButtonStyle = { - ...baseButtonStyle, - backgroundColor: '#f44336', - color: '#fff', -}; const confirmButtonStyle = { ...baseButtonStyle, @@ -273,7 +271,6 @@ const confirmButtonStyle = { color: '#fff', }; -// Desktop styles const desktopLayoutStyle = { display: 'flex', height: '100vh', @@ -289,26 +286,6 @@ const sidebarStyle = { borderRight: '1px solid #e0e0e0', }; -const sidebarTitleStyle = { - margin: '0 0 30px 0', - fontSize: '24px', - fontWeight: 'bold', - color: '#333', -}; - -const sidebarContentStyle = { - display: 'flex', - flexDirection: 'column', - gap: '15px', -}; - -const sidebarTextStyle = { - margin: '0', - fontSize: '16px', - lineHeight: '1.4', - color: '#666', -}; - const mainContentStyle = { flex: 1, position: 'relative', diff --git a/src/ChatBot.js b/src/ChatBot.js index 6c6c6ff..7d96478 100644 --- a/src/ChatBot.js +++ b/src/ChatBot.js @@ -1,6 +1,6 @@ import React, { useState, useEffect } from 'react'; import styles from './ChatBot.module.css'; -import Camera from './Camera' +import Camera from './Camera'; const ChatBot = ({ existingConversation }) => { const [messages, setMessages] = useState([ @@ -15,22 +15,19 @@ const ChatBot = ({ existingConversation }) => { }, ]); - const [input, setInput] = useState(''); - const [isLoading, setIsLoading] = useState(false); - - + const [isLoading, setIsLoading] = useState(''); const [isPoppedUp, setIsPoppedUp] = useState(''); const [name, setName] = useState(''); const [phoneNumber, setPhoneNumber] = useState(''); - const [isOpenCamera, setIsOpenCamera] = useState(false); - useEffect(() => { + useEffect(() => { if (existingConversation && existingConversation.length > 0) { setMessages(existingConversation); } - }, [existingConversation]) + }, [existingConversation]); + useEffect(() => { if (!localStorage.getItem('session')) { function generateUUID() { @@ -48,19 +45,107 @@ const ChatBot = ({ existingConversation }) => { } }, []); + function base64ToFile(base64Data, filename) { + const arr = base64Data.split(','); + const mime = arr[0].match(/:(.*?);/)[1]; + const bstr = atob(arr[1]); + let n = bstr.length; + const u8arr = new Uint8Array(n); + + while (n--) { + u8arr[n] = bstr.charCodeAt(n); + } + + return new File([u8arr], filename, { type: mime }); + } + + const askToBot = async ({ type = 'text', content, tryCount = 0 }) => { + const session = JSON.parse(localStorage.getItem('session')); + if (!session || !session.sessionId) return; + + let body; + let headers; + + const isBase64Image = type === 'image' && typeof content === 'string' && content.startsWith('data:image/'); + + if (isBase64Image) { + const file = base64ToFile(content, 'photo.jpg'); + const formData = new FormData(); + formData.append('sessionId', session.sessionId); + formData.append('lastSeen', new Date().toISOString()); + formData.append('name', session.name || ''); + formData.append('phoneNumber', session.phoneNumber || ''); + formData.append('type', type); + formData.append('image', file); + + body = formData; + headers = {}; + } else { + body = JSON.stringify({ + sessionId: session.sessionId, + lastSeen: new Date().toISOString(), + name: session.name, + phoneNumber: session.phoneNumber, + pertanyaan: content, + type: type, + }); + headers = { 'Content-Type': 'application/json' }; + } + + try { + const response = await fetch('https://bot.kediritechnopark.com/webhook/master-agent/ask', { + method: 'POST', + headers, + body, + }); + + const data = await response.json(); + return data; + } catch (error) { + if (tryCount < 3) { + return new Promise((resolve) => + setTimeout(() => resolve(askToBot({ type, content, tryCount: tryCount + 1 })), 3000) + ); + } else { + console.error('Bot unavailable:', error); + return { jawaban: 'Maaf saya sedang tidak tersedia sekarang, coba lagi nanti' }; + } + } + }; + + const handleUploadImage = async (img) => { + setIsOpenCamera(false); + + const newMessages = [ + ...messages, + { sender: 'user', img: img, time: getTime() }, + ]; + setMessages(newMessages); + setIsLoading('Menganalisa gambar anda...'); + + const data = await askToBot({ type: 'image', content: img }); + + const botAnswer = data.jawaban || 'Maaf, saya tidak bisa menganalisis gambar tersebut.'; + + setMessages((prev) => [ + ...prev, + { sender: 'bot', text: botAnswer, time: getTime() }, + ]); + + setIsLoading(''); + }; + const sendMessage = async (textOverride = null, name, phoneNumber, tryCount = 0) => { const message = textOverride || input.trim(); if (message === '') return; const session = JSON.parse(localStorage.getItem('session')); - - if ((!session || !session.name || !session.phoneNumber) && messages.length > 2) { - setIsPoppedUp(message); // munculkan form input + if ((!session || !session.name || !session.phoneNumber) && messages.length > 2) { + setIsPoppedUp(message); setInput(''); return; } - // Show user's message immediately const newMessages = [ ...messages, { sender: 'user', text: message, time: getTime() }, @@ -68,87 +153,68 @@ const ChatBot = ({ existingConversation }) => { setMessages(newMessages); setInput(''); - - setIsLoading(true); - try { - // Send to backend - const response = await fetch('https://bot.kediritechnopark.com/webhook/master-agent/ask', { - method: 'POST', - headers: { 'Content-Type': 'application/json' }, - body: JSON.stringify({ pertanyaan: message, sessionId: JSON.parse(localStorage.getItem('session')).sessionId, lastSeen: new Date().toISOString(), name: JSON.parse(localStorage.getItem('session')).name, phoneNumber: JSON.parse(localStorage.getItem('session')).phoneNumber }), - }); + setIsLoading('Mengetik...'); + + try { + const data = await askToBot({ type: 'text', content: message, tryCount }); - const data = await response.json(); - console.log(data) - // Assuming your backend sends back something like: { answer: "text" } - // Adjust this according to your actual response shape const botAnswer = data.jawaban || 'Maaf saya sedang tidak tersedia sekarang, coba lagi nanti'; - // Add bot's reply setMessages(prev => [ ...prev, { sender: 'bot', text: botAnswer, time: getTime() }, ]); - setIsLoading(false); + setIsLoading(''); } catch (error) { - console.log(tryCount) - if (tryCount > 3) { - // Add bot's error reply + console.error('Error sending message:', error); + if (tryCount >= 3) { setMessages(prev => [ ...prev, { sender: 'bot', text: 'Maaf saya sedang tidak tersedia sekarang, coba lagi nanti', time: getTime() }, ]); - setIsLoading(false); - return; + setIsLoading(''); + } else { + setTimeout(() => sendMessage(message, name, phoneNumber, tryCount + 1), 3000); } - setTimeout(() => sendMessage(message, name, phoneNumber, tryCount + 1), 3000); - - console.error('Fetch error:', error); } }; -function formatBoldText(text) { - const parts = text.split(/(\*\*[^\*]+\*\*)/g); - return parts.flatMap((part, index) => { - const elements = []; + function formatBoldText(text) { + const parts = text.split(/(\*\*[^\*]+\*\*)/g); - if (part.startsWith('**') && part.endsWith('**')) { - // Bold text - part = part.slice(2, -2); - part.split('\n').forEach((line, i) => { - if (i > 0) elements.push(
); - elements.push({line}); - }); - } else { - // Normal text - part.split('\n').forEach((line, i) => { - if (i > 0) elements.push(
); - elements.push({line}); - }); - } + return parts.flatMap((part, index) => { + const elements = []; - return elements; - }); -} + if (part.startsWith('**') && part.endsWith('**')) { + part = part.slice(2, -2); + part.split('\n').forEach((line, i) => { + if (i > 0) elements.push(
); + elements.push({line}); + }); + } else { + part.split('\n').forEach((line, i) => { + if (i > 0) elements.push(
); + elements.push({line}); + }); + } -const handleUploadImage = (e) => { - console.log(e) -} + return elements; + }); + } return ( -
+
Bot Avatar DERMALOUNGE
- - {isLoading && ( + {isLoading != '' && (
- Mengetik... + {isLoading}
)} @@ -159,15 +225,18 @@ const handleUploadImage = (e) => { >
{msg.sender !== 'bot' - ? msg.text - : (() => { - try { - return formatBoldText(msg.text); // Apply formatting here - } catch (e) { - return msg.text; - } - })()} - + ? (msg.text ? + msg.text + : + + ) + : (() => { + try { + return formatBoldText(msg.text); + } catch (e) { + return msg.text; + } + })()} {msg.quickReplies && (
{msg.quickReplies.map((reply, i) => ( @@ -179,14 +248,14 @@ const handleUploadImage = (e) => { {reply}
))} -
setIsOpenCamera(true)} - style={{color: 'white', backgroundColor: '#075e54', display: 'flex', flexDirection: 'row', alignItems:'center'}} - > - - Analisa Kulit -
+
setIsOpenCamera(true)} + style={{ color: 'white', backgroundColor: '#075e54', display: 'flex', flexDirection: 'row', alignItems: 'center' }} + > + + Analisa Gambar +
)}
{msg.time}
@@ -195,21 +264,34 @@ const handleUploadImage = (e) => { ))}
-
+
setInput(e.target.value)} onKeyDown={(e) => e.key === 'Enter' && sendMessage()} - disabled={isLoading} + disabled={isLoading != ''} /> - + +
- {isPoppedUp != '' && + + {isPoppedUp !== '' &&
Untuk bisa membantu Anda lebih jauh, boleh saya tahu nama dan nomor telepon Anda? @@ -218,7 +300,6 @@ const handleUploadImage = (e) => { console.log('Nama focused')} value={name} onChange={(e) => setName(e.target.value)} maxLength={40} @@ -235,14 +316,11 @@ const handleUploadImage = (e) => { value={phoneNumber} onChange={(e) => { const value = e.target.value; - // Hanya angka, maksimal 11 karakter if (/^\d{0,11}$/.test(value)) { setPhoneNumber(value); } }} - onFocus={() => console.log('Telepon focused')} /> -
{ onClick={() => { if (name.length > 2 && phoneNumber.length >= 10) { const sessionData = JSON.parse(localStorage.getItem('session')) || {}; - sessionData.name = name; sessionData.phoneNumber = phoneNumber; - localStorage.setItem('session', JSON.stringify(sessionData)); - setIsPoppedUp('') - sendMessage(isPoppedUp) + setIsPoppedUp(''); + sendMessage(isPoppedUp); } }} > @@ -266,7 +342,13 @@ const handleUploadImage = (e) => {
} - {isOpenCamera && setIsOpenCamera(false)} handleUploadImage={(e)=>handleUploadImage(e)}/>} + + {isOpenCamera && ( + setIsOpenCamera(false)} + handleUploadImage={(e) => handleUploadImage(e)} + /> + )}
); };