diff --git a/src/main/java/BsK/client/ui/component/DashboardPage/DashboardPage.java b/src/main/java/BsK/client/ui/component/DashboardPage/DashboardPage.java
index a475b5f..76c920f 100644
--- a/src/main/java/BsK/client/ui/component/DashboardPage/DashboardPage.java
+++ b/src/main/java/BsK/client/ui/component/DashboardPage/DashboardPage.java
@@ -344,7 +344,7 @@ public class DashboardPage extends JPanel {
private JButton createActionButton(String title, String icon, Color color) {
JButton button = new JButton();
- button.setUI(new RoundedButtonUI(10));
+ button.setUI(new RoundedButtonUI(color, Color.WHITE, 10));
button.setLayout(new BorderLayout());
button.setBackground(color);
button.setForeground(Color.WHITE);
diff --git a/src/main/java/BsK/client/ui/component/DataDialog/DataDialog.java b/src/main/java/BsK/client/ui/component/DataDialog/DataDialog.java
index cbfe27a..bdd464a 100644
--- a/src/main/java/BsK/client/ui/component/DataDialog/DataDialog.java
+++ b/src/main/java/BsK/client/ui/component/DataDialog/DataDialog.java
@@ -53,6 +53,7 @@ public class DataDialog extends JDialog {
// --- Panels for the other tabs
private MedicineManagementPanel medicinePanel;
private ServiceManagementPanel servicePanel;
+ private UserManagementPanel userPanel;
public DataDialog(JFrame parent, CheckUpPage checkUpPage) {
super(parent, "Quản Lý Dữ Liệu", true);
@@ -87,11 +88,14 @@ public class DataDialog extends JDialog {
medicinePanel = new MedicineManagementPanel();
tabbedPane.addTab("
Quản Lý Thuốc", medicinePanel);
- // --- Tab 3: Service Management (Instantiate new panel) ---
- // *** THIS IS THE CORRECTED PART ***
+ // --- Tab 3: Service Management ---
servicePanel = new ServiceManagementPanel();
tabbedPane.addTab("Quản Lý Dịch Vụ", servicePanel);
+ // --- Tab 4: User Management ---
+ userPanel = new UserManagementPanel();
+ tabbedPane.addTab("Quản Lý Người Dùng", userPanel);
+
add(tabbedPane, BorderLayout.CENTER);
loadFiltersFromLocalStorage();
@@ -112,6 +116,9 @@ public class DataDialog extends JDialog {
if (servicePanel != null) {
servicePanel.cleanup();
}
+ if (userPanel != null) {
+ userPanel.cleanup();
+ }
super.windowClosing(e);
}
});
diff --git a/src/main/java/BsK/client/ui/component/DataDialog/MedicineManagementPanel.java b/src/main/java/BsK/client/ui/component/DataDialog/MedicineManagementPanel.java
index ea0a53b..7ce1633 100644
--- a/src/main/java/BsK/client/ui/component/DataDialog/MedicineManagementPanel.java
+++ b/src/main/java/BsK/client/ui/component/DataDialog/MedicineManagementPanel.java
@@ -41,6 +41,9 @@ public class MedicineManagementPanel extends JPanel {
private JSpinner morningSpinner, noonSpinner, eveningSpinner;
private JTextArea noteField;
+ // --- Action Buttons ---
+ private JButton btnAdd, btnEdit, btnDelete, btnClear;
+
// --- Data & State
private List allMedicines = new ArrayList<>();
private String selectedMedicineId = null;
@@ -330,10 +333,10 @@ public class MedicineManagementPanel extends JPanel {
private JPanel createMedicineButtonPanel() {
JPanel buttonPanel = new JPanel(new FlowLayout(FlowLayout.CENTER, 10, 5));
- JButton btnAdd = new JButton("Thêm mới");
- JButton btnEdit = new JButton("Chỉnh sửa");
- JButton btnDelete = new JButton("Xoá");
- JButton btnClear = new JButton("Làm mới");
+ btnAdd = new JButton("Thêm mới");
+ btnEdit = new JButton("Chỉnh sửa");
+ btnDelete = new JButton("Xoá");
+ btnClear = new JButton("Làm mới");
Dimension btnSize = new Dimension(100, 35);
btnAdd.setPreferredSize(btnSize);
@@ -383,6 +386,10 @@ public class MedicineManagementPanel extends JPanel {
}
});
+ // Initial button states
+ btnEdit.setEnabled(false);
+ btnDelete.setEnabled(false);
+
return buttonPanel;
}
@@ -458,6 +465,11 @@ public class MedicineManagementPanel extends JPanel {
medicineQuantityField.setText(med.getQuantity());
medicineUnitComboBox.setSelectedItem(med.getUnit());
medicinePriceField.setText(med.getSellingPrice());
+
+ // Update button states
+ btnAdd.setEnabled(false);
+ btnEdit.setEnabled(true);
+ btnDelete.setEnabled(true);
}
private void clearMedicineFields() {
@@ -470,6 +482,11 @@ public class MedicineManagementPanel extends JPanel {
medicinePriceField.setText("");
medicineTable.clearSelection();
medicineNameField.requestFocusInWindow();
+
+ // Reset button states
+ btnAdd.setEnabled(true);
+ btnEdit.setEnabled(false);
+ btnDelete.setEnabled(false);
}
private void filterMedicineTable() {
diff --git a/src/main/java/BsK/client/ui/component/DataDialog/ServiceManagementPanel.java b/src/main/java/BsK/client/ui/component/DataDialog/ServiceManagementPanel.java
index d38822d..822e3b1 100644
--- a/src/main/java/BsK/client/ui/component/DataDialog/ServiceManagementPanel.java
+++ b/src/main/java/BsK/client/ui/component/DataDialog/ServiceManagementPanel.java
@@ -37,6 +37,8 @@ public class ServiceManagementPanel extends JPanel {
private JTextField totalField;
private JTextArea noteField;
+ private JButton btnAdd, btnEdit, btnDelete, btnClear;
+
// --- Data & State ---
private List allServices = new ArrayList<>();
private String selectedServiceId = null;
@@ -202,10 +204,10 @@ public class ServiceManagementPanel extends JPanel {
*/
private JPanel createServiceButtonPanel() {
JPanel buttonPanel = new JPanel(new FlowLayout(FlowLayout.CENTER, 10, 5));
- JButton btnAdd = new JButton("Thêm mới");
- JButton btnEdit = new JButton("Chỉnh sửa");
- JButton btnDelete = new JButton("Xoá");
- JButton btnClear = new JButton("Làm mới");
+ btnAdd = new JButton("Thêm mới");
+ btnEdit = new JButton("Chỉnh sửa");
+ btnDelete = new JButton("Xoá");
+ btnClear = new JButton("Làm mới");
Dimension btnSize = new Dimension(100, 35);
btnAdd.setPreferredSize(btnSize);
@@ -255,6 +257,10 @@ public class ServiceManagementPanel extends JPanel {
}
});
+ // Initial button states
+ btnEdit.setEnabled(false);
+ btnDelete.setEnabled(false);
+
return buttonPanel;
}
@@ -332,6 +338,11 @@ public class ServiceManagementPanel extends JPanel {
priceField.setText(service.getCost());
noteField.setText(""); // Assuming notes are not stored in the main service entity
quantitySpinner.setValue(1);
+
+ // Update button states
+ btnAdd.setEnabled(false);
+ btnEdit.setEnabled(true);
+ btnDelete.setEnabled(true);
}
private void clearServiceFields() {
@@ -343,6 +354,11 @@ public class ServiceManagementPanel extends JPanel {
quantitySpinner.setValue(1);
serviceTable.clearSelection();
serviceNameField.requestFocusInWindow();
+
+ // Reset button states
+ btnAdd.setEnabled(true);
+ btnEdit.setEnabled(false);
+ btnDelete.setEnabled(false);
}
private void filterServiceTable() {
diff --git a/src/main/java/BsK/client/ui/component/DataDialog/UserManagementPanel.java b/src/main/java/BsK/client/ui/component/DataDialog/UserManagementPanel.java
new file mode 100644
index 0000000..8759f4a
--- /dev/null
+++ b/src/main/java/BsK/client/ui/component/DataDialog/UserManagementPanel.java
@@ -0,0 +1,359 @@
+package BsK.client.ui.component.DataDialog;
+
+import BsK.common.util.text.TextUtils;
+
+import javax.swing.*;
+import javax.swing.border.EmptyBorder;
+import javax.swing.border.TitledBorder;
+import javax.swing.event.DocumentEvent;
+import javax.swing.event.DocumentListener;
+import javax.swing.table.DefaultTableModel;
+import javax.swing.text.AbstractDocument;
+import javax.swing.text.AttributeSet;
+import javax.swing.text.BadLocationException;
+import javax.swing.text.DocumentFilter;
+import java.awt.*;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.UUID;
+
+public class UserManagementPanel extends JPanel {
+
+ // --- UI Components ---
+ private JTable userTable;
+ private DefaultTableModel userTableModel;
+ private JTextField userSearchField;
+
+ // --- Input Fields ---
+ private JTextField userIdField;
+ private JTextField usernameField;
+ private JTextField firstNameField;
+ private JTextField lastNameField;
+ private JPasswordField passwordField;
+ private JComboBox roleComboBox;
+ private JButton btnAdd, btnEdit, btnDelete, btnClear;
+
+ // --- Data & State ---
+ private List allUsers = new ArrayList<>();
+ private User selectedUser = null;
+
+ // A simple record to hold user data locally
+ private record User(String id, String username, String password, String firstName, String lastName, String role) {}
+
+ public UserManagementPanel() {
+ super(new BorderLayout(10, 10));
+ initComponents();
+ createFakeData();
+ filterUserTable(); // Initial population
+ }
+
+ private void initComponents() {
+ this.setBorder(new EmptyBorder(15, 15, 15, 15));
+ this.add(createUserInputPanel(), BorderLayout.WEST);
+ this.add(createUserListPanel(), BorderLayout.CENTER);
+ }
+
+ private void createFakeData() {
+ allUsers.add(new User(UUID.randomUUID().toString().substring(0, 8), "admin_user", "password123", "Admin", "Super", "ADMIN"));
+ allUsers.add(new User(UUID.randomUUID().toString().substring(0, 8), "doctor_phil", "pass", "Phil", "McGraw", "USER"));
+ allUsers.add(new User(UUID.randomUUID().toString().substring(0, 8), "nurse_jane", "pass", "Jane", "Doe", "USER"));
+ }
+
+ private JPanel createUserInputPanel() {
+ 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;
+ mainGbc.gridx = 0;
+
+ Font titleFont = new Font("Arial", Font.BOLD, 14);
+ Font labelFont = new Font("Arial", Font.BOLD, 13);
+ Font textFont = new Font("Arial", Font.PLAIN, 13);
+ Dimension textFieldSize = new Dimension(100, 30);
+
+ // --- User Details Panel ---
+ JPanel detailsPanel = new JPanel(new GridBagLayout());
+ detailsPanel.setBorder(BorderFactory.createTitledBorder(
+ BorderFactory.createEtchedBorder(), "Thông tin người dùng",
+ TitledBorder.LEADING, TitledBorder.TOP, titleFont, new Color(50, 50, 50)
+ ));
+ GridBagConstraints gbc = new GridBagConstraints();
+ gbc.fill = GridBagConstraints.HORIZONTAL;
+ gbc.anchor = GridBagConstraints.WEST;
+ gbc.insets = new Insets(5, 5, 5, 5);
+
+ // User ID (Row 0)
+ gbc.gridy = 0;
+ gbc.gridx = 0;
+ gbc.weightx = 0.2; // Label column width
+ JLabel userIdLabel = new JLabel("UserID:");
+ userIdLabel.setFont(labelFont);
+ detailsPanel.add(userIdLabel, gbc);
+
+ gbc.gridx = 1;
+ gbc.weightx = 0.8; // Field column width
+ userIdField = new JTextField();
+ userIdField.setEditable(false);
+ userIdField.setFont(textFont);
+ userIdField.setPreferredSize(textFieldSize);
+ detailsPanel.add(userIdField, gbc);
+
+ // Username (Row 1)
+ gbc.gridy++;
+ gbc.gridx = 0;
+ JLabel usernameLabel = new JLabel("Username:");
+ usernameLabel.setFont(labelFont);
+ detailsPanel.add(usernameLabel, gbc);
+
+ gbc.gridx = 1;
+ usernameField = new JTextField();
+ usernameField.setFont(textFont);
+ usernameField.setPreferredSize(textFieldSize);
+ ((AbstractDocument) usernameField.getDocument()).setDocumentFilter(new DocumentFilter() {
+ @Override
+ public void replace(FilterBypass fb, int offset, int length, String text, AttributeSet attrs) throws BadLocationException {
+ super.replace(fb, offset, length, text.toLowerCase().replaceAll("[^a-z0-9_]", ""), attrs);
+ }
+ });
+ detailsPanel.add(usernameField, gbc);
+
+ // First Name (Row 2)
+ gbc.gridy++;
+ gbc.gridx = 0;
+ JLabel firstNameLabel = new JLabel("Họ:");
+ firstNameLabel.setFont(labelFont);
+ detailsPanel.add(firstNameLabel, gbc);
+
+ gbc.gridx = 1;
+ firstNameField = new JTextField();
+ firstNameField.setFont(textFont);
+ firstNameField.setPreferredSize(textFieldSize);
+ detailsPanel.add(firstNameField, gbc);
+
+ // Last Name (Row 3)
+ gbc.gridy++;
+ gbc.gridx = 0;
+ JLabel lastNameLabel = new JLabel("Tên:");
+ lastNameLabel.setFont(labelFont);
+ detailsPanel.add(lastNameLabel, gbc);
+
+ gbc.gridx = 1;
+ lastNameField = new JTextField();
+ lastNameField.setFont(textFont);
+ lastNameField.setPreferredSize(textFieldSize);
+ detailsPanel.add(lastNameField, gbc);
+
+ // Role (Row 4)
+ gbc.gridy++;
+ gbc.gridx = 0;
+ JLabel roleLabel = new JLabel("Vai trò:");
+ roleLabel.setFont(labelFont);
+ detailsPanel.add(roleLabel, gbc);
+
+ gbc.gridx = 1;
+ roleComboBox = new JComboBox<>(new String[]{"USER", "ADMIN"});
+ roleComboBox.setFont(textFont);
+ roleComboBox.setPreferredSize(textFieldSize);
+ detailsPanel.add(roleComboBox, gbc);
+
+ // Password (Row 5)
+ gbc.gridy++;
+ gbc.gridx = 0;
+ JLabel passwordLabel = new JLabel("Mật khẩu:");
+ passwordLabel.setFont(labelFont);
+ detailsPanel.add(passwordLabel, gbc);
+
+ gbc.gridx = 1;
+ passwordField = new JPasswordField();
+ passwordField.setFont(textFont);
+ passwordField.setPreferredSize(textFieldSize);
+ detailsPanel.add(passwordField, gbc);
+
+ mainGbc.gridy = 0;
+ mainInputPanel.add(detailsPanel, mainGbc);
+
+ mainGbc.gridy = 1;
+ mainInputPanel.add(createButtonPanel(), mainGbc);
+
+ mainGbc.gridy = 2;
+ mainGbc.weighty = 1.0; // Filler to push content up
+ mainInputPanel.add(new JPanel(), mainGbc);
+
+ return mainInputPanel;
+ }
+
+ private JPanel createButtonPanel() {
+ JPanel buttonPanel = new JPanel(new FlowLayout(FlowLayout.CENTER, 10, 5));
+ btnAdd = new JButton("Thêm mới");
+ btnEdit = new JButton("Chỉnh sửa");
+ btnDelete = new JButton("Xoá");
+ btnClear = new JButton("Làm mới");
+
+ Dimension btnSize = new Dimension(100, 35);
+ btnAdd.setPreferredSize(btnSize);
+ btnEdit.setPreferredSize(btnSize);
+ btnDelete.setPreferredSize(btnSize);
+ btnClear.setPreferredSize(btnSize);
+
+ buttonPanel.add(btnAdd);
+ buttonPanel.add(btnEdit);
+ buttonPanel.add(btnDelete);
+ buttonPanel.add(btnClear);
+
+ btnClear.addActionListener(e -> clearUserFields());
+ btnAdd.addActionListener(e -> handleAddUser());
+ btnEdit.addActionListener(e -> handleEditUser());
+ btnDelete.addActionListener(e -> handleDeleteUser());
+
+ // Initial state
+ btnEdit.setEnabled(false);
+ btnDelete.setEnabled(false);
+
+ return buttonPanel;
+ }
+
+ private JPanel createUserListPanel() {
+ JPanel listPanel = new JPanel(new BorderLayout(10, 10));
+ listPanel.setBorder(BorderFactory.createTitledBorder(
+ BorderFactory.createEtchedBorder(), "Danh sách người dùng",
+ TitledBorder.LEFT, TitledBorder.TOP, new Font("Arial", Font.BOLD, 14)));
+
+ // Search Panel
+ JPanel searchPanel = new JPanel(new FlowLayout(FlowLayout.LEFT));
+ searchPanel.add(new JLabel("Tìm theo username:"));
+ userSearchField = new JTextField(25);
+ userSearchField.getDocument().addDocumentListener(new DocumentListener() {
+ @Override public void insertUpdate(DocumentEvent e) { filterUserTable(); }
+ @Override public void removeUpdate(DocumentEvent e) { filterUserTable(); }
+ @Override public void changedUpdate(DocumentEvent e) { filterUserTable(); }
+ });
+ searchPanel.add(userSearchField);
+ listPanel.add(searchPanel, BorderLayout.NORTH);
+
+ // Table
+ String[] userColumns = {"UserID", "Username", "Họ", "Tên", "Vai trò"};
+ userTableModel = new DefaultTableModel(userColumns, 0) {
+ @Override public boolean isCellEditable(int row, int column) { return false; }
+ };
+ userTable = new JTable(userTableModel);
+ userTable.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
+ userTable.setRowHeight(28);
+ userTable.getSelectionModel().addListSelectionListener(e -> {
+ if (!e.getValueIsAdjusting() && userTable.getSelectedRow() != -1) {
+ int viewRow = userTable.getSelectedRow();
+ String userId = (String) userTableModel.getValueAt(viewRow, 0);
+ selectedUser = allUsers.stream().filter(u -> u.id().equals(userId)).findFirst().orElse(null);
+ if (selectedUser != null) {
+ populateUserFields(selectedUser);
+ }
+ }
+ });
+ listPanel.add(new JScrollPane(userTable), BorderLayout.CENTER);
+ return listPanel;
+ }
+
+ private void filterUserTable() {
+ String filterText = userSearchField.getText().trim().toLowerCase();
+ userTableModel.setRowCount(0);
+ for (User user : allUsers) {
+ if (filterText.isEmpty() || user.username().toLowerCase().contains(filterText)) {
+ userTableModel.addRow(new Object[]{user.id(), user.username(), user.firstName(), user.lastName(), user.role()});
+ }
+ }
+ }
+
+ private void populateUserFields(User user) {
+ userIdField.setText(user.id());
+ usernameField.setText(user.username());
+ firstNameField.setText(user.firstName());
+ lastNameField.setText(user.lastName());
+ roleComboBox.setSelectedItem(user.role());
+ passwordField.setText("");
+ passwordField.setEnabled(false);
+ btnAdd.setEnabled(false);
+ btnEdit.setEnabled(true);
+ btnDelete.setEnabled(true);
+ }
+
+ private void clearUserFields() {
+ selectedUser = null;
+ userIdField.setText("(Tự động)");
+ usernameField.setText("");
+ firstNameField.setText("");
+ lastNameField.setText("");
+ roleComboBox.setSelectedIndex(0);
+ passwordField.setText("");
+ passwordField.setEnabled(true);
+ userTable.clearSelection();
+ btnAdd.setEnabled(true);
+ btnEdit.setEnabled(false);
+ btnDelete.setEnabled(false);
+ usernameField.requestFocusInWindow();
+ }
+
+ private void handleAddUser() {
+ String username = usernameField.getText().trim();
+ String password = new String(passwordField.getPassword());
+ if (username.isEmpty() || password.isEmpty()) {
+ JOptionPane.showMessageDialog(this, "Username và Mật khẩu không được để trống.", "Lỗi", JOptionPane.ERROR_MESSAGE);
+ return;
+ }
+ if (allUsers.stream().anyMatch(u -> u.username().equals(username))) {
+ JOptionPane.showMessageDialog(this, "Username đã tồn tại.", "Lỗi", JOptionPane.ERROR_MESSAGE);
+ return;
+ }
+ User newUser = new User(
+ UUID.randomUUID().toString().substring(0, 8),
+ username,
+ password, // In a real app, hash this!
+ firstNameField.getText().trim(),
+ lastNameField.getText().trim(),
+ (String) roleComboBox.getSelectedItem()
+ );
+ allUsers.add(newUser);
+ filterUserTable();
+ clearUserFields();
+ JOptionPane.showMessageDialog(this, "Thêm người dùng thành công!", "Thông báo", JOptionPane.INFORMATION_MESSAGE);
+ }
+
+ private void handleEditUser() {
+ if (selectedUser == null) return;
+ // Find the user in the list and update them
+ for (int i = 0; i < allUsers.size(); i++) {
+ if (allUsers.get(i).id().equals(selectedUser.id())) {
+ User updatedUser = new User(
+ selectedUser.id(),
+ usernameField.getText().trim(),
+ selectedUser.password(), // Keep original password
+ firstNameField.getText().trim(),
+ lastNameField.getText().trim(),
+ (String) roleComboBox.getSelectedItem()
+ );
+ allUsers.set(i, updatedUser);
+ break;
+ }
+ }
+ filterUserTable();
+ clearUserFields();
+ JOptionPane.showMessageDialog(this, "Cập nhật thành công!", "Thông báo", JOptionPane.INFORMATION_MESSAGE);
+ }
+
+ private void handleDeleteUser() {
+ if (selectedUser == null) return;
+ int choice = JOptionPane.showConfirmDialog(this,
+ "Bạn có chắc chắn muốn xóa người dùng '" + selectedUser.username() + "' không?",
+ "Xác nhận xóa", JOptionPane.YES_NO_OPTION, JOptionPane.WARNING_MESSAGE);
+ if (choice == JOptionPane.YES_OPTION) {
+ allUsers.removeIf(u -> u.id().equals(selectedUser.id()));
+ filterUserTable();
+ clearUserFields();
+ }
+ }
+
+ public void cleanup() {
+ // No listeners to clean up yet, but good practice to have.
+ }
+}
diff --git a/src/main/java/BsK/client/ui/component/LandingPage/LandingPage.java b/src/main/java/BsK/client/ui/component/LandingPage/LandingPage.java
index f701cc8..f9ef2ca 100644
--- a/src/main/java/BsK/client/ui/component/LandingPage/LandingPage.java
+++ b/src/main/java/BsK/client/ui/component/LandingPage/LandingPage.java
@@ -1,11 +1,10 @@
package BsK.client.ui.component.LandingPage;
import BsK.client.ui.component.MainFrame;
+import BsK.client.ui.component.common.RoundedButtonUI;
import javax.swing.*;
import java.awt.*;
-import java.awt.event.ActionEvent;
-import java.awt.event.ActionListener;
public class LandingPage extends JPanel {
public LandingPage(MainFrame mainFrame) {
@@ -64,8 +63,14 @@ public class LandingPage extends JPanel {
gbc.gridx = 0;
gbc.gridy = 0;
- JButton loginButton = new RoundedButton("Login");
- JButton registerButton = new RoundedButton("Register");
+ JButton loginButton = new JButton("Đăng nhập");
+ loginButton.setUI(new RoundedButtonUI(new Color(0, 0, 0, 0), Color.WHITE, Color.WHITE, 30));
+ loginButton.setFont(new Font("Arial", Font.BOLD, 14));
+
+ JButton registerButton = new JButton("Đăng ký");
+ registerButton.setUI(new RoundedButtonUI(new Color(0, 0, 0, 0), Color.WHITE, Color.WHITE, 30));
+ registerButton.setFont(new Font("Arial", Font.BOLD, 14));
+
// Set the same preferred size for both buttons
Dimension buttonSize = new Dimension(150, 40);
@@ -80,55 +85,8 @@ public class LandingPage extends JPanel {
add(rightPanel, BorderLayout.EAST);
// Action listeners for buttons
- loginButton.addActionListener(new ActionListener() {
- @Override
- public void actionPerformed(ActionEvent e) {
- mainFrame.showPage("LoginPage");
- }
- });
+ loginButton.addActionListener(e -> mainFrame.showPage("LoginPage"));
- registerButton.addActionListener(new ActionListener() {
- @Override
- public void actionPerformed(ActionEvent e) {
- mainFrame.showPage("RegisterPage");
- }
- });
+ registerButton.addActionListener(e -> mainFrame.showPage("RegisterPage"));
}
-
- // Custom button class with rounded edges and stroke
- private static class RoundedButton extends JButton {
- public RoundedButton(String text) {
- super(text);
- setContentAreaFilled(false);
- setFocusPainted(false);
- setOpaque(false);
- setBorderPainted(false); // Ensure the border is not painted
- }
-
- @Override
- protected void paintComponent(Graphics g) {
- // Do not call super.paintComponent(g) to avoid painting the background
- Graphics2D g2 = (Graphics2D) g.create();
- g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
- g2.setColor(getBackground());
- g2.fillRoundRect(0, 0, getWidth(), getHeight(), 30, 30);
- g2.dispose();
- super.paintComponent(g); // Call super to paint the text
- }
-
- @Override
- protected void paintBorder(Graphics g) {
- Graphics2D g2 = (Graphics2D) g.create();
- g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
- g2.setColor(Color.WHITE);
- g2.setStroke(new BasicStroke(2));
- g2.drawRoundRect(0, 0, getWidth() - 1, getHeight() - 1, 30, 30);
- g2.dispose();
- }
-
- @Override
- public Insets getInsets() {
- return new Insets(10, 20, 10, 20);
- }
- }
-}
\ No newline at end of file
+}
diff --git a/src/main/java/BsK/client/ui/component/LoginPage/LoginPage.java b/src/main/java/BsK/client/ui/component/LoginPage/LoginPage.java
index 4d0e6bd..722ccd9 100644
--- a/src/main/java/BsK/client/ui/component/LoginPage/LoginPage.java
+++ b/src/main/java/BsK/client/ui/component/LoginPage/LoginPage.java
@@ -3,8 +3,7 @@ package BsK.client.ui.component.LoginPage;
import BsK.client.LocalStorage;
import BsK.client.network.handler.ClientHandler;
import BsK.client.ui.component.MainFrame;
-import BsK.common.packet.Packet;
-import BsK.common.packet.PacketSerializer;
+import BsK.client.ui.component.common.RoundedButtonUI;
import BsK.common.packet.req.ClinicInfoRequest;
import BsK.common.packet.req.GetDoctorGeneralInfo;
import BsK.common.packet.req.GetProvinceRequest;
@@ -16,8 +15,6 @@ import lombok.extern.slf4j.Slf4j;
import javax.swing.*;
import java.awt.*;
-import java.awt.event.ActionEvent;
-import java.awt.event.ActionListener;
@Slf4j
public class LoginPage extends JPanel {
@@ -39,44 +36,58 @@ public class LoginPage extends JPanel {
}
};
backgroundPanel.setLayout(new GridBagLayout());
+ add(backgroundPanel, BorderLayout.CENTER);
+
+ JPanel formPanel = new JPanel(new GridBagLayout());
+ formPanel.setOpaque(false);
+
GridBagConstraints gbc = new GridBagConstraints();
- gbc.insets = new Insets(5, 5, 5, 5);
+ gbc.insets = new Insets(10, 10, 4, 10);
gbc.gridx = 0;
gbc.gridy = 0;
- gbc.gridwidth = 2; // Span across two columns
+ gbc.gridwidth = 2;
+ gbc.anchor = GridBagConstraints.CENTER;
- JLabel promptLabel = new JLabel("Vui lòng nhập thông tin chi tiết của bạn:");
+ JLabel promptLabel = new JLabel("Đăng nhập");
promptLabel.setForeground(Color.WHITE);
- promptLabel.setFont(new Font("Arial", Font.BOLD, 20));
- backgroundPanel.add(promptLabel, gbc);
+ promptLabel.setFont(new Font("Arial", Font.BOLD, 32));
+ formPanel.add(promptLabel, gbc);
- gbc.gridwidth = 1; // Reset to default
+ gbc.gridwidth = 1;
gbc.gridy++;
- JLabel usernameLabel = new JLabel("Nhập tên đăng nhập:");
+ gbc.anchor = GridBagConstraints.EAST;
+ JLabel usernameLabel = new JLabel("Tên đăng nhập:");
usernameLabel.setForeground(Color.WHITE);
- backgroundPanel.add(usernameLabel, gbc);
+ usernameLabel.setFont(new Font("Arial", Font.PLAIN, 14));
+ formPanel.add(usernameLabel, gbc);
gbc.gridx = 1;
+ gbc.anchor = GridBagConstraints.WEST;
JTextField loginField = new JTextField(20);
- backgroundPanel.add(loginField, gbc);
+ formPanel.add(loginField, gbc);
gbc.gridx = 0;
gbc.gridy++;
- JLabel passwordLabel = new JLabel("Nhập mật khẩu:");
+ gbc.anchor = GridBagConstraints.EAST;
+ JLabel passwordLabel = new JLabel("Mật khẩu:");
passwordLabel.setForeground(Color.WHITE);
- backgroundPanel.add(passwordLabel, gbc);
+ passwordLabel.setFont(new Font("Arial", Font.PLAIN, 14));
+ formPanel.add(passwordLabel, gbc);
gbc.gridx = 1;
+ gbc.anchor = GridBagConstraints.WEST;
JPasswordField passwordField = new JPasswordField(20);
- backgroundPanel.add(passwordField, gbc);
+ formPanel.add(passwordField, gbc);
+ gbc.gridx = 0;
gbc.gridy++;
+ gbc.gridwidth = 2;
+ gbc.anchor = GridBagConstraints.CENTER;
JButton loginButton = new JButton("Đăng nhập");
+ loginButton.setUI(new RoundedButtonUI(new Color(13, 110, 253), Color.WHITE, 10));
+ loginButton.setFont(new Font("Arial", Font.BOLD, 14));
- // listener for Password Field to press Enter
- passwordField.addActionListener(e -> {
- loginButton.doClick();
- });
+ passwordField.addActionListener(e -> loginButton.doClick());
loginButton.addActionListener(e -> {
char[] passwordChars = passwordField.getPassword();
@@ -105,17 +116,19 @@ public class LoginPage extends JPanel {
});
- backgroundPanel.add(loginButton, gbc);
- add(backgroundPanel, BorderLayout.CENTER);
+ formPanel.add(loginButton, gbc);
+ backgroundPanel.add(formPanel, new GridBagConstraints());
JButton backButton = new JButton("Trở về");
- backButton.addActionListener(new ActionListener() {
- @Override
- public void actionPerformed(ActionEvent e) {
- mainFrame.showPage("LandingPage");
- }
- });
- add(backButton, BorderLayout.SOUTH);
+ backButton.setUI(new RoundedButtonUI(new Color(108, 117, 125), Color.WHITE, 10));
+ backButton.setFont(new Font("Arial", Font.BOLD, 14));
+
+ backButton.addActionListener(e -> mainFrame.showPage("LandingPage"));
+
+ JPanel southPanel = new JPanel(new FlowLayout(FlowLayout.RIGHT));
+ southPanel.setOpaque(false);
+ southPanel.add(backButton);
+ add(southPanel, BorderLayout.SOUTH);
}
-}
\ No newline at end of file
+}
diff --git a/src/main/java/BsK/client/ui/component/RegisterPage/RegisterPage.java b/src/main/java/BsK/client/ui/component/RegisterPage/RegisterPage.java
index f7ca2b7..eb34f43 100644
--- a/src/main/java/BsK/client/ui/component/RegisterPage/RegisterPage.java
+++ b/src/main/java/BsK/client/ui/component/RegisterPage/RegisterPage.java
@@ -26,78 +26,12 @@ public class RegisterPage extends JPanel {
}
};
backgroundPanel.setLayout(new GridBagLayout());
- GridBagConstraints gbc = new GridBagConstraints();
- gbc.insets = new Insets(10, 10, 10, 10);
- gbc.gridx = 0;
- gbc.gridy = 0;
- gbc.anchor = GridBagConstraints.WEST;
+
+ JLabel announcementLabel = new JLabel("Hãy liên hệ với Admin để tạo tài khoản");
+ announcementLabel.setForeground(Color.WHITE);
+ announcementLabel.setFont(new Font("Arial", Font.BOLD, 20));
+ backgroundPanel.add(announcementLabel, new GridBagConstraints());
- JLabel promptLabel = new JLabel("Please enter your details:");
- promptLabel.setForeground(Color.WHITE);
- promptLabel.setFont(new Font("Arial", Font.BOLD, 20));
- gbc.gridwidth = 2;
- backgroundPanel.add(promptLabel, gbc);
-
- gbc.gridwidth = 1;
- gbc.gridy++;
- JLabel usernameLabel = new JLabel("Username:");
- usernameLabel.setForeground(Color.WHITE);
- backgroundPanel.add(usernameLabel, gbc);
-
- gbc.gridx = 1;
- JTextField usernameField = new JTextField(20);
- backgroundPanel.add(usernameField, gbc);
-
- gbc.gridx = 0;
- gbc.gridy++;
- JLabel nameLabel = new JLabel("Name:");
- nameLabel.setForeground(Color.WHITE);
- backgroundPanel.add(nameLabel, gbc);
-
- gbc.gridx = 1;
- JTextField nameField = new JTextField(20);
- backgroundPanel.add(nameField, gbc);
-
- gbc.gridx = 0;
- gbc.gridy++;
- JLabel passwordLabel = new JLabel("Password:");
- passwordLabel.setForeground(Color.WHITE);
- backgroundPanel.add(passwordLabel, gbc);
-
- gbc.gridx = 1;
- JPasswordField passwordField = new JPasswordField(20);
- backgroundPanel.add(passwordField, gbc);
-
- gbc.gridx = 0;
- gbc.gridy++;
- JLabel rePasswordLabel = new JLabel("Re-enter your password:");
- rePasswordLabel.setForeground(Color.WHITE);
- backgroundPanel.add(rePasswordLabel, gbc);
-
- gbc.gridx = 1;
- JPasswordField rePasswordField = new JPasswordField(20);
- backgroundPanel.add(rePasswordField, gbc);
-
- gbc.gridx = 0;
- gbc.gridy++;
- JLabel roleLabel = new JLabel("Role:");
- roleLabel.setForeground(Color.WHITE);
- backgroundPanel.add(roleLabel, gbc);
-
- gbc.gridx = 1;
- String[] roles = {"user", "admin", "doctor", "nurse"};
- JComboBox roleComboBox = new JComboBox<>(roles);
- backgroundPanel.add(roleComboBox, gbc);
-
- gbc.gridy++;
- JButton loginButton = new JButton("Register");
- loginButton.addActionListener(new ActionListener() {
- @Override
- public void actionPerformed(ActionEvent e) {
- mainFrame.showPage("LandingPage");
- }
- });
- backgroundPanel.add(loginButton, gbc);
add(backgroundPanel, BorderLayout.CENTER);
// Back button to return to the landing page
@@ -110,7 +44,4 @@ public class RegisterPage extends JPanel {
});
add(backButton, BorderLayout.SOUTH);
}
- public static void main(String[] args) {
- System.out.println("Working Directory = " + System.getProperty("user.dir"));
- }
-}
\ No newline at end of file
+}
diff --git a/src/main/java/BsK/client/ui/component/common/RoundedButtonUI.java b/src/main/java/BsK/client/ui/component/common/RoundedButtonUI.java
index 56c3dfc..06d13af 100644
--- a/src/main/java/BsK/client/ui/component/common/RoundedButtonUI.java
+++ b/src/main/java/BsK/client/ui/component/common/RoundedButtonUI.java
@@ -3,11 +3,23 @@ package BsK.client.ui.component.common;
import javax.swing.*;
import javax.swing.plaf.basic.BasicButtonUI;
import java.awt.*;
+import java.awt.event.MouseAdapter;
+import java.awt.event.MouseEvent;
public class RoundedButtonUI extends BasicButtonUI {
private final int cornerRadius;
+ private final Color backgroundColor;
+ private final Color foregroundColor;
+ private final Color borderColor;
- public RoundedButtonUI(int cornerRadius) {
+ public RoundedButtonUI(Color backgroundColor, Color foregroundColor, int cornerRadius) {
+ this(backgroundColor, foregroundColor, null, cornerRadius);
+ }
+
+ public RoundedButtonUI(Color backgroundColor, Color foregroundColor, Color borderColor, int cornerRadius) {
+ this.backgroundColor = backgroundColor;
+ this.foregroundColor = foregroundColor;
+ this.borderColor = borderColor;
this.cornerRadius = cornerRadius;
}
@@ -16,7 +28,23 @@ public class RoundedButtonUI extends BasicButtonUI {
super.installUI(c);
JButton button = (JButton) c;
button.setOpaque(false);
- button.setBorder(BorderFactory.createEmptyBorder(5, 15, 5, 15));
+ button.setFocusPainted(false);
+ button.setBorderPainted(false);
+ button.setBackground(backgroundColor);
+ button.setForeground(foregroundColor);
+ button.setBorder(BorderFactory.createEmptyBorder(10, 20, 10, 20));
+
+ button.addMouseListener(new MouseAdapter() {
+ @Override
+ public void mouseEntered(MouseEvent e) {
+ button.repaint();
+ }
+
+ @Override
+ public void mouseExited(MouseEvent e) {
+ button.repaint();
+ }
+ });
}
@Override
@@ -24,16 +52,38 @@ public class RoundedButtonUI extends BasicButtonUI {
JButton button = (JButton) c;
Graphics2D g2 = (Graphics2D) g.create();
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
- int width = button.getWidth();
- int height = button.getHeight();
- g2.setColor(button.getBackground());
- g2.fillRoundRect(0, 0, width, height, cornerRadius, cornerRadius);
+
+ Color bgColor = button.getBackground();
+ if (button.getModel().isRollover()) {
+ if (bgColor.getAlpha() == 0) {
+ bgColor = new Color(255, 255, 255, 50);
+ } else {
+ bgColor = bgColor.darker();
+ }
+ }
+
+ if (bgColor.getAlpha() > 0) {
+ g2.setColor(bgColor);
+ g2.fillRoundRect(0, 0, button.getWidth(), button.getHeight(), cornerRadius, cornerRadius);
+ }
+
+ if (borderColor != null) {
+ Color actualBorderColor = borderColor;
+ if (button.getModel().isRollover()) {
+ actualBorderColor = borderColor.brighter();
+ }
+ g2.setColor(actualBorderColor);
+ g2.setStroke(new BasicStroke(2));
+ g2.drawRoundRect(0, 0, c.getWidth() - 1, c.getHeight() - 1, cornerRadius, cornerRadius);
+ }
+
g2.setColor(button.getForeground());
g2.setFont(button.getFont());
FontMetrics fm = g2.getFontMetrics();
int stringWidth = fm.stringWidth(button.getText());
int stringHeight = fm.getAscent();
- g2.drawString(button.getText(), (width - stringWidth) / 2, (height + stringHeight) / 2 - 2);
+ g2.drawString(button.getText(), (stringWidth > 0 ? (c.getWidth() - stringWidth) / 2 : 0), (c.getHeight() + fm.getAscent()) / 2 - 2);
+
g2.dispose();
}
-}
\ No newline at end of file
+}
diff --git a/src/main/java/BsK/client/ui/component/common/TemplateDialog/TemplateDialog.java b/src/main/java/BsK/client/ui/component/common/TemplateDialog/TemplateDialog.java
index f2f28b9..2384e1a 100644
--- a/src/main/java/BsK/client/ui/component/common/TemplateDialog/TemplateDialog.java
+++ b/src/main/java/BsK/client/ui/component/common/TemplateDialog/TemplateDialog.java
@@ -214,7 +214,7 @@ public class TemplateDialog extends JDialog {
// Buttons
addNewButton = new JButton("Thêm mới");
- cancelButton = new JButton("Huỷ");
+ cancelButton = new JButton("Làm mới");
saveButton = new JButton("Lưu");
deleteButton = new JButton("Xoá");
}
@@ -335,6 +335,9 @@ public class TemplateDialog extends JDialog {
leftPanel.add(infoPanel, BorderLayout.CENTER);
+ saveButton.setEnabled(false);
+ deleteButton.setEnabled(false);
+
// Template table at bottom
JPanel tablePanel = new JPanel(new BorderLayout());
tablePanel.setBorder(BorderFactory.createTitledBorder(
@@ -726,9 +729,7 @@ public class TemplateDialog extends JDialog {
});
cancelButton.addActionListener(e -> {
- // TODO: Implement cancel functionality
- log.info("Cancel button clicked");
- dispose();
+ clearFields();
});
saveButton.addActionListener(e -> {
@@ -802,6 +803,11 @@ public class TemplateDialog extends JDialog {
conclusionField.setText(template.getConclusion());
suggestionField.setText(template.getSuggestion());
+ // Update button states
+ addNewButton.setEnabled(false);
+ saveButton.setEnabled(true);
+ deleteButton.setEnabled(true);
+
try {
contentRTFField.setText(""); // Clear previous content
RTFEditorKit rtfEditorKit = (RTFEditorKit) contentRTFField.getEditorKit();
@@ -915,5 +921,13 @@ public class TemplateDialog extends JDialog {
if (undoManager != null) {
undoManager.discardAllEdits();
}
+
+ // Reset button states
+ addNewButton.setEnabled(true);
+ saveButton.setEnabled(false);
+ deleteButton.setEnabled(false);
+
+ // Clear table selection
+ templateTable.clearSelection();
}
}
\ No newline at end of file
diff --git a/src/main/java/BsK/server/network/handler/ServerHandler.java b/src/main/java/BsK/server/network/handler/ServerHandler.java
index 31ebcfc..bb83349 100644
--- a/src/main/java/BsK/server/network/handler/ServerHandler.java
+++ b/src/main/java/BsK/server/network/handler/ServerHandler.java
@@ -1531,7 +1531,7 @@ public class ServerHandler extends SimpleChannelInboundHandler