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