mirror of
https://github.com/tiennm99/BSK-All-in-One-Clinic-Management-System.git
synced 2026-10-14 16:16:50 +00:00
[add] Implement call patient feature and enhance CheckUpPage UI
This commit is contained in:
1 parent
178795a695
commit
fc99bc6e1f
10 files changed
+902
-318
No files matched your search
@@ -121,3 +121,4 @@ buildNumber.properties
|
||||
.project
|
||||
# JDT-specific (Eclipse Java Development Tools)
|
||||
.classpath
|
||||
src/main/resources/database/BSK.db
|
||||
@@ -10,6 +10,8 @@ import BsK.client.ui.component.CheckUpPage.ServiceDialog.ServiceDialog;
|
||||
import BsK.client.ui.component.MainFrame;
|
||||
import BsK.client.ui.component.common.DateLabelFormatter;
|
||||
import BsK.client.ui.component.common.RoundedPanel;
|
||||
import BsK.client.ui.component.QueueViewPage.QueueViewPage;
|
||||
import BsK.common.entity.Status;
|
||||
import BsK.common.packet.req.*;
|
||||
import BsK.common.packet.res.*;
|
||||
import BsK.common.util.network.NetworkUtil;
|
||||
@@ -22,6 +24,7 @@ import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import javax.swing.*;
|
||||
import javax.swing.border.TitledBorder;
|
||||
import javax.swing.table.DefaultTableModel;
|
||||
import java.awt.*;
|
||||
import java.awt.event.ActionEvent;
|
||||
@@ -45,6 +48,7 @@ public class CheckUpPage extends JPanel {
|
||||
private final ResponseListener<GetCustomerHistoryResponse> customerHistoryListener = this::handleGetCustomerHistoryResponse;
|
||||
private final ResponseListener<GetDistrictResponse> districtResponseListener = this::handleGetDistrictResponse;
|
||||
private final ResponseListener<GetWardResponse> wardResponseListener = this::handleGetWardResponse;
|
||||
private final ResponseListener<CallPatientResponse> callPatientResponseListener = this::handleCallPatientResponse;
|
||||
private JTextField checkupIdField, customerLastNameField, customerFirstNameField,customerAddressField, customerPhoneField, customerIdField;
|
||||
private JTextArea symptomsField, diagnosisField, notesField;
|
||||
private JComboBox<String> doctorComboBox, statusComboBox, genderComboBox, provinceComboBox, districtComboBox, wardComboBox;
|
||||
@@ -59,6 +63,11 @@ public class CheckUpPage extends JPanel {
|
||||
private int previousSelectedRow = -1;
|
||||
private boolean saved = false;
|
||||
private DefaultComboBoxModel<String> districtModel, wardModel;
|
||||
private JComboBox<String> callRoomComboBox;
|
||||
private JButton callPatientButton;
|
||||
private JLabel callingStatusLabel;
|
||||
|
||||
private QueueViewPage tvQueueFrame;
|
||||
|
||||
boolean returnCell = false;
|
||||
public void updateQueue() {
|
||||
@@ -99,12 +108,12 @@ public class CheckUpPage extends JPanel {
|
||||
public CheckUpPage(MainFrame mainFrame) {
|
||||
setLayout(new BorderLayout());
|
||||
|
||||
|
||||
ClientHandler.addResponseListener(GetCheckUpQueueResponse.class, checkUpQueueListener);
|
||||
ClientHandler.addResponseListener(GetCheckUpQueueUpdateResponse.class, checkUpQueueUpdateListener);
|
||||
ClientHandler.addResponseListener(GetCustomerHistoryResponse.class, customerHistoryListener);
|
||||
ClientHandler.addResponseListener(GetDistrictResponse.class, districtResponseListener);
|
||||
ClientHandler.addResponseListener(GetWardResponse.class, wardResponseListener);
|
||||
ClientHandler.addResponseListener(CallPatientResponse.class, callPatientResponseListener);
|
||||
updateQueue();
|
||||
|
||||
// Navigation bar
|
||||
@@ -194,22 +203,49 @@ public class CheckUpPage extends JPanel {
|
||||
public void mouseClicked(MouseEvent e) {
|
||||
if (SwingUtilities.isLeftMouseButton(e)) { // Check if it's a left-click
|
||||
JPopupMenu popupMenu = new JPopupMenu();
|
||||
JMenuItem item1 = new JMenuItem("Option 1");
|
||||
JMenuItem item2 = new JMenuItem("Option 2");
|
||||
JMenuItem item3 = new JMenuItem("Option 3");
|
||||
|
||||
// Add action listeners to the menu items
|
||||
item1.addActionListener(event -> System.out.println("Option 1 selected"));
|
||||
item2.addActionListener(event -> System.out.println("Option 2 selected"));
|
||||
item3.addActionListener(event -> System.out.println("Option 3 selected"));
|
||||
JMenuItem profileItem = new JMenuItem("User Profile");
|
||||
JMenuItem settingsItem = new JMenuItem("Settings");
|
||||
JMenuItem logoutItem = new JMenuItem("Logout");
|
||||
|
||||
profileItem.addActionListener(event -> {
|
||||
System.out.println("User Profile selected");
|
||||
// Placeholder for profile action
|
||||
JOptionPane.showMessageDialog(mainFrame, "User Profile feature coming soon!", "Info", JOptionPane.INFORMATION_MESSAGE);
|
||||
});
|
||||
|
||||
settingsItem.addActionListener(event -> {
|
||||
System.out.println("Settings selected");
|
||||
// Placeholder for settings action
|
||||
JOptionPane.showMessageDialog(mainFrame, "Settings feature coming soon!", "Info", JOptionPane.INFORMATION_MESSAGE);
|
||||
});
|
||||
|
||||
logoutItem.addActionListener(event -> {
|
||||
System.out.println("Logout selected");
|
||||
// Send LogoutRequest to server
|
||||
NetworkUtil.sendPacket(ClientHandler.ctx.channel(), new LogoutRequest());
|
||||
|
||||
// Clear local storage
|
||||
LocalStorage.username = null;
|
||||
LocalStorage.userId = -1; // Or whatever your default/unauthenticated user ID is
|
||||
// Clear any other sensitive session data from LocalStorage
|
||||
|
||||
// Navigate to LandingPage
|
||||
mainFrame.showPage("LandingPage");
|
||||
});
|
||||
|
||||
// Add items to the popup menu
|
||||
popupMenu.add(item1);
|
||||
popupMenu.add(item2);
|
||||
popupMenu.add(item3);
|
||||
popupMenu.add(profileItem);
|
||||
popupMenu.add(settingsItem);
|
||||
popupMenu.addSeparator(); // Adds a visual separator before logout
|
||||
popupMenu.add(logoutItem);
|
||||
|
||||
// Set preferred width after items are added, height will be based on content
|
||||
int currentPreferredHeight = popupMenu.getPreferredSize().height;
|
||||
popupMenu.setPreferredSize(new Dimension(150, currentPreferredHeight));
|
||||
|
||||
// Show the popup
|
||||
popupMenu.show(welcomeLabel, e.getX(), e.getY());
|
||||
popupMenu.show(welcomeLabel, 0, welcomeLabel.getHeight());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -247,6 +283,33 @@ public class CheckUpPage extends JPanel {
|
||||
titleText1.setBackground(Color.WHITE);
|
||||
titleText1.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10)); // Padding
|
||||
|
||||
callingStatusLabel = new JLabel(" ", SwingConstants.CENTER);
|
||||
callingStatusLabel.setFont(new Font("Arial", Font.BOLD, 15));
|
||||
callingStatusLabel.setForeground(new Color(0, 100, 0));
|
||||
callingStatusLabel.setBorder(BorderFactory.createCompoundBorder(
|
||||
BorderFactory.createLineBorder(Color.LIGHT_GRAY),
|
||||
BorderFactory.createEmptyBorder(5, 10, 5, 10)
|
||||
));
|
||||
callingStatusLabel.setOpaque(true);
|
||||
callingStatusLabel.setBackground(new Color(230, 255, 230));
|
||||
|
||||
JButton tvQueueButton = new JButton("TV Queue Display");
|
||||
tvQueueButton.setBackground(new Color(0, 150, 136)); // A teal color for distinction
|
||||
tvQueueButton.setForeground(Color.WHITE);
|
||||
tvQueueButton.setFocusPainted(false);
|
||||
tvQueueButton.setBorder(BorderFactory.createEmptyBorder(10, 15, 10, 15));
|
||||
tvQueueButton.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
|
||||
|
||||
tvQueueButton.addActionListener(e -> {
|
||||
if (tvQueueFrame == null || !tvQueueFrame.isDisplayable()) {
|
||||
tvQueueFrame = new QueueViewPage();
|
||||
} else {
|
||||
tvQueueFrame.toFront(); // Bring to front if already open
|
||||
}
|
||||
tvQueueFrame.updateQueueData(this.queue); // Pass current queue data
|
||||
tvQueueFrame.setVisible(true);
|
||||
// tvQueueFrame.optimizeForTv(); // Optional: Call if you want it to try to go fullscreen
|
||||
});
|
||||
|
||||
JButton rightButton = new JButton(" ADD ");
|
||||
rightButton.setBackground(new Color(63, 81, 181));
|
||||
@@ -262,7 +325,12 @@ public class CheckUpPage extends JPanel {
|
||||
});
|
||||
|
||||
topPanel.add(titleText1, BorderLayout.WEST);
|
||||
topPanel.add(rightButton, BorderLayout.EAST);
|
||||
topPanel.add(callingStatusLabel, BorderLayout.CENTER);
|
||||
JPanel buttonPanelEast = new JPanel(new FlowLayout(FlowLayout.RIGHT));
|
||||
buttonPanelEast.setOpaque(false); // Make panel transparent
|
||||
buttonPanelEast.add(tvQueueButton);
|
||||
buttonPanelEast.add(rightButton);
|
||||
topPanel.add(buttonPanelEast, BorderLayout.EAST);
|
||||
|
||||
leftPanel.setLayout(new BorderLayout());
|
||||
leftPanel.add(topPanel, BorderLayout.NORTH);
|
||||
@@ -301,41 +369,40 @@ public class CheckUpPage extends JPanel {
|
||||
gbc.insets = new Insets(5, 5, 5, 5); // Add some padding between components
|
||||
gbc.fill = GridBagConstraints.HORIZONTAL;
|
||||
|
||||
// --- Patient Info Sub-Panel with TitledBorder ---
|
||||
JPanel patientInfoInnerPanel = new JPanel(new GridBagLayout());
|
||||
patientInfoInnerPanel.setBorder(BorderFactory.createTitledBorder(
|
||||
BorderFactory.createEtchedBorder(), "Thông tin bệnh nhân",
|
||||
TitledBorder.LEADING, TitledBorder.TOP,
|
||||
new Font("Arial", Font.BOLD, 14), new Color(50, 50, 50)
|
||||
));
|
||||
GridBagConstraints gbcPatient = new GridBagConstraints();
|
||||
gbcPatient.insets = new Insets(3, 3, 3, 3);
|
||||
gbcPatient.fill = GridBagConstraints.HORIZONTAL;
|
||||
|
||||
JLabel patientInfoLabel = new JLabel("Thông tin bệnh nhân");
|
||||
patientInfoLabel.setFont(patientInfoLabel.getFont().deriveFont(Font.BOLD, 16)); // Bold, size 16
|
||||
patientInfoLabel.setHorizontalAlignment(SwingConstants.CENTER);
|
||||
gbcPatient.gridwidth = 1;
|
||||
gbcPatient.gridx = 0;
|
||||
gbcPatient.gridy = 0;
|
||||
patientInfoInnerPanel.add(new JLabel("Họ"), gbcPatient);
|
||||
gbcPatient.gridx = 1;
|
||||
customerLastNameField = new JTextField(10); // Adjusted preferred size
|
||||
patientInfoInnerPanel.add(customerLastNameField, gbcPatient);
|
||||
gbcPatient.gridx = 2;
|
||||
patientInfoInnerPanel.add(new JLabel("Tên"), gbcPatient);
|
||||
gbcPatient.gridx = 3;
|
||||
customerFirstNameField = new JTextField(10); // Adjusted preferred size
|
||||
patientInfoInnerPanel.add(customerFirstNameField, gbcPatient);
|
||||
|
||||
gbc.gridwidth = 4;
|
||||
gbc.gridx = 0;
|
||||
gbc.gridy = 0;
|
||||
gbc.anchor = GridBagConstraints.CENTER;
|
||||
inputPanel.add(patientInfoLabel, gbc);
|
||||
|
||||
gbc.gridwidth = 1;
|
||||
gbc.gridx = 0;
|
||||
gbc.gridy++;
|
||||
inputPanel.add(new JLabel("Họ"), gbc);
|
||||
gbc.gridx = 1;
|
||||
customerLastNameField = new JTextField(5);
|
||||
inputPanel.add(customerLastNameField, gbc);
|
||||
gbc.gridx = 2;
|
||||
inputPanel.add(new JLabel("Tên"), gbc);
|
||||
gbc.gridx = 3;
|
||||
customerFirstNameField = new JTextField(5);
|
||||
inputPanel.add(customerFirstNameField, gbc);
|
||||
|
||||
gbc.gridx = 0;
|
||||
gbc.gridy++;
|
||||
gbc.gridwidth = 1;
|
||||
inputPanel.add(new JLabel("Giới tính"), gbc);
|
||||
gbc.gridx = 1;
|
||||
gbcPatient.gridx = 0;
|
||||
gbcPatient.gridy++;
|
||||
patientInfoInnerPanel.add(new JLabel("Giới tính"), gbcPatient);
|
||||
gbcPatient.gridx = 1;
|
||||
String[] genderOptions = {"Nam", "Nữ"};
|
||||
genderComboBox = new JComboBox<>(genderOptions);
|
||||
inputPanel.add(genderComboBox, gbc);
|
||||
gbc.gridx = 2;
|
||||
inputPanel.add(new JLabel("Ngày sinh"), gbc);
|
||||
gbc.gridx = 3;
|
||||
patientInfoInnerPanel.add(genderComboBox, gbcPatient);
|
||||
gbcPatient.gridx = 2;
|
||||
patientInfoInnerPanel.add(new JLabel("Ngày sinh"), gbcPatient);
|
||||
gbcPatient.gridx = 3;
|
||||
UtilDateModel dobModel = new UtilDateModel();
|
||||
Properties dobProperties = new Properties();
|
||||
dobProperties.put("text.today", "Today");
|
||||
@@ -343,192 +410,253 @@ public class CheckUpPage extends JPanel {
|
||||
dobProperties.put("text.year", "Year");
|
||||
JDatePanelImpl dobPanel = new JDatePanelImpl(dobModel, dobProperties);
|
||||
dobPicker = new JDatePickerImpl(dobPanel, new DateLabelFormatter());
|
||||
dobPicker.setPreferredSize(new Dimension(100, 30));
|
||||
inputPanel.add(dobPicker, gbc);
|
||||
dobPicker.setPreferredSize(new Dimension(120, 30)); // Adjusted preferred size
|
||||
patientInfoInnerPanel.add(dobPicker, gbcPatient);
|
||||
|
||||
// Địa chỉ
|
||||
gbc.gridx = 0;
|
||||
gbc.gridy++;
|
||||
gbc.gridwidth = 1;
|
||||
inputPanel.add(new JLabel("Địa chỉ"), gbc);
|
||||
gbc.gridwidth = 3;
|
||||
gbc.gridx = 1;
|
||||
gbcPatient.gridx = 0;
|
||||
gbcPatient.gridy++;
|
||||
patientInfoInnerPanel.add(new JLabel("Địa chỉ"), gbcPatient);
|
||||
gbcPatient.gridx = 1;
|
||||
gbcPatient.gridwidth = 3;
|
||||
customerAddressField = new JTextField();
|
||||
inputPanel.add(customerAddressField, gbc);
|
||||
patientInfoInnerPanel.add(customerAddressField, gbcPatient);
|
||||
|
||||
gbc.gridy++;
|
||||
gbc.gridx = 1;
|
||||
gbc.gridwidth = 1;
|
||||
gbcPatient.gridy++;
|
||||
gbcPatient.gridx = 1; // Aligned with address field above
|
||||
gbcPatient.gridwidth = 1;
|
||||
provinceComboBox = new JComboBox<>(LocalStorage.provinces);
|
||||
inputPanel.add(provinceComboBox, gbc);
|
||||
|
||||
|
||||
gbc.gridx = 2;
|
||||
districtComboBox = new JComboBox<>(new String[]{"Huyện 1", "Huyện 2", "Huyện 3"});
|
||||
inputPanel.add(districtComboBox, gbc);
|
||||
// set not editable
|
||||
patientInfoInnerPanel.add(provinceComboBox, gbcPatient);
|
||||
gbcPatient.gridx = 2;
|
||||
districtModel = new DefaultComboBoxModel<>(new String[]{"Huyện"}); // Placeholder for district
|
||||
districtComboBox = new JComboBox<>(districtModel);
|
||||
patientInfoInnerPanel.add(districtComboBox, gbcPatient);
|
||||
districtComboBox.setEnabled(false);
|
||||
|
||||
|
||||
gbc.gridx = 3;
|
||||
wardComboBox = new JComboBox<>(new String[]{"Phường 1", "Phường 2", "Phường 3"});
|
||||
inputPanel.add(wardComboBox, gbc);
|
||||
// set not editable
|
||||
gbcPatient.gridx = 3;
|
||||
wardModel = new DefaultComboBoxModel<>(new String[]{"Phường"}); // Placeholder for ward
|
||||
wardComboBox = new JComboBox<>(wardModel);
|
||||
patientInfoInnerPanel.add(wardComboBox, gbcPatient);
|
||||
wardComboBox.setEnabled(false);
|
||||
|
||||
// Province ComboBox Listener
|
||||
provinceComboBox.addActionListener(new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
int selectedIndex = provinceComboBox.getSelectedIndex();
|
||||
districtModel = new DefaultComboBoxModel<>(new String[]{"Quận/Huyện"});
|
||||
districtComboBox.setModel(districtModel); // Set district combo box model
|
||||
if (selectedIndex != 0) { // If the selected index is not 0 (which corresponds to "Tỉnh/Thành phố")
|
||||
NetworkUtil.sendPacket(ClientHandler.ctx.channel(), new GetDistrictRequest(LocalStorage.provinceToId
|
||||
.get(provinceComboBox.getSelectedItem().toString())));
|
||||
} else {
|
||||
districtComboBox.setEnabled(false); // Disable district combo box if "Tỉnh/Thành phố" is selected
|
||||
wardComboBox.setEnabled(false); // Disable ward combo box as well
|
||||
provinceComboBox.addActionListener(e -> {
|
||||
String selectedProvince = (String) provinceComboBox.getSelectedItem();
|
||||
if (selectedProvince != null && !selectedProvince.equals("Tỉnh/Thành phố")) {
|
||||
String provinceId = LocalStorage.provinceToId.get(selectedProvince);
|
||||
if (provinceId != null) {
|
||||
NetworkUtil.sendPacket(ClientHandler.ctx.channel(), new GetDistrictRequest(provinceId));
|
||||
districtComboBox.setEnabled(false);
|
||||
districtModel.removeAllElements();
|
||||
districtModel.addElement("Loading districts...");
|
||||
wardComboBox.setEnabled(false);
|
||||
wardModel.removeAllElements();
|
||||
wardModel.addElement("Phường"); // Reset ward
|
||||
}
|
||||
} else {
|
||||
districtComboBox.setEnabled(false);
|
||||
districtModel.removeAllElements();
|
||||
districtModel.addElement("Huyện");
|
||||
wardComboBox.setEnabled(false);
|
||||
wardModel.removeAllElements();
|
||||
wardModel.addElement("Phường");
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
// District ComboBox Listener
|
||||
districtComboBox.addActionListener(new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
int selectedIndex = districtComboBox.getSelectedIndex();
|
||||
wardModel = new DefaultComboBoxModel<>(new String[]{"Xã/Phường"});
|
||||
wardComboBox.setModel(wardModel); // Set district combo box model
|
||||
if (selectedIndex != 0) { // If the selected index is not 0 (which corresponds to "Quận/Huyện")
|
||||
NetworkUtil.sendPacket(ClientHandler.ctx.channel(), new GetWardRequest(LocalStorage.districtToId
|
||||
.get(districtComboBox.getSelectedItem().toString())));
|
||||
} else {
|
||||
wardComboBox.setEnabled(false); // Disable ward combo box as well
|
||||
districtComboBox.addActionListener(e -> {
|
||||
String selectedDistrict = (String) districtComboBox.getSelectedItem();
|
||||
// Check if selectedDistrict is not null and not the placeholder/loading message
|
||||
if (selectedDistrict != null && LocalStorage.districtToId != null && LocalStorage.districtToId.containsKey(selectedDistrict)) {
|
||||
String districtId = LocalStorage.districtToId.get(selectedDistrict);
|
||||
if (districtId != null) {
|
||||
NetworkUtil.sendPacket(ClientHandler.ctx.channel(), new GetWardRequest(districtId));
|
||||
wardComboBox.setEnabled(false);
|
||||
wardModel.removeAllElements();
|
||||
wardModel.addElement("Loading wards...");
|
||||
}
|
||||
} else {
|
||||
// If no valid district is selected (or district data is not yet loaded), disable and reset wardComboBox
|
||||
wardComboBox.setEnabled(false);
|
||||
wardModel.removeAllElements();
|
||||
wardModel.addElement("Phường");
|
||||
}
|
||||
});
|
||||
|
||||
gbcPatient.gridx = 0;
|
||||
gbcPatient.gridy++;
|
||||
patientInfoInnerPanel.add(new JLabel("Mã số BN"), gbcPatient); // Shortened label
|
||||
gbcPatient.gridx = 1;
|
||||
customerIdField = new JTextField(10);
|
||||
patientInfoInnerPanel.add(customerIdField, gbcPatient);
|
||||
gbcPatient.gridx = 2;
|
||||
patientInfoInnerPanel.add(new JLabel("SĐT"), gbcPatient); // Shortened label
|
||||
gbcPatient.gridx = 3;
|
||||
customerPhoneField = new JTextField(10);
|
||||
patientInfoInnerPanel.add(customerPhoneField, gbcPatient);
|
||||
|
||||
gbc.gridx = 0;
|
||||
gbc.gridy++;
|
||||
gbc.gridwidth = 1;
|
||||
inputPanel.add(new JLabel("Mã số bệnh nhân"), gbc);
|
||||
customerIdField = new JTextField();
|
||||
|
||||
gbc.gridx = 1;
|
||||
inputPanel.add(customerIdField, gbc);
|
||||
|
||||
gbc.gridx = 2;
|
||||
inputPanel.add(new JLabel("Số điện thoại"), gbc);
|
||||
|
||||
gbc.gridx = 3;
|
||||
customerPhoneField = new JTextField();
|
||||
inputPanel.add(customerPhoneField, gbc);
|
||||
|
||||
gbc.gridx = 0;
|
||||
gbc.gridy++;
|
||||
gbc.gridwidth = 1;
|
||||
inputPanel.add(new JLabel("Cân nặng"), gbc);
|
||||
gbc.gridx = 1;
|
||||
gbcPatient.gridx = 0;
|
||||
gbcPatient.gridy++;
|
||||
patientInfoInnerPanel.add(new JLabel("Cân nặng (kg)"), gbcPatient);
|
||||
gbcPatient.gridx = 1;
|
||||
SpinnerModel weightModel = new SpinnerNumberModel(60, 0, 300, 0.5);
|
||||
customerWeightSpinner = new JSpinner(weightModel);
|
||||
inputPanel.add(customerWeightSpinner, gbc);
|
||||
gbc.gridx = 2;
|
||||
inputPanel.add(new JLabel("Chiều cao"), gbc);
|
||||
gbc.gridx = 3;
|
||||
patientInfoInnerPanel.add(customerWeightSpinner, gbcPatient);
|
||||
gbcPatient.gridx = 2;
|
||||
patientInfoInnerPanel.add(new JLabel("Chiều cao (cm)"), gbcPatient);
|
||||
gbcPatient.gridx = 3;
|
||||
SpinnerModel heightModel = new SpinnerNumberModel(170, 0, 230, 0.5);
|
||||
customerHeightSpinner = new JSpinner(heightModel);
|
||||
inputPanel.add(customerHeightSpinner, gbc);
|
||||
|
||||
JLabel checkupInfoLabel = new JLabel("Thông tin khám bệnh");
|
||||
checkupInfoLabel.setFont(checkupInfoLabel.getFont().deriveFont(Font.BOLD, 16)); // Bold, size 16
|
||||
checkupInfoLabel.setHorizontalAlignment(SwingConstants.CENTER);
|
||||
patientInfoInnerPanel.add(customerHeightSpinner, gbcPatient);
|
||||
|
||||
// Add patientInfoInnerPanel to the main inputPanel
|
||||
gbc.gridx = 0;
|
||||
gbc.gridy = 0; // First element in the main inputPanel
|
||||
gbc.gridwidth = 4;
|
||||
gbc.gridy++;
|
||||
gbc.gridx = 0;
|
||||
gbc.anchor = GridBagConstraints.CENTER;
|
||||
inputPanel.add(checkupInfoLabel, gbc);
|
||||
gbc.weightx = 1.0; // Allow horizontal fill
|
||||
inputPanel.add(patientInfoInnerPanel, gbc);
|
||||
gbc.weightx = 0; // Reset
|
||||
|
||||
gbc.gridx = 0;
|
||||
gbc.gridy++;
|
||||
gbc.gridwidth = 1;
|
||||
gbc.anchor = GridBagConstraints.NORTHWEST;
|
||||
|
||||
inputPanel.add(new JLabel("Mã khám bệnh:"), gbc);
|
||||
// --- Checkup Info Sub-Panel with TitledBorder ---
|
||||
JPanel checkupInfoInnerPanel = new JPanel(new GridBagLayout());
|
||||
checkupInfoInnerPanel.setBorder(BorderFactory.createTitledBorder(
|
||||
BorderFactory.createEtchedBorder(), "Thông tin khám bệnh",
|
||||
TitledBorder.LEADING, TitledBorder.TOP,
|
||||
new Font("Arial", Font.BOLD, 14), new Color(50, 50, 50)
|
||||
));
|
||||
GridBagConstraints gbcCheckup = new GridBagConstraints();
|
||||
gbcCheckup.insets = new Insets(3, 3, 3, 3);
|
||||
gbcCheckup.fill = GridBagConstraints.HORIZONTAL;
|
||||
|
||||
gbc.gridx = 1;
|
||||
checkupIdField = new JTextField(5);
|
||||
gbcCheckup.gridx = 0;
|
||||
gbcCheckup.gridy = 0;
|
||||
gbcCheckup.gridwidth = 1;
|
||||
gbcCheckup.anchor = GridBagConstraints.NORTHWEST; // Default anchor
|
||||
checkupInfoInnerPanel.add(new JLabel("Mã khám bệnh:"), gbcCheckup);
|
||||
gbcCheckup.gridx = 1;
|
||||
checkupIdField = new JTextField(10);
|
||||
checkupIdField.setEditable(false);
|
||||
inputPanel.add(checkupIdField, gbc);
|
||||
checkupInfoInnerPanel.add(checkupIdField, gbcCheckup);
|
||||
|
||||
UtilDateModel model = new UtilDateModel();
|
||||
UtilDateModel dateModel = new UtilDateModel(); // Renamed from 'model' to avoid conflict
|
||||
Properties p = new Properties();
|
||||
p.put("text.today", "Today");
|
||||
p.put("text.month", "Month");
|
||||
p.put("text.year", "Year");
|
||||
JDatePanelImpl datePanel = new JDatePanelImpl(model, p);
|
||||
JDatePanelImpl datePanel = new JDatePanelImpl(dateModel, p);
|
||||
datePicker = new JDatePickerImpl(datePanel, new DateLabelFormatter());
|
||||
datePicker.setPreferredSize(new Dimension(150, 30));
|
||||
datePicker.setPreferredSize(new Dimension(120, 30));
|
||||
|
||||
gbc.gridx = 2;
|
||||
inputPanel.add(new JLabel("Đơn Ngày:"), gbc);
|
||||
gbc.gridwidth = 0;
|
||||
gbc.gridx = 3;
|
||||
inputPanel.add(datePicker, gbc);
|
||||
gbcCheckup.gridx = 2;
|
||||
checkupInfoInnerPanel.add(new JLabel("Đơn Ngày:"), gbcCheckup);
|
||||
gbcCheckup.gridx = 3; // Adjusted gridx for datePicker
|
||||
checkupInfoInnerPanel.add(datePicker, gbcCheckup);
|
||||
|
||||
gbc.gridwidth = 1;
|
||||
gbc.gridx = 0;
|
||||
gbc.gridy++;
|
||||
inputPanel.add(new JLabel("Bác Sĩ"), gbc);
|
||||
gbcCheckup.gridwidth = 1;
|
||||
gbcCheckup.gridx = 0;
|
||||
gbcCheckup.gridy++;
|
||||
checkupInfoInnerPanel.add(new JLabel("Bác Sĩ"), gbcCheckup);
|
||||
gbcCheckup.gridwidth = 3;
|
||||
gbcCheckup.gridx = 1;
|
||||
doctorComboBox = new JComboBox<>(LocalStorage.doctorsName != null ? LocalStorage.doctorsName : new String[]{"Loading..."});
|
||||
checkupInfoInnerPanel.add(doctorComboBox, gbcCheckup);
|
||||
|
||||
gbc.gridwidth = 3;
|
||||
gbc.gridx = 1;
|
||||
doctorComboBox = new JComboBox<>(LocalStorage.doctorsName);
|
||||
inputPanel.add(doctorComboBox, gbc);
|
||||
|
||||
gbc.gridwidth = 1;
|
||||
gbc.gridx = 0;
|
||||
gbc.gridy++;
|
||||
inputPanel.add(new JLabel("Triệu chứng"), gbc);
|
||||
|
||||
gbc.gridwidth = 3;
|
||||
gbc.gridx = 1;
|
||||
gbcCheckup.gridwidth = 1;
|
||||
gbcCheckup.gridx = 0;
|
||||
gbcCheckup.gridy++;
|
||||
checkupInfoInnerPanel.add(new JLabel("Triệu chứng"), gbcCheckup);
|
||||
gbcCheckup.gridwidth = 3;
|
||||
gbcCheckup.gridx = 1;
|
||||
symptomsField = new JTextArea(3, 20);
|
||||
inputPanel.add(symptomsField, gbc);
|
||||
symptomsField.setLineWrap(true);
|
||||
symptomsField.setWrapStyleWord(true);
|
||||
gbcCheckup.weighty = 1.0; // Allow vertical expansion
|
||||
gbcCheckup.fill = GridBagConstraints.BOTH; // Allow expansion in both directions
|
||||
checkupInfoInnerPanel.add(new JScrollPane(symptomsField), gbcCheckup);
|
||||
gbcCheckup.weighty = 0.0; // Reset for next components
|
||||
gbcCheckup.fill = GridBagConstraints.HORIZONTAL; // Reset fill
|
||||
|
||||
gbc.gridwidth = 1;
|
||||
gbc.gridx = 0;
|
||||
gbc.gridy++;
|
||||
inputPanel.add(new JLabel("Chẩn đoán"), gbc);
|
||||
|
||||
gbc.gridwidth = 3;
|
||||
gbc.gridx = 1;
|
||||
gbcCheckup.gridwidth = 1;
|
||||
gbcCheckup.gridx = 0;
|
||||
gbcCheckup.gridy++;
|
||||
checkupInfoInnerPanel.add(new JLabel("Chẩn đoán"), gbcCheckup);
|
||||
gbcCheckup.gridwidth = 3;
|
||||
gbcCheckup.gridx = 1;
|
||||
diagnosisField = new JTextArea(3, 20);
|
||||
inputPanel.add(diagnosisField, gbc);
|
||||
diagnosisField.setLineWrap(true);
|
||||
diagnosisField.setWrapStyleWord(true);
|
||||
gbcCheckup.weighty = 1.0; // Allow vertical expansion
|
||||
gbcCheckup.fill = GridBagConstraints.BOTH; // Allow expansion in both directions
|
||||
checkupInfoInnerPanel.add(new JScrollPane(diagnosisField), gbcCheckup);
|
||||
gbcCheckup.weighty = 0.0; // Reset for next components
|
||||
gbcCheckup.fill = GridBagConstraints.HORIZONTAL; // Reset fill
|
||||
|
||||
gbc.gridwidth = 1;
|
||||
gbc.gridx = 0;
|
||||
gbc.gridy++;
|
||||
inputPanel.add(new JLabel("Ghi chú"), gbc);
|
||||
|
||||
gbc.gridwidth = 3;
|
||||
gbc.gridx = 1;
|
||||
gbcCheckup.gridwidth = 1;
|
||||
gbcCheckup.gridx = 0;
|
||||
gbcCheckup.gridy++;
|
||||
checkupInfoInnerPanel.add(new JLabel("Ghi chú"), gbcCheckup);
|
||||
gbcCheckup.gridwidth = 3;
|
||||
gbcCheckup.gridx = 1;
|
||||
notesField = new JTextArea(3, 20);
|
||||
inputPanel.add(notesField, gbc);
|
||||
notesField.setLineWrap(true);
|
||||
notesField.setWrapStyleWord(true);
|
||||
gbcCheckup.weighty = 1.0; // Allow vertical expansion
|
||||
gbcCheckup.fill = GridBagConstraints.BOTH; // Allow expansion in both directions
|
||||
checkupInfoInnerPanel.add(new JScrollPane(notesField), gbcCheckup);
|
||||
gbcCheckup.weighty = 0.0; // Reset for next components
|
||||
gbcCheckup.fill = GridBagConstraints.HORIZONTAL; // Reset fill
|
||||
|
||||
gbc.gridwidth = 1;
|
||||
gbc.gridx = 0;
|
||||
gbc.gridy++;
|
||||
inputPanel.add(new JLabel("Trạng thái"), gbc);
|
||||
|
||||
gbc.gridwidth = 3;
|
||||
gbc.gridx = 1;
|
||||
gbcCheckup.gridwidth = 1;
|
||||
gbcCheckup.gridx = 0;
|
||||
gbcCheckup.gridy++;
|
||||
checkupInfoInnerPanel.add(new JLabel("Trạng thái"), gbcCheckup);
|
||||
gbcCheckup.gridwidth = 3;
|
||||
gbcCheckup.gridx = 1;
|
||||
String[] statusOptions = {"PROCESSING", "NOT", "DONE"};
|
||||
statusComboBox = new JComboBox<>(statusOptions);
|
||||
inputPanel.add(statusComboBox, gbc);
|
||||
checkupInfoInnerPanel.add(statusComboBox, gbcCheckup);
|
||||
|
||||
// Add checkupInfoInnerPanel to the main inputPanel
|
||||
gbc.gridx = 0;
|
||||
gbc.gridy = 1; // Second element in the main inputPanel
|
||||
gbc.gridwidth = 4;
|
||||
gbc.weightx = 1.0; // Allow horizontal fill
|
||||
gbc.weighty = 1.0; // Allow checkupInfoInnerPanel to take vertical space
|
||||
gbc.insets = new Insets(10, 0, 5, 0); // Add some top margin before this panel
|
||||
inputPanel.add(checkupInfoInnerPanel, gbc);
|
||||
gbc.weightx = 0; // Reset
|
||||
gbc.weighty = 0; // Reset for subsequent components (like the call panel row)
|
||||
gbc.insets = new Insets(5,5,5,5); // Reset insets for subsequent components
|
||||
|
||||
// --- Call Patient components --- (now added after the two sub-panels)
|
||||
gbc.gridwidth = 1; // Reset gridwidth
|
||||
gbc.gridx = 0;
|
||||
gbc.gridy = 2; // This is now the third major "row" in inputPanel
|
||||
inputPanel.add(new JLabel("Call to Room:"), gbc);
|
||||
|
||||
gbc.gridx = 1;
|
||||
gbc.gridwidth = 1;
|
||||
String[] roomOptions = {"Room 1", "Room 2", "Room 3"};
|
||||
callRoomComboBox = new JComboBox<>(roomOptions);
|
||||
inputPanel.add(callRoomComboBox, gbc);
|
||||
|
||||
gbc.gridx = 2;
|
||||
gbc.gridwidth = 2;
|
||||
callPatientButton = new JButton("Call Patient");
|
||||
callPatientButton.setBackground(new Color(33, 150, 243));
|
||||
callPatientButton.setForeground(Color.WHITE);
|
||||
callPatientButton.setFocusPainted(false);
|
||||
callPatientButton.addActionListener(e -> handleCallPatient());
|
||||
inputPanel.add(callPatientButton, gbc);
|
||||
|
||||
// Add Free Room button
|
||||
gbc.gridx = 0;
|
||||
gbc.gridy = 3;
|
||||
gbc.gridwidth = 4;
|
||||
JButton freeRoomButton = new JButton("Mark Room as Free");
|
||||
freeRoomButton.setBackground(new Color(46, 204, 113)); // Green color
|
||||
freeRoomButton.setForeground(Color.WHITE);
|
||||
freeRoomButton.setFocusPainted(false);
|
||||
freeRoomButton.addActionListener(e -> handleFreeRoom());
|
||||
inputPanel.add(freeRoomButton, gbc);
|
||||
|
||||
table1.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
|
||||
|
||||
table1.getSelectionModel().addListSelectionListener(e -> {
|
||||
@@ -604,6 +732,9 @@ public class CheckUpPage extends JPanel {
|
||||
}
|
||||
// Save action
|
||||
saved = true;
|
||||
callingStatusLabel.setText(" ");
|
||||
callingStatusLabel.setBackground(new Color(230, 255, 230));
|
||||
callingStatusLabel.setForeground(new Color(0, 100, 0));
|
||||
break;
|
||||
}
|
||||
case "medicine":
|
||||
@@ -657,18 +788,50 @@ public class CheckUpPage extends JPanel {
|
||||
}
|
||||
|
||||
JScrollPane inputScroll = new JScrollPane(inputPanel);
|
||||
// Configure scroll settings for smoother scrolling
|
||||
inputScroll.getVerticalScrollBar().setUnitIncrement(16); // Increase scroll speed
|
||||
inputScroll.getVerticalScrollBar().setBlockIncrement(64); // Increase block increment
|
||||
inputScroll.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED);
|
||||
inputScroll.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
|
||||
// Add mouse wheel listener for smoother scrolling
|
||||
inputScroll.addMouseWheelListener(e -> {
|
||||
JScrollBar scrollBar = inputScroll.getVerticalScrollBar();
|
||||
int notches = e.getWheelRotation();
|
||||
int currentValue = scrollBar.getValue();
|
||||
int newValue = currentValue + (notches * scrollBar.getUnitIncrement() * 2);
|
||||
scrollBar.setValue(newValue);
|
||||
});
|
||||
|
||||
rightBottomPanel.add(inputScroll, BorderLayout.CENTER);
|
||||
rightBottomPanel.add(iconPanel, BorderLayout.SOUTH);
|
||||
|
||||
// Apply TitledBorder to rightBottomPanel
|
||||
rightBottomPanel.setBorder(BorderFactory.createCompoundBorder(
|
||||
BorderFactory.createEmptyBorder(10, 10, 10, 10), // Outer padding
|
||||
BorderFactory.createTitledBorder(
|
||||
BorderFactory.createLineBorder(new Color(63, 81, 181), 1, true),
|
||||
"Chi tiết và Thao tác",
|
||||
TitledBorder.LEADING,
|
||||
TitledBorder.TOP,
|
||||
new Font("Arial", Font.BOLD, 16),
|
||||
new Color(63, 81, 181)
|
||||
)
|
||||
));
|
||||
|
||||
// Right top panel
|
||||
JLabel titleText3 = new JLabel("History");
|
||||
titleText3.setFont(new Font("Arial", Font.BOLD, 16));
|
||||
|
||||
rightTopPanel.setLayout(new BorderLayout());
|
||||
rightTopPanel.add(titleText3, BorderLayout.NORTH);
|
||||
rightTopPanel.setBorder(BorderFactory.createEmptyBorder(20, 20, 20, 10));
|
||||
// Apply TitledBorder to rightTopPanel
|
||||
rightTopPanel.setBorder(BorderFactory.createCompoundBorder(
|
||||
BorderFactory.createEmptyBorder(10, 10, 10, 10), // Outer padding to keep content away from split pane edge
|
||||
BorderFactory.createTitledBorder(
|
||||
BorderFactory.createLineBorder(new Color(63, 81, 181), 1, true),
|
||||
"Lịch sử khám bệnh",
|
||||
TitledBorder.LEADING,
|
||||
TitledBorder.TOP,
|
||||
new Font("Arial", Font.BOLD, 16),
|
||||
new Color(63, 81, 181)
|
||||
)
|
||||
));
|
||||
|
||||
String historyColumns[] = {"Ngày Tháng","Mã khám bệnh", "Triệu chứng", "Chẩn đoán", "Ghi chú"};
|
||||
|
||||
@@ -817,17 +980,40 @@ public class CheckUpPage extends JPanel {
|
||||
|
||||
LocalStorage.districts = response.getDistricts();
|
||||
LocalStorage.districtToId = response.getDistrictToId();
|
||||
districtModel = new DefaultComboBoxModel<>(LocalStorage.districts);
|
||||
districtModel.removeAllElements(); // Clear previous items
|
||||
for (String district : LocalStorage.districts) {
|
||||
districtModel.addElement(district);
|
||||
}
|
||||
districtComboBox.setModel(districtModel);
|
||||
districtComboBox.setEnabled(true); // Enable district combo box
|
||||
// Automatically select the first actual district if available, or keep placeholder
|
||||
if (LocalStorage.districts.length > 1) { // more than just the placeholder
|
||||
districtComboBox.setSelectedIndex(0); // Should be the placeholder "Huyện" or "Quận/Huyện"
|
||||
} else if (LocalStorage.districts.length == 1 && !LocalStorage.districts[0].startsWith("Loading")){
|
||||
districtComboBox.setSelectedIndex(0); // Only one actual district
|
||||
}
|
||||
|
||||
// Reset ward combo box as district has changed
|
||||
wardModel.removeAllElements();
|
||||
wardModel.addElement("Phường");
|
||||
wardComboBox.setModel(wardModel);
|
||||
wardComboBox.setEnabled(false); // Ward should be fetched after district selection
|
||||
}
|
||||
|
||||
private void handleGetWardResponse(GetWardResponse response) {
|
||||
log.info("Received ward data");
|
||||
LocalStorage.wards = response.getWards();
|
||||
wardModel = new DefaultComboBoxModel<>(LocalStorage.wards);
|
||||
// Assuming wardToId is not strictly needed on client unless for specific reverse lookups
|
||||
// If it is, it should be part of GetWardResponse and stored in LocalStorage
|
||||
wardModel.removeAllElements(); // Clear previous items
|
||||
for (String ward : LocalStorage.wards) {
|
||||
wardModel.addElement(ward);
|
||||
}
|
||||
wardComboBox.setModel(wardModel);
|
||||
wardComboBox.setEnabled(true); // Enable ward combo box
|
||||
if (LocalStorage.wards.length > 0 && !LocalStorage.wards[0].startsWith("Loading")) {
|
||||
wardComboBox.setSelectedIndex(0); // Select the placeholder or first ward
|
||||
}
|
||||
}
|
||||
|
||||
private void handleGetCustomerHistoryResponse(GetCustomerHistoryResponse response) {
|
||||
@@ -846,16 +1032,132 @@ public class CheckUpPage extends JPanel {
|
||||
log.info("Received checkup update queue");
|
||||
this.queue = response.getQueue();
|
||||
model.setDataVector(this.queue, new String[]{"Mã khám bệnh", "Ngày Tháng", "Họ", "Tên", "Bác Sĩ", "Triệu chứng", "Chẩn đoán", "Ghi chú", "Trạng thái"});
|
||||
if (tvQueueFrame != null && tvQueueFrame.isVisible()) {
|
||||
tvQueueFrame.updateQueueData(this.queue);
|
||||
}
|
||||
}
|
||||
|
||||
private void handleGetCheckUpQueueResponse(GetCheckUpQueueResponse response) {
|
||||
log.info("Received checkup queue");
|
||||
this.queue = response.getQueue();
|
||||
model.setDataVector(this.queue, new String[]{"Mã khám bệnh", "Ngày Tháng", "Họ", "Tên", "Bác Sĩ", "Triệu chứng", "Chẩn đoán", "Ghi chú", "Trạng thái"});
|
||||
if (tvQueueFrame != null && tvQueueFrame.isVisible()) {
|
||||
tvQueueFrame.updateQueueData(this.queue);
|
||||
}
|
||||
}
|
||||
|
||||
private void handleCallPatientResponse(CallPatientResponse response) {
|
||||
log.info("Received call patient response: Room {}, Patient ID {}, Status {}", response.getRoomId(), response.getPatientId(), response.getStatus());
|
||||
if (tvQueueFrame != null && tvQueueFrame.isVisible()) {
|
||||
if (response.getStatus() == Status.PROCESSING) {
|
||||
String patientIdToFind = String.valueOf(response.getPatientId());
|
||||
String patientDisplayInfo = patientIdToFind; // Default to ID if not found
|
||||
|
||||
if (this.queue != null) {
|
||||
for (String[] patientData : this.queue) {
|
||||
if (patientData != null && patientData.length > 15 && patientIdToFind.equals(patientData[0])) { // patientData[0] is maKhamBenh
|
||||
String ho = patientData[2];
|
||||
String ten = patientData[3];
|
||||
String customerDob = patientData[15]; // Assuming this is the DoB field
|
||||
String namSinh = "N/A";
|
||||
|
||||
try {
|
||||
SimpleDateFormat dobFormat;
|
||||
Date parsedDate;
|
||||
if (customerDob.matches("\\d+")) { // Check if the string is a timestamp
|
||||
long timestamp = Long.parseLong(customerDob);
|
||||
parsedDate = new Date(timestamp);
|
||||
} else {
|
||||
dobFormat = new SimpleDateFormat("dd/MM/yyyy"); // Or your existing format
|
||||
parsedDate = dobFormat.parse(customerDob);
|
||||
}
|
||||
Calendar calendar = Calendar.getInstance();
|
||||
calendar.setTime(parsedDate);
|
||||
namSinh = String.valueOf(calendar.get(Calendar.YEAR));
|
||||
} catch (ParseException | NumberFormatException e) {
|
||||
log.error("Error parsing DoB for TV display: {} for patient ID {}", customerDob, patientIdToFind, e);
|
||||
}
|
||||
patientDisplayInfo = ho + " " + ten + " (" + namSinh + ")";
|
||||
break; // Found the patient
|
||||
}
|
||||
}
|
||||
}
|
||||
// Pass both the raw patient ID for the room box and the formatted info for the central display
|
||||
tvQueueFrame.updateSpecificRoomStatus(response.getRoomId(), String.valueOf(response.getPatientId()), patientDisplayInfo, response.getStatus());
|
||||
} else if (response.getStatus() == Status.EMPTY) {
|
||||
tvQueueFrame.markRoomAsFree(response.getRoomId());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void handleErrorResponse(ErrorResponse response) {
|
||||
log.error("Error response: {}", response.getError());
|
||||
}
|
||||
|
||||
private void handleFreeRoom() {
|
||||
int selectedRoomIndex = callRoomComboBox.getSelectedIndex();
|
||||
if (selectedRoomIndex == -1) {
|
||||
JOptionPane.showMessageDialog(this, "Please select a room to mark as free.", "No Room Selected", JOptionPane.WARNING_MESSAGE);
|
||||
return;
|
||||
}
|
||||
String selectedRoomName = callRoomComboBox.getSelectedItem().toString();
|
||||
int roomId = selectedRoomIndex + 1; // 1-based room ID
|
||||
|
||||
// Update the calling status label to show room is free
|
||||
String freeText = "<html><b>Room Status:</b> " + selectedRoomName + " is now free</html>";
|
||||
callingStatusLabel.setText(freeText);
|
||||
callingStatusLabel.setForeground(new Color(0, 100, 0));
|
||||
callingStatusLabel.setBackground(new Color(230, 255, 230)); // Light green background
|
||||
|
||||
// Show confirmation message
|
||||
JOptionPane.showMessageDialog(this,
|
||||
"Room " + selectedRoomName + " has been marked as free.",
|
||||
"Room Status Updated",
|
||||
JOptionPane.INFORMATION_MESSAGE);
|
||||
|
||||
log.info("Room {} marked as free", selectedRoomName);
|
||||
|
||||
// Update the TV Queue display as well
|
||||
// if (tvQueueFrame != null && tvQueueFrame.isVisible()) {
|
||||
// tvQueueFrame.markRoomAsFree(roomId);
|
||||
// }
|
||||
// TODO: Consider sending a packet to the server to notify other clients/instances about the room being free.
|
||||
// For example: NetworkUtil.sendPacket(ClientHandler.ctx.channel(), new UpdateRoomStatusRequest(roomId, Status.FREE));
|
||||
NetworkUtil.sendPacket(ClientHandler.ctx.channel(), new CallPatientRequest(roomId, -1, Status.EMPTY));
|
||||
}
|
||||
|
||||
private void handleCallPatient() {
|
||||
int selectedRow = table1.getSelectedRow();
|
||||
if (selectedRow == -1) {
|
||||
JOptionPane.showMessageDialog(this, "Please select a patient from the queue to call.", "No Patient Selected", JOptionPane.WARNING_MESSAGE);
|
||||
return;
|
||||
}
|
||||
|
||||
// Assuming column indices from your table model setup:
|
||||
// 0: Mã khám bệnh, 2: Họ, 3: Tên
|
||||
String maKhamBenh = model.getValueAt(selectedRow, 0).toString();
|
||||
String ho = model.getValueAt(selectedRow, 2).toString();
|
||||
String ten = model.getValueAt(selectedRow, 3).toString();
|
||||
String patientName = ho + " " + ten;
|
||||
|
||||
int selectedRoom = callRoomComboBox.getSelectedIndex() + 1; //Index
|
||||
|
||||
// For now, just a popup. Later, this will send a packet.
|
||||
JOptionPane.showMessageDialog(this,
|
||||
"Calling patient " + patientName + " (ID: " + maKhamBenh + ") to " + selectedRoom,
|
||||
"Calling Patient",
|
||||
JOptionPane.INFORMATION_MESSAGE);
|
||||
|
||||
// TODO: Implement sending CallPatientPacket to server
|
||||
NetworkUtil.sendPacket(ClientHandler.ctx.channel(), new CallPatientRequest(selectedRoom, Integer.parseInt(maKhamBenh),
|
||||
Status.PROCESSING));
|
||||
log.info("Called patient {} (ID: {}) to room {}", patientName, maKhamBenh, selectedRoom);
|
||||
|
||||
// Update the calling status label
|
||||
String callingText = "<html><b>Calling:</b> Patient " + patientName + " (ID: " + maKhamBenh + ") to " + selectedRoom + "</html>";
|
||||
callingStatusLabel.setText(callingText);
|
||||
callingStatusLabel.setForeground(Color.WHITE);
|
||||
callingStatusLabel.setBackground(new Color(217, 83, 79)); // A reddish color for active call
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,122 +0,0 @@
|
||||
package BsK.client.ui.component.CheckUpPage;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
|
||||
public class SidebarAnimationDemo {
|
||||
public static void main(String[] args) {
|
||||
SwingUtilities.invokeLater(() -> {
|
||||
JFrame frame = new JFrame("Sidebar Animation");
|
||||
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
|
||||
frame.setSize(800, 500);
|
||||
frame.setLayout(new BorderLayout());
|
||||
|
||||
// Sidebar with gradient
|
||||
JPanel sidebar = new JPanel() {
|
||||
@Override
|
||||
protected void paintComponent(Graphics g) {
|
||||
super.paintComponent(g);
|
||||
Graphics2D g2d = (Graphics2D) g;
|
||||
int width = getWidth();
|
||||
int height = getHeight();
|
||||
Color color1 = new Color(63, 81, 181);
|
||||
Color color2 = new Color(33, 150, 243);
|
||||
GradientPaint gp = new GradientPaint(0, 0, color1, 0, height, color2);
|
||||
g2d.setPaint(gp);
|
||||
g2d.fillRect(0, 0, width, height);
|
||||
}
|
||||
};
|
||||
sidebar.setLayout(new GridLayout(15, 1));
|
||||
sidebar.setBorder(BorderFactory.createEmptyBorder(20, 20, 20, 20));
|
||||
sidebar.setPreferredSize(new Dimension(0, 500)); // Initially hidden
|
||||
|
||||
// Sidebar items
|
||||
String[] sidebarItems = {"Thống kê", "Thăm khám", "Dữ liệu bệnh nhân", "Kho", "Người dùng", "Thông tin"};
|
||||
String[] destination = {"DashboardPage", "CheckUpPage", "PatientDataPage", "InventoryPage", "UserPage", "InfoPage"};
|
||||
for (int i = 0; i < sidebarItems.length; i++) {
|
||||
String item = sidebarItems[i];
|
||||
String dest = destination[i];
|
||||
JLabel label = new JLabel(item);
|
||||
label.setForeground(Color.WHITE);
|
||||
label.setHorizontalAlignment(SwingConstants.CENTER);
|
||||
label.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
|
||||
label.setFont(new Font("Arial", Font.BOLD, 14));
|
||||
|
||||
// Add hover and click effects
|
||||
label.addMouseListener(new java.awt.event.MouseAdapter() {
|
||||
@Override
|
||||
public void mouseClicked(java.awt.event.MouseEvent e) {
|
||||
System.out.println("Navigating to: " + dest);
|
||||
// mainFrame.showPage(dest); // Example navigation call
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mouseEntered(java.awt.event.MouseEvent e) {
|
||||
label.setForeground(new Color(200, 230, 255)); // Highlight on hover
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mouseExited(java.awt.event.MouseEvent e) {
|
||||
label.setForeground(Color.WHITE); // Restore original color
|
||||
}
|
||||
});
|
||||
|
||||
sidebar.add(label);
|
||||
}
|
||||
|
||||
frame.add(sidebar, BorderLayout.WEST);
|
||||
|
||||
// Main content with toggle button
|
||||
JPanel mainContent = new JPanel(new BorderLayout());
|
||||
JLabel contentLabel = new JLabel("Main Content Area");
|
||||
contentLabel.setHorizontalAlignment(SwingConstants.CENTER);
|
||||
mainContent.add(contentLabel, BorderLayout.CENTER);
|
||||
|
||||
JButton toggleButton = new JButton("Toggle Sidebar");
|
||||
mainContent.add(toggleButton, BorderLayout.SOUTH);
|
||||
|
||||
frame.add(mainContent, BorderLayout.CENTER);
|
||||
|
||||
// Sidebar animation variables
|
||||
boolean[] isSidebarOpen = {false}; // Track the sidebar state
|
||||
|
||||
// Toggle button action
|
||||
toggleButton.addActionListener(e -> {
|
||||
new Timer(10, event -> {
|
||||
int currentWidth = sidebar.getWidth();
|
||||
if (!isSidebarOpen[0]) {
|
||||
if (currentWidth < 200) { // Expand to target width
|
||||
sidebar.setPreferredSize(new Dimension(currentWidth + 10, 500));
|
||||
sidebar.revalidate();
|
||||
} else {
|
||||
isSidebarOpen[0] = true;
|
||||
((Timer) event.getSource()).stop();
|
||||
}
|
||||
} else {
|
||||
if (currentWidth > 0) { // Retract to hidden
|
||||
sidebar.setPreferredSize(new Dimension(currentWidth - 10, 500));
|
||||
sidebar.revalidate();
|
||||
} else {
|
||||
isSidebarOpen[0] = false;
|
||||
((Timer) event.getSource()).stop();
|
||||
}
|
||||
}
|
||||
}).start();
|
||||
});
|
||||
|
||||
frame.setVisible(true);
|
||||
|
||||
// Animate sidebar on startup
|
||||
Timer timer = new Timer(10, event -> {
|
||||
int currentWidth = sidebar.getWidth();
|
||||
if (currentWidth < 200) { // Target width
|
||||
sidebar.setPreferredSize(new Dimension(currentWidth + 10, 500));
|
||||
sidebar.revalidate();
|
||||
} else {
|
||||
((Timer) event.getSource()).stop(); // Stop animation
|
||||
}
|
||||
});
|
||||
timer.start();
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,333 @@
|
||||
package BsK.client.ui.component.QueueViewPage;
|
||||
|
||||
import BsK.client.LocalStorage;
|
||||
|
||||
import javax.swing.*;
|
||||
import javax.swing.border.EmptyBorder;
|
||||
import javax.swing.table.DefaultTableModel;
|
||||
import javax.swing.table.JTableHeader;
|
||||
import java.awt.*;
|
||||
import java.text.ParseException;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Calendar;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
public class QueueViewPage extends JFrame {
|
||||
private DefaultTableModel tvQueueTableModel;
|
||||
private JTable tvQueueTable;
|
||||
private final String[] tvQueueColumns = {"Mã khám bệnh", "Họ và Tên", "Năm sinh"};
|
||||
|
||||
private JLabel clinicNameLabel;
|
||||
private JLabel clinicAddressLabel;
|
||||
private JLabel clinicPhoneLabel;
|
||||
|
||||
private JLabel room1StatusLabel;
|
||||
private JLabel room2StatusLabel;
|
||||
private JPanel room1Panel;
|
||||
private JPanel room2Panel;
|
||||
|
||||
private JPanel callingPatientDisplayPanel;
|
||||
private JLabel nowCallingTextLabel;
|
||||
private JLabel nowCallingInfoLine1Label;
|
||||
private JLabel nowCallingInfoLine2Label;
|
||||
|
||||
private String room1PatientInfo = null; // Stores "Name (Year)"
|
||||
private String room2PatientInfo = null; // Stores "Name (Year)"
|
||||
|
||||
public QueueViewPage() {
|
||||
setTitle("TV Queue Display");
|
||||
setSize(1280, 720); // Common 720p resolution for TVs
|
||||
setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
|
||||
setLocationRelativeTo(null);
|
||||
setLayout(new BorderLayout(0, 10)); // Main layout with vertical gap
|
||||
getContentPane().setBackground(Color.DARK_GRAY); // Dark background for TV
|
||||
|
||||
// --- Top Panel ---
|
||||
JPanel topPanel = new JPanel(new BorderLayout(20, 0)); // Hgap for spacing
|
||||
topPanel.setOpaque(false); // Transparent to show frame background
|
||||
topPanel.setBorder(new EmptyBorder(20, 20, 10, 20)); // Padding
|
||||
|
||||
// Clinic Info Panel (Top-Left)
|
||||
JPanel clinicInfoPanel = new JPanel();
|
||||
clinicInfoPanel.setLayout(new BoxLayout(clinicInfoPanel, BoxLayout.Y_AXIS));
|
||||
clinicInfoPanel.setOpaque(false);
|
||||
|
||||
clinicNameLabel = new JLabel("Clinic: Loading...");
|
||||
styleLabelForTv(clinicNameLabel, 28, Font.BOLD, Color.WHITE);
|
||||
clinicAddressLabel = new JLabel("Address: Loading...");
|
||||
styleLabelForTv(clinicAddressLabel, 20, Font.PLAIN, Color.LIGHT_GRAY);
|
||||
clinicPhoneLabel = new JLabel("Phone: Loading...");
|
||||
styleLabelForTv(clinicPhoneLabel, 20, Font.PLAIN, Color.LIGHT_GRAY);
|
||||
|
||||
clinicInfoPanel.add(clinicNameLabel);
|
||||
clinicInfoPanel.add(Box.createRigidArea(new Dimension(0, 5)));
|
||||
clinicInfoPanel.add(clinicAddressLabel);
|
||||
clinicInfoPanel.add(Box.createRigidArea(new Dimension(0, 5)));
|
||||
clinicInfoPanel.add(clinicPhoneLabel);
|
||||
loadClinicInfo(); // Load data from LocalStorage
|
||||
|
||||
topPanel.add(clinicInfoPanel, BorderLayout.WEST);
|
||||
|
||||
// Room Status Panel (Top-Right)
|
||||
JPanel roomsOuterPanel = new JPanel(new FlowLayout(FlowLayout.RIGHT, 0, 0)); // Align to right
|
||||
roomsOuterPanel.setOpaque(false);
|
||||
JPanel roomsPanel = new JPanel(new GridLayout(1, 2, 20, 0)); // 1 row, 2 cols, hgap
|
||||
roomsPanel.setOpaque(false);
|
||||
|
||||
room1Panel = new JPanel(new BorderLayout());
|
||||
room1StatusLabel = new JLabel("ROOM 1", SwingConstants.CENTER);
|
||||
styleRoomLabel(room1StatusLabel, room1Panel, Color.GREEN.darker(), "EMPTY");
|
||||
room1Panel.add(room1StatusLabel, BorderLayout.CENTER);
|
||||
room1Panel.setPreferredSize(new Dimension(220, 100));
|
||||
|
||||
room2Panel = new JPanel(new BorderLayout());
|
||||
room2StatusLabel = new JLabel("ROOM 2", SwingConstants.CENTER);
|
||||
styleRoomLabel(room2StatusLabel, room2Panel, Color.GREEN.darker(), "EMPTY");
|
||||
room2Panel.add(room2StatusLabel, BorderLayout.CENTER);
|
||||
room2Panel.setPreferredSize(new Dimension(220, 100));
|
||||
|
||||
roomsPanel.add(room1Panel);
|
||||
roomsPanel.add(room2Panel);
|
||||
roomsOuterPanel.add(roomsPanel);
|
||||
topPanel.add(roomsOuterPanel, BorderLayout.EAST);
|
||||
|
||||
add(topPanel, BorderLayout.NORTH);
|
||||
|
||||
// --- "Now Calling" Display Panel (NEW) ---
|
||||
callingPatientDisplayPanel = new JPanel();
|
||||
callingPatientDisplayPanel.setLayout(new BoxLayout(callingPatientDisplayPanel, BoxLayout.Y_AXIS)); // Vertical alignment
|
||||
callingPatientDisplayPanel.setOpaque(false); // Transparent background
|
||||
callingPatientDisplayPanel.setBorder(new EmptyBorder(15, 20, 15, 20)); // Padding
|
||||
|
||||
nowCallingTextLabel = new JLabel("NOW CALLING:");
|
||||
styleLabelForTv(nowCallingTextLabel, 38, Font.BOLD, new Color(255, 215, 0)); // Gold color
|
||||
nowCallingTextLabel.setAlignmentX(Component.CENTER_ALIGNMENT);
|
||||
nowCallingTextLabel.setVisible(false); // Initially hidden
|
||||
|
||||
nowCallingInfoLine1Label = new JLabel("Room 1: FREE"); // Default message
|
||||
styleLabelForTv(nowCallingInfoLine1Label, 32, Font.BOLD, Color.WHITE);
|
||||
nowCallingInfoLine1Label.setAlignmentX(Component.CENTER_ALIGNMENT);
|
||||
|
||||
nowCallingInfoLine2Label = new JLabel("Room 2: FREE"); // Default message
|
||||
styleLabelForTv(nowCallingInfoLine2Label, 32, Font.BOLD, Color.WHITE);
|
||||
nowCallingInfoLine2Label.setAlignmentX(Component.CENTER_ALIGNMENT);
|
||||
|
||||
callingPatientDisplayPanel.add(nowCallingTextLabel);
|
||||
callingPatientDisplayPanel.add(Box.createRigidArea(new Dimension(0, 5))); // Spacer
|
||||
callingPatientDisplayPanel.add(nowCallingInfoLine1Label);
|
||||
callingPatientDisplayPanel.add(Box.createRigidArea(new Dimension(0, 5))); // Spacer
|
||||
callingPatientDisplayPanel.add(nowCallingInfoLine2Label);
|
||||
|
||||
// --- Center Panel to hold "Now Calling" and Table ---
|
||||
JPanel centerContentPanel = new JPanel(new BorderLayout(0, 0));
|
||||
centerContentPanel.setOpaque(false);
|
||||
centerContentPanel.add(callingPatientDisplayPanel, BorderLayout.NORTH);
|
||||
|
||||
// --- Queue Table Panel (Center/Bottom) ---
|
||||
tvQueueTableModel = new DefaultTableModel(new Object[][]{}, tvQueueColumns) {
|
||||
@Override
|
||||
public boolean isCellEditable(int row, int column) {
|
||||
return false;
|
||||
}
|
||||
};
|
||||
tvQueueTable = new JTable(tvQueueTableModel);
|
||||
|
||||
tvQueueTable.setFont(new Font("Arial", Font.BOLD, 26));
|
||||
tvQueueTable.setRowHeight(45);
|
||||
tvQueueTable.setFillsViewportHeight(true);
|
||||
tvQueueTable.setBackground(new Color(220, 220, 220)); // Light gray for table background
|
||||
tvQueueTable.setGridColor(Color.GRAY);
|
||||
|
||||
JTableHeader tableHeader = tvQueueTable.getTableHeader();
|
||||
tableHeader.setFont(new Font("Arial", Font.BOLD, 28));
|
||||
tableHeader.setBackground(new Color(63, 81, 181));
|
||||
tableHeader.setForeground(Color.WHITE);
|
||||
tableHeader.setPreferredSize(new Dimension(0, 50)); // Header height
|
||||
|
||||
JScrollPane scrollPane = new JScrollPane(tvQueueTable);
|
||||
scrollPane.setBorder(new EmptyBorder(10, 20, 20, 20)); // Padding around table
|
||||
scrollPane.getViewport().setBackground(Color.DARK_GRAY); // Match frame background
|
||||
centerContentPanel.add(scrollPane, BorderLayout.CENTER); // Add table to center of centerContentPanel
|
||||
add(centerContentPanel, BorderLayout.CENTER); // Add centerContentPanel to main frame's center
|
||||
}
|
||||
|
||||
private void styleLabelForTv(JLabel label, int size, int style, Color color) {
|
||||
label.setFont(new Font("Segoe UI", style, size)); // Segoe UI is a common nice font
|
||||
label.setForeground(color);
|
||||
}
|
||||
|
||||
private void styleRoomLabel(JLabel label, JPanel panel, Color bgColor, String text) {
|
||||
label.setFont(new Font("Segoe UI", Font.BOLD, 22));
|
||||
label.setForeground(Color.WHITE);
|
||||
label.setText("<html><div style='text-align: center;'>" + text.replace(" ", "<br>") + "</div></html>");
|
||||
panel.setBackground(bgColor);
|
||||
panel.setBorder(BorderFactory.createLineBorder(Color.LIGHT_GRAY, 1));
|
||||
}
|
||||
|
||||
private void loadClinicInfo() {
|
||||
if (LocalStorage.ClinicName != null) {
|
||||
clinicNameLabel.setText("Clinic: " + LocalStorage.ClinicName);
|
||||
clinicAddressLabel.setText("Address: " + LocalStorage.ClinicAddress);
|
||||
clinicPhoneLabel.setText("Phone: " + LocalStorage.ClinicPhone);
|
||||
}
|
||||
}
|
||||
|
||||
private void updateNowCallingDisplay() {
|
||||
boolean room1Busy = room1PatientInfo != null;
|
||||
boolean room2Busy = room2PatientInfo != null;
|
||||
|
||||
if (room1Busy) {
|
||||
nowCallingInfoLine1Label.setText("Room 1: " + room1PatientInfo);
|
||||
styleLabelForTv(nowCallingInfoLine1Label, 32, Font.BOLD, Color.WHITE);
|
||||
} else {
|
||||
nowCallingInfoLine1Label.setText("Room 1: FREE");
|
||||
styleLabelForTv(nowCallingInfoLine1Label, 32, Font.ITALIC, Color.LIGHT_GRAY);
|
||||
}
|
||||
|
||||
if (room2Busy) {
|
||||
nowCallingInfoLine2Label.setText("Room 2: " + room2PatientInfo);
|
||||
styleLabelForTv(nowCallingInfoLine2Label, 32, Font.BOLD, Color.WHITE);
|
||||
} else {
|
||||
nowCallingInfoLine2Label.setText("Room 2: FREE");
|
||||
styleLabelForTv(nowCallingInfoLine2Label, 32, Font.ITALIC, Color.LIGHT_GRAY);
|
||||
}
|
||||
|
||||
if (room1Busy || room2Busy) {
|
||||
nowCallingTextLabel.setVisible(true);
|
||||
} else {
|
||||
nowCallingTextLabel.setVisible(false);
|
||||
// Optional: could make one line say "All rooms free" and hide the other
|
||||
// For now, both lines will show "Room X: FREE" and title is hidden.
|
||||
}
|
||||
}
|
||||
|
||||
public void updateSpecificRoomStatus(int roomId, String patientIdForRoomBox, String fullPatientInfoForCentralDisplay, BsK.common.entity.Status status) {
|
||||
JLabel targetLabel;
|
||||
JPanel targetPanel;
|
||||
|
||||
if (roomId == 1) {
|
||||
targetLabel = room1StatusLabel;
|
||||
targetPanel = room1Panel;
|
||||
} else if (roomId == 2) {
|
||||
targetLabel = room2StatusLabel;
|
||||
targetPanel = room2Panel;
|
||||
} else {
|
||||
System.err.println("QueueViewPage: Invalid roomId for status update: " + roomId);
|
||||
return;
|
||||
}
|
||||
|
||||
if (status == BsK.common.entity.Status.PROCESSING) {
|
||||
// Use patientIdForRoomBox for the small room panel
|
||||
styleRoomLabel(targetLabel, targetPanel, Color.RED.darker(), "P" + roomId + "\n" + patientIdForRoomBox);
|
||||
// Store fullPatientInfoForCentralDisplay for the main "Now Calling" display
|
||||
if (roomId == 1) {
|
||||
room1PatientInfo = fullPatientInfoForCentralDisplay;
|
||||
} else {
|
||||
room2PatientInfo = fullPatientInfoForCentralDisplay;
|
||||
}
|
||||
} else {
|
||||
// Room is not PROCESSING (e.g., EMPTY, DONE)
|
||||
styleRoomLabel(targetLabel, targetPanel, Color.GREEN.darker(), "ROOM " + roomId + "\nEMPTY");
|
||||
if (roomId == 1) {
|
||||
room1PatientInfo = null;
|
||||
} else {
|
||||
room2PatientInfo = null;
|
||||
}
|
||||
}
|
||||
updateNowCallingDisplay();
|
||||
}
|
||||
|
||||
public void markRoomAsFree(int roomId) {
|
||||
JLabel targetLabel;
|
||||
JPanel targetPanel;
|
||||
|
||||
if (roomId == 1) {
|
||||
targetLabel = room1StatusLabel;
|
||||
targetPanel = room1Panel;
|
||||
} else if (roomId == 2) {
|
||||
targetLabel = room2StatusLabel;
|
||||
targetPanel = room2Panel;
|
||||
} else {
|
||||
System.err.println("QueueViewPage: Invalid roomId for marking as free: " + roomId);
|
||||
return;
|
||||
}
|
||||
styleRoomLabel(targetLabel, targetPanel, Color.GREEN.darker(), "ROOM " + roomId + "\nEMPTY");
|
||||
if (roomId == 1) {
|
||||
room1PatientInfo = null;
|
||||
} else {
|
||||
room2PatientInfo = null;
|
||||
}
|
||||
updateNowCallingDisplay();
|
||||
}
|
||||
|
||||
public void updateQueueData(String[][] fullQueueData) {
|
||||
if (fullQueueData == null) {
|
||||
tvQueueTableModel.setRowCount(0);
|
||||
styleRoomLabel(room1StatusLabel, room1Panel, Color.GREEN.darker(), "ROOM 1 EMPTY");
|
||||
styleRoomLabel(room2StatusLabel, room2Panel, Color.GREEN.darker(), "ROOM 2 EMPTY");
|
||||
return;
|
||||
}
|
||||
|
||||
List<Object[]> tvDataList = new ArrayList<>();
|
||||
SimpleDateFormat inputDateFormat = new SimpleDateFormat("dd/MM/yyyy");
|
||||
|
||||
for (String[] row : fullQueueData) {
|
||||
// Assuming row[0] is MaKhamBenh, row[1] is Date for year, row[2] is Ho, row[3] is Ten
|
||||
// As per user: "Mã khám bệnh (the first collum and last and first nam (concate index 2 and 3 (3rd and 4th collumn)) and take the year out from the second column))"
|
||||
if (row.length > 3) {
|
||||
String maKhamBenh = row[0];
|
||||
String ho = row[2];
|
||||
String ten = row[3];
|
||||
String hoVaTen = ho + " " + ten;
|
||||
String dateStr = row[1]; // Second column for date for year extraction
|
||||
String namSinh = "N/A"; // Or Nam Kham as discussed
|
||||
|
||||
try {
|
||||
Date parsedDate;
|
||||
if (dateStr.matches("\\d+")) { // Unix timestamp
|
||||
parsedDate = new Date(Long.parseLong(dateStr));
|
||||
} else { // dd/MM/yyyy format
|
||||
parsedDate = inputDateFormat.parse(dateStr);
|
||||
}
|
||||
Calendar calendar = Calendar.getInstance();
|
||||
calendar.setTime(parsedDate);
|
||||
namSinh = String.valueOf(calendar.get(Calendar.YEAR));
|
||||
} catch (ParseException | NumberFormatException e) {
|
||||
System.err.println("Error parsing date for TV Queue year: " + dateStr + " - " + e.getMessage());
|
||||
}
|
||||
tvDataList.add(new Object[]{maKhamBenh, hoVaTen, namSinh});
|
||||
}
|
||||
}
|
||||
tvQueueTableModel.setDataVector(tvDataList.toArray(new Object[0][0]), tvQueueColumns);
|
||||
|
||||
// Update Room 1 Status - This part will be superseded by updateSpecificRoomStatus or needs to be re-evaluated
|
||||
// if (fullQueueData.length > 0 && fullQueueData[0] != null && fullQueueData[0].length > 0) {
|
||||
// styleRoomLabel(room1StatusLabel, room1Panel, Color.RED.darker(), "ROOM 1 " + fullQueueData[0][0]);
|
||||
// } else {
|
||||
// styleRoomLabel(room1StatusLabel, room1Panel, Color.GREEN.darker(), "ROOM 1 EMPTY");
|
||||
// }
|
||||
|
||||
// Update Room 2 Status - This part will be superseded by updateSpecificRoomStatus or needs to be re-evaluated
|
||||
// if (fullQueueData.length > 1 && fullQueueData[1] != null && fullQueueData[1].length > 0) {
|
||||
// styleRoomLabel(room2StatusLabel, room2Panel, Color.RED.darker(), "ROOM 2 " + fullQueueData[1][0]);
|
||||
// } else {
|
||||
// styleRoomLabel(room2SṭatusLabel, room2Panel, Color.GREEN.darker(), "ROOM 2 EMPTY");
|
||||
// }
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setVisible(boolean b) {
|
||||
if (b) { // When making visible, reload clinic info in case it changed or was not available at init
|
||||
loadClinicInfo();
|
||||
}
|
||||
super.setVisible(b);
|
||||
}
|
||||
|
||||
// Optional: A method to make the frame more TV-friendly (e.g., full screen)
|
||||
public void optimizeForTv() {
|
||||
setExtendedState(JFrame.MAXIMIZED_BOTH);
|
||||
// setUndecorated(true); // Optional: removes window borders, use with caution
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
package BsK.common.entity;
|
||||
|
||||
public enum Status {
|
||||
PENDING,
|
||||
PROCESSING,
|
||||
COMPLETED,
|
||||
CANCELLED,
|
||||
EMPTY
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
package BsK.common.packet.req;
|
||||
|
||||
import BsK.common.entity.Status;
|
||||
import BsK.common.packet.Packet;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
public class CallPatientRequest implements Packet {
|
||||
int roomId;
|
||||
int patientId;
|
||||
Status status;
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
package BsK.common.packet.req;
|
||||
|
||||
import BsK.common.packet.Packet;
|
||||
|
||||
public class LogoutRequest implements Packet {
|
||||
// This packet can be empty as the server identifies the user by channel.
|
||||
// If more specific logout information were needed (e.g., for auditing),
|
||||
// fields could be added here.
|
||||
public LogoutRequest() {
|
||||
// Constructor
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
package BsK.common.packet.res;
|
||||
|
||||
import BsK.common.entity.Status;
|
||||
import BsK.common.packet.Packet;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
public class CallPatientResponse implements Packet {
|
||||
int patientId;
|
||||
int roomId;
|
||||
Status status;
|
||||
}
|
||||
@@ -5,6 +5,7 @@ import BsK.common.packet.PacketSerializer;
|
||||
import BsK.common.packet.req.*;
|
||||
import BsK.common.packet.res.*;
|
||||
import BsK.common.packet.res.ErrorResponse.Error;
|
||||
import BsK.common.entity.Status;
|
||||
import BsK.common.util.date.DateUtils;
|
||||
import BsK.server.Server;
|
||||
import BsK.server.network.manager.SessionManager;
|
||||
@@ -61,6 +62,16 @@ public class ServerHandler extends SimpleChannelInboundHandler<TextWebSocketFram
|
||||
registerRequest.getPassword());
|
||||
// Tạo user trong database hoặc check exist
|
||||
boolean isUserExist = false;
|
||||
} else if (packet instanceof LogoutRequest) {
|
||||
var user = SessionManager.getUserByChannel(ctx.channel().id().asLongText());
|
||||
if (user != null) {
|
||||
log.info("User {} (Session {}) requested logout.", user.getUserId(), user.getSessionId());
|
||||
SessionManager.onUserDisconnect(ctx.channel());
|
||||
// Optionally, you could send a LogoutResponse back to the client if needed,
|
||||
// but since the client navigates away, it might not be processed.
|
||||
} else {
|
||||
log.warn("Received LogoutRequest from a channel with no active user session: {}", ctx.channel().id().asLongText());
|
||||
}
|
||||
} else {
|
||||
// Check if user is authenticated
|
||||
var user = SessionManager.getUserByChannel(ctx.channel().id().asLongText());
|
||||
@@ -246,7 +257,7 @@ public class ServerHandler extends SimpleChannelInboundHandler<TextWebSocketFram
|
||||
);
|
||||
|
||||
if (!rs.isBeforeFirst()) {
|
||||
System.out.println("No data found in the checkup table.");
|
||||
System.out.println("No history data found in the checkup table.");
|
||||
UserUtil.sendPacket(user.getSessionId(), new GetCustomerHistoryResponse(new String[0][7]));
|
||||
} else {
|
||||
ArrayList<String> resultList = new ArrayList<>();
|
||||
@@ -607,7 +618,17 @@ public class ServerHandler extends SimpleChannelInboundHandler<TextWebSocketFram
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (packet instanceof CallPatientRequest callPatientRequest) {
|
||||
log.debug("Received CallPatientRequest to call patient{}", callPatientRequest.getPatientId());
|
||||
int patientId = callPatientRequest.getPatientId();
|
||||
int roomId = callPatientRequest.getRoomId();
|
||||
Status status = callPatientRequest.getStatus();
|
||||
// send to all clients
|
||||
int maxCurId = SessionManager.getMaxSessionId();
|
||||
for (int sessionId = 1; sessionId <= maxCurId; sessionId++) {
|
||||
UserUtil.sendPacket(sessionId, new CallPatientResponse(patientId, roomId, status));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Binary file not shown.
Reference in new issue
Block a user