From 64c43b12fd20930fe72c53fa91309f74ac236d6a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=AA=20Th=C3=A0nh=20=C4=90=E1=BA=A1t?= <91755733+lds217@users.noreply.github.com> Date: Thu, 31 Jul 2025 03:08:12 +0700 Subject: [PATCH] [update] Enhance UI components across multiple pages. Update button styles in DashboardPage and LandingPage for improved aesthetics. Add UserManagementPanel to DataDialog and implement button state management in MedicineManagementPanel and ServiceManagementPanel for better user interaction. Refactor RoundedButtonUI for enhanced button behavior and visual feedback. Adjust RegisterPage to streamline user registration process. --- .../DashboardPage/DashboardPage.java | 2 +- .../ui/component/DataDialog/DataDialog.java | 11 +- .../DataDialog/MedicineManagementPanel.java | 25 +- .../DataDialog/ServiceManagementPanel.java | 24 +- .../DataDialog/UserManagementPanel.java | 359 ++++++++++++++++++ .../ui/component/LandingPage/LandingPage.java | 66 +--- .../ui/component/LoginPage/LoginPage.java | 73 ++-- .../component/RegisterPage/RegisterPage.java | 81 +--- .../ui/component/common/RoundedButtonUI.java | 66 +++- .../common/TemplateDialog/TemplateDialog.java | 22 +- .../server/network/handler/ServerHandler.java | 2 +- src/main/resources/database/BSK.db | Bin 1339392 -> 1339392 bytes 12 files changed, 548 insertions(+), 183 deletions(-) create mode 100644 src/main/java/BsK/client/ui/component/DataDialog/UserManagementPanel.java 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 SimpleChannelInboundHandlerNlZciC*AgNM3mTlvKNkq1MQTgYlF{%= zLmwc52nRnwV>AY}INM-jZ9T*91N=Ipd}oyJ#h`vWo7L;e%K83F(X@cy)vayN2CtUr z7@8Lp@MHyJAUGS0p8wim?p;s-n21G%NZQGC!p zQ%#k0`Ch?e(Byg*9Z=;{6-&Tmq=rQRc~-+~cTQ1qt}%O%eh0%c?%?9`%>tXz>7xi? z-e;Dg-3=W8qTRVI03G_f-^C-wR);4JUT`^YPKV^z6?&w99N;qD#yt-GgGu~n=rpkR F`wy9mW<&r0 delta 348 zcmWO1JxfAS7y#h&p4;&w@A0aK6w?YTqQ$OAA`&e+I-~>9{D7x7$@V7MegJBNV2ahqM*aMupy|M_j`a*EqbHsB zoQeYo*i)QR;H*8G-2ZgF%n>30ln4BrM6K7K$5Jd`_K@3@t71@v-%_0X< z5l2p>As2EZ&v>c}U&NCmT2q^I-Z~Tfg=f`wH8*lclB#lIQh8VsEoy@ND2ayBG>P0T zizY30rDDP;#a=a#i9)TxtC