diff --git a/medical_invoice.pdf b/medical_invoice.pdf index 5936645..539a736 100644 Binary files a/medical_invoice.pdf and b/medical_invoice.pdf differ diff --git a/src/main/java/BsK/client/Client.java b/src/main/java/BsK/client/Client.java index 7994e24..1c4f532 100644 --- a/src/main/java/BsK/client/Client.java +++ b/src/main/java/BsK/client/Client.java @@ -29,6 +29,12 @@ import javax.swing.SwingUtilities; @Slf4j public class Client { + private static Properties config = new Properties(); + + public static Properties getConfig() { + return config; + } + private static void showConnectionErrorDialog(String serverAddress, int port, Exception error) { SwingUtilities.invokeLater(() -> { String message = String.format( @@ -69,15 +75,11 @@ public class Client { public static void main(String[] args) throws Exception { var thread = new Thread(() -> { - Properties props = new Properties(); - String serverAddress = "localhost"; - int port = 1999; - // First try to load from external config file File externalConfig = new File("config/config.properties"); if (externalConfig.exists()) { try (var input = Files.newInputStream(externalConfig.toPath())) { - props.load(input); + config.load(input); log.info("Loaded configuration from external file: {}", externalConfig.getAbsolutePath()); } catch (IOException e) { log.error("Error loading external config file", e); @@ -85,33 +87,60 @@ public class Client { } // If external config failed or doesn't exist, try internal config - if (props.isEmpty()) { + if (config.isEmpty()) { try (InputStream input = Client.class.getClassLoader().getResourceAsStream("config.properties")) { if (input == null) { log.error("Unable to find config.properties"); - showConnectionErrorDialog(serverAddress, port, + showConnectionErrorDialog("localhost", 1999, new Exception("Không tìm thấy file cấu hình config.properties")); return; } - props.load(input); + config.load(input); log.info("Loaded configuration from internal resources"); } catch (IOException e) { log.error("Error loading internal config file", e); - showConnectionErrorDialog(serverAddress, port, e); + showConnectionErrorDialog("localhost", 1999, e); return; } } // Get server configuration - serverAddress = props.getProperty("server.address", "localhost"); - String portStr = props.getProperty("server.port"); + String serverAddress = config.getProperty("server.address", "localhost"); + String portStr = config.getProperty("server.port"); + + // Load media directory setting into LocalStorage + String mediaDir = config.getProperty("storage.checkup_media_base_dir"); + if (mediaDir != null && !mediaDir.trim().isEmpty()) { + LocalStorage.checkupMediaBaseDir = mediaDir.trim(); + log.info("Using configured media directory: {}", mediaDir); + } else { + log.info("Using default media directory: {}", LocalStorage.checkupMediaBaseDir); + } + + // Load ultrasound folder setting into LocalStorage + String ultrasoundFolder = config.getProperty("storage.ultrasound_folder_path"); + if (ultrasoundFolder != null && !ultrasoundFolder.trim().isEmpty()) { + LocalStorage.ULTRASOUND_FOLDER_PATH = ultrasoundFolder.trim(); + log.info("Using configured ultrasound folder: {}", ultrasoundFolder); + } else { + log.info("Using default ultrasound folder: {}", LocalStorage.ULTRASOUND_FOLDER_PATH); + } + + // Load auto change status setting into LocalStorage + String autoChangeStatus = config.getProperty("app.auto_change_status_to_finished"); + if (autoChangeStatus != null && !autoChangeStatus.trim().isEmpty()) { + LocalStorage.autoChangeStatusToFinished = Boolean.parseBoolean(autoChangeStatus.trim()); + log.info("Auto change status to finished: {}", LocalStorage.autoChangeStatusToFinished); + } else { + log.info("Using default auto change status: {}", LocalStorage.autoChangeStatusToFinished); + } // Use defaults if not configured if (portStr != null) { - port = Integer.parseInt(portStr); + int port = Integer.parseInt(portStr); log.info("Using configured port: {}", port); } else { - log.info("Using default port: {}", port); + log.info("Using default port: {}", 1999); } log.info("Using server address: {}", serverAddress); @@ -121,9 +150,9 @@ public class Client { URI uri = null; try { - uri = new URI("ws://" + serverAddress + ":" + port + "/"); + uri = new URI("ws://" + serverAddress + ":" + 1999 + "/"); } catch (URISyntaxException e) { - showConnectionErrorDialog(serverAddress, port, e); + showConnectionErrorDialog(serverAddress, 1999, e); return; } @@ -154,13 +183,13 @@ public class Client { .addLast("ws", ClientHandler.INSTANCE); } }); - log.info("Connecting to {}:{}", serverAddress, port); - Channel channel = bootstrap.connect(serverAddress, port).sync().channel(); + log.info("Connecting to {}:{}", serverAddress, 1999); + Channel channel = bootstrap.connect(serverAddress, 1999).sync().channel(); channel.closeFuture().sync(); } catch (Exception e) { log.error("Connection error", e); - showConnectionErrorDialog(serverAddress, port, e); + showConnectionErrorDialog(serverAddress, 1999, e); return; } finally { try { diff --git a/src/main/java/BsK/client/LocalStorage.java b/src/main/java/BsK/client/LocalStorage.java index 515121e..9dffe98 100644 --- a/src/main/java/BsK/client/LocalStorage.java +++ b/src/main/java/BsK/client/LocalStorage.java @@ -4,21 +4,36 @@ import BsK.server.network.entity.Role; import lombok.AllArgsConstructor; import lombok.Data; +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 public class LocalStorage { + public static String sessionId; public static String username; public static Role role; public static int userId; public static String ClinicName = "Phòng khám BSK"; public static String ClinicAddress = "Số ABC, Đường XYZ, Quận 1, TP.HCM"; public static String ClinicPhone = "0123456789"; - public static String[] doctorsName; - public static String[] provinces; - public static String[] wards; - public static HashMap provinceToId; + + public static List doctorsName = new ArrayList<>(); + public static String[] provinces = new String[]{}; + public static String[] wards = new String[]{}; + public static Map provinceToId = new java.util.HashMap<>(); public static HashMap cachedWards; // cache local areas later will do public static HashMap medUnitConversion; // hash by med id inside is unit id and unit name and conversion rate and unit price + + // these variable can be changed by settings page + // need restart + public static String checkupMediaBaseDir = "src/main/resources/image/checkup_media"; + public static String ULTRASOUND_FOLDER_PATH = "ANH SIEU AM"; + + // does not need restart + public static Boolean autoChangeStatusToFinished = false; // turn this on will change status to finished when checkup is save by hitting print + } \ No newline at end of file diff --git a/src/main/java/BsK/client/network/handler/ClientHandler.java b/src/main/java/BsK/client/network/handler/ClientHandler.java index c72e57b..f88e32d 100644 --- a/src/main/java/BsK/client/network/handler/ClientHandler.java +++ b/src/main/java/BsK/client/network/handler/ClientHandler.java @@ -25,6 +25,14 @@ import java.util.concurrent.ConcurrentHashMap; 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; +import BsK.common.packet.res.GetMedInfoResponse; +import BsK.common.packet.res.GetOrderInfoByCheckupRes; @Slf4j public class ClientHandler extends SimpleChannelInboundHandler { @@ -76,10 +84,20 @@ public class ClientHandler extends SimpleChannelInboundHandler= 2) { + LocalStorage.doctorsName.add(new DoctorItem(doctorData[1], doctorData[0])); // id, name + } + } + } + log.info("Updated doctors list in LocalStorage. Total doctors: {}", LocalStorage.doctorsName.size()); + } else if (packet instanceof GetMedInfoResponse) { + GetMedInfoResponse res = (GetMedInfoResponse) packet; + log.debug("GetMedInfoResponse received"); } if (packet instanceof GetProvinceResponse provinceResponse) { diff --git a/src/main/java/BsK/client/ui/component/CheckUpPage/AddDialog/AddDialog.java b/src/main/java/BsK/client/ui/component/CheckUpPage/AddDialog/AddDialog.java index 700482d..0b37cde 100644 --- a/src/main/java/BsK/client/ui/component/CheckUpPage/AddDialog/AddDialog.java +++ b/src/main/java/BsK/client/ui/component/CheckUpPage/AddDialog/AddDialog.java @@ -14,6 +14,8 @@ import org.jdatepicker.impl.JDatePickerImpl; import org.jdatepicker.impl.UtilDateModel; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import BsK.client.ui.component.CheckUpPage.DoctorItem; + import javax.swing.*; import javax.swing.event.DocumentEvent; @@ -47,7 +49,7 @@ public class AddDialog extends JDialog { private final ResponseListener wardResponseListener = this::handleGetWardResponse; private final ResponseListener addPatientResponseListener = this::handleAddPatientResponse; private final ResponseListener addCheckupResponseListener = this::handleAddCheckupResponse; - private JComboBox doctorComboBox; + private JComboBox doctorComboBox; private JComboBox checkupTypeComboBox; JButton saveButton; private DefaultComboBoxModel wardModel; @@ -417,7 +419,7 @@ public class AddDialog extends JDialog { gbc.gridx = 1; gbc.gridwidth = 1; // Doctor ComboBox takes 1 column gbc.weightx = 0.5; // Doctor ComboBox takes some horizontal space - doctorComboBox = new JComboBox<>(LocalStorage.doctorsName != null ? LocalStorage.doctorsName : new String[]{"Đang tải..."}); + doctorComboBox = new JComboBox<>(LocalStorage.doctorsName.toArray(new DoctorItem[0])); doctorComboBox.setFont(textFont); doctorComboBox.setPreferredSize(comboBoxSize); checkupInfoPanel.add(doctorComboBox, gbc); @@ -590,7 +592,12 @@ public class AddDialog extends JDialog { saveButton.setFont(labelFont); saveButton.addActionListener(e -> { int patientId = Integer.parseInt(patientIdField.getText()); - int doctorId = doctorComboBox.getSelectedIndex()+ 1; + DoctorItem selectedDoctor = (DoctorItem) doctorComboBox.getSelectedItem(); + if (selectedDoctor == null || selectedDoctor.getId() == null) { + JOptionPane.showMessageDialog(this, "Vui lòng chọn một bác sĩ hợp lệ.", "Lỗi", JOptionPane.ERROR_MESSAGE); + return; + } + int doctorId = Integer.parseInt(selectedDoctor.getId()); String selectedCheckupType = (String) checkupTypeComboBox.getSelectedItem(); NetworkUtil.sendPacket(ClientHandler.ctx.channel(), new AddCheckupRequest(patientId, doctorId, LocalStorage.userId, selectedCheckupType, "ĐANG KHÁM")); @@ -700,7 +707,9 @@ public class AddDialog extends JDialog { provinceComboBox.setSelectedIndex(0); wardComboBox.setSelectedIndex(0); wardComboBox.setEnabled(false); - doctorComboBox.setSelectedIndex(0); + if (doctorComboBox.getItemCount() > 0) { + doctorComboBox.setSelectedIndex(0); + } checkupTypeComboBox.setSelectedIndex(0); // Reset targetWard 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 f7a3f14..f9c9bb3 100644 --- a/src/main/java/BsK/client/ui/component/CheckUpPage/CheckUpPage.java +++ b/src/main/java/BsK/client/ui/component/CheckUpPage/CheckUpPage.java @@ -1,5 +1,6 @@ package BsK.client.ui.component.CheckUpPage; +import BsK.client.Client; import BsK.client.LocalStorage; import BsK.client.network.handler.ClientHandler; import BsK.client.network.handler.ResponseListener; @@ -152,6 +153,7 @@ 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 { @@ -173,15 +175,14 @@ public class CheckUpPage extends JPanel { private JTextField checkupIdField, customerLastNameField, customerFirstNameField,customerAddressField, customerPhoneField, customerIdField, customerCccdDdcnField; private JTextArea suggestionField, diagnosisField, conclusionField; // Changed symptomsField to suggestionField private JTextPane notesField; - private JComboBox doctorComboBox, statusComboBox, genderComboBox, provinceComboBox, wardComboBox, checkupTypeComboBox, templateComboBox, orientationComboBox; // Added orientationComboBox - private JComboBox ultrasoundDoctorComboBox; + 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 String[] doctorOptions; private MedicineDialog medDialog = null; private ServiceDialog serDialog = null; private AddDialog addDialog = null; @@ -231,7 +232,7 @@ public class CheckUpPage extends JPanel { private String currentCheckupIdForMedia; private Path currentCheckupMediaPath; private javax.swing.Timer imageRefreshTimer; - private static final String CHECKUP_MEDIA_BASE_DIR = "src/main/resources/image/checkup_media"; // Updated media directory path + // Using LocalStorage.checkupMediaBaseDir which is loaded at startup private static final int THUMBNAIL_WIDTH = 100; private static final int THUMBNAIL_HEIGHT = 100; @@ -333,8 +334,8 @@ public class CheckUpPage extends JPanel { // Ensure the base media directory exists try { - Files.createDirectories(Paths.get(CHECKUP_MEDIA_BASE_DIR)); - log.info("Created or verified media directory at: {}", CHECKUP_MEDIA_BASE_DIR); + Files.createDirectories(Paths.get(LocalStorage.checkupMediaBaseDir)); + log.info("Created or verified media directory at: {}", LocalStorage.checkupMediaBaseDir); } catch (IOException e) { log.error("Failed to create media directory: {}", e.getMessage(), e); JOptionPane.showMessageDialog(this, @@ -497,7 +498,7 @@ public class CheckUpPage extends JPanel { BorderFactory.createEmptyBorder(3, 10, 3, 10), // Reduced top/bottom from 5 to 3 BorderFactory.createTitledBorder( BorderFactory.createLineBorder(new Color(63, 81, 181), 1, true), - "Đơn thuốc và Dịch vụ", + "Đơn thuốc và Dịch vụ (tham khảo)", TitledBorder.LEADING, TitledBorder.TOP, new Font("Arial", Font.BOLD, 16), new Color(63, 81, 181) ) @@ -920,7 +921,7 @@ public class CheckUpPage extends JPanel { doctorPanel.add(doctorLabel, gbcDoctor); gbcDoctor.gridx = 1; gbcDoctor.weightx = 0.4; - doctorComboBox = new JComboBox<>(LocalStorage.doctorsName != null ? LocalStorage.doctorsName : new String[]{"Đang tải bác sĩ..."}); + doctorComboBox = new JComboBox<>(LocalStorage.doctorsName.toArray(new DoctorItem[0])); doctorComboBox.setFont(fieldFont); doctorPanel.add(doctorComboBox, gbcDoctor); @@ -930,7 +931,7 @@ public class CheckUpPage extends JPanel { doctorPanel.add(ultrasoundDoctorLabel, gbcDoctor); gbcDoctor.gridx = 3; gbcDoctor.weightx = 0.4; - ultrasoundDoctorComboBox = new JComboBox<>(LocalStorage.doctorsName != null ? LocalStorage.doctorsName : new String[]{"Đang tải bác sĩ..."}); + ultrasoundDoctorComboBox = new JComboBox<>(LocalStorage.doctorsName.toArray(new DoctorItem[0])); ultrasoundDoctorComboBox.setFont(fieldFont); doctorPanel.add(ultrasoundDoctorComboBox, gbcDoctor); @@ -1779,8 +1780,8 @@ public class CheckUpPage extends JPanel { if (medicinePrescription != null) { for (String[] med : medicinePrescription) { - // Check if this is a supplement (index 10 is the supplement flag) - if (med.length > 10 && "1".equals(med[10])) { + // The supplement flag is at index 10 (after returned from the med dialog) + if ("1".equals(med[10])) { log.info("Supplement: {}", med[1]); supplements.add(med); } else { @@ -1790,13 +1791,21 @@ public class CheckUpPage extends JPanel { } } + Patient printerPatient = getCurrentSelectedPatient(); + String printerPatientDriveUrl = (printerPatient != null) ? printerPatient.getDriveUrl() : ""; + + DoctorItem selectedDoctor = (DoctorItem) doctorComboBox.getSelectedItem(); + String doctorName = (selectedDoctor != null) ? selectedDoctor.getName() : ""; + MedicineInvoice medicineInvoice = new MedicineInvoice(checkupIdField.getText(), customerLastNameField.getText() + " " + customerFirstNameField.getText(), dobPicker.getJFormattedTextField().getText(), customerPhoneField.getText(), genderComboBox.getSelectedItem().toString(), customerAddressField.getText() + ", " + (wardComboBox.getSelectedItem() != null ? wardComboBox.getSelectedItem().toString() : "") + ", " + (provinceComboBox.getSelectedItem() != null ? provinceComboBox.getSelectedItem().toString() : ""), - doctorComboBox.getSelectedItem().toString(), diagnosisField.getText(), - conclusionField.getText(), + doctorName, + diagnosisField.getText(), + conclusionField.getText(), + printerPatientDriveUrl, regularMeds.toArray(new String[0][]), servicePrescription, supplements.toArray(new String[0][]) // Pass supplements @@ -1845,14 +1854,20 @@ public class CheckUpPage extends JPanel { Patient currentPatient = getCurrentSelectedPatient(); String currentPatientDriveUrl = (currentPatient != null) ? currentPatient.getDriveUrl() : ""; + DoctorItem selectedDoctorForPrint = (DoctorItem) doctorComboBox.getSelectedItem(); + String doctorNameForPrint = (selectedDoctorForPrint != null) ? selectedDoctorForPrint.getName() : ""; + + DoctorItem selectedUltrasoundDoctorForPrint = (DoctorItem) ultrasoundDoctorComboBox.getSelectedItem(); + String ultrasoundDoctorNameForPrint = (selectedUltrasoundDoctorForPrint != null) ? selectedUltrasoundDoctorForPrint.getName() : ""; + UltrasoundResult ultrasoundResultPrint = new UltrasoundResult( checkupIdField.getText(), customerLastNameField.getText() + " " + customerFirstNameField.getText(), dobPicker.getJFormattedTextField().getText(), (String) genderComboBox.getSelectedItem(), customerAddressField.getText() + ", " + (wardComboBox.getSelectedItem() != null ? wardComboBox.getSelectedItem().toString() : "") + ", " + (provinceComboBox.getSelectedItem() != null ? provinceComboBox.getSelectedItem().toString() : ""), - (String) doctorComboBox.getSelectedItem(), - (String) ultrasoundDoctorComboBox.getSelectedItem(), + doctorNameForPrint, + ultrasoundDoctorNameForPrint, datePicker.getJFormattedTextField().getText(), TextUtils.scaleRtfFontSize(getRtfContentAsString()), conclusionField.getText(), @@ -1920,14 +1935,20 @@ public class CheckUpPage extends JPanel { Patient viewPatient = getCurrentSelectedPatient(); String viewPatientDriveUrl = (viewPatient != null) ? viewPatient.getDriveUrl() : ""; + DoctorItem selectedDoctorForView = (DoctorItem) doctorComboBox.getSelectedItem(); + String doctorNameForView = (selectedDoctorForView != null) ? selectedDoctorForView.getName() : ""; + + DoctorItem selectedUltrasoundDoctorForView = (DoctorItem) ultrasoundDoctorComboBox.getSelectedItem(); + String ultrasoundDoctorNameForView = (selectedUltrasoundDoctorForView != null) ? selectedUltrasoundDoctorForView.getName() : ""; + UltrasoundResult ultrasoundResultView = new UltrasoundResult( checkupIdField.getText(), customerLastNameField.getText() + " " + customerFirstNameField.getText(), dobPicker.getJFormattedTextField().getText(), (String) genderComboBox.getSelectedItem(), customerAddressField.getText() + ", " + (wardComboBox.getSelectedItem() != null ? wardComboBox.getSelectedItem().toString() : "") + ", " + (provinceComboBox.getSelectedItem() != null ? provinceComboBox.getSelectedItem().toString() : ""), - (String) doctorComboBox.getSelectedItem(), - (String) ultrasoundDoctorComboBox.getSelectedItem(), + doctorNameForView, + ultrasoundDoctorNameForView, datePicker.getJFormattedTextField().getText(), TextUtils.scaleRtfFontSize(getRtfContentAsString()), conclusionField.getText(), @@ -2181,8 +2202,24 @@ public class CheckUpPage extends JPanel { customerLastNameField.setText(selectedPatient.getCustomerLastName()); customerFirstNameField.setText(selectedPatient.getCustomerFirstName()); - doctorComboBox.setSelectedItem(selectedPatient.getDoctorName()); - ultrasoundDoctorComboBox.setSelectedItem(selectedPatient.getDoctorUltrasoundId()); + + // Select doctor by name + DoctorItem doctorToSelect = findDoctorByName(selectedPatient.getDoctorName()); + if (doctorToSelect != null) { + doctorComboBox.setSelectedItem(doctorToSelect); + } else if (doctorComboBox.getItemCount() > 0) { + doctorComboBox.setSelectedIndex(0); + log.warn("Doctor '{}' not found in the list for patient selection.", selectedPatient.getDoctorName()); + } + + DoctorItem ultrasoundDoctorToSelect = findDoctorByName(selectedPatient.getDoctorUltrasoundId()); + if (ultrasoundDoctorToSelect != null) { + ultrasoundDoctorComboBox.setSelectedItem(ultrasoundDoctorToSelect); + } else if (ultrasoundDoctorComboBox.getItemCount() > 0) { + ultrasoundDoctorComboBox.setSelectedIndex(0); + log.warn("Ultrasound Doctor '{}' not found in the list for patient selection.", selectedPatient.getDoctorUltrasoundId()); + } + suggestionField.setText(selectedPatient.getSuggestion()); // De nghi diagnosisField.setText(selectedPatient.getDiagnosis()); // Chuan doan conclusionField.setText(selectedPatient.getConclusion()); // Ket luan @@ -2301,7 +2338,7 @@ public class CheckUpPage extends JPanel { currentCheckupIdForMedia = selectedPatient.getCheckupId(); if (currentCheckupIdForMedia != null && !currentCheckupIdForMedia.trim().isEmpty()) { ensureMediaDirectoryExists(currentCheckupIdForMedia); - currentCheckupMediaPath = Paths.get(CHECKUP_MEDIA_BASE_DIR, currentCheckupIdForMedia.trim()); + currentCheckupMediaPath = Paths.get(LocalStorage.checkupMediaBaseDir, currentCheckupIdForMedia.trim()); if (Files.exists(currentCheckupMediaPath)) { loadAndDisplayImages(currentCheckupMediaPath); // Load initial images for this patient @@ -3977,7 +4014,7 @@ public class CheckUpPage extends JPanel { private void ensureMediaDirectoryExists(String checkupId) { try { // First ensure base directory exists - Path baseDir = Paths.get(CHECKUP_MEDIA_BASE_DIR); + Path baseDir = Paths.get(LocalStorage.checkupMediaBaseDir); if (!Files.exists(baseDir)) { Files.createDirectories(baseDir); log.info("Created base media directory at: {}", baseDir); @@ -4483,111 +4520,62 @@ public class CheckUpPage extends JPanel { // Update the save method to get RTF content private void handleSave() { - // Get all the field values - String rtfContent = getRtfContentAsString(); - String checkupId = checkupIdField.getText(); - String checkupDate = datePicker.getJFormattedTextField().getText(); - String customerId = customerIdField.getText(); - String customerLastName = customerLastNameField.getText(); - String customerFirstName = customerFirstNameField.getText(); - String customerDob = dobPicker.getJFormattedTextField().getText(); - String customerGender = (String) genderComboBox.getSelectedItem(); - - // Construct full address - String address = customerAddressField.getText(); - String ward = (String) wardComboBox.getSelectedItem(); - String province = (String) provinceComboBox.getSelectedItem(); - String fullAddress = String.format("%s, %s, %s, %s", - address, - ward != null && !ward.equals("Xã/Phường") ? ward : "", - province != null && !province.equals("Tỉnh/Thành phố") ? province : "" - ).replaceAll(", ,", ",").trim().replaceAll(",$", ""); - - String customerNumber = customerPhoneField.getText(); - String customerWeight = customerWeightSpinner.getValue().toString(); - String customerHeight = customerHeightSpinner.getValue().toString(); - String doctorId = String.valueOf(doctorComboBox.getSelectedIndex() + 1); - String ultrasoundDoctorId = String.valueOf(ultrasoundDoctorComboBox.getSelectedIndex() + 1); - String suggestions = suggestionField.getText(); - String diagnosis = diagnosisField.getText(); - String conclusion = conclusionField.getText(); - String status = (String) statusComboBox.getSelectedItem(); - String checkupType = (String) checkupTypeComboBox.getSelectedItem(); - String reCheckupDate = recheckupDatePicker.getJFormattedTextField().getText(); - String customerCccdDdcn = customerCccdDdcnField.getText(); - - // Log all fields that will be sent to backend - log.info("=== SaveCheckupRequest Data ==="); - log.info("checkupId: {}", checkupId); - log.info("checkupDate: {}", checkupDate); - log.info("customerId: {}", customerId); - log.info("customerLastName: {}", customerLastName); - log.info("customerFirstName: {}", customerFirstName); - log.info("customerDob: {}", customerDob); - log.info("customerGender: {}", customerGender); - log.info("customerAddress: {}", fullAddress); - log.info("customerNumber: {}", customerNumber); - log.info("customerWeight: {}", customerWeight); - log.info("customerHeight: {}", customerHeight); - log.info("doctorId: {}", doctorId); - log.info("ultrasoundDoctorId: {}", ultrasoundDoctorId); - log.info("suggestions: {}", suggestions); - log.info("diagnosis: {}", diagnosis); - log.info("conclusion: {}", conclusion); - log.info("notes (RTF): {}", rtfContent); - log.info("status: {}", status); - log.info("checkupType: {}", checkupType); - log.info("medicinePrescription: {}", (Object) medicinePrescription); - log.info("servicePrescription: {}", (Object) servicePrescription); - log.info("reCheckupDate: {}", reCheckupDate); - log.info("customerCccdDdcn: {}", customerCccdDdcn); - log.info("heartBeat: {}", patientHeartRateSpinner.getValue()); - log.info("bloodPressure: {}", bloodPressureSystolicSpinner.getValue() + "/" + bloodPressureDiastolicSpinner.getValue()); - log.info("=== End SaveCheckupRequest Data ==="); - - String bloodPressure = bloodPressureSystolicSpinner.getValue() + "/" + bloodPressureDiastolicSpinner.getValue(); - Long customerDobLong = DateUtils.convertToDate(customerDob).getTime(); - Long reCheckupDateLong = DateUtils.convertToDate(reCheckupDate).getTime(); - Long checkupDateLong = DateUtils.convertToDate(checkupDate).getTime(); - Integer heartBeat = (Integer) patientHeartRateSpinner.getValue(); - Boolean needsRecheckup = needRecheckupCheckbox.isSelected(); - - // If re-checkup is not needed, clear the re-checkup date - if (!needsRecheckup) { - reCheckupDateLong = 0L; // Use 0 to indicate no re-checkup date + if (checkupIdField.getText().isEmpty()) { + JOptionPane.showMessageDialog(this, "Chưa chọn bệnh nhân.", "Lỗi", JOptionPane.ERROR_MESSAGE); + return; } - + + DoctorItem selectedDoctor = (DoctorItem) doctorComboBox.getSelectedItem(); + String doctorIdStr = (selectedDoctor != null) ? selectedDoctor.getId() : null; + DoctorItem selectedUltrasoundDoctor = (DoctorItem) ultrasoundDoctorComboBox.getSelectedItem(); + String ultrasoundDoctorIdStr = (selectedUltrasoundDoctor != null) ? selectedUltrasoundDoctor.getId() : null; + + if (doctorIdStr == null) { + JOptionPane.showMessageDialog(this, "Chưa chọn bác sĩ.", "Lỗi", JOptionPane.ERROR_MESSAGE); + return; + } + + Date recheckupDate = (Date) recheckupDatePicker.getModel().getValue(); + if (needRecheckupCheckbox.isSelected() && recheckupDate == null) { + JOptionPane.showMessageDialog(this, "Vui lòng chọn ngày tái khám.", "Thiếu thông tin", JOptionPane.WARNING_MESSAGE); + return; + } + + try { SaveCheckupRequest request = new SaveCheckupRequest( - Integer.parseInt(checkupId), - Integer.parseInt(customerId), - Integer.parseInt(doctorId), - Integer.parseInt(ultrasoundDoctorId), - checkupDateLong, - suggestions, - diagnosis, - rtfContent, - status, - checkupType, - conclusion, - reCheckupDateLong, - needsRecheckup, - customerFirstName, - customerLastName, - customerDobLong, - customerGender, - fullAddress, - customerNumber, - Double.parseDouble(customerWeight), - Double.parseDouble(customerHeight), - customerCccdDdcn, - heartBeat, - bloodPressure, + Integer.parseInt(checkupIdField.getText()), + Integer.parseInt(customerIdField.getText()), + Integer.parseInt(doctorIdStr), + ultrasoundDoctorIdStr != null ? Integer.parseInt(ultrasoundDoctorIdStr) : null, + DateUtils.convertToDate(datePicker.getJFormattedTextField().getText()).getTime(), + suggestionField.getText(), + diagnosisField.getText(), + getRtfContentAsString(), + (String) statusComboBox.getSelectedItem(), + (String) checkupTypeComboBox.getSelectedItem(), + conclusionField.getText(), + recheckupDate != null ? recheckupDate.getTime() : null, + needRecheckupCheckbox.isSelected(), + customerFirstNameField.getText(), + customerLastNameField.getText(), + DateUtils.convertToDate(dobPicker.getJFormattedTextField().getText()).getTime(), + (String) genderComboBox.getSelectedItem(), + customerAddressField.getText() + ", " + (wardComboBox.getSelectedItem() != null ? wardComboBox.getSelectedItem().toString() : "") + ", " + (provinceComboBox.getSelectedItem() != null ? provinceComboBox.getSelectedItem().toString() : ""), + customerPhoneField.getText(), + (Double) customerWeightSpinner.getValue(), + (Double) customerHeightSpinner.getValue(), + customerCccdDdcnField.getText(), + (Integer) patientHeartRateSpinner.getValue(), + bloodPressureSystolicSpinner.getValue() + "/" + bloodPressureDiastolicSpinner.getValue(), medicinePrescription, servicePrescription ); - NetworkUtil.sendPacket(ClientHandler.ctx.channel(), request); saved = true; + } catch (Exception e) { + log.error("Failed to create or send SaveCheckupRequest", e); + JOptionPane.showMessageDialog(this, "Lỗi khi lưu dữ liệu: " + e.getMessage(), "Lỗi", JOptionPane.ERROR_MESSAGE); + } } private void handleTemplateSelection() { @@ -4653,28 +4641,28 @@ public class CheckUpPage extends JPanel { } private void handleGetAllTemplatesResponse(GetAllTemplatesRes response) { - log.info("Get all templates response"); - this.allTemplates = response.getTemplates(); - List