mirror of
https://github.com/tiennm99/BSK-All-in-One-Clinic-Management-System.git
synced 2026-10-11 12:11:43 +00:00
[update] Enhance CheckUpPage and AddDialog by integrating new patient fields including CCCD/DDCN, heart rate, and blood pressure measurements. Revise layout for improved data entry and user experience, ensuring comprehensive patient information management. Update data structures and server handling to accommodate new fields, enhancing overall functionality.
This commit is contained in:
1 parent
f816ce64b2
commit
2f5d2bcf1b
9 files changed
+1241
-1006
No files matched your search
@@ -35,6 +35,7 @@ public class AddDialog extends JDialog {
|
||||
private JTextField patientYearField;
|
||||
private JTextField patientIdField;
|
||||
private JTextField patientPhoneField;
|
||||
private JTextField cccdField;
|
||||
private JComboBox patientGenderField;
|
||||
private JComboBox wardComboBox, districtComboBox, provinceComboBox;
|
||||
private JTextField customerAddressField;
|
||||
@@ -172,11 +173,18 @@ public class AddDialog extends JDialog {
|
||||
setDefaultCloseOperation(DISPOSE_ON_CLOSE);
|
||||
|
||||
// Set size of the dialog
|
||||
setSize(1000, 400);
|
||||
setSize(1200, 700);
|
||||
// Put in the middle of parent window
|
||||
setLocationRelativeTo(parent);
|
||||
setResizable(true);
|
||||
|
||||
// UI Fonts and Dimensions
|
||||
Font labelFont = new Font("Arial", Font.BOLD, 15);
|
||||
Font textFont = new Font("Arial", Font.PLAIN, 15);
|
||||
Font titleFont = new Font("Arial", Font.BOLD, 16);
|
||||
Dimension textFieldSize = new Dimension(100, 30);
|
||||
Dimension comboBoxSize = new Dimension(100, 30);
|
||||
|
||||
// Ensure modal behavior and proper parent relationship
|
||||
setModalityType(Dialog.ModalityType.APPLICATION_MODAL);
|
||||
setAlwaysOnTop(false); // Don't force always on top, let modal behavior handle this
|
||||
@@ -215,8 +223,8 @@ public class AddDialog extends JDialog {
|
||||
};
|
||||
|
||||
patientTable = new JTable(patientTableModel);
|
||||
patientTable.setFont(new Font("Serif", Font.PLAIN, 14));
|
||||
patientTable.setRowHeight(30);
|
||||
patientTable.setFont(textFont);
|
||||
patientTable.setRowHeight(35);
|
||||
patientTable.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
|
||||
JScrollPane scrollPane = new JScrollPane(patientTable);
|
||||
|
||||
@@ -250,7 +258,7 @@ public class AddDialog extends JDialog {
|
||||
patientInfoPanel.setBorder(BorderFactory.createTitledBorder(
|
||||
BorderFactory.createEtchedBorder(), "Thông tin bệnh nhân",
|
||||
javax.swing.border.TitledBorder.LEADING, javax.swing.border.TitledBorder.TOP,
|
||||
new Font("Arial", Font.BOLD, 14), new Color(50, 50, 50)
|
||||
titleFont, new Color(50, 50, 50)
|
||||
));
|
||||
mainGbc.gridx = 0;
|
||||
mainGbc.gridy = 0;
|
||||
@@ -262,7 +270,7 @@ public class AddDialog extends JDialog {
|
||||
addressInfoPanel.setBorder(BorderFactory.createTitledBorder(
|
||||
BorderFactory.createEtchedBorder(), "Địa chỉ",
|
||||
javax.swing.border.TitledBorder.LEADING, javax.swing.border.TitledBorder.TOP,
|
||||
new Font("Arial", Font.BOLD, 14), new Color(50, 50, 50)
|
||||
titleFont, new Color(50, 50, 50)
|
||||
));
|
||||
mainGbc.gridy = 1;
|
||||
inputPanel.add(addressInfoPanel, mainGbc);
|
||||
@@ -272,7 +280,7 @@ public class AddDialog extends JDialog {
|
||||
checkupInfoPanel.setBorder(BorderFactory.createTitledBorder(
|
||||
BorderFactory.createEtchedBorder(), "Thông tin đăng ký khám",
|
||||
javax.swing.border.TitledBorder.LEADING, javax.swing.border.TitledBorder.TOP,
|
||||
new Font("Arial", Font.BOLD, 14), new Color(50, 50, 50)
|
||||
titleFont, new Color(50, 50, 50)
|
||||
));
|
||||
mainGbc.gridy = 2;
|
||||
inputPanel.add(checkupInfoPanel, mainGbc);
|
||||
@@ -294,20 +302,25 @@ public class AddDialog extends JDialog {
|
||||
gbc.gridy = 0;
|
||||
gbc.gridx = 0;
|
||||
gbc.gridwidth = 1;
|
||||
patientInfoPanel.add(new JLabel("Họ và tên:"), gbc);
|
||||
JLabel nameLabel = new JLabel("Họ và tên:");
|
||||
nameLabel.setFont(labelFont);
|
||||
patientInfoPanel.add(nameLabel, gbc);
|
||||
|
||||
gbc.gridx = 1;
|
||||
gbc.weightx = 1.0; // Allow patient name field to expand
|
||||
patientNameField = new JTextField(15);
|
||||
patientNameField.setFont(textFont);
|
||||
patientNameField.setPreferredSize(textFieldSize);
|
||||
patientInfoPanel.add(patientNameField, gbc);
|
||||
gbc.weightx = 0.0; // Reset
|
||||
|
||||
gbc.gridx = 2;
|
||||
gbc.gridwidth = 1;
|
||||
ImageIcon originalIcon = new ImageIcon("src/main/java/BsK/client/ui/assets/icon/add.png");
|
||||
Image scaledImage = originalIcon.getImage().getScaledInstance(20, 20, Image.SCALE_SMOOTH);
|
||||
Image scaledImage = originalIcon.getImage().getScaledInstance(24, 24, Image.SCALE_SMOOTH);
|
||||
ImageIcon addIcon = new ImageIcon(scaledImage);
|
||||
JButton addButton = new JButton(addIcon);
|
||||
addButton.setPreferredSize(new Dimension(40, 30));
|
||||
addButton.setToolTipText("Thêm bệnh nhân mới (nếu không tìm thấy)");
|
||||
patientInfoPanel.add(addButton, gbc);
|
||||
|
||||
@@ -315,7 +328,9 @@ public class AddDialog extends JDialog {
|
||||
gbc.gridy++;
|
||||
gbc.gridx = 0;
|
||||
gbc.gridwidth = 1;
|
||||
patientInfoPanel.add(new JLabel("Ngày sinh:"), gbc);
|
||||
JLabel dobLabel = new JLabel("Ngày sinh:");
|
||||
dobLabel.setFont(labelFont);
|
||||
patientInfoPanel.add(dobLabel, gbc);
|
||||
|
||||
gbc.gridx = 1;
|
||||
UtilDateModel model = new UtilDateModel();
|
||||
@@ -325,33 +340,62 @@ public class AddDialog extends JDialog {
|
||||
p.put("text.year", "Năm");
|
||||
JDatePanelImpl datePanel = new JDatePanelImpl(model, p);
|
||||
dobPicker = new JDatePickerImpl(datePanel, new DateLabelFormatter());
|
||||
dobPicker.getJFormattedTextField().setFont(textFont);
|
||||
dobPicker.setPreferredSize(new Dimension(150, 30));
|
||||
patientInfoPanel.add(dobPicker, gbc);
|
||||
|
||||
gbc.gridx = 2;
|
||||
patientInfoPanel.add(new JLabel("Giới tính:"), gbc);
|
||||
JLabel genderLabel = new JLabel("Giới tính:");
|
||||
genderLabel.setFont(labelFont);
|
||||
patientInfoPanel.add(genderLabel, gbc);
|
||||
|
||||
gbc.gridx = 3;
|
||||
patientGenderField = new JComboBox<>(new String[]{"Nam", "Nữ"});
|
||||
patientGenderField.setFont(textFont);
|
||||
patientGenderField.setPreferredSize(comboBoxSize);
|
||||
patientInfoPanel.add(patientGenderField, gbc);
|
||||
|
||||
// Phone (Row 2, Col 0-1) & Patient ID (Row 2, Col 2-3)
|
||||
gbc.gridy++;
|
||||
gbc.gridx = 0;
|
||||
patientInfoPanel.add(new JLabel("Số điện thoại:"), gbc);
|
||||
JLabel phoneLabel = new JLabel("Số điện thoại:");
|
||||
phoneLabel.setFont(labelFont);
|
||||
patientInfoPanel.add(phoneLabel, gbc);
|
||||
|
||||
gbc.gridx = 1;
|
||||
patientPhoneField = new JTextField(10);
|
||||
patientPhoneField.setFont(textFont);
|
||||
patientPhoneField.setPreferredSize(textFieldSize);
|
||||
patientInfoPanel.add(patientPhoneField, gbc);
|
||||
|
||||
gbc.gridx = 2;
|
||||
patientInfoPanel.add(new JLabel("Mã BN:"), gbc);
|
||||
JLabel patientIdLabel = new JLabel("Mã BN:");
|
||||
patientIdLabel.setFont(labelFont);
|
||||
patientInfoPanel.add(patientIdLabel, gbc);
|
||||
|
||||
gbc.gridx = 3;
|
||||
patientIdField = new JTextField(5);
|
||||
patientIdField.setFont(textFont);
|
||||
patientIdField.setPreferredSize(textFieldSize);
|
||||
patientIdField.setEditable(false);
|
||||
patientInfoPanel.add(patientIdField, gbc);
|
||||
|
||||
// CCCD (Row 3, Col 0-1)
|
||||
gbc.gridy++;
|
||||
gbc.gridx = 0;
|
||||
gbc.gridwidth = 1;
|
||||
JLabel cccdLabel = new JLabel("CCCD/DDCN:");
|
||||
cccdLabel.setFont(labelFont);
|
||||
patientInfoPanel.add(cccdLabel, gbc);
|
||||
|
||||
gbc.gridx = 1;
|
||||
gbc.gridwidth = 3; // Span across remaining columns
|
||||
cccdField = new JTextField(15);
|
||||
cccdField.setFont(textFont);
|
||||
cccdField.setPreferredSize(textFieldSize);
|
||||
patientInfoPanel.add(cccdField, gbc);
|
||||
gbc.gridwidth = 1; // Reset
|
||||
|
||||
// Add event listener to the addButton (moved here as it's part of this panel now)
|
||||
addButton.addActionListener(e -> {
|
||||
if (!patientIdField.getText().isEmpty()) {
|
||||
@@ -366,6 +410,7 @@ public class AddDialog extends JDialog {
|
||||
String district = (String) districtComboBox.getSelectedItem();
|
||||
String ward = (String) wardComboBox.getSelectedItem();
|
||||
String address = String.join(", ", customerAddress, ward, district, province);
|
||||
String cccd = cccdField.getText();
|
||||
|
||||
//split name into first name and last name
|
||||
String[] nameParts = patientName.split(" ");
|
||||
@@ -392,7 +437,7 @@ public class AddDialog extends JDialog {
|
||||
Date date = dateFormat.parse(dateText);
|
||||
long timestamp = date.getTime(); // This converts the Date to milliseconds since epoch (long)
|
||||
NetworkUtil.sendPacket(ClientHandler.ctx.channel(), new AddPatientRequest(firstName, lastNameStr, timestamp,
|
||||
patientPhone, address, patientGender));
|
||||
patientPhone, address, patientGender, cccd));
|
||||
} catch (ParseException pe) {
|
||||
pe.printStackTrace();
|
||||
JOptionPane.showMessageDialog(null, "Invalid date format: " + dateText);
|
||||
@@ -405,25 +450,33 @@ public class AddDialog extends JDialog {
|
||||
gbc.gridx = 0;
|
||||
gbc.gridwidth = 1;
|
||||
gbc.weightx = 0.0; // Label doesn't expand
|
||||
checkupInfoPanel.add(new JLabel("Bác sĩ khám:"), gbc);
|
||||
JLabel doctorLabel = new JLabel("Bác sĩ khám:");
|
||||
doctorLabel.setFont(labelFont);
|
||||
checkupInfoPanel.add(doctorLabel, gbc);
|
||||
|
||||
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.setFont(textFont);
|
||||
doctorComboBox.setPreferredSize(comboBoxSize);
|
||||
checkupInfoPanel.add(doctorComboBox, gbc);
|
||||
|
||||
// Checkup Type on the same row
|
||||
gbc.gridx = 2;
|
||||
gbc.gridwidth = 1;
|
||||
gbc.weightx = 0.0; // Label doesn't expand
|
||||
checkupInfoPanel.add(new JLabel("Loại khám:"), gbc);
|
||||
JLabel checkupTypeLabel = new JLabel("Loại khám:");
|
||||
checkupTypeLabel.setFont(labelFont);
|
||||
checkupInfoPanel.add(checkupTypeLabel, gbc);
|
||||
|
||||
gbc.gridx = 3;
|
||||
gbc.gridwidth = 1; // Checkup Type ComboBox takes 1 column
|
||||
gbc.weightx = 0.5; // Checkup Type ComboBox takes some horizontal space
|
||||
String[] checkupTypeOptions = {"BENH", "THAI", "KHAC"};
|
||||
String[] checkupTypeOptions = {"BỆNH", "THAI", "KHÁC"};
|
||||
checkupTypeComboBox = new JComboBox<>(checkupTypeOptions);
|
||||
checkupTypeComboBox.setFont(textFont);
|
||||
checkupTypeComboBox.setPreferredSize(comboBoxSize);
|
||||
checkupInfoPanel.add(checkupTypeComboBox, gbc);
|
||||
gbc.weightx = 0.0; // Reset weightx
|
||||
|
||||
@@ -433,13 +486,17 @@ public class AddDialog extends JDialog {
|
||||
gbc.gridy = 0;
|
||||
gbc.gridx = 0;
|
||||
gbc.gridwidth = 1;
|
||||
gbc.weightx = 0.0;
|
||||
addressInfoPanel.add(new JLabel("Địa chỉ cụ thể:"), gbc); // Changed label slightly for clarity
|
||||
gbc.weightx = 0.0;
|
||||
JLabel addressLabel = new JLabel("Địa chỉ cụ thể:");
|
||||
addressLabel.setFont(labelFont);
|
||||
addressInfoPanel.add(addressLabel, gbc); // Changed label slightly for clarity
|
||||
|
||||
gbc.gridx = 1;
|
||||
gbc.gridwidth = 3;
|
||||
gbc.weightx = 1.0;
|
||||
customerAddressField = new JTextField(20);
|
||||
customerAddressField.setFont(textFont);
|
||||
customerAddressField.setPreferredSize(textFieldSize);
|
||||
addressInfoPanel.add(customerAddressField, gbc);
|
||||
gbc.weightx = 0.0;
|
||||
|
||||
@@ -449,17 +506,23 @@ public class AddDialog extends JDialog {
|
||||
gbc.gridwidth = 1; // Each combo box takes 1 logical column in this setup
|
||||
gbc.weightx = 0.33; // Distribute space among the three combo boxes
|
||||
provinceComboBox = new JComboBox<>(LocalStorage.provinces != null ? LocalStorage.provinces : new String[]{"Tỉnh/TP"});
|
||||
provinceComboBox.setFont(textFont);
|
||||
provinceComboBox.setPreferredSize(comboBoxSize);
|
||||
addressInfoPanel.add(provinceComboBox, gbc);
|
||||
|
||||
gbc.gridx = 1;
|
||||
districtModel = new DefaultComboBoxModel<>(new String[]{"Quận/Huyện"});
|
||||
districtComboBox = new JComboBox<>(districtModel);
|
||||
districtComboBox.setFont(textFont);
|
||||
districtComboBox.setPreferredSize(comboBoxSize);
|
||||
districtComboBox.setEnabled(false);
|
||||
addressInfoPanel.add(districtComboBox, gbc);
|
||||
|
||||
gbc.gridx = 2;
|
||||
wardModel = new DefaultComboBoxModel<>(new String[]{"Phường/Xã"});
|
||||
wardComboBox = new JComboBox<>(wardModel);
|
||||
wardComboBox.setFont(textFont);
|
||||
wardComboBox.setPreferredSize(comboBoxSize);
|
||||
wardComboBox.setEnabled(false);
|
||||
addressInfoPanel.add(wardComboBox, gbc);
|
||||
gbc.weightx = 0.0; // Reset weightx for any subsequent components in this panel
|
||||
@@ -548,18 +611,20 @@ public class AddDialog extends JDialog {
|
||||
inputScrollPane.setBorder(BorderFactory.createEmptyBorder()); // Remove scroll pane's own border
|
||||
|
||||
JSplitPane splitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, inputScrollPane, scrollPane);
|
||||
splitPane.setResizeWeight(0.6); // Keep or adjust as needed
|
||||
splitPane.setResizeWeight(0.5); // Keep or adjust as needed
|
||||
add(splitPane, BorderLayout.CENTER);
|
||||
|
||||
|
||||
JPanel ButtonPanel = new JPanel();
|
||||
JButton closeButton = new JButton("Close");
|
||||
closeButton.setFont(labelFont);
|
||||
closeButton.addActionListener(e -> {
|
||||
setVisible(false);
|
||||
});
|
||||
ButtonPanel.add(closeButton);
|
||||
|
||||
saveButton = new JButton("Add to Checkup");
|
||||
saveButton.setFont(labelFont);
|
||||
saveButton.addActionListener(e -> {
|
||||
int patientId = Integer.parseInt(patientIdField.getText());
|
||||
int doctorId = doctorComboBox.getSelectedIndex()+ 1;
|
||||
@@ -585,10 +650,12 @@ public class AddDialog extends JDialog {
|
||||
String patientAddress = patientTable.getValueAt(selectedRow, 4).toString();
|
||||
String patientGender = patientData[selectedRow][5];
|
||||
String patientDob = patientData[selectedRow][6];
|
||||
String patientCccd = patientData[selectedRow][7];
|
||||
patientIdField.setText(patientId);
|
||||
patientNameField.setText(patientName);
|
||||
patientPhoneField.setText(patientPhone);
|
||||
patientGenderField.setSelectedItem(patientGender);
|
||||
cccdField.setText(patientCccd);
|
||||
|
||||
// Extract province, district, ward from the address
|
||||
String[] addressParts = patientAddress.split(", ");
|
||||
|
||||
@@ -142,11 +142,11 @@ public class CheckUpPage extends JPanel {
|
||||
private final ResponseListener<GetOrderInfoByCheckupRes> orderInfoByCheckupListener = this::handleGetOrderInfoByCheckupResponse;
|
||||
private final ResponseListener<GetAllTemplatesRes> getAllTemplatesListener = this::handleGetAllTemplatesResponse;
|
||||
private final ResponseListener<UploadCheckupImageResponse> uploadImageResponseListener = this::handleUploadImageResponse;
|
||||
private JTextField checkupIdField, customerLastNameField, customerFirstNameField,customerAddressField, customerPhoneField, customerIdField;
|
||||
private JTextField checkupIdField, customerLastNameField, customerFirstNameField,customerAddressField, customerPhoneField, customerIdField, customerCccdDdcnField;
|
||||
private JTextArea suggestionField, diagnosisField, conclusionField; // Changed symptomsField to suggestionField
|
||||
private JTextPane notesField;
|
||||
private JComboBox<String> doctorComboBox, statusComboBox, genderComboBox, provinceComboBox, districtComboBox, wardComboBox, checkupTypeComboBox, templateComboBox;
|
||||
private JSpinner customerWeightSpinner, customerHeightSpinner;
|
||||
private JSpinner customerWeightSpinner, customerHeightSpinner, patientHeartRateSpinner, bloodPressureSystolicSpinner, bloodPressureDiastolicSpinner;
|
||||
private JDatePickerImpl datePicker, dobPicker, recheckupDatePicker;
|
||||
private String[][] medicinePrescription = new String[0][0]; // Initialize to empty
|
||||
private String[][] servicePrescription = new String[0][0]; // Initialize to empty
|
||||
@@ -504,8 +504,20 @@ public class CheckUpPage extends JPanel {
|
||||
gbcPatient.fill = GridBagConstraints.HORIZONTAL;
|
||||
gbcPatient.anchor = GridBagConstraints.WEST;
|
||||
|
||||
// Row 1: Name
|
||||
// Row 0: CCCD/DDCN
|
||||
gbcPatient.gridx = 0; gbcPatient.gridy = 0; gbcPatient.weightx = 0.1;
|
||||
JLabel cccdLabel = new JLabel("CCCD/DDCN", SwingConstants.RIGHT);
|
||||
cccdLabel.setFont(labelFont);
|
||||
patientInfoInnerPanel.add(cccdLabel, gbcPatient);
|
||||
|
||||
gbcPatient.gridx = 1; gbcPatient.weightx = 0.4; gbcPatient.gridwidth = 3;
|
||||
customerCccdDdcnField = new JTextField(15);
|
||||
customerCccdDdcnField.setFont(fieldFont);
|
||||
patientInfoInnerPanel.add(customerCccdDdcnField, gbcPatient);
|
||||
gbcPatient.gridwidth = 1; // Reset gridwidth
|
||||
|
||||
// Row 1: Name
|
||||
gbcPatient.gridx = 0; gbcPatient.gridy = 1; gbcPatient.weightx = 0.1;
|
||||
JLabel hoLabel = new JLabel("Họ", SwingConstants.RIGHT);
|
||||
hoLabel.setFont(labelFont);
|
||||
patientInfoInnerPanel.add(hoLabel, gbcPatient);
|
||||
@@ -526,7 +538,7 @@ public class CheckUpPage extends JPanel {
|
||||
patientInfoInnerPanel.add(customerFirstNameField, gbcPatient);
|
||||
|
||||
// Row 2: ID and Phone
|
||||
gbcPatient.gridx = 0; gbcPatient.gridy = 1; gbcPatient.weightx = 0.1;
|
||||
gbcPatient.gridx = 0; gbcPatient.gridy = 2; gbcPatient.weightx = 0.1;
|
||||
JLabel idLabel = new JLabel("Mã BN", SwingConstants.RIGHT);
|
||||
idLabel.setFont(labelFont);
|
||||
patientInfoInnerPanel.add(idLabel, gbcPatient);
|
||||
@@ -553,7 +565,7 @@ public class CheckUpPage extends JPanel {
|
||||
patientInfoInnerPanel.add(customerPhoneField, gbcPatient);
|
||||
|
||||
// Row 3: Gender and DOB
|
||||
gbcPatient.gridx = 0; gbcPatient.gridy = 2;
|
||||
gbcPatient.gridx = 0; gbcPatient.gridy = 3;
|
||||
JLabel genderLabel = new JLabel("Giới tính", SwingConstants.RIGHT);
|
||||
genderLabel.setFont(labelFont);
|
||||
patientInfoInnerPanel.add(genderLabel, gbcPatient);
|
||||
@@ -581,7 +593,7 @@ public class CheckUpPage extends JPanel {
|
||||
patientInfoInnerPanel.add(dobPicker, gbcPatient);
|
||||
|
||||
// Row 4: Weight and Height
|
||||
gbcPatient.gridx = 0; gbcPatient.gridy = 3;
|
||||
gbcPatient.gridx = 0; gbcPatient.gridy = 4;
|
||||
JLabel weightLabel = new JLabel("Cân nặng (kg)", SwingConstants.RIGHT);
|
||||
weightLabel.setFont(labelFont);
|
||||
patientInfoInnerPanel.add(weightLabel, gbcPatient);
|
||||
@@ -611,8 +623,58 @@ public class CheckUpPage extends JPanel {
|
||||
}
|
||||
patientInfoInnerPanel.add(customerHeightSpinner, gbcPatient);
|
||||
|
||||
// Row 5: Address (full width)
|
||||
gbcPatient.gridx = 0; gbcPatient.gridy = 4;
|
||||
// Row 5: Heart Rate and Blood Pressure
|
||||
gbcPatient.gridy++;
|
||||
gbcPatient.gridx = 0;
|
||||
JLabel heartRateLabel = new JLabel("Nhịp tim (l/p)", SwingConstants.RIGHT);
|
||||
heartRateLabel.setFont(labelFont);
|
||||
patientInfoInnerPanel.add(heartRateLabel, gbcPatient);
|
||||
|
||||
gbcPatient.gridx = 1;
|
||||
SpinnerModel heartRateModel = new SpinnerNumberModel(80, 30, 250, 1);
|
||||
patientHeartRateSpinner = new JSpinner(heartRateModel);
|
||||
patientHeartRateSpinner.setFont(fieldFont);
|
||||
JComponent heartRateEditor = patientHeartRateSpinner.getEditor();
|
||||
if (heartRateEditor instanceof JSpinner.DefaultEditor) {
|
||||
((JSpinner.DefaultEditor)heartRateEditor).getTextField().setFont(fieldFont);
|
||||
}
|
||||
patientInfoInnerPanel.add(patientHeartRateSpinner, gbcPatient);
|
||||
|
||||
gbcPatient.gridx = 2;
|
||||
JLabel bloodPressureLabel = new JLabel("Huyết áp (mmHg)", SwingConstants.RIGHT);
|
||||
bloodPressureLabel.setFont(labelFont);
|
||||
patientInfoInnerPanel.add(bloodPressureLabel, gbcPatient);
|
||||
|
||||
gbcPatient.gridx = 3;
|
||||
JPanel bloodPressurePanel = new JPanel(new FlowLayout(FlowLayout.LEFT, 0, 0));
|
||||
bloodPressurePanel.setOpaque(false);
|
||||
|
||||
SpinnerModel systolicModel = new SpinnerNumberModel(120, 50, 300, 1);
|
||||
bloodPressureSystolicSpinner = new JSpinner(systolicModel);
|
||||
bloodPressureSystolicSpinner.setFont(fieldFont);
|
||||
JComponent systolicEditor = bloodPressureSystolicSpinner.getEditor();
|
||||
if (systolicEditor instanceof JSpinner.DefaultEditor) {
|
||||
((JSpinner.DefaultEditor)systolicEditor).getTextField().setFont(fieldFont);
|
||||
}
|
||||
|
||||
SpinnerModel diastolicModel = new SpinnerNumberModel(80, 30, 200, 1);
|
||||
bloodPressureDiastolicSpinner = new JSpinner(diastolicModel);
|
||||
bloodPressureDiastolicSpinner.setFont(fieldFont);
|
||||
JComponent diastolicEditor = bloodPressureDiastolicSpinner.getEditor();
|
||||
if (diastolicEditor instanceof JSpinner.DefaultEditor) {
|
||||
((JSpinner.DefaultEditor)diastolicEditor).getTextField().setFont(fieldFont);
|
||||
}
|
||||
|
||||
JLabel slashLabel = new JLabel(" / ");
|
||||
slashLabel.setFont(fieldFont);
|
||||
|
||||
bloodPressurePanel.add(bloodPressureSystolicSpinner);
|
||||
bloodPressurePanel.add(slashLabel);
|
||||
bloodPressurePanel.add(bloodPressureDiastolicSpinner);
|
||||
patientInfoInnerPanel.add(bloodPressurePanel, gbcPatient);
|
||||
|
||||
// Row 6: Address (full width)
|
||||
gbcPatient.gridx = 0; gbcPatient.gridy = 6;
|
||||
JLabel addressLabel = new JLabel("Địa chỉ", SwingConstants.RIGHT);
|
||||
addressLabel.setFont(labelFont);
|
||||
patientInfoInnerPanel.add(addressLabel, gbcPatient);
|
||||
@@ -622,9 +684,9 @@ public class CheckUpPage extends JPanel {
|
||||
customerAddressField.setFont(fieldFont);
|
||||
patientInfoInnerPanel.add(customerAddressField, gbcPatient);
|
||||
|
||||
// Row 6: Location dropdowns
|
||||
// Row 7: Location dropdowns
|
||||
gbcPatient.gridwidth = 1; // Reset gridwidth
|
||||
gbcPatient.gridx = 1; gbcPatient.gridy = 5;
|
||||
gbcPatient.gridx = 1; gbcPatient.gridy = 7;
|
||||
provinceComboBox = new JComboBox<>(LocalStorage.provinces);
|
||||
provinceComboBox.setFont(fieldFont);
|
||||
patientInfoInnerPanel.add(provinceComboBox, gbcPatient);
|
||||
@@ -690,7 +752,7 @@ public class CheckUpPage extends JPanel {
|
||||
roomControlPanel.add(freeRoomButton, gbcRoom);
|
||||
|
||||
// Add room control panel to the bottom of patient info panel
|
||||
gbcPatient.gridx = 0; gbcPatient.gridy = 6; gbcPatient.gridwidth = 4;
|
||||
gbcPatient.gridx = 0; gbcPatient.gridy = 8; gbcPatient.gridwidth = 4;
|
||||
patientInfoInnerPanel.add(roomControlPanel, gbcPatient);
|
||||
|
||||
// Add back the event listeners
|
||||
@@ -1732,6 +1794,7 @@ public class CheckUpPage extends JPanel {
|
||||
try { customerHeightSpinner.setValue(Double.parseDouble(selectedPatient.getCustomerHeight())); } catch (NumberFormatException e) {log.warn("Invalid height: {}", selectedPatient.getCustomerHeight()); customerHeightSpinner.setValue(0.0);}
|
||||
genderComboBox.setSelectedItem(selectedPatient.getCustomerGender());
|
||||
checkupTypeComboBox.setSelectedItem(selectedPatient.getCheckupType());
|
||||
customerCccdDdcnField.setText(selectedPatient.getCccdDdcn() != null ? selectedPatient.getCccdDdcn() : "");
|
||||
|
||||
NetworkUtil.sendPacket(ClientHandler.ctx.channel(), new GetPatientHistoryRequest(Integer.parseInt(selectedPatient.getCustomerId())));
|
||||
NetworkUtil.sendPacket(ClientHandler.ctx.channel(), new GetOrderInfoByCheckupReq(selectedPatient.getCheckupId()));
|
||||
@@ -3145,6 +3208,7 @@ public class CheckUpPage extends JPanel {
|
||||
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 ===");
|
||||
@@ -3169,6 +3233,7 @@ public class CheckUpPage extends JPanel {
|
||||
log.info("medicinePrescription: {}", (Object) medicinePrescription);
|
||||
log.info("servicePrescription: {}", (Object) servicePrescription);
|
||||
log.info("reCheckupDate: {}", reCheckupDate);
|
||||
log.info("customerCccdDdcn: {}", customerCccdDdcn);
|
||||
log.info("=== End SaveCheckupRequest Data ===");
|
||||
|
||||
|
||||
@@ -3192,6 +3257,7 @@ public class CheckUpPage extends JPanel {
|
||||
checkupType,
|
||||
conclusion, // Ket luan
|
||||
reCheckupDate,
|
||||
customerCccdDdcn,
|
||||
medicinePrescription,
|
||||
servicePrescription
|
||||
);
|
||||
@@ -3280,6 +3346,7 @@ public class CheckUpPage extends JPanel {
|
||||
diagnosisField.setText("");
|
||||
conclusionField.setText("");
|
||||
setRtfContentFromString("{\\rtf1\\ansi\\ansicpg1252\\deff0\\deflang1033{\\fonttbl{\\f0\\fnil\\fcharset163 Times New Roman;}}\\viewkind4\\uc1\\pard\\f0\\fs32\\par}"); // Clear notes
|
||||
customerCccdDdcnField.setText("");
|
||||
|
||||
if (doctorComboBox.getItemCount() > 0) doctorComboBox.setSelectedIndex(0);
|
||||
statusComboBox.setSelectedIndex(0);
|
||||
@@ -3291,6 +3358,9 @@ public class CheckUpPage extends JPanel {
|
||||
|
||||
customerWeightSpinner.setValue(0);
|
||||
customerHeightSpinner.setValue(0);
|
||||
patientHeartRateSpinner.setValue(80);
|
||||
bloodPressureSystolicSpinner.setValue(120);
|
||||
bloodPressureDiastolicSpinner.setValue(80);
|
||||
|
||||
datePicker.getModel().setValue(null);
|
||||
dobPicker.getModel().setValue(null);
|
||||
|
||||
File diff suppressed because it is too large.
Load diff
@@ -1,646 +0,0 @@
|
||||
package BsK.client.ui.component.CheckoutPage;
|
||||
|
||||
import javax.swing.*;
|
||||
import javax.swing.event.DocumentEvent;
|
||||
import javax.swing.event.DocumentListener;
|
||||
import javax.swing.table.DefaultTableModel;
|
||||
import javax.swing.table.TableColumnModel;
|
||||
|
||||
import BsK.client.network.handler.ClientHandler;
|
||||
import BsK.client.network.handler.ResponseListener;
|
||||
import BsK.common.packet.req.GetMedInfoRequest;
|
||||
import BsK.common.packet.res.GetMedInfoResponse;
|
||||
import BsK.common.util.network.NetworkUtil;
|
||||
import BsK.common.util.text.TextUtils;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.awt.*;
|
||||
import java.awt.event.KeyAdapter;
|
||||
import java.awt.event.KeyEvent;
|
||||
import java.awt.event.MouseAdapter;
|
||||
import java.awt.event.MouseEvent;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
|
||||
@Slf4j
|
||||
public class StandaloneMedicineDialog extends JDialog {
|
||||
private JTextField medicineNameField;
|
||||
private JTextField barcodeField; // New field for barcode
|
||||
private JTextField medicineCompanyField;
|
||||
private JTextArea medicineDescriptionField;
|
||||
private JSpinner quantitySpinner;
|
||||
private JTextField quantityLeftField;
|
||||
private JComboBox<String> UnitComboBox;
|
||||
private JTextField priceField;
|
||||
private JTextField totalField;
|
||||
private JSpinner morningSpinner, noonSpinner, eveningSpinner;
|
||||
private JTextArea noteField;
|
||||
private DefaultTableModel tableModel, selectedTableModel;
|
||||
private String[] medcineColumns = {"ID", "Tên thuốc", "Barcode", "Công ty", "Mô tả", "Tồn kho", "ĐVT", "Giá"}; // Added Barcode Column
|
||||
private String[][] medicineData;
|
||||
private final ResponseListener<GetMedInfoResponse> getMedInfoResponseListener = this::getMedInfoHandler;
|
||||
private TableColumnModel columnModel;
|
||||
private HashMap<String, Boolean> selectedMedicine = new HashMap<>();
|
||||
private JTable medicineTable;
|
||||
private JTable selectedTable;
|
||||
private boolean isProgrammaticallySettingMedicineNameField = false;
|
||||
|
||||
private String[][] medicinePrescription;
|
||||
private static final Logger logger = LoggerFactory.getLogger(StandaloneMedicineDialog.class);
|
||||
|
||||
public String[][] getMedicinePrescription() {
|
||||
return medicinePrescription;
|
||||
}
|
||||
|
||||
void getMedInfoHandler(GetMedInfoResponse response) {
|
||||
logger.info("Received medicine data for Standalone Dialog");
|
||||
medicineData = response.getMedInfo(); // Assuming GetMedInfoResponse also returns barcode in medInfo array
|
||||
tableModel.setDataVector(medicineData, medcineColumns);
|
||||
resizeMedicineTableColumns();
|
||||
}
|
||||
|
||||
private void sendGetMedInfoRequest() {
|
||||
logger.info("Sending GetMedInfoRequest for Standalone Dialog");
|
||||
NetworkUtil.sendPacket(ClientHandler.ctx.channel(), new GetMedInfoRequest());
|
||||
}
|
||||
|
||||
public StandaloneMedicineDialog(Frame parent) {
|
||||
super(parent, "Thêm thuốc vào hóa đơn (khách lẻ)", true);
|
||||
setDefaultCloseOperation(DISPOSE_ON_CLOSE);
|
||||
setSize(1250, 800);
|
||||
setLocationRelativeTo(parent);
|
||||
setResizable(true);
|
||||
|
||||
ClientHandler.addResponseListener(GetMedInfoResponse.class, getMedInfoResponseListener);
|
||||
sendGetMedInfoRequest();
|
||||
|
||||
setLayout(new BorderLayout(10, 10));
|
||||
|
||||
JPanel mainInputPanel = new JPanel(new GridBagLayout());
|
||||
mainInputPanel.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));
|
||||
GridBagConstraints mainGbc = new GridBagConstraints();
|
||||
mainGbc.fill = GridBagConstraints.HORIZONTAL;
|
||||
mainGbc.anchor = GridBagConstraints.NORTHWEST;
|
||||
mainGbc.insets = new Insets(5, 5, 5, 5);
|
||||
mainGbc.weightx = 1.0;
|
||||
|
||||
// Search Panel (Name and Barcode)
|
||||
JPanel searchPanel = new JPanel(new GridBagLayout());
|
||||
searchPanel.setBorder(BorderFactory.createTitledBorder(
|
||||
BorderFactory.createEtchedBorder(), "Tìm kiếm thuốc",
|
||||
javax.swing.border.TitledBorder.LEADING, javax.swing.border.TitledBorder.TOP,
|
||||
new Font("Arial", Font.BOLD, 14), new Color(50, 50, 50)
|
||||
));
|
||||
mainGbc.gridx = 0; mainGbc.gridy = 0;
|
||||
mainInputPanel.add(searchPanel, mainGbc);
|
||||
|
||||
JPanel medicineInfoPanel = new JPanel(new GridBagLayout());
|
||||
medicineInfoPanel.setBorder(BorderFactory.createTitledBorder(
|
||||
BorderFactory.createEtchedBorder(), "Thông tin thuốc",
|
||||
javax.swing.border.TitledBorder.LEADING, javax.swing.border.TitledBorder.TOP,
|
||||
new Font("Arial", Font.BOLD, 14), new Color(50, 50, 50)
|
||||
));
|
||||
mainGbc.gridy = 1;
|
||||
mainInputPanel.add(medicineInfoPanel, mainGbc);
|
||||
|
||||
JPanel quantityPricePanel = new JPanel(new GridBagLayout());
|
||||
quantityPricePanel.setBorder(BorderFactory.createTitledBorder(
|
||||
BorderFactory.createEtchedBorder(), "Số lượng & Giá",
|
||||
javax.swing.border.TitledBorder.LEADING, javax.swing.border.TitledBorder.TOP,
|
||||
new Font("Arial", Font.BOLD, 14), new Color(50, 50, 50)
|
||||
));
|
||||
mainGbc.gridy = 2;
|
||||
mainInputPanel.add(quantityPricePanel, mainGbc);
|
||||
|
||||
JPanel dosagePanel = new JPanel(new GridBagLayout());
|
||||
dosagePanel.setBorder(BorderFactory.createTitledBorder(
|
||||
BorderFactory.createEtchedBorder(), "Liều dùng (nếu có)", // Dosage might be optional for direct sale
|
||||
javax.swing.border.TitledBorder.LEADING, javax.swing.border.TitledBorder.TOP,
|
||||
new Font("Arial", Font.BOLD, 14), new Color(50, 50, 50)
|
||||
));
|
||||
mainGbc.gridy = 3;
|
||||
mainInputPanel.add(dosagePanel, mainGbc);
|
||||
|
||||
JPanel notePanel = new JPanel(new GridBagLayout());
|
||||
notePanel.setBorder(BorderFactory.createTitledBorder(
|
||||
BorderFactory.createEtchedBorder(), "Ghi chú (nếu có)",
|
||||
javax.swing.border.TitledBorder.LEADING, javax.swing.border.TitledBorder.TOP,
|
||||
new Font("Arial", Font.BOLD, 14), new Color(50, 50, 50)
|
||||
));
|
||||
mainGbc.gridy = 4;
|
||||
mainInputPanel.add(notePanel, mainGbc);
|
||||
|
||||
JPanel addMedicineButtonPanel = new JPanel(new FlowLayout(FlowLayout.CENTER));
|
||||
JButton addMedicineButton = new JButton("Thêm thuốc vào HĐ");
|
||||
addMedicineButtonPanel.add(addMedicineButton);
|
||||
mainGbc.gridy = 5;
|
||||
mainInputPanel.add(addMedicineButtonPanel, mainGbc);
|
||||
|
||||
mainGbc.gridy = 6; mainGbc.weighty = 1.0;
|
||||
mainInputPanel.add(new JPanel(), mainGbc); // Filler panel
|
||||
|
||||
GridBagConstraints gbc = new GridBagConstraints();
|
||||
gbc.fill = GridBagConstraints.HORIZONTAL;
|
||||
gbc.anchor = GridBagConstraints.WEST;
|
||||
gbc.insets = new Insets(3, 5, 3, 5); // Reduced insets slightly
|
||||
gbc.weightx = 0.0; gbc.weighty = 0.0;
|
||||
|
||||
// Search Panel Content
|
||||
gbc.gridy = 0; gbc.gridx = 0;
|
||||
searchPanel.add(new JLabel("Tên thuốc:"), gbc);
|
||||
gbc.gridx = 1; gbc.weightx = 1.0;
|
||||
medicineNameField = new JTextField(20);
|
||||
searchPanel.add(medicineNameField, gbc);
|
||||
gbc.weightx = 0.0;
|
||||
gbc.gridx = 2; gbc.insets = new Insets(3, 15, 3, 5); // More left inset for barcode label
|
||||
searchPanel.add(new JLabel("Barcode:"), gbc);
|
||||
gbc.insets = new Insets(3, 5, 3, 5);
|
||||
gbc.gridx = 3; gbc.weightx = 1.0;
|
||||
barcodeField = new JTextField(15);
|
||||
searchPanel.add(barcodeField, gbc);
|
||||
gbc.weightx = 0.0;
|
||||
|
||||
// Medicine Info Panel Content
|
||||
gbc.gridy = 0; gbc.gridx = 0;
|
||||
medicineInfoPanel.add(new JLabel("Công ty:"), gbc);
|
||||
gbc.gridx = 1; gbc.weightx = 1.0;
|
||||
medicineCompanyField = new JTextField(20);
|
||||
medicineCompanyField.setEditable(false);
|
||||
medicineInfoPanel.add(medicineCompanyField, gbc);
|
||||
gbc.weightx = 0.0;
|
||||
|
||||
gbc.gridy++; gbc.gridx = 0;
|
||||
gbc.anchor = GridBagConstraints.NORTHWEST;
|
||||
medicineInfoPanel.add(new JLabel("Mô tả:"), gbc);
|
||||
gbc.anchor = GridBagConstraints.WEST;
|
||||
gbc.gridx = 1; gbc.weightx = 1.0;
|
||||
medicineDescriptionField = new JTextArea(2, 20); // Reduced rows
|
||||
medicineDescriptionField.setLineWrap(true);
|
||||
medicineDescriptionField.setWrapStyleWord(true);
|
||||
medicineDescriptionField.setEditable(false);
|
||||
JScrollPane descriptionScrollPane = new JScrollPane(medicineDescriptionField);
|
||||
descriptionScrollPane.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED);
|
||||
medicineInfoPanel.add(descriptionScrollPane, gbc);
|
||||
gbc.weightx = 0.0;
|
||||
|
||||
// Quantity & Price Panel Content (similar to MedicineDialog)
|
||||
gbc.gridy = 0; gbc.gridx = 0;
|
||||
quantityPricePanel.add(new JLabel("Số lượng:"), gbc);
|
||||
gbc.gridx = 1; gbc.weightx = 0.5;
|
||||
quantitySpinner = new JSpinner(new SpinnerNumberModel(1, 1, 1000, 1)); // Increased max quantity
|
||||
quantitySpinner.setPreferredSize(new Dimension(80, 25));
|
||||
quantityPricePanel.add(quantitySpinner, gbc);
|
||||
gbc.gridx = 2; gbc.weightx = 0.0;
|
||||
quantityPricePanel.add(new JLabel("Còn lại:"), gbc);
|
||||
gbc.gridx = 3; gbc.weightx = 0.5;
|
||||
quantityLeftField = new JTextField(5);
|
||||
quantityLeftField.setEditable(false);
|
||||
quantityPricePanel.add(quantityLeftField, gbc);
|
||||
gbc.weightx = 0.0;
|
||||
gbc.gridy++; gbc.gridx = 0;
|
||||
quantityPricePanel.add(new JLabel("ĐVT:"), gbc);
|
||||
gbc.gridx = 1; gbc.weightx = 0.5;
|
||||
String[] units = {"Viên", "Vỉ", "Hộp", "Chai", "Tuýp", "Gói"};
|
||||
UnitComboBox = new JComboBox<>(units);
|
||||
UnitComboBox.setEnabled(false);
|
||||
quantityPricePanel.add(UnitComboBox, gbc);
|
||||
gbc.gridx = 2; gbc.weightx = 0.0;
|
||||
quantityPricePanel.add(new JLabel("Giá (VNĐ):"), gbc);
|
||||
gbc.gridx = 3; gbc.weightx = 0.5;
|
||||
priceField = new JTextField(10);
|
||||
priceField.setEditable(false);
|
||||
quantityPricePanel.add(priceField, gbc);
|
||||
gbc.weightx = 0.0;
|
||||
gbc.gridy++; gbc.gridx = 0;
|
||||
quantityPricePanel.add(new JLabel("Thành tiền (VNĐ):"), gbc);
|
||||
gbc.gridx = 1; gbc.gridwidth = 3; gbc.weightx = 1.0;
|
||||
totalField = new JTextField(10);
|
||||
totalField.setEditable(false);
|
||||
quantityPricePanel.add(totalField, gbc);
|
||||
gbc.gridwidth = 1; gbc.weightx = 0.0;
|
||||
|
||||
// Dosage Panel Content
|
||||
gbc.gridy = 0; gbc.gridx = 0; gbc.weightx = 0.0;
|
||||
dosagePanel.add(new JLabel("Sáng:"), gbc);
|
||||
gbc.gridx = 1; gbc.weightx = 0.3;
|
||||
morningSpinner = new JSpinner(new SpinnerNumberModel(0, 0, 10, 1));
|
||||
morningSpinner.setPreferredSize(new Dimension(60,25));
|
||||
dosagePanel.add(morningSpinner, gbc);
|
||||
gbc.gridx = 2; gbc.weightx = 0.0;
|
||||
dosagePanel.add(new JLabel("Trưa:"), gbc);
|
||||
gbc.gridx = 3; gbc.weightx = 0.3;
|
||||
noonSpinner = new JSpinner(new SpinnerNumberModel(0, 0, 10, 1));
|
||||
noonSpinner.setPreferredSize(new Dimension(60,25));
|
||||
dosagePanel.add(noonSpinner, gbc);
|
||||
gbc.gridx = 4; gbc.weightx = 0.0;
|
||||
dosagePanel.add(new JLabel("Chiều:"), gbc);
|
||||
gbc.gridx = 5; gbc.weightx = 0.3;
|
||||
eveningSpinner = new JSpinner(new SpinnerNumberModel(0, 0, 10, 1));
|
||||
eveningSpinner.setPreferredSize(new Dimension(60,25));
|
||||
dosagePanel.add(eveningSpinner, gbc);
|
||||
gbc.weightx = 0.0;
|
||||
|
||||
// Note Panel Content
|
||||
gbc.gridy = 0; gbc.gridx = 0;
|
||||
notePanel.add(new JLabel("Ghi chú:"), gbc);
|
||||
gbc.anchor = GridBagConstraints.WEST;
|
||||
gbc.gridx = 1; gbc.weightx = 1.0; gbc.fill = GridBagConstraints.BOTH; gbc.weighty = 1.0;
|
||||
noteField = new JTextArea(2, 20); // Reduced rows
|
||||
noteField.setLineWrap(true);
|
||||
noteField.setWrapStyleWord(true);
|
||||
JScrollPane noteScrollPane = new JScrollPane(noteField);
|
||||
noteScrollPane.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED);
|
||||
notePanel.add(noteScrollPane, gbc);
|
||||
gbc.fill = GridBagConstraints.HORIZONTAL; gbc.weightx = 0.0; gbc.weighty = 0.0;
|
||||
|
||||
// Medicine Table (Right Side)
|
||||
tableModel = new DefaultTableModel(medicineData, medcineColumns) {
|
||||
@Override public boolean isCellEditable(int row, int column) { return false; }
|
||||
};
|
||||
medicineTable = new JTable(tableModel);
|
||||
medicineTable.setFont(new Font("Arial", Font.PLAIN, 13));
|
||||
medicineTable.setRowHeight(22);
|
||||
medicineTable.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
|
||||
medicineTable.setAutoCreateRowSorter(true);
|
||||
JScrollPane medicineTableScrollPane = new JScrollPane(medicineTable);
|
||||
medicineTableScrollPane.setPreferredSize(new Dimension(650, 250)); // Wider table
|
||||
|
||||
// Selected Medicine Table (Right Side, Bottom)
|
||||
String[] selectedColumnNames = {"ID", "Tên thuốc", "SL", "ĐVT", "Sáng", "Trưa", "Chiều", "Đơn giá", "Thành tiền", "Ghi chú"};
|
||||
selectedTableModel = new DefaultTableModel(new String[][]{}, selectedColumnNames) {
|
||||
@Override public boolean isCellEditable(int row, int column) {
|
||||
// Allow editing for SL, Dosage, Note in selected table
|
||||
return column == 2 || column == 4 || column == 5 || column == 6 || column == 9;
|
||||
}
|
||||
};
|
||||
selectedTable = new JTable(selectedTableModel);
|
||||
selectedTable.setFont(new Font("Arial", Font.PLAIN, 13));
|
||||
selectedTable.setRowHeight(22);
|
||||
JScrollPane selectedTableScrollPane = new JScrollPane(selectedTable);
|
||||
selectedTableScrollPane.setPreferredSize(new Dimension(650, 180)); // Wider table
|
||||
|
||||
JPanel removeButtonPanel = new JPanel(new FlowLayout(FlowLayout.RIGHT));
|
||||
JButton removeMedicineButton = new JButton("Xóa thuốc đã chọn");
|
||||
removeButtonPanel.add(removeMedicineButton);
|
||||
|
||||
JPanel rightPanel = new JPanel(new BorderLayout(0, 5));
|
||||
rightPanel.add(medicineTableScrollPane, BorderLayout.CENTER);
|
||||
JPanel bottomRightsPanel = new JPanel(new BorderLayout(0,5));
|
||||
bottomRightsPanel.add(selectedTableScrollPane, BorderLayout.CENTER);
|
||||
bottomRightsPanel.add(removeButtonPanel, BorderLayout.SOUTH);
|
||||
rightPanel.add(bottomRightsPanel, BorderLayout.SOUTH);
|
||||
|
||||
JScrollPane mainInputScrollPane = new JScrollPane(mainInputPanel);
|
||||
mainInputScrollPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED);
|
||||
mainInputScrollPane.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
|
||||
mainInputScrollPane.setBorder(BorderFactory.createEmptyBorder());
|
||||
|
||||
JSplitPane splitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, mainInputScrollPane, rightPanel);
|
||||
splitPane.setResizeWeight(0.42); // Adjusted resize weight slightly
|
||||
add(splitPane, BorderLayout.CENTER);
|
||||
|
||||
JPanel bottomButtonPanel = new JPanel(new FlowLayout(FlowLayout.RIGHT));
|
||||
JButton okButton = new JButton("Lưu & Đóng");
|
||||
JButton cancelButton = new JButton("Hủy");
|
||||
bottomButtonPanel.add(okButton);
|
||||
bottomButtonPanel.add(cancelButton);
|
||||
add(bottomButtonPanel, BorderLayout.SOUTH);
|
||||
|
||||
// Event Listeners
|
||||
medicineNameField.getDocument().addDocumentListener(new DocumentListener() {
|
||||
public void changedUpdate(DocumentEvent e) { if (!isProgrammaticallySettingMedicineNameField) SwingUtilities.invokeLater(() -> filterMedicineTableByName()); }
|
||||
public void removeUpdate(DocumentEvent e) { if (!isProgrammaticallySettingMedicineNameField) SwingUtilities.invokeLater(() -> filterMedicineTableByName()); }
|
||||
public void insertUpdate(DocumentEvent e) { if (!isProgrammaticallySettingMedicineNameField) SwingUtilities.invokeLater(() -> filterMedicineTableByName()); }
|
||||
});
|
||||
|
||||
barcodeField.addKeyListener(new KeyAdapter() {
|
||||
@Override
|
||||
public void keyPressed(KeyEvent e) {
|
||||
if (e.getKeyCode() == KeyEvent.VK_ENTER) {
|
||||
filterMedicineTableByBarcode();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
medicineTable.addMouseListener(new MouseAdapter() {
|
||||
@Override
|
||||
public void mouseClicked(MouseEvent e) {
|
||||
if (e.getClickCount() == 1) {
|
||||
SwingUtilities.invokeLater(() -> {
|
||||
int selectedRow = medicineTable.getSelectedRow();
|
||||
if (selectedRow != -1) handleMedicineTableRowSelection(selectedRow);
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
medicineNameField.addKeyListener(new KeyAdapter() {
|
||||
@Override
|
||||
public void keyPressed(KeyEvent e) {
|
||||
handleTableNavigationKeys(e, medicineTable);
|
||||
}
|
||||
});
|
||||
barcodeField.addKeyListener(new KeyAdapter() { // Allow table nav from barcode field too
|
||||
@Override
|
||||
public void keyPressed(KeyEvent e) {
|
||||
if (e.getKeyCode() == KeyEvent.VK_ENTER) {
|
||||
filterMedicineTableByBarcode();
|
||||
} else {
|
||||
handleTableNavigationKeys(e, medicineTable);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
quantitySpinner.addChangeListener(e -> updateTotalField());
|
||||
UnitComboBox.addActionListener(e -> updateTotalField()); // Though disabled, good practice
|
||||
|
||||
addMedicineButton.addActionListener(e -> addSelectedMedicine());
|
||||
removeMedicineButton.addActionListener(e -> removeSelectedMedicine());
|
||||
|
||||
okButton.addActionListener(e -> {
|
||||
collectPrescriptionData();
|
||||
if (medicinePrescription == null || medicinePrescription.length == 0) {
|
||||
// For standalone sale, it's okay to have no prescription if just closing
|
||||
// But if they intend to add items, perhaps a different message or behavior
|
||||
}
|
||||
logger.info("Standalone prescription/items saved.");
|
||||
// Log for debugging
|
||||
for (String[] row : medicinePrescription) {
|
||||
logger.info("Med: ID={}, Name={}, Qty={}, Unit={}, M={}, N={}, E={}, Price={}, Total={}, Note={}",
|
||||
(Object[]) row);
|
||||
}
|
||||
dispose();
|
||||
});
|
||||
|
||||
cancelButton.addActionListener(e -> {
|
||||
medicinePrescription = null; // Clear any collected data if cancelled
|
||||
dispose();
|
||||
});
|
||||
}
|
||||
|
||||
private void handleTableNavigationKeys(KeyEvent e, JTable targetTable) {
|
||||
if (e.getKeyCode() == KeyEvent.VK_ENTER) {
|
||||
if (targetTable.getSelectedRow() != -1) addSelectedMedicine();
|
||||
} else if (e.getKeyCode() == KeyEvent.VK_DOWN) {
|
||||
if (targetTable.getRowCount() > 0) {
|
||||
int selectedRow = targetTable.getSelectedRow();
|
||||
selectedRow = (selectedRow < targetTable.getRowCount() - 1) ? selectedRow + 1 : 0;
|
||||
targetTable.setRowSelectionInterval(selectedRow, selectedRow);
|
||||
targetTable.scrollRectToVisible(targetTable.getCellRect(selectedRow, 0, true));
|
||||
handleMedicineTableRowSelection(selectedRow);
|
||||
}
|
||||
} else if (e.getKeyCode() == KeyEvent.VK_UP) {
|
||||
if (targetTable.getRowCount() > 0) {
|
||||
int selectedRow = targetTable.getSelectedRow();
|
||||
selectedRow = (selectedRow > 0) ? selectedRow - 1 : targetTable.getRowCount() - 1;
|
||||
targetTable.setRowSelectionInterval(selectedRow, selectedRow);
|
||||
targetTable.scrollRectToVisible(targetTable.getCellRect(selectedRow, 0, true));
|
||||
handleMedicineTableRowSelection(selectedRow);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void filterMedicineTableByName() {
|
||||
filterMedicineTable(medicineNameField.getText().trim(), null);
|
||||
}
|
||||
|
||||
private void filterMedicineTableByBarcode() {
|
||||
filterMedicineTable(null, barcodeField.getText().trim());
|
||||
if (medicineTable.getRowCount() == 1) { // If unique match by barcode
|
||||
medicineTable.setRowSelectionInterval(0,0);
|
||||
handleMedicineTableRowSelection(0);
|
||||
addSelectedMedicine(); // Optionally auto-add if unique and quantity is set
|
||||
barcodeField.setText(""); // Clear barcode field after processing
|
||||
medicineNameField.requestFocusInWindow(); // Or quantitySpinner
|
||||
}
|
||||
}
|
||||
|
||||
private void filterMedicineTable(String nameFilter, String barcodeFilter) {
|
||||
if (medicineData == null) return;
|
||||
|
||||
boolean nameIsEmpty = (nameFilter == null || nameFilter.isEmpty());
|
||||
boolean barcodeIsEmpty = (barcodeFilter == null || barcodeFilter.isEmpty());
|
||||
|
||||
if (nameIsEmpty && barcodeIsEmpty) {
|
||||
tableModel.setDataVector(medicineData, medcineColumns);
|
||||
resizeMedicineTableColumns();
|
||||
medicineTable.clearSelection();
|
||||
clearInputFields(); // Also clear input fields when filter is cleared
|
||||
} else {
|
||||
List<String[]> filteredData = new ArrayList<>();
|
||||
String lowerCaseNameFilter = nameIsEmpty ? "" : TextUtils.removeAccents(nameFilter.toLowerCase());
|
||||
// Barcode is usually exact match or startsWith, not contains typically
|
||||
String lowerCaseBarcodeFilter = barcodeIsEmpty ? "" : barcodeFilter.toLowerCase();
|
||||
|
||||
for (String[] row : medicineData) {
|
||||
boolean nameMatch = nameIsEmpty; // True if no name filter
|
||||
boolean barcodeMatch = barcodeIsEmpty; // True if no barcode filter
|
||||
|
||||
if (!nameIsEmpty && row.length > 1 && row[1] != null) {
|
||||
nameMatch = TextUtils.removeAccents(row[1].toLowerCase()).contains(lowerCaseNameFilter);
|
||||
}
|
||||
// Assuming barcode is at index 2 in medicineData from server (ID, Name, Barcode, Company...)
|
||||
if (!barcodeIsEmpty && row.length > 2 && row[2] != null) {
|
||||
barcodeMatch = row[2].toLowerCase().equals(lowerCaseBarcodeFilter); // Exact match for barcode
|
||||
}
|
||||
|
||||
if (nameMatch && barcodeMatch) { // If name filter provided, must match name. If barcode provided, must match barcode.
|
||||
filteredData.add(row);
|
||||
}
|
||||
}
|
||||
tableModel.setDataVector(filteredData.toArray(new String[0][0]), medcineColumns);
|
||||
resizeMedicineTableColumns();
|
||||
if (!filteredData.isEmpty()) {
|
||||
medicineTable.setRowSelectionInterval(0,0);
|
||||
handleMedicineTableRowSelection(0);
|
||||
} else {
|
||||
clearInputFields();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void resizeMedicineTableColumns() {
|
||||
if (medicineTable.getColumnCount() == 0) return;
|
||||
columnModel = medicineTable.getColumnModel();
|
||||
// ID, Tên thuốc, Barcode, Công ty, Mô tả, Tồn kho, ĐVT, Giá
|
||||
columnModel.getColumn(0).setPreferredWidth(30); // ID
|
||||
columnModel.getColumn(1).setPreferredWidth(150); // Tên thuốc
|
||||
columnModel.getColumn(2).setPreferredWidth(100); // Barcode
|
||||
columnModel.getColumn(3).setPreferredWidth(100); // Công ty
|
||||
columnModel.getColumn(4).setPreferredWidth(180); // Mô tả
|
||||
columnModel.getColumn(5).setPreferredWidth(50); // Tồn kho
|
||||
columnModel.getColumn(6).setPreferredWidth(40); // ĐVT
|
||||
columnModel.getColumn(7).setPreferredWidth(60); // Giá
|
||||
}
|
||||
|
||||
private void handleMedicineTableRowSelection(int viewRow) {
|
||||
if (viewRow < 0 || viewRow >= medicineTable.getRowCount()) {
|
||||
clearInputFields();
|
||||
return;
|
||||
}
|
||||
int modelRow = medicineTable.convertRowIndexToModel(viewRow);
|
||||
|
||||
isProgrammaticallySettingMedicineNameField = true;
|
||||
medicineNameField.setText(tableModel.getValueAt(modelRow, 1).toString());
|
||||
isProgrammaticallySettingMedicineNameField = false;
|
||||
// Assuming barcode is column 2. If not present in tableModel directly, might need to fetch from medicineData using ID
|
||||
if (tableModel.getColumnCount() > 2 && tableModel.getValueAt(modelRow, 2) != null) {
|
||||
barcodeField.setText(tableModel.getValueAt(modelRow, 2).toString());
|
||||
}
|
||||
medicineCompanyField.setText(tableModel.getValueAt(modelRow, 3).toString());
|
||||
medicineDescriptionField.setText(tableModel.getValueAt(modelRow, 4).toString());
|
||||
quantityLeftField.setText(tableModel.getValueAt(modelRow, 5).toString());
|
||||
UnitComboBox.setSelectedItem(tableModel.getValueAt(modelRow, 6).toString());
|
||||
priceField.setText(tableModel.getValueAt(modelRow, 7).toString());
|
||||
|
||||
quantitySpinner.setValue(1);
|
||||
morningSpinner.setValue(0); // Reset dosage for standalone sale, or make it optional
|
||||
noonSpinner.setValue(0);
|
||||
eveningSpinner.setValue(0);
|
||||
noteField.setText("");
|
||||
updateTotalField();
|
||||
}
|
||||
|
||||
private void clearInputFields() {
|
||||
// Don't clear medicineNameField or barcodeField as they are used for filtering
|
||||
medicineCompanyField.setText("");
|
||||
medicineDescriptionField.setText("");
|
||||
quantityLeftField.setText("");
|
||||
UnitComboBox.setSelectedIndex(0); // Or set to a default/blank if applicable
|
||||
priceField.setText("");
|
||||
totalField.setText("");
|
||||
quantitySpinner.setValue(1);
|
||||
morningSpinner.setValue(0);
|
||||
noonSpinner.setValue(0);
|
||||
eveningSpinner.setValue(0);
|
||||
noteField.setText("");
|
||||
}
|
||||
|
||||
private void updateTotalField() {
|
||||
try {
|
||||
int quantity = (Integer) quantitySpinner.getValue();
|
||||
if (quantity < 0) { quantitySpinner.setValue(0); quantity = 0; }
|
||||
double price = priceField.getText().isEmpty() ? 0 : Double.parseDouble(priceField.getText().replace(",",""));
|
||||
totalField.setText(String.format("%,.0f", quantity * price)); // Format with commas
|
||||
} catch (NumberFormatException e) {
|
||||
totalField.setText("Giá trị không hợp lệ");
|
||||
logger.error("Error parsing price for total calculation: " + priceField.getText(), e);
|
||||
}
|
||||
}
|
||||
|
||||
private void addSelectedMedicine() {
|
||||
int selectedRowInMedicineTable = medicineTable.getSelectedRow();
|
||||
String medicineId, name, unit, currentPrice, barcodeVal;
|
||||
|
||||
if (selectedRowInMedicineTable != -1) {
|
||||
int modelRow = medicineTable.convertRowIndexToModel(selectedRowInMedicineTable);
|
||||
medicineId = tableModel.getValueAt(modelRow, 0).toString();
|
||||
name = tableModel.getValueAt(modelRow, 1).toString();
|
||||
barcodeVal = tableModel.getColumnCount() > 2 && tableModel.getValueAt(modelRow, 2) != null ? tableModel.getValueAt(modelRow, 2).toString() : "N/A";
|
||||
unit = tableModel.getValueAt(modelRow, 6).toString(); // ĐVT is at 6 (0-indexed)
|
||||
currentPrice = tableModel.getValueAt(modelRow, 7).toString(); // Giá is at 7
|
||||
} else if (!medicineNameField.getText().isEmpty() || !barcodeField.getText().isEmpty()){
|
||||
// Attempt to find by name or barcode if no table selection but fields have text
|
||||
String searchName = medicineNameField.getText().trim();
|
||||
String searchBarcode = barcodeField.getText().trim();
|
||||
String foundId = null, foundUnit = null, foundPrice = null, actualName = null, actualBarcode = null;
|
||||
|
||||
for (String[] med : medicineData) { // medicineData: ID, Tên thuốc, Barcode, Công ty, Mô tả, Tồn kho, ĐVT, Giá
|
||||
boolean nameMatches = !searchName.isEmpty() && TextUtils.removeAccents(med[1].toLowerCase()).contains(TextUtils.removeAccents(searchName.toLowerCase()));
|
||||
boolean barcodeMatches = !searchBarcode.isEmpty() && med.length > 2 && med[2] != null && med[2].equalsIgnoreCase(searchBarcode);
|
||||
if (nameMatches || barcodeMatches) {
|
||||
foundId = med[0]; actualName = med[1]; actualBarcode = med[2];
|
||||
foundUnit = med[6]; foundPrice = med[7];
|
||||
break; // Take first match
|
||||
}
|
||||
}
|
||||
if (foundId == null) {
|
||||
JOptionPane.showMessageDialog(this, "Không tìm thấy thuốc khớp với tên hoặc barcode đã nhập.", "Không tìm thấy thuốc", JOptionPane.WARNING_MESSAGE);
|
||||
return;
|
||||
}
|
||||
medicineId = foundId; name = actualName; unit = foundUnit; currentPrice = foundPrice; barcodeVal = actualBarcode;
|
||||
} else {
|
||||
JOptionPane.showMessageDialog(this, "Vui lòng chọn một thuốc từ danh sách hoặc nhập tên/barcode.", "Chưa chọn thuốc", JOptionPane.WARNING_MESSAGE);
|
||||
return;
|
||||
}
|
||||
|
||||
int quantity = (Integer) quantitySpinner.getValue();
|
||||
int morningVal = (Integer) morningSpinner.getValue();
|
||||
int noonVal = (Integer) noonSpinner.getValue();
|
||||
int eveningVal = (Integer) eveningSpinner.getValue();
|
||||
String note = noteField.getText();
|
||||
String totalAmount = totalField.getText().replace(",",""); // Remove comma for internal storage if needed
|
||||
|
||||
if (quantity <= 0) {
|
||||
JOptionPane.showMessageDialog(this, "Số lượng phải lớn hơn 0.", "Số lượng không hợp lệ", JOptionPane.WARNING_MESSAGE);
|
||||
return;
|
||||
}
|
||||
selectedTableModel.addRow(new Object[]{medicineId, name, quantity, unit, morningVal, noonVal, eveningVal, currentPrice, totalAmount, note});
|
||||
}
|
||||
|
||||
private void removeSelectedMedicine() {
|
||||
int selectedRow = selectedTable.getSelectedRow();
|
||||
if (selectedRow != -1) {
|
||||
selectedTableModel.removeRow(selectedRow);
|
||||
} else {
|
||||
JOptionPane.showMessageDialog(this, "Vui lòng chọn một thuốc từ bảng dưới để xóa.", "Chưa chọn thuốc", JOptionPane.WARNING_MESSAGE);
|
||||
}
|
||||
}
|
||||
|
||||
private void collectPrescriptionData() {
|
||||
int rowCount = selectedTableModel.getRowCount();
|
||||
if (rowCount == 0) {
|
||||
medicinePrescription = new String[0][0];
|
||||
return;
|
||||
}
|
||||
medicinePrescription = new String[rowCount][10];
|
||||
for (int i = 0; i < rowCount; i++) {
|
||||
for (int j = 0; j < 10; j++) {
|
||||
medicinePrescription[i][j] = selectedTableModel.getValueAt(i, j) != null ? selectedTableModel.getValueAt(i, j).toString() : "";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dispose() {
|
||||
logger.info("Cleaning up StandaloneMedicineDialog listeners");
|
||||
ClientHandler.deleteListener(GetMedInfoResponse.class); // Ensure this matches the listener added
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
// Main method for testing this dialog independently
|
||||
public static void main(String[] args) {
|
||||
SwingUtilities.invokeLater(() -> {
|
||||
JFrame frame = new JFrame("Test Standalone Medicine Dialog");
|
||||
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
|
||||
frame.setSize(600, 400);
|
||||
frame.setLocationRelativeTo(null);
|
||||
JButton openDialogButton = new JButton("Open Standalone Medicine Dialog");
|
||||
openDialogButton.addActionListener(e -> {
|
||||
StandaloneMedicineDialog dialog = new StandaloneMedicineDialog(frame);
|
||||
dialog.setVisible(true);
|
||||
String[][] prescription = dialog.getMedicinePrescription();
|
||||
if (prescription != null && prescription.length > 0) {
|
||||
System.out.println("Standalone Items obtained:");
|
||||
for (String[] item : prescription) {
|
||||
// Ensure correct number of items for format string
|
||||
if (item.length == 10) {
|
||||
System.out.println(String.format("ID:%s, Name:%s, Qty:%s, Unit:%s, M:%s, N:%s, E:%s, Price:%s, Total:%s, Note:%s",
|
||||
(Object[]) item));
|
||||
} else {
|
||||
System.out.println("Item with incorrect number of fields: " + java.util.Arrays.toString(item));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
System.out.println("No items or dialog was cancelled.");
|
||||
}
|
||||
});
|
||||
frame.setLayout(new FlowLayout());
|
||||
frame.add(openDialogButton);
|
||||
frame.setVisible(true);
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -26,6 +26,8 @@ public class Patient {
|
||||
private String checkupType;
|
||||
private String conclusion;
|
||||
private String reCheckupDate;
|
||||
private String cccdDdcn;
|
||||
|
||||
|
||||
public Patient(String[][] array) {
|
||||
this.checkupId = array[0][0];
|
||||
@@ -47,6 +49,9 @@ public class Patient {
|
||||
this.checkupType = array[0][16];
|
||||
this.conclusion = array[0][17];
|
||||
this.reCheckupDate = array[0][18];
|
||||
if (array[0].length > 19) {
|
||||
this.cccdDdcn = array[0][19];
|
||||
}
|
||||
}
|
||||
|
||||
// New constructor for a single patient data row
|
||||
@@ -73,5 +78,8 @@ public class Patient {
|
||||
this.checkupType = data[16];
|
||||
this.conclusion = data[17];
|
||||
this.reCheckupDate = data[18];
|
||||
if (data.length > 19) {
|
||||
this.cccdDdcn = data[19];
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -15,4 +15,5 @@ public class AddPatientRequest implements Packet {
|
||||
String patientPhone;
|
||||
String patientAddress;
|
||||
String patientGender;
|
||||
String patientCccdDdcn;
|
||||
}
|
||||
@@ -5,29 +5,35 @@ import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
@EqualsAndHashCode//(callSuper = true) // Cannot call super on an interface implementation
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
public class SaveCheckupRequest implements Packet {
|
||||
private String checkupId;
|
||||
private String checkupDate; // Consider sending as long (timestamp) if consistency is needed
|
||||
private String customerId;
|
||||
private String customerLastName;
|
||||
private String customerFirstName;
|
||||
private String customerDob; // Consider sending as long (timestamp)
|
||||
private String customerGender;
|
||||
private String customerAddress; // Full address string: "Street, Ward, District, Province"
|
||||
private String customerNumber; // Phone number
|
||||
private String customerWeight;
|
||||
private String customerHeight;
|
||||
private String doctorId; // Or doctorId if preferred for backend processing
|
||||
private String suggestions;
|
||||
private String diagnosis;
|
||||
private String notes;
|
||||
private String status;
|
||||
private String checkupType;
|
||||
private String conclusion;
|
||||
private String reCheckupDate;
|
||||
private String[][] medicinePrescription; // Structure: [med_id, name, quantity, unit, dose_morning, dose_noon, dose_evening, unit_price, total_price, notes]
|
||||
private String[][] servicePrescription; // Structure: [ser_id, name, quantity, unit_price, total_price, notes]
|
||||
String checkupId;
|
||||
String customerId;
|
||||
String doctorId;
|
||||
String checkupDate;
|
||||
|
||||
// Checkup Details
|
||||
String suggestions;
|
||||
String diagnosis;
|
||||
String notes;
|
||||
String status;
|
||||
String checkupType;
|
||||
String conclusion;
|
||||
String reCheckupDate;
|
||||
|
||||
// Patient Details
|
||||
String customerFirstName;
|
||||
String customerLastName;
|
||||
String customerDob;
|
||||
String customerGender;
|
||||
String customerAddress;
|
||||
String customerNumber;
|
||||
String customerWeight;
|
||||
String customerHeight;
|
||||
String customerCccdDdcn;
|
||||
|
||||
// Prescriptions
|
||||
String[][] medicinePrescription;
|
||||
String[][] servicePrescription;
|
||||
}
|
||||
@@ -110,7 +110,7 @@ public class ServerHandler extends SimpleChannelInboundHandler<TextWebSocketFram
|
||||
ResultSet rs = statement.executeQuery(
|
||||
"select a.checkup_id, a.checkup_date, c.customer_last_name, c.customer_first_name,\n" +
|
||||
"d.doctor_first_name, d.doctor_last_name, a.suggestion, a.diagnosis, a.notes, a.status, a.customer_id, \n" +
|
||||
"c.customer_number, c.customer_address, c.customer_weight, c.customer_height, c.customer_gender, c.customer_dob, a.checkup_type, a.conclusion, a.reCheckupDate\n" +
|
||||
"c.customer_number, c.customer_address, c.customer_weight, c.customer_height, c.customer_gender, c.customer_dob, a.checkup_type, a.conclusion, a.reCheckupDate, c.cccd_ddcn\n" +
|
||||
"from checkup as a\n" +
|
||||
"join customer as c on a.customer_id = c.customer_id\n" +
|
||||
"join Doctor D on a.doctor_id = D.doctor_id\n" +
|
||||
@@ -148,11 +148,12 @@ public class ServerHandler extends SimpleChannelInboundHandler<TextWebSocketFram
|
||||
String checkupType = rs.getString("checkup_type");
|
||||
String conclusion = rs.getString("conclusion");
|
||||
String reCheckupDate = rs.getString("reCheckupDate");
|
||||
String cccdDdcn = rs.getString("cccd_ddcn");
|
||||
String result = String.join("|", checkupId,
|
||||
checkupDate, customerLastName, customerFirstName,
|
||||
doctorLastName + " " + doctorFirstName, suggestion,
|
||||
diagnosis, notes, status, customerId, customerNumber, customerAddress, customerWeight, customerHeight,
|
||||
customerGender, customerDob, checkupType, conclusion, reCheckupDate
|
||||
customerGender, customerDob, checkupType, conclusion, reCheckupDate, cccdDdcn
|
||||
);
|
||||
|
||||
resultList.add(result);
|
||||
@@ -177,7 +178,7 @@ public class ServerHandler extends SimpleChannelInboundHandler<TextWebSocketFram
|
||||
ResultSet rs = statement.executeQuery(
|
||||
"select a.checkup_id, a.checkup_date, c.customer_last_name, c.customer_first_name,\n" +
|
||||
"d.doctor_first_name, d.doctor_last_name, a.suggestion, a.diagnosis, a.notes, a.status, a.customer_id, \n" +
|
||||
"c.customer_number, c.customer_address, c.customer_weight, c.customer_height, c.customer_gender, c.customer_dob, a.checkup_type, a.conclusion, a.reCheckupDate\n" +
|
||||
"c.customer_number, c.customer_address, c.customer_weight, c.customer_height, c.customer_gender, c.customer_dob, a.checkup_type, a.conclusion, a.reCheckupDate, c.cccd_ddcn\n" +
|
||||
"from checkup as a\n" +
|
||||
"join customer as c on a.customer_id = c.customer_id\n" +
|
||||
"join Doctor D on a.doctor_id = D.doctor_id\n" +
|
||||
@@ -219,12 +220,13 @@ public class ServerHandler extends SimpleChannelInboundHandler<TextWebSocketFram
|
||||
String checkupType = rs.getString("checkup_type");
|
||||
String conclusion = rs.getString("conclusion");
|
||||
String reCheckupDate = rs.getString("reCheckupDate");
|
||||
String cccdDdcn = rs.getString("cccd_ddcn");
|
||||
|
||||
String result = String.join("|", checkupId,
|
||||
checkupDate, customerLastName, customerFirstName,
|
||||
doctorLastName + " " + doctorFirstName, suggestion,
|
||||
diagnosis, notes, status, customerId, customerNumber, customerAddress, customerWeight, customerHeight,
|
||||
customerGender, customerDob, checkupType, conclusion, reCheckupDate
|
||||
customerGender, customerDob, checkupType, conclusion, reCheckupDate, cccdDdcn
|
||||
);
|
||||
|
||||
resultList.add(result);
|
||||
@@ -446,7 +448,7 @@ public class ServerHandler extends SimpleChannelInboundHandler<TextWebSocketFram
|
||||
try {
|
||||
ResultSet rs = statement.executeQuery(
|
||||
"SELECT customer_id, customer_last_name, customer_first_name, customer_dob, customer_number, " +
|
||||
"customer_address, customer_address, customer_gender\n" +
|
||||
"customer_address, customer_address, customer_gender, cccd_ddcn\n" +
|
||||
"FROM Customer\n" +
|
||||
"ORDER BY customer_id DESC\n" +
|
||||
"LIMIT 20;");
|
||||
@@ -463,9 +465,10 @@ public class ServerHandler extends SimpleChannelInboundHandler<TextWebSocketFram
|
||||
String customerNumber = rs.getString("customer_number");
|
||||
String customerAddress = rs.getString("customer_address");
|
||||
String customerGender = rs.getString("customer_gender");
|
||||
String cccdDdcn = rs.getString("cccd_ddcn");
|
||||
|
||||
String result = String.join("|", customerId, customerLastName + " " + customerFirstName,
|
||||
year, customerNumber, customerAddress, customerGender, customerDob);
|
||||
year, customerNumber, customerAddress, customerGender, customerDob, cccdDdcn);
|
||||
resultList.add(result);
|
||||
}
|
||||
|
||||
@@ -594,7 +597,7 @@ public class ServerHandler extends SimpleChannelInboundHandler<TextWebSocketFram
|
||||
Server.connection.setAutoCommit(false);
|
||||
|
||||
PreparedStatement preparedStatement = Server.connection.prepareStatement(
|
||||
"INSERT INTO Customer (customer_last_name, customer_first_name, customer_dob, customer_number, customer_address, customer_gender) VALUES (?, ?, ?, ?, ?, ?)",
|
||||
"INSERT INTO Customer (customer_last_name, customer_first_name, customer_dob, customer_number, customer_address, customer_gender, cccd_ddcn) VALUES (?, ?, ?, ?, ?, ?, ?)",
|
||||
PreparedStatement.RETURN_GENERATED_KEYS // Use this instead of separate query
|
||||
);
|
||||
preparedStatement.setString(1, addPatientRequest.getPatientLastName());
|
||||
@@ -603,6 +606,7 @@ public class ServerHandler extends SimpleChannelInboundHandler<TextWebSocketFram
|
||||
preparedStatement.setString(4, addPatientRequest.getPatientPhone());
|
||||
preparedStatement.setString(5, addPatientRequest.getPatientAddress());
|
||||
preparedStatement.setString(6, addPatientRequest.getPatientGender());
|
||||
preparedStatement.setString(7, addPatientRequest.getPatientCccdDdcn());
|
||||
preparedStatement.executeUpdate();
|
||||
|
||||
// Get the generated key safely
|
||||
@@ -722,8 +726,8 @@ public class ServerHandler extends SimpleChannelInboundHandler<TextWebSocketFram
|
||||
INSERT INTO Customer (
|
||||
customer_id, customer_first_name, customer_last_name, customer_dob,
|
||||
customer_gender, customer_address, customer_number,
|
||||
customer_weight, customer_height
|
||||
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)
|
||||
customer_weight, customer_height, cccd_ddcn
|
||||
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
||||
ON CONFLICT(customer_id) DO UPDATE SET
|
||||
customer_first_name = excluded.customer_first_name,
|
||||
customer_last_name = excluded.customer_last_name,
|
||||
@@ -732,7 +736,8 @@ public class ServerHandler extends SimpleChannelInboundHandler<TextWebSocketFram
|
||||
customer_address = excluded.customer_address,
|
||||
customer_number = excluded.customer_number,
|
||||
customer_weight = excluded.customer_weight,
|
||||
customer_height = excluded.customer_height
|
||||
customer_height = excluded.customer_height,
|
||||
cccd_ddcn = excluded.cccd_ddcn
|
||||
""";
|
||||
|
||||
PreparedStatement customerStmt = conn.prepareStatement(customerSql);
|
||||
@@ -745,6 +750,7 @@ public class ServerHandler extends SimpleChannelInboundHandler<TextWebSocketFram
|
||||
customerStmt.setString(7, saveCheckupRequest.getCustomerNumber());
|
||||
customerStmt.setString(8, saveCheckupRequest.getCustomerWeight());
|
||||
customerStmt.setString(9, saveCheckupRequest.getCustomerHeight());
|
||||
customerStmt.setString(10, saveCheckupRequest.getCustomerCccdDdcn());
|
||||
customerStmt.executeUpdate();
|
||||
log.info("Customer saved successfully");
|
||||
// 2. Generate prescription_id if we have medicine prescriptions
|
||||
|
||||
Binary file not shown.
Reference in new issue
Block a user