From 01f2f846fa86a1f05688559a3ff912377294756e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=AA=20Th=C3=A0nh=20=C4=90=E1=BA=A1t?= <91755733+lds217@users.noreply.github.com> Date: Tue, 29 Jul 2025 01:06:57 +0700 Subject: [PATCH] [update] Refactor CheckUpPage and related components to improve organization and clarity. Remove unused DoctorItem class and related UI components, consolidating imports for better maintainability. Enhance image handling in ServerHandler for improved image synchronization and storage, ensuring consistent PNG format for archival purposes. Streamline UI elements in CheckUpPage for a more cohesive user experience. --- src/main/java/BsK/client/LocalStorage.java | 2 +- .../client/network/handler/ClientHandler.java | 2 +- .../component/CheckUpPage/AddDialog/add.png | Bin 14292 -> 0 bytes .../ui/component/CheckUpPage/CheckUpPage.java | 112 +- .../ui/component/CheckUpPage/Debug.java | 49 - .../CheckUpPage/MedicineDialog/Demo.java | 34 - .../ui/component/DataPage/DataPage.java | 4813 +++++++++++++++++ .../ui/component/LoginPage/LoginPage.java | 12 +- .../AddDialog/AddDialog.java | 5 +- .../HistoryViewDialog/HistoryViewDialog.java | 2 +- .../MedicineDialog/MedicineDialog.java | 2 +- .../client/ui/component/common/NavBar.java | 2 +- .../PrintDialog/MedicineInvoice.java | 4 +- .../PrintDialog/UltrasoundResult.java | 2 +- .../PrintDialog/print_forms/InvoiceItem.java | 2 +- .../print_forms/medserinvoice.jrxml | 0 .../PrintDialog/print_forms/test_print.java | 2 +- .../print_forms/test_ultrasound_print.java | 2 +- .../print_forms/ultrasoundresult.jrxml | 0 .../ultrasoundresult_potrait.jrxml | 0 .../ServiceDialog/ServiceDialog.java | 2 +- .../TemplateDialog/TemplateDialog.java | 2 +- .../entity}/DoctorItem.java | 2 +- .../packet/req/SyncCheckupImagesRequest.java | 13 + .../packet/res/SyncCheckupImagesResponse.java | 23 + .../server/network/handler/ServerHandler.java | 72 +- src/main/resources/database/BSK.db | Bin 1339392 -> 1339392 bytes src/main/resources/images/landingpagebg.jpeg | Bin 405865 -> 0 bytes 28 files changed, 5035 insertions(+), 126 deletions(-) delete mode 100644 src/main/java/BsK/client/ui/component/CheckUpPage/AddDialog/add.png delete mode 100644 src/main/java/BsK/client/ui/component/CheckUpPage/Debug.java delete mode 100644 src/main/java/BsK/client/ui/component/CheckUpPage/MedicineDialog/Demo.java create mode 100644 src/main/java/BsK/client/ui/component/DataPage/DataPage.java rename src/main/java/BsK/client/ui/component/{CheckUpPage => common}/AddDialog/AddDialog.java (99%) rename src/main/java/BsK/client/ui/component/{CheckUpPage => common}/HistoryViewDialog/HistoryViewDialog.java (99%) rename src/main/java/BsK/client/ui/component/{CheckUpPage => common}/MedicineDialog/MedicineDialog.java (99%) rename src/main/java/BsK/client/ui/component/{CheckUpPage => common}/PrintDialog/MedicineInvoice.java (99%) rename src/main/java/BsK/client/ui/component/{CheckUpPage => common}/PrintDialog/UltrasoundResult.java (99%) rename src/main/java/BsK/client/ui/component/{CheckUpPage => common}/PrintDialog/print_forms/InvoiceItem.java (97%) rename src/main/java/BsK/client/ui/component/{CheckUpPage => common}/PrintDialog/print_forms/medserinvoice.jrxml (100%) rename src/main/java/BsK/client/ui/component/{CheckUpPage => common}/PrintDialog/print_forms/test_print.java (98%) rename src/main/java/BsK/client/ui/component/{CheckUpPage => common}/PrintDialog/print_forms/test_ultrasound_print.java (98%) rename src/main/java/BsK/client/ui/component/{CheckUpPage => common}/PrintDialog/print_forms/ultrasoundresult.jrxml (100%) rename src/main/java/BsK/client/ui/component/{CheckUpPage => common}/PrintDialog/print_forms/ultrasoundresult_potrait.jrxml (100%) rename src/main/java/BsK/client/ui/component/{CheckUpPage => common}/ServiceDialog/ServiceDialog.java (99%) rename src/main/java/BsK/client/ui/component/{CheckUpPage => common}/TemplateDialog/TemplateDialog.java (99%) rename src/main/java/BsK/{client/ui/component/CheckUpPage => common/entity}/DoctorItem.java (88%) create mode 100644 src/main/java/BsK/common/packet/req/SyncCheckupImagesRequest.java create mode 100644 src/main/java/BsK/common/packet/res/SyncCheckupImagesResponse.java delete mode 100644 src/main/resources/images/landingpagebg.jpeg diff --git a/src/main/java/BsK/client/LocalStorage.java b/src/main/java/BsK/client/LocalStorage.java index 9dffe98..96e0b46 100644 --- a/src/main/java/BsK/client/LocalStorage.java +++ b/src/main/java/BsK/client/LocalStorage.java @@ -1,5 +1,6 @@ package BsK.client; +import BsK.common.entity.DoctorItem; import BsK.server.network.entity.Role; import lombok.AllArgsConstructor; import lombok.Data; @@ -8,7 +9,6 @@ import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; -import BsK.client.ui.component.CheckUpPage.DoctorItem; @AllArgsConstructor @Data diff --git a/src/main/java/BsK/client/network/handler/ClientHandler.java b/src/main/java/BsK/client/network/handler/ClientHandler.java index f88e32d..29051af 100644 --- a/src/main/java/BsK/client/network/handler/ClientHandler.java +++ b/src/main/java/BsK/client/network/handler/ClientHandler.java @@ -3,6 +3,7 @@ package BsK.client.network.handler; import BsK.client.LocalStorage; import BsK.client.ui.handler.UIHandler; +import BsK.common.entity.DoctorItem; import BsK.common.packet.Packet; import BsK.common.packet.PacketSerializer; import BsK.common.packet.req.GetDoctorGeneralInfo; @@ -27,7 +28,6 @@ import lombok.extern.slf4j.Slf4j; import org.w3c.dom.Text; import BsK.client.ui.component.CheckUpPage.AddDialog.AddDialog; import BsK.client.ui.component.CheckUpPage.CheckUpPage; -import BsK.client.ui.component.CheckUpPage.DoctorItem; import BsK.client.ui.component.LoginPage.LoginPage; import BsK.client.ui.component.MainFrame; import BsK.common.packet.res.GetDoctorGeneralInfoResponse; diff --git a/src/main/java/BsK/client/ui/component/CheckUpPage/AddDialog/add.png b/src/main/java/BsK/client/ui/component/CheckUpPage/AddDialog/add.png deleted file mode 100644 index 3697b352f6ec42cf8069d0358abf59ef407f8f64..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 14292 zcmbVzhhI}m(CA4*kuJUW08$i?DjlUHbVC&s5UwCiKtqw5=vC<@pdv^SLJ3HdjtEgH zR|J$$rAUN}bO?eFsqf@|@4Y|Z;|ITxGrP01v$NArqMeO78?z8I003-Agb4}&py0ny z;0y!!u^Tyh0DjQjyNq-=1OCLE`6~hZ&J=>Ub`Jp9yJ>%rr;6;t;6p*QsSDaZ*asbP z^X@GmA|m2~-<^Pa-Zw*TT?oGGo42Va1OO5M(!|&y^5w>CM8_@1`;_gu{9c~N5d6d| zCRRszk~{tT1p1zfnmi>}t%@1EtyIcfyiyWndv9Bv<>GY%czJl~99VB~;`vt)!alb@ z5*wqJj=g6;v8pT<+#CP?#Xb78v+&E#3#QtwOJ80$?CE^D7QNAAgo7jh_rLgO0!cPT zs5wnw+{4sL==h#g-31l;oTHS}_^LOok?7LXLwQe06>%44J*bl4@toepgQb2+f&?Fc z+6jaXh@=K#2hC5X%ZNV2-V)UdvhN&)AU^>P2nWECc5>`azC*SlvwPmLi^CPXhZ{TV?V}8%0s%9>e4aj?r-9g$}5@Wp}cnD77KQJIFd1`qYl9caPPn8gVmxRJ7 z0b~pEr+@Hx%{M^CugM4H@xxoNb=H)0t4f*2*tafM&nhXi-+|9YWsEYi0ECD&2qTmc z!U#Krja*S%E$hR4##&;Mv7a$=m(_60UJ!}uSw6h-!4*W;`o3IsopS>#Obf=J$^3u? z$-*I1{eT{`8yF2$mWo{wXAR`dOJfM(CrGsNP%o{FW8q2w9OFk!#yUflVa;jQ=DbmW zHitHg_H(qb@hY4J2piiYUd1aP^W&V>tK6R9#?QW_e`y;v<$3M487fr?80A&NJkN;x zA&zXXRjyvYLlz+iqKwH8E;r@UW2OQXLbNHGWJjV-{Yr%d3(}OhLKMVrWRyD919sC^ zkTk#tRx2|*_ncvyhhmRXrQGl|4%9)3@d5r1KjBx7zYzlvjAVqPOPc_debcVu!8M@5 zVF9`SYwmLH_kBx`uxK8t0fmk1+p74A*&9+s3N&snKYfB9`GuFIic+k}miV5(ad_6= ztj)DTGoAFf7dO?_A0rQ02N+}}G;-7c|2NebZ;T;BGt-di>R2ps0((lgnPP2<%MF&I zFpz31IOpSs1$&F?d8m>h>ILlb$S)T~wF?>}qIWSt0**Z!L?(PH0dMymYS%c3-OuPe zn&22Rt^B+|bjE(k;5%!9@?B?p300Ckaei^rq(_PrR;P;_^}2!|JM!f;qzIXf%uA6V zjza?${;5nvU4(DFImesF!@I4x#Gwhk2Jgk1S$45j zD()=!Y(WSmDS=E4rwgIqepq(1@%#lD-f`UMIdkASw;@8vYV`1T3Fg(VwKD&Hg;ACm$jUqa5}2V-oY z;Yl_osPi>)gACXC@)PD;&(uw80ycDUX&xu2=j#mDFSnnRGcFZN3<2ngKyq^HWtY|V zL(D$Z*G#TB>KcIl!bg0LbvBWcB3$i+95GQ4XsOC4^hPZr*6kBrSJ6^9p%pQb%>#bA zrB_0&3`N3a8R5TlVO>Wu)!)a7Ul0pDc=B}zRbOB#*n>3seP}rGTwW=$*>2L6zXsn%u1FwJ%cYP2+(7kjNJX=_$ZyP zrLPv#0&OvoEB1E*8Yi^L${5>>@ICuW1<*}kQzZ52X&gVr&dSyM4O89uI#HD!!Fo|b zh25nBiF|pA2e`f=3nqLjw~>+h>izxOgJN_wf~jj5VWh_|4u+o&O@oL>#2TVlNxht( zlkwnheUj|uonr2*27JKA4g=W`Inw0+_z^zUxdu`rni_z)l!??B@WFd|Dm(Eoy!{co zEZg?H(TL&;uEW8C*>ic)7_y{4oS1Nk%zJ%Z?_lXE5%)EvzmdI;BjjudWw~(EjWgiy z##>Z5v(p;z0ylnqMvTC~in&)RrjZ_d{HZ7RVFm3@PtPNIh>|7o1{{SxNgA)g~{6BNEg;jiT? zFDP9b+YY9-);qN2BdY!>QKoA4UMDSNnM1gH53m(y77%L;1{``uF&+Wl*G*hYBni-3 z`1$t4&acxvI~2>VfZm2;fe;^w-~kA`@S(Y+pVCRv?xgiD{rAU_+3M$GwC~)Q4&%l? zhk3|sMDfpRO`lE1%!wbGOZbJ!0;k4Drn8S*A2f!Lq7Pi3uHaMe3`uv^HcJ|$v-p&D zS~JF39X+~!R}cCUF?GjDsOlQA9JzM6_%P&Cs8GSF#P2{$vckMF8Rh+__IR=U8}c}Z zbwGBIIg+KOt5qOf@_BEd_{=E2FcM0YT0t_&x6ER)kiNPm`@c!^3?xZA+&H-ue{ZTp zc@j5oO!mg#_<^qsy1W|9!8x~Ynbd~g$djr55Q@LCRIEITn)e~q1l#N=e$c_2KGfoh zKcCHIo7sHlnY#ZOs?s*UuYBkQzp`%LUjGN7cu_`WsgtR5l8>?bzsE?Z&#Vv+iIZX_ z$syR@R_%*YR}t2u6ly@}-&AyAkW$l!ND>2lnBQw;L5f6pf|6&4#2FtojqKK)v6Hig zc3K|MPyXAQ)96;{P$`Y^;EX@7ajDa!Jyj~~g9BM)Ub&;J_ZI%$pVDS+Xe*8yP(|1d z(@VZ0sv=s>;LP6w)UI~nvY>U*1QLf5An#Ej+J$`gB2)tO0AP7&TbHL;(BT@u`|J zL+_^_C`?8X7rQ+W)(JBBo%iKzqs6GVgAzC7K6ZOFSSP4$uK>KanOEGMcIij|rn1$| zc@D~l^-D(f5`SsuH~Qr|{EZ~0Cv=4rFCa;)apD`9QCct1$4XKsu4!qtoLHDJym0SBI>W0NU~G*#Y2&8elrIp=!po&ZpNw#6V<%^ z7*C95xMM1x#c?*?*rX?wxWgEH8L6+6vRR;5#}oORY<-UHCog_TAlBHVTb_Eoi^q?F zVm;sYAi)J#H;m-AIR3^M`GCsuYBT3y-){@+yGj)8ZSO0yq2hJckN2{o-iT6wZGNNK zP)OZ3@}Qi2Lp~-TL0oz@EdcSh#-b_5SWCH)JJepB@JTjHb1+d%aW$tPVyiP_9+mxl(b0>>qenuHo`kme`FyZ z@VM&)#R4h)S2DNiSttVAqHoh8p<0s}Q_DAqT=RW7I`bDi7xV_pF66P#7{xrPk=|t7 z`#che6I$M19!h_)gM4xh87m0wyb@zxBVEJj>p0Fclv29nL!A}U(IrqK~=3-&EXj6AN5(q zY+&wpN6aXA(^2!Tv&j+=+}NxH@$|~HHRM_wUL%+Fx^c{t>Vwax$8ADZsBHtYqgIEo zm)La8fb&zGBXeBj>Tj-=C^z)Y!I39#nx45XZFEO`Rq*Ddv|c%u%Z?sm_wcG)^+dT}>Rk`n_+0 z`2O8K6q){#FmmvX;Ks{?Q^b%N4&NkDoWE3d{b658%XmcMmS@{S*PG@HcK5N~#*{X%VMU|O$o#PIAK_U_|oCrkhKW_>Yg zd&gjj&bpE7py2HNyFG$<-(VT=+QFR98v6W9dW$7ob3;5mglvn-InU6&e%^8)PPjM? z<=`|7|C!YF3B*VG(H)U^}G0)w?}%YAvboF~5Yp!1o4F5nRjt>=6dy^?6;3G;MK#LfSgvBUs@? zar=ASyscL}y<@RdcAWGky=MQ6CXVNp^3;yQc>RlMGr<8UANSlPhEz`SE$}O@xan3_ z5hI20y7$r(YFehWLEhV&a028pMx5KQ_h&-aml;hVqGH0<*-P^Zp7{eo(n#xi`i)6( zvV4qE9p__=Vj>9A85N`9%KdqJzHeG&dvS)Xa;q_(Y>uC8+55w zVgXZ?xOL`X@3+=3UHHu$v#EK#sC7~G&S!6Ls)zTTor5r>GGeXoYNfz6W;$t_gKX?2 zUuU`bm|*#-OGggS0(4E~E*5D)%FX0njSHJc@kJYwFipIE3rYysw=2YayvHqmNW^Gi zvCgtMhQnM=wa6a1(CWWyGhfwZyukR)&D8bg8Eqb_!n>`E`?`K1dlCwce#{{(+uqv} zs;uiT-rj7C%0hJ66&q5G=T%9yD)KF%cn|m`_8uWf9G!^ET9?s{yXOdnrs~#5@^Peu%jW;qhGZWUOYV{|*OlzFCJD&Kk+wzxIqRu*Z z_x{Sw^@;v9<;1OthuzP?hwRcP4@KcIKRqtJ%V=b|hVF7_m`Q(oO`-4;KK5MkVOUo^ zFnKPz3O$paaO!!OYD&Df17h;$8l2W!%(gh~Sfr|Kyp7YCLTWjt5tCJgWN;-_q_I zoO>^?sxZ>_M0TZM5b3mL5c_aRe7@ZdzT>5OTjq3+_?DS ze-D@9h4V44OGV3cy~`QPbfXF^*!UzHFChMGzER>Hyz}mw)^)aOh3klzIWfzl8;)#6 zLkfR*Ce4wyTk1AhzJNvS-(G@ups)M``SXba8)rdezLI{%k%>MTHaepM)(|mC5Qm%| zn}y?j9Q8#1nfBXC2D@@={LJ|W!fgU|1T`QSI-YJ*%<&nMZVuiPg+=(MPs2i_0L#{_y#oH}cbj zrlr|<-Lh5$WMRRnHpRB5T=^Jy7*U1NvkX6QSl!rg?RZ4>%Z;0#R}i}5n%Dy1dCTm7 zW_d{y_jnu4J#sZ+Ay#N;>_H$JiW`;O!77`}4L^}2+24tJ%!V=TcE0_tHz>P7$8GU0 zgHcrbdHEgP5>?wI4L=5QQ})iwo&J*-Xj==MLt!-5z9eh;V*#;d7-`hNjL|Za`}*Vw zw$@Zm5-IvykW{-$8c4GNa_xaYIuX8n6Y)+ur39PHIGt5ja``ZF_s8HclhHk9%mjqH zIBR*B3k8utChgP?Gwt5w_uOBG=c0gY?c;d9ka#o~ZZy;v7C|GFvh_}u2grjcr+~*G zXDTOw^!giZX5{xF7^eOTh}2)yH;dp1aR;Zs0h_Xp^7?RKFU_imiQb5+ju5w455$c+ zm7bhqIX+3g05k*a%tNo7KN6jbvohfNgWy^2O74adm!afaZ2!D+UdpJnMxyS;h(}83 zB#LbS>mt8@4tsPev&5aowNhW=NhY3ki$hW$$ z3k!b(XrFO0q#Pe^vym8#aQL5X^sP!Dws&W9gtmJ#>5URcPG!XOB#}4nx}u@_xmI7D zsC>PMexg@g2nqL%W;ZU8CLv(R&&zR{2!{K{IUi$aIw2RlVT z>U3|-p2mx`s)Ia2c?>1m6qz$#UD&@nOK(&?X3enl*;hO*auSQ zQ|g$G!}C6aESbp-mrQlaod?EWH>OD=qjV-9ug&u5iG0KXp}AnY2`DHel1QO{Y|jNa z6P@^gCWG%8*bxw8=M$`lsoe0x4Wwa?qO&i=ZfduS9s_T>;TR}qjV*n6<$?980XE!~HgX($Y4=51n`bVOZV-#h@)4 zU5LP`hszujr{Aq=Rg?hdR<;f6fDC-If?v!W>tsd$e-Hf*;>9S_G!c3V@)|3);kuYS z0UmoJK=JQ)g-aoY-sWM;!JGH~j$>ylJ#pj)H>gJl7e5kHL22-GdaCRm22m+UI)%Kr z!B2yrWRAZoMlpC=dfx5X${ZP^ovcDw5Gb>g_5J*{?Lf}8?X@L!)|s>5?!eK!fE&cV zGHSb$1+$?Lcl`1WeL)JiM+XA#4kV@I!`4+646ns14-S8#cV-~brkL^RECYp)$Sh;c z0{WoNq{v{1-9wxXh$~)Zkh*C%#uClq`6#cLI|DvejK6|yCagZHQUYXgVlbum7s;En ztv0o)fm;o{F~;J24G6q4b*6%jW1btpjq*mA$bEe%PBN&i;4Z108#konl#vcp_+8rqU5;6sZ}TRDgA;u1{)IQ*@e4g{jYrY#Z)spDALer`>O z>tbH~4JH3rh6|BZNwGikFjbgB$b|jSd_%LM-_I7j_$V-Av$|}Z&e^Z?rZwm>W)3za zp`Ro;E6!Td-wLDB-Kx&?uX=uVPP|vhqq>Z#vH?Ri6SmZIb%fonPLm3HFEY!>TC(ZF zdZfjB=T~vlR2DT(WnBAh5<`W*f0&R;Q}M)5&>b{Xw2?Q2odWaRCtt^(;l@S)T2S#1 z)7LqFnu421t%@A3)R{fteRl^uDY_tv1*!JrxtW}l22q`?Mr_Oe{jY;?w)$SMT~D$r zkUhp^v2RR1%pNnu>xi&lXIK}>M?6u2&sJVAmhtv+q&JcovoP(Tw@c^7#PKvT9lo$%L^mcFIDAo5@{++gKde9V=uGO4HEx}2*NfH%$xyb7gIrC|p$k7xd}3I2l!5TmD)$bOCh zK1xo*D*Lj0$yfUC$2W`{mr|KuRpN=2!0bs5cdR~J&5;Quf_p;DJ z(84ZSOuf-L+^?iJisCW(b1Y+XZ23@!Yf?)mk331XPD z9U#vd%Z=*oz|Hq)&$q~rjl_7^W-5*S}G4dz$6?5Nyh3h?CZ{XzvZaHFPTD5c_ zghxMbLhK&ldgFZo1v?bux%V2N`Z$la2bsOdYD8}V9?U8r)B5nu(Bw0VkWlckBZ-6P z_@ji*#1kMIf z3*fNfL}qiKuvU$toS|C@HpS8wLZ|0xY@>In+`(#jb4pYXS`$BG{|qOhP2}l`Ud*m^ zE+~kd1>?Ed2<*fUqHOihEutjxAqYpvFT~5VTs;r;uK+|k9$E_ZF@{N-^~-R@ z2)h3pV-ap^w2~QvJ(=+4yfyb=3s)t)rzG0IAm>VH8W z!cY`v3yEh~XMbsPt=!z=k{%F~fMz>7r~SM}!Ee3L9@LtSfYGJ>`ZA~*XkIGvkhW*m z&%`jd%4mubP{|l^SRXJAIkmd>wyb&ZCn#Yc0V7O~9m^G$h(o-caW-n$D$ud4)5UfP zr7l4kfoRw?EYEHzw!LzL8}!@tv1@vKSyMm6P&cDxLR4>U;HJXWO1PJeL+Op=)c{Y( zS9nWGul#VL`oLKguKaF+8`iFa7c{8a~2O7t{1REoqL-IQ?1bAQV_%39O-U!J8*-xQ8Z41rT zSa1u3g!uN<7G}{LnK^c1<1#!d#LZE8ot4O(2NR}wLY1I;*yH;lMVxA7H^NO-<3mr_ zJzFdPGuJRZ)OPg04yaq_kgKzsAa}^m6g)asp#V8o=)3fDoWd0(YRlr_RYdGlm@j;#yQ=#N3+Mrns61*Weg?j$qFvn$_hb zmnqB@r9sI$Bttw8qv@GnJ&yr^-;~x1Kx2A0mbP{{neg8zPYCawzwEFNOF%n+OUvZi z!r_=>m+_7L%NFfypytQ~^IA4US+U1biz>;ZH{r-d-JD$>Bl!!}3)ZVMoGbG}a{+b>7-^atd~2IT^J#C2275v3qLh=t zL&@&R1UCX|lFvHdD~6!tiwb%Ztx$8+cy=ayvP8!_r(I?_7nwS1e4k$W- z7Cn2KDkw@fK#QkFpYua$k=T1t;?`C3z3#1`Qx=Um+4OTjoEW9x;pCafP@3=-bV!0u zl|J2!-IA~w511;7pzqj{uvkOjM#E}Bi8o)$7#bv4n?QgSaaY^~l%`POsh`|wf#L4* zdi$J8B~WoJu2aND@dJa&HY*V)i0(1lFKEb6ms(??p; zmT)|HxJ-9&He6S)9XJ;x3J^nS*Sz4?6_QdA(hRdx{2c^PZnqcq1LW zIbcwqegXE=_4vw@TRMY$)^|SHvb27xxa&rvPnbt+VVwo3f(yQ00DP1TPPsT^O21%T@3L9AMOx4fW)t z9D}hc#mqC0HnGH=eq9KR%7s+dX0xGyP>3O(gB!d5Khe7{D9AVELwwL&)@qzNj7o}1 zVlW?vuVSSB#|c|&-l@q7{xH8=hg@?Lhl#y`*g3o)Mkf0jZ?*XgVLJrs(}|uA)t;N+V?MD$Grmd_jZja)kh^HEScOp4B=}RG*#37LQx#h+WxN33A*s*jk{gSa2HA># zc4*%}O=Tp@lING5Piy#;ZMa+Xh84!g4dZCm*8~rT&xinsMI$3+iiU3ATu#LdWMz?)4))^K@s+lQshgV8)_Eq* zcaFP%tGBeG+Q5non563H0uxNWL1s~p4cdeExm$+6Zap-U)mVj)`@p;7$44mx(djsw zf#{q;bmMKj-#%_gh%Y{-+tQf6c>$t%-nSISkTK1Eb@oNcuop z?wqw%k{xuf;8;L>u`!EJIPMLlCH^$A=*N*@;?KSnuxraViRs$Z>U1}bM)yZ2oSr>Q zy`+A7&bR5q5}1e!VCE+(l)ppvEt&1F#Vy?blZSUJ`+DS|ACUCrXE0aTq>^V2HSS$y zD`WZT(+T=++Mtf3!C`B0nUjy}T6~Z%gS6z}7Ux{8GjGj_vrR+d)(Dsm-O)m71tDCo z^BiOMgbn|pjah=SfD0=21!F%so|KHqXJK{04ITGtw4RS~@{l^YA_{lMbsQ$(Nz_n z_hdFP*}|A5hf`aJCn6^I3hxS9>ZPT}Ij?ff8~$rN??&Tki}>#^bk|{l*ZK@?@>Q8y z)2OOZ8Puiq>f-WCNmP#eUn6hrIbEIDu+sUvGVLUqq0U|ZR4MGAIW9v@4lWjKbwf*1 zfzO%NmsF1EjMlun=}ivztm#j(R?F;`U|S#i^0Mb@)VGGm-9Pr!Y226J7T+t{ezaaK zCBul@XTshjRaaH79+_9D^+Nc$3}r!#n8ABmDNeP!>}po76e-8WGbCAud7d$LP;|7 zZcKk6y$i#U`R3zHJcAJ9bt77(W1#0)Md;P88uVFT6-WbIW57I7JmB8n(I;Bncfgv4 zZgZh5C6E{_)h1JVsAp^vH{~ltD@X*UMY{cL9>!=&%w{ES z3S63p{a3SzeMGI-Fu!i>+E?`WzTtMhw7C-9-Vm+OvzXeQUUdn~GYVf}Q!hYU`Jv@L zaYoEvTf_CYsBJ|48!YIjWvwv@7NKz0LoX02GVxs1ma%;f&Y~=spkJEll@!>#u4N6? z<$GBs-jx+n&TaS@tXvI&m8*XC?D*#0Ujh*KELyqguDER6(Ex7*%zg))wktTVYh4pb zH>n!DgFxMKXH}AkTOZ(UpusdnThpm&S&B99Q{~_qbK^vj`M!bcp`4q8D7<&#mfocW z;rn^!xHqnhpitFcbOsLqEZ0?zUFwb~e);1v57JtlE+(IXowxP@r* zqHB4TJ*o#L_o+E*cNk=SgCrkO?dNsvhg?it{{rh&6r1_Jo|mc*yaNMLU>77i?H5z- z<3*d{@}yUIahYMTYN)O13zPpYhNl-D7FG0}VGqo0$b=IZ8xZO8=IM_vEyR(2-1UE9 z%Qe?_x34zjAv5y#^h>l4a#tWn*FCR3byQ*v(BhhVf447!5@~__eeF3~>CW!tbKOo_ zO;nE&`msBrab}x$=JjRNZ&`>hx8cvlv_8yvwdO3L)w#s2K*#PSTD?^Nqsdg*0x3$MYka8Dx#?_~`el8Ljb)H%86{E#qP1~_xg-KRmpXv=19#4F3$a3>2kv&n2$4+qoAI2H_eL^^N-yjWniSDbut!Pld%HVti|) zp8@eX<=@~MU$^nfz037wX;do^+!qAQn1LM*iUx@+KHz5QVxCg#OKYf?R3yzmA~W_< z-Hl@UY7~dM<>>I5lhD>2s%mLXE8`^G@-tHLKK)8a{xZ9}^9*!7vvd(|s!a!8pL%>v zqzJ!y)#V$L@*#^k9386Q*vgU6#`u7pr{40EN?Jq5d(aTBhxH}m-+hqLnC2lXcBc!5 z^+n%PFKE7pxR|Nb{BKAc`m_T+Lx z!e?wg1K9QwJC%RO=8v-U#^C%y9P_@Er{p%jiHV+#YmgGb;0pf6al6ju04!XrmABL? z?UgViWAz0anT?!t1Xnlc5_kNdc@OmZ6Ffr{<7@{SfWqCEF#9X=Z+-5yHAq2iP&V__6m1NKQm zSDCc8K;&l-IJP*_?V)a+(16%ilKJhUOP1^Q_&BTz?eHZwXZ!CfcYEkrCzvB_nIpUF z8p9V56Q5(|YiDJ<3pvJLqEbT9Ypk11J%5Po57jG1??#Udikdm|$LqV?v#9Td&4G;Y zw@{MWaQ!J|?DvQbInl#4UprjZy~N;ul^`h#os&Cx;E$SN5lL>L9}VJ0+Omg*X$_C{ zbg_{tP$Mafon}Xm#u{6p+J9lfpIU@zhn(M@@En;JXY_L*5PD&9-0@fq)gh?Q-s~IH zrEsZyPyX0J4OP8y=W0zl(0Z^`C)NX00hM=iy-$S#rAb-F$%$R#xqQ;Z!o9gh)HSfL z#dKmcM|aBL0*`~R6{8IxCUY|7@09{R(EN4uo zB!f`#gG!G63M&SC54$}St<%AVm}8BGQG;NhKsa( zG^P`=v5hUGU<1>aZDpCxt>-+?VR?JQ-%;g(bl0tp=-s@IpxQz?U++~}R%tOsa#Jkl z4FR5KzRMbqnSSyUl$vCQ{nhF}W1J0$uDvBLaBt~y z80X*PM>waYTSV_}kIA6K&lnD<+x{=fim+xmebj;Q{NZ12^X{H=?gn(ofEI2saaYsp zwo`r~pX=j!6eh><`3Dz1$e+xFa@PHsG-O7;1G_k%Qd!=ms#*yV)B22G2Q_yqA6G7z z%#_+!&YY!4dNOVE$GUmThe%R5$$v_MYVM}M_81K;+GiJ>rpJ1q>s(f(nnid$CrWRlpKb{-R#|OVJ z=dzHd6gjLS#W`+vTiWwsQ=EmrQn|+TO;K_o#xT(aU-AszL?BKZqatx^U|wR^LxBV z9yZk9mH+;cIE@ttdzIgV&9h%F5L+-yrgFvQ*H~wmk8*b>f3Oj2F^p1K{t0ZDS%mQR zy4k^_E-jVw7v=Rof5CcV=fJ^wO2Cw#DA}G^IPW`y-p||%Z)IrZY`v$xDLLzUJ2?^m zTVWcahP{E+$LeDS=Sd_1CCJG$^^Gkhr)28l*E`CP&c{{bmW|oFmTNZTw5KN>4|h#I zbPV5qAW6PdQZK*45~u4F^X&^=vy}B(l~PNF*!Ei~9nM8x$k#Ywh+JmcKaOuxGB!UA zxmhbQ{7gRyE~Mj2Jvq)CHU!&$_xe6dT5zDEizsNBB z($Uyu_r}>!CCU~)pH9XvObm8%h8hkwX+Hy-wAWcLclC8^KTXs-vq6_Iw}>+1l_EW4yyYl=A^`v zH7c5pt2zBh`P`L7Yc4NAor*?=feqmPp*j=;l62|nIToNgP?K!M5zt_ISWeVJ=2)B`;vY67 zsV`4~kh~<3w_cdH$L;qi$5%gS0UBkciHmr`M|onWi@Jq%%ioR9mNf9@N6&i7O3Hrm zVWR34DVNBl;3iy4cd!e{wflIDH-MdC8uWyB(g36hm|=}MOAQ5So(kq#dEV=dmpA*U zvYP$`Y-^n;8Reb;Dm*^oe?vTE*bJg!+)~^)oqw6g4a7Xe$jQh06~yYBYD7BQ1^9_` z=FLV8KByctPZG)2z~+Z>y?o^9ClHiqieK|*ffIiC;22()c5@UwzUr^UVDp~71;^Z| z=m!YP#;Itepu7aM*(RBg3Nzn{EtGN0&DZjLxS@qfdV<#`tf)Q6M(5#Cq~|eM#wv?^ zxoa|L2-)u~E3T;n?6Oygx>!S4Gy9Nf(p@=9Vac{jpaRaJHjx-ee%@`{C1iFZR3=1e zGhY%3h(KSO>im5!3Zt1aqY8a#K4sy?ymTJW7#;#&rD!>$3E~hMg%KwZ$%l8?hD>ou zDv9W5vffKxmHwogsIGkL_CXnqG&Mk>CynTaY=B-6a^?O^zO!~fBI80XtUkMimvgoeO+EA)$&B)a6gB5Cb>!|U zu9GJnM!mFva@ZVQobbzJ^|LHM({MQc8nz{CNGgM&{>bulnm7n9^34UP*w~}{j!-xg z&N^he*qYfm^zZ0!mt{5hKFft~1&tU=#jv4VUs(ymedbmH?ZQUEF*fj^#u@-SXKTr7 zUTtV3?{|geVz8N>x&-ru*>;ynk9~$3Sv>o~E&}Obb&D~ zJWQu9yOI>ZGWqd0954NQ2vMxHqRz$^IstuNKW}+@@-+qj0fgSSk~j~a5sv(Rdz~pz z;Dv+b0DTQZ+?4~zc;1!!M?b(9pGemL#Ml(iWIp<{rxq%+Zf7}uVr16#z^jY1^-igw zc#@Tczak4D-`kE)O$?_C7dXBrOhP`HhT1Qnss^};vx+@I#Ojhz;W~*68iZ(&V4tZB z2i8DXAZwuN!P2j;V7frywQXR19T16D|CtfjW4N2rHODq{#r3H&K@uGQ%i7CSwQh5H zP7c&J%zmNs=z=(hjlYLan`dG?S1eBVNyDdmJS)R(fA9;>#YK+~e<>gLd^^?n-@lp$ eN0NXO!^4)yiVt)rD&QM<0MgXPq~@~cgZ~36lhUgI diff --git a/src/main/java/BsK/client/ui/component/CheckUpPage/CheckUpPage.java b/src/main/java/BsK/client/ui/component/CheckUpPage/CheckUpPage.java index 6231715..7f1df53 100644 --- a/src/main/java/BsK/client/ui/component/CheckUpPage/CheckUpPage.java +++ b/src/main/java/BsK/client/ui/component/CheckUpPage/CheckUpPage.java @@ -4,18 +4,19 @@ import BsK.client.Client; import BsK.client.LocalStorage; import BsK.client.network.handler.ClientHandler; import BsK.client.network.handler.ResponseListener; -import BsK.client.ui.component.CheckUpPage.AddDialog.AddDialog; -import BsK.client.ui.component.CheckUpPage.HistoryViewDialog.HistoryViewDialog; -import BsK.client.ui.component.CheckUpPage.MedicineDialog.MedicineDialog; -import BsK.client.ui.component.CheckUpPage.PrintDialog.MedicineInvoice; -import BsK.client.ui.component.CheckUpPage.PrintDialog.UltrasoundResult; -import BsK.client.ui.component.CheckUpPage.ServiceDialog.ServiceDialog; -import BsK.client.ui.component.CheckUpPage.TemplateDialog.TemplateDialog; +import BsK.client.ui.component.common.AddDialog.AddDialog; +import BsK.client.ui.component.common.HistoryViewDialog.HistoryViewDialog; +import BsK.client.ui.component.common.MedicineDialog.MedicineDialog; +import BsK.client.ui.component.common.PrintDialog.MedicineInvoice; +import BsK.client.ui.component.common.PrintDialog.UltrasoundResult; +import BsK.client.ui.component.common.ServiceDialog.ServiceDialog; +import BsK.client.ui.component.common.TemplateDialog.TemplateDialog; import BsK.client.ui.component.MainFrame; import BsK.client.ui.component.common.DateLabelFormatter; import BsK.client.ui.component.common.NavBar; import BsK.client.ui.component.common.RoundedPanel; import BsK.client.ui.component.QueueViewPage.QueueViewPage; +import BsK.common.entity.DoctorItem; import BsK.common.entity.Patient; import BsK.common.entity.Status; import BsK.common.entity.Template; @@ -153,7 +154,6 @@ import BsK.common.util.date.DateUtils; import java.awt.event.FocusAdapter; import java.awt.event.FocusEvent; import javax.swing.text.JTextComponent; -import BsK.client.ui.component.CheckUpPage.DoctorItem; @Slf4j public class CheckUpPage extends JPanel { @@ -172,6 +172,7 @@ public class CheckUpPage extends JPanel { private final ResponseListener getAllTemplatesListener = this::handleGetAllTemplatesResponse; private final ResponseListener uploadImageResponseListener = this::handleUploadImageResponse; private final ResponseListener uploadPdfResponseListener = this::handleUploadPdfResponse; + private final ResponseListener syncImagesResponseListener = this::handleSyncImagesResponse; private JTextField checkupIdField, customerLastNameField, customerFirstNameField,customerAddressField, customerPhoneField, customerIdField, customerCccdDdcnField; private JTextArea suggestionField, diagnosisField, conclusionField; // Changed symptomsField to suggestionField private JTextPane notesField; @@ -353,6 +354,7 @@ public class CheckUpPage extends JPanel { ClientHandler.addResponseListener(GetAllTemplatesRes.class, getAllTemplatesListener); ClientHandler.addResponseListener(UploadCheckupImageResponse.class, uploadImageResponseListener); ClientHandler.addResponseListener(UploadCheckupPdfResponse.class, uploadPdfResponseListener); + ClientHandler.addResponseListener(SyncCheckupImagesResponse.class, syncImagesResponseListener); // Instantiate the new queue page but don't show it yet queueManagementPage = new QueueManagementPage(); @@ -2289,6 +2291,8 @@ public class CheckUpPage extends JPanel { NetworkUtil.sendPacket(ClientHandler.ctx.channel(), new GetPatientHistoryRequest(Integer.parseInt(selectedPatient.getCustomerId()))); NetworkUtil.sendPacket(ClientHandler.ctx.channel(), new GetOrderInfoByCheckupReq(selectedPatient.getCheckupId())); + // Sync images from server to client for consistency + NetworkUtil.sendPacket(ClientHandler.ctx.channel(), new SyncCheckupImagesRequest(selectedPatient.getCheckupId())); String fullAddress = selectedPatient.getCustomerAddress(); String[] addressParts = fullAddress.split(", "); @@ -3442,20 +3446,20 @@ public class CheckUpPage extends JPanel { } String timestamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date()); - String fileName = "IMG_" + currentCheckupIdForMedia + "_" + timestamp + ".png"; + String fileName = "IMG_" + currentCheckupIdForMedia + "_" + timestamp + ".jpg"; Path filePath = currentCheckupMediaPath.resolve(fileName); try { BufferedImage image = selectedWebcam.getImage(); if (image != null) { - // Save locally first for immediate UI feedback (PNG for high quality local cache) - ImageIO.write(image, "PNG", filePath.toFile()); - log.info("Picture taken and saved locally at: {}", filePath); + // Save locally as JPG for consistency (compressed format for client storage) + ImageIO.write(image, "JPG", filePath.toFile()); + log.info("Picture taken and saved locally as JPG at: {}", filePath); // Refresh UI to show the new image immediately loadAndDisplayImages(currentCheckupMediaPath); - // Now, upload in the background (will be compressed to JPG) + // Now, upload in the background (server will convert to PNG for archival) uploadImageInBackground(filePath.getFileName().toString(), image); } else { @@ -3499,8 +3503,8 @@ public class CheckUpPage extends JPanel { // Create and send the request String checkupId = currentCheckupIdForMedia; - // Adjust file name to have .jpg extension for the server - String jpgFileName = fileName.substring(0, fileName.lastIndexOf('.')) + ".jpg"; + // Keep original filename since we're already using JPG locally + String jpgFileName = fileName; // Schedule a timeout task for this upload Future timeoutTask = timeoutExecutor.schedule(() -> { @@ -3568,6 +3572,84 @@ public class CheckUpPage extends JPanel { } } + private void handleSyncImagesResponse(SyncCheckupImagesResponse response) { + if (response.isSuccess()) { + log.info("Successfully synced images for checkup {}: {}", response.getCheckupId(), response.getMessage()); + + SwingUtilities.invokeLater(() -> { + try { + // Create media directory for this checkup if it doesn't exist + java.io.File mediaDir = new java.io.File("src/main/resources/image/checkup_media", response.getCheckupId()); + if (!mediaDir.exists()) { + mediaDir.mkdirs(); + } + + // Save each image to local media directory, converting to JPG format for client consistency + for (int i = 0; i < response.getImageNames().size(); i++) { + String imageName = response.getImageNames().get(i); + byte[] imageData = response.getImageDatas().get(i); + + // Convert filename to JPG extension for client storage consistency + String jpgImageName = imageName.substring(0, imageName.lastIndexOf('.')) + ".jpg"; + java.io.File imageFile = new java.io.File(mediaDir, jpgImageName); + + try { + // Convert image data to JPG format for client storage + try (java.io.ByteArrayInputStream bais = new java.io.ByteArrayInputStream(imageData)) { + java.awt.image.BufferedImage image = javax.imageio.ImageIO.read(bais); + if (image != null) { + javax.imageio.ImageIO.write(image, "JPG", imageFile); + log.debug("Synced and converted image to JPG: {}", imageFile.getAbsolutePath()); + } else { + // Fallback: save as original format if conversion fails + try (java.io.FileOutputStream fos = new java.io.FileOutputStream(new java.io.File(mediaDir, imageName))) { + fos.write(imageData); + log.warn("Failed to convert image to JPG, saved as original format: {}", imageName); + } + } + } + } catch (Exception e) { + log.error("Failed to process synced image {}: {}", imageName, e.getMessage()); + // Fallback: save as original format + try (java.io.FileOutputStream fos = new java.io.FileOutputStream(new java.io.File(mediaDir, imageName))) { + fos.write(imageData); + log.warn("Saved image as original format due to conversion error: {}", imageName); + } + } + } + + // Update the current media path and refresh the gallery if this is for the current checkup + if (response.getCheckupId().equals(currentCheckupIdForMedia)) { + currentCheckupMediaPath = mediaDir.toPath(); + loadAndDisplayImages(currentCheckupMediaPath); + log.info("Refreshed image gallery with {} synced images", response.getImageNames().size()); + } + + // Update UI status + if (callingStatusLabel != null) { + callingStatusLabel.setText("Đã đồng bộ " + response.getImageNames().size() + " hình ảnh từ server"); + callingStatusLabel.setForeground(new Color(0, 100, 0)); + } + + } catch (Exception e) { + log.error("Failed to save synced images locally: {}", e.getMessage()); + if (callingStatusLabel != null) { + callingStatusLabel.setText("Lỗi khi lưu hình ảnh đồng bộ: " + e.getMessage()); + callingStatusLabel.setForeground(Color.RED); + } + } + }); + } else { + log.warn("Image sync failed for checkup {}: {}", response.getCheckupId(), response.getMessage()); + SwingUtilities.invokeLater(() -> { + if (callingStatusLabel != null) { + callingStatusLabel.setText("Đồng bộ hình ảnh: " + response.getMessage()); + callingStatusLabel.setForeground(new Color(200, 100, 0)); // Orange for warning + } + }); + } + } + /** * Uploads PDF to backend asynchronously * @param ultrasoundResult The UltrasoundResult object to export as PDF diff --git a/src/main/java/BsK/client/ui/component/CheckUpPage/Debug.java b/src/main/java/BsK/client/ui/component/CheckUpPage/Debug.java deleted file mode 100644 index 0e1490c..0000000 --- a/src/main/java/BsK/client/ui/component/CheckUpPage/Debug.java +++ /dev/null @@ -1,49 +0,0 @@ -package BsK.client.ui.component.CheckUpPage; - -import BsK.client.LocalStorage; -import BsK.client.network.handler.ClientHandler; -import BsK.common.packet.res.GetWardResponse; - -import lombok.extern.slf4j.Slf4j; - -/** - * Debug class to help troubleshoot ward loading issues - * This is just a test class and should be removed after fixing the issue - */ -@Slf4j -public class Debug { - - /** - * Log ward data when received to help diagnose any issues - */ - public static void logWardInfo() { - log.info("DEBUG: Setting up ward monitoring"); - - ClientHandler.addResponseListener(GetWardResponse.class, (response) -> { - log.info("DEBUG: Received ward response with {} wards", - (response.getWards() != null ? response.getWards().length - 1 : 0)); - - if (response.getWards() == null || response.getWards().length <= 1) { - log.warn("DEBUG: Ward data is empty!"); - return; - } - - log.info("DEBUG: First 5 wards:"); - for (int i = 0; i < Math.min(5, response.getWards().length); i++) { - log.info("DEBUG: Ward[{}] = '{}'", i, response.getWards()[i]); - } - - log.info("DEBUG: First 5 ward IDs:"); - int count = 0; - for (String ward : response.getWardToId().keySet()) { - if (count >= 5) break; - log.info("DEBUG: Ward '{}' -> ID '{}'", ward, response.getWardToId().get(ward)); - count++; - } - - // Check LocalStorage after processing - log.info("DEBUG: LocalStorage.wards now contains {} elements", - (LocalStorage.wards != null ? LocalStorage.wards.length : 0)); - }); - } -} \ No newline at end of file diff --git a/src/main/java/BsK/client/ui/component/CheckUpPage/MedicineDialog/Demo.java b/src/main/java/BsK/client/ui/component/CheckUpPage/MedicineDialog/Demo.java deleted file mode 100644 index fc6006a..0000000 --- a/src/main/java/BsK/client/ui/component/CheckUpPage/MedicineDialog/Demo.java +++ /dev/null @@ -1,34 +0,0 @@ -package BsK.client.ui.component.CheckUpPage.MedicineDialog; - -import javax.swing.*; -import org.jdesktop.swingx.autocomplete.AutoCompleteDecorator; -import java.awt.*; -public class Demo { - - JFrame frame = new JFrame(""); - AutoCompleteDecorator decorator; - - - public Demo() { - //JTable demo - JFrame frame = new JFrame(); - frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); - frame.setSize(300, 200); - JTable table = new JTable(new String[][] { - { "1", "2", "3" }, - { "4", "5", "6" }, - { "7", "8", "9" }, - { "10", "11", "12" } - }, new String[] { "A", "B", "C" }); - //set size of custom colum - table.getColumnModel().getColumn(0).setPreferredWidth(200); - JScrollPane scrollPane = new JScrollPane(table); - frame.add(scrollPane, BorderLayout.NORTH); - - frame.setVisible(true); - } - - public static void main(String[] args) { - Demo d = new Demo(); - } -} \ No newline at end of file diff --git a/src/main/java/BsK/client/ui/component/DataPage/DataPage.java b/src/main/java/BsK/client/ui/component/DataPage/DataPage.java new file mode 100644 index 0000000..59306f2 --- /dev/null +++ b/src/main/java/BsK/client/ui/component/DataPage/DataPage.java @@ -0,0 +1,4813 @@ +package BsK.client.ui.component.DataPage; + +import BsK.client.Client; +import BsK.client.LocalStorage; +import BsK.client.network.handler.ClientHandler; +import BsK.client.network.handler.ResponseListener; +import BsK.client.ui.component.common.AddDialog.AddDialog; +import BsK.client.ui.component.common.HistoryViewDialog.HistoryViewDialog; +import BsK.client.ui.component.common.MedicineDialog.MedicineDialog; +import BsK.client.ui.component.common.PrintDialog.MedicineInvoice; +import BsK.client.ui.component.common.PrintDialog.UltrasoundResult; +import BsK.client.ui.component.common.ServiceDialog.ServiceDialog; +import BsK.client.ui.component.common.TemplateDialog.TemplateDialog; +import BsK.client.ui.component.MainFrame; +import BsK.client.ui.component.common.DateLabelFormatter; +import BsK.client.ui.component.common.NavBar; +import BsK.client.ui.component.common.RoundedPanel; +import BsK.client.ui.component.QueueViewPage.QueueViewPage; +import BsK.common.entity.DoctorItem; +import BsK.common.entity.Patient; +import BsK.common.entity.Status; +import BsK.common.entity.Template; +import BsK.common.packet.req.*; +import BsK.common.packet.res.*; +import BsK.common.util.network.NetworkUtil; +import BsK.common.util.text.TextUtils; +import lombok.extern.slf4j.Slf4j; +import org.jdatepicker.impl.JDatePanelImpl; +import org.jdatepicker.impl.JDatePickerImpl; +import org.jdatepicker.impl.UtilDateModel; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.swing.*; +import javax.swing.border.TitledBorder; +import javax.swing.border.Border; +import javax.swing.table.DefaultTableModel; +import javax.swing.RowSorter; +import javax.swing.SortOrder; +import javax.swing.table.TableRowSorter; +import java.util.Comparator; +import java.text.SimpleDateFormat; +import java.text.ParseException; +import javax.swing.tree.DefaultMutableTreeNode; +import javax.swing.tree.DefaultTreeModel; +import javax.imageio.ImageIO; +import javax.imageio.ImageWriter; +import javax.imageio.ImageWriteParam; +import javax.imageio.IIOImage; +import javax.imageio.stream.ImageOutputStream; +import java.awt.*; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import java.awt.event.KeyEvent; +import java.awt.event.KeyAdapter; +import java.awt.event.FocusAdapter; +import java.awt.event.FocusEvent; +import java.awt.event.WindowAdapter; +import java.awt.event.WindowEvent; +import java.awt.datatransfer.*; +import java.text.DecimalFormat; +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.Calendar; +import java.util.Date; +import java.util.List; +import java.util.Properties; +import java.awt.image.BufferedImage; + +// Imports for new functionality +import java.io.File; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.nio.file.WatchService; +import java.nio.file.WatchKey; +import java.nio.file.WatchEvent; +import java.nio.file.StandardWatchEventKinds; +import java.nio.file.FileSystems; +import javax.imageio.ImageIO; +import javax.swing.JColorChooser; + +// Webcam imports +import com.github.sarxos.webcam.Webcam; +import com.github.sarxos.webcam.WebcamDiscoveryEvent; +import com.github.sarxos.webcam.WebcamDiscoveryListener; +import com.github.sarxos.webcam.WebcamEvent; +import com.github.sarxos.webcam.WebcamListener; +import com.github.sarxos.webcam.WebcamPanel; +import com.github.sarxos.webcam.WebcamResolution; + +// JavaCV imports for video recording +import org.bytedeco.javacv.FFmpegFrameRecorder; +import org.bytedeco.javacv.Frame; +import org.bytedeco.javacv.Java2DFrameConverter; +import org.bytedeco.javacv.OpenCVFrameConverter; +import org.bytedeco.opencv.opencv_core.IplImage; +import static org.bytedeco.opencv.global.opencv_core.cvFlip; + +// Java imports for concurrent tasks +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.Future; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeUnit; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import java.util.stream.Collectors; +import javax.swing.JFrame; +import javax.swing.JTextPane; +import javax.swing.JToolBar; +import javax.swing.text.StyledEditorKit; +import javax.swing.text.rtf.RTFEditorKit; +import javax.swing.text.MutableAttributeSet; +import javax.swing.text.SimpleAttributeSet; +import javax.swing.text.StyleConstants; +import javax.swing.text.BadLocationException; +import javax.swing.text.Document; +import java.io.ByteArrayOutputStream; +import java.io.ByteArrayInputStream; +import java.io.OutputStream; +import java.io.InputStream; +import java.io.StringReader; + +// --- JasperReports Imports --- +import net.sf.jasperreports.engine.JasperPrint; +import net.sf.jasperreports.engine.JasperPrintManager; +import net.sf.jasperreports.engine.JRException; +import net.sf.jasperreports.view.JasperViewer; +// --- End JasperReports Imports --- + +// Add new imports +import BsK.common.entity.PatientHistory; +import BsK.common.packet.req.GetPatientHistoryRequest; +import BsK.common.packet.res.GetPatientHistoryResponse; +import BsK.common.packet.req.SaveCheckupRequest; +import BsK.common.packet.req.SearchAllRole; +import BsK.common.packet.req.SearchAllUser; +import BsK.common.packet.req.UploadCheckupImageRequest; +import BsK.common.packet.req.UploadCheckupPdfRequest; +import BsK.common.packet.res.AddCheckupResponse; +import BsK.common.packet.res.AddPatientResponse; +import BsK.common.packet.res.RegisterSuccessResponse; +import BsK.common.packet.res.SaveCheckupRes; +import BsK.common.packet.res.UploadCheckupImageResponse; +import BsK.common.packet.res.UploadCheckupPdfResponse; +import BsK.common.util.date.DateUtils; +import java.awt.event.FocusAdapter; +import java.awt.event.FocusEvent; +import javax.swing.text.JTextComponent; + +@Slf4j +public class DataPage extends JPanel { + private MainFrame mainFrame; + private List patientQueue = new ArrayList<>(); + private String[][] rawQueueForTv = new String[][]{}; + private String[][] history; + private DefaultTableModel historyModel; + private JTable historyTable; + private final ResponseListener checkUpQueueUpdateListener = this::handleGetCheckUpQueueUpdateResponse; + private final ResponseListener checkUpQueueListener = this::handleGetCheckUpQueueResponse; + private final ResponseListener patientHistoryListener = this::handleGetPatientHistoryResponse; + private final ResponseListener wardResponseListener = this::handleGetWardResponse; + private final ResponseListener callPatientResponseListener = this::handleCallPatientResponse; + private final ResponseListener orderInfoByCheckupListener = this::handleGetOrderInfoByCheckupResponse; + private final ResponseListener getAllTemplatesListener = this::handleGetAllTemplatesResponse; + private final ResponseListener uploadImageResponseListener = this::handleUploadImageResponse; + private final ResponseListener uploadPdfResponseListener = this::handleUploadPdfResponse; + private JTextField checkupIdField, customerLastNameField, customerFirstNameField,customerAddressField, customerPhoneField, customerIdField, customerCccdDdcnField; + private JTextArea suggestionField, diagnosisField, conclusionField; // Changed symptomsField to suggestionField + private JTextPane notesField; + private JComboBox doctorComboBox, ultrasoundDoctorComboBox; + private JComboBox statusComboBox, genderComboBox, provinceComboBox, wardComboBox, checkupTypeComboBox, templateComboBox, orientationComboBox; // Added orientationComboBox + private JCheckBox needRecheckupCheckbox; // Checkbox to indicate if re-checkup is needed + private JSpinner customerWeightSpinner, customerHeightSpinner, patientHeartRateSpinner, bloodPressureSystolicSpinner, bloodPressureDiastolicSpinner; + private JDatePickerImpl datePicker, dobPicker, recheckupDatePicker; + private JButton recheckupDatePickerButton; + private String[][] medicinePrescription = new String[0][0]; // Initialize to empty + private String[][] servicePrescription = new String[0][0]; // Initialize to empty + private MedicineDialog medDialog = null; + private ServiceDialog serDialog = null; + private AddDialog addDialog = null; + private String selectedCheckupId = null; // Use checkupId to track selection instead of row index + private boolean saved = true; // Initially true, changed when patient selected or dialog opened. + private DefaultComboBoxModel wardModel; + + // Variables to store target ward and ward when loading patient address + private String targetWard = null; + private JComboBox callRoomComboBox; + private JPanel rightContainer; // Add this field + private List