Affiliated To Aryabhatta Knowledge University
Affiliated To Aryabhatta Knowledge University
(IMPACT), Patna
Project Report on
“Hospital Management System”
In Partial fulfilment for the award of the degree of
I would like to express my sincere gratitude to all those who have helped and supported
System”.
First and foremost, I extend my heartfelt thanks to Mr. Devi Dayal Sinha, my project
suggestions throughout the development of this project. His mentorship has been a
I am also grateful to our respected Director, Mr. Manish Kumar, and Principal, Dr.
Niharika, for providing us with the opportunity, facilities, and academic environment to
Last but not least, I am thankful to my family for their moral support and
and enhance my skills in Java and database development, which will be invaluable for
my future career.
Session: 2022–2025
CERTIFICATE
This is to certify that the project report entitled “Hospital Management System”
Session 2022–2025, has been carried out under my supervision in partial fulfilment of
This is a genuine and original work done by the student and has not been submitted to
any other university or institution for the award of any degree or diploma.
The project work has been found satisfactory and is hereby approved.
………………………………………….. …………………………………………………
Signature of Guide Signature of Student
DECLARATION
declare that the project work entitled: “Hospital Management System” submitted in
partial fulfilment of the requirements for the degree of BCA is my original work and has
not been submitted previously by me or any other student to any other university or
I further declare that all the information and data presented in this report have been
obtained and presented as per academic ethics and that any source used has been duly
acknowledged.
…………………………………………………………
Signature of the Student
INDEX
The proposed Hospital Management System (HMS) is designed to simplify the day-to-
day operations of a hospital by providing a well-structured, role-based software
solution. It serves as an integrated platform that connects various departments such as
reception, doctor consultation, laboratory, and pharmacy. This system reduces the
paperwork burden and facilitates easy retrieval and storage of patient data, medical
history, and transaction records. It enables receptionists to manage appointments,
update patient information, and track billing seamlessly. Doctors can access scheduled
appointments, view patient details, and eventually add diagnoses or prescriptions.
Similarly, lab technicians will be able to upload and manage test results, ensuring swift
delivery of information to patients.
This system is built using Java (for GUI) and MySQL (for data storage), forming a reliable
and scalable architecture suitable for small to mid-sized hospitals or clinics. The
software provides secure login access to different users based on their roles, and each
module is designed to perform specific functions without overlapping responsibilities.
The overall goal is to create a simple, user-friendly, and efficient hospital management
environment that reduces operational delays and improves service delivery to patients.
The development of this project is not just about building software it is about
transforming the way hospitals work internally, ensuring better healthcare outcomes
through improved administration. In the long run, such systems pave the way for smart
hospitals that can adapt to modern challenges and provide better care through
technology-driven solutions.
1
OBJECTIVE OF THE PROJECT
The primary objective of this project, Hospital Management System, is to design and
implement a fully functional software solution that effectively manages all the critical
operations of a hospital in a structured, reliable, and efficient manner. This project aims
to reduce the burden of manual administrative work, ensure data integrity, and provide
a user-friendly interface for hospital staff across all departments. By introducing
automation and digital workflows, the system helps bridge the gap between technology
and healthcare services, ensuring that both patients and hospital staff benefit from
accurate, timely, and accessible information.
A major focus of the project is data accuracy and consistency. In manual systems,
duplication and errors in patient records, medication details, or billing are common.
Through digitization, the system ensures that data entered once is reused across
relevant modules, minimizing mistakes and delays. It also supports historical data
tracking, which allows doctors and staff to refer to previous treatments, test results, and
prescriptions, thereby improving diagnosis and decision-making.
The system also supports inventory automation, where medicines and consumables
are tracked in real-time. Whenever a doctor prescribes a medicine or a test is conducted,
the corresponding items are automatically deducted from the inventory. Alerts for low
2
stock levels help hospital administrators reorder supplies on time, avoiding out-of-stock
situations.
Security and access control are also essential objectives. The system enforces login-
based authentication, and users are restricted to the modules and actions relevant to
their role. For example, doctors cannot alter billing data, and receptionists cannot edit
medical diagnoses. This not only ensures data safety but also maintains accountability.
Improving patient care quality through accurate medical history access and
faster lab reporting.
Providing scalability, so the hospital can add more users or modules in the
future without reworking the entire system.
Ultimately, the goal is to modernize the hospital’s functioning by offering a powerful yet
easy-to-use system that ensures operational excellence, enhances patient satisfaction,
and sets the foundation for further digital transformation in the healthcare sector.
3
PROJECT DEFINITION
The Hospital Management System (HMS) is a comprehensive, modular software
application designed to automate the core operations and workflow of a hospital or
medical facility. It provides a unified platform that integrates different departments such
as patient registration, appointments, doctor consultations, billing, inventory, laboratory
management, and report handling under one centralized system.
Real-Time Data Management: The system allows for instant updates. For
example, once a patient is registered, the receptionist can immediately schedule
appointments. Once a doctor prescribes medicines or lab tests, the inventory is
updated and a lab report is initiated. This eliminates unnecessary delays and
miscommunication.
Automated Inventory: The system tracks all medical supplies, drugs, and
consumables. It automatically reduces inventory quantities when a prescription
4
is issued or a test is conducted. This ensures accurate stock levels, helps in
procurement planning, and avoids shortage crises.
Billing & Payment Processing: The billing module calculates total charges,
maintains the status of each bill (unpaid or paid), and records the payment mode.
It also links with appointments to ensure that bills are generated only after
consultations or lab services are completed.
Security and Role-Based Access Control: Each user must log in using secure
credentials. The system restricts access according to roles. For instance, a
receptionist can’t access or edit doctor’s diagnoses, and a lab technician cannot
view financial reports.
User Interface and Usability: The software has been designed using Java Swing
with a clean, modern UI. All forms and tables follow a consistent color palette
and intuitive layouts to make the system easy to learn and use, even by non-
technical staff.
5
PROJECT CATEGORY
The Hospital Management System falls under the category of Application Software in
the domain of Healthcare Information Systems (HIS). It is specifically designed as a
Java-based Desktop Application with a backend powered by MySQL for data storage
and management.
1. Application Software
The system is a real-time, interactive application intended for use by hospital
staff, doctors, and administrators. It performs specific tasks such as patient
registration, appointment scheduling, billing, inventory control, and lab report
management. As application software, it runs on end-user machines and is
developed with a user-friendly interface to simplify hospital workflow.
5. Database-Driven System
It is a Relational Database Management System (RDBMS) powered
6
application, using MySQL as the backend. This allows efficient storage, retrieval,
and manipulation of structured data, such as patient records, appointments,
billing transactions, inventory items, and test reports.
7
TOOLS & PLATFORM
The Hospital Management System (HMS) project uses a combination of tools and
technologies that are easy to work with, reliable, and suitable for desktop-based
applications. Below is a categorized list of tools and platforms used:
Toolkit: javax.swing
Language: Java
Database
Usage: Storing patient data, appointments, lab reports, inventory, users, login
info
8
Version Control
Tool: Git
Hosting: GitHub
Tool: JUnit
Documentation
Operating Environment
This setup is suitable for offline desktop use in hospitals or clinics and is beginner-
friendly for students working on Java + MySQL projects.
9
SOFTWARE & HARDWARE REQUIREMENTS
To run and develop the Hospital Management System (HMS) smoothly, the following
hardware and software setup is required:
Hardware Requirements:
Around 200 MB free disk space for project files and database
Software Requirements:
IDE (Editor): Apache NetBeans 18 for writing and designing the application
PDF Reader: Adobe Acrobat Reader (for viewing reports, if PDF generation is
added later)
This configuration is easy to arrange in most college labs or clinics and supports
both development and real-time use.
10
NUMBER OF MODULES
The Hospital Management System is designed with multiple modules to handle different
tasks in a hospital. Each module has a specific purpose and works together with others
to manage hospital operations effectively. Below is the logic and purpose of each
module:
1. Login Module
Allows only registered users (Admin, Receptionist, Doctor, Lab Assistant, etc.) to
log in.
2. Admin Dashboard
Controls the entire system — add/edit/delete users, doctors, lab staff, and
receptionists.
Used by receptionists to add new patients with their personal and medical
details.
Stores patient info like name, age, gender, contact, address, and admission
reason.
4. Appointment Module
11
Allows reception to schedule appointments with doctors.
Stores appointment details like patient ID, doctor ID, date, and time.
12
Generates bill based on patient treatments, tests, and medications.
Ends the user session securely and returns to the login screen.
Each module is built using Java Swing for frontend, and all data operations are handled
using MySQL queries via JDBC.
13
DATA STRUCTURE
The Hospital Management System uses structured relational database tables in
MySQL to store and manage all institutional data securely and efficiently. Each table is
linked using primary and foreign keys to maintain data integrity. Temporary processing
within the Java application uses in-memory structures like Array, List, HashMap, and
StringBuilder.
MAIN DATABASE
Schema Overview:
PK = Primary Key
FK = Foreign Key
NN = NOT NULL
UQ = UNIQUE
DEF = Default
14
1. RECEPTIONIST TABLE:
2. DOCTOR TABLE:
15
3. PATIENT TABLE:
4. APPOINTMENT TABLE;
16
5. PRESCRIPTION TABLE:
17
8. INVENTORY TABLE:
9. BILL TABLE :
Design Notes
18
2. Security
3. Scalability
4. Extensibility
JAVA DATABASE
In the Hospital Management System, Java is used as the primary programming language
to build the desktop application. To manage and process the data efficiently within the
application (in memory), various Java Collection Framework (JCF) and basic data
structure concepts are used. These data structures help manage patient information,
appointments, prescriptions, and inventory before syncing with the MySQL database.
The key Java data structures used in this project are described below:
1. ArrayList
Used to store lists of data like patients, doctors, lab reports, and appointments
temporarily.
o ArrayList<Patient> patientList
o ArrayList<Appointment> appointments
2. HashMap
Provides constant time complexity for search, insert, and update operations.
Example use:
3. HashSet
Example use:
o HashSet<String> departmentSet
o HashSet<String> bookedSlots
Though not required in all modules, it’s useful for future extensions like patient
waitlists or token systems.
Example:
20
5. Custom Classes (POJOs)
To represent each module’s entity (like patients, doctors, lab reports), Plain Old Java
Objects (POJOs) were created. These act like local data structures to:
Patient.java
Doctor.java
Appointment.java
Prescription.java
LabReport.java
InventoryItem.java
Constructors
6. 2D Arrays (Optional/Legacy)
Sometimes used to pass data directly into table models (e.g., Object[][]
tableData).
Useful for quick visualization in GUIs but replaced by more modern TableModel
techniques.
21
7. Model-View-Controller (MVC) Pattern
While not a data structure itself, the MVC pattern organizes Java code into:
Controller: Java logic that processes actions and connects models to views
This architecture indirectly improves data structure clarity and usage across the
application.
22
INPUT OF THE PROJECT
Every software system relies on accurate and properly structured inputs to function
correctly. In the Hospital Management System, inputs are taken from users such as
receptionists, doctors, lab assistants, and patients, and are used to process, store,
and retrieve healthcare data effectively.
The input process has been carefully designed to ensure validity, reliability, and
security. All input forms are user-friendly and equipped with validations to reduce data
entry errors.
1. Receptionist Input
Appointment Booking
o Doctor Name or ID
2. Doctor Input
Prescription Entry
o Medicines prescribed
o Medical Notes
23
o Date of prescription
Patient Assessment
o Upload Date
Inventory Management
o Quantity in Stock
5. Billing Input
Bill Generation
o Total Amount
24
6. Login and Access Input
To maintain accuracy and prevent invalid entries, the following checks are enforced:
25
OUTPUT OF THE PROJECT
The primary goal of the Hospital Management System is to deliver accurate, real-time,
and organized output based on the inputs given by various users. The system provides
a wide range of outputs that assist in clinical decisions, patient management,
administrative workflow, and inventory tracking.
Appointment History
o View of all prescriptions and uploaded lab reports associated with the
patient.
Prescription Summary
26
3. Receptionist Module Output
o Displays appointment number, patient name, doctor name, date and time.
Success/Failure Messages
o Patient-wise listing of lab results with date and doctor (if referred).
5. Inventory Output
6. Billing Output
27
o Shows final payable after any tax or discount (if applicable).
Payment Status
Dashboard Redirection
Login Feedback
28
DATA FLOW DIAGRAM
LEVEL 0 DFD: DOCTOR
RECEPTIONIST
HOSPITAL
PATIENT MANAGEMNT
SYSTEM
LEVEL 1 DFD:
29
LEVEL 2 DFD:
30
SECURITY MECHANISM
Security is a critical aspect of any software system, especially in a hospital environment
where sensitive patient data, confidential medical records, and financial transactions are
involved. The Hospital Management System has been developed with a focus on
ensuring data protection, role-based access, and secure operations across all
modules.
The following mechanisms have been implemented to protect the system from
unauthorized access, data breaches, and misuse.
1. Authentication System
The system ensures that only registered users can access their respective panels:
Username and Password login system for:
o Receptionist
o Doctor
o Patient
Login credentials are validated at the database level using encrypted or hashed
passwords (can be added using SHA or bcrypt in future).
Incorrect login attempts are blocked with error messages to prevent brute-force
attacks.
2. Role-Based Access Control (RBAC)
Each user has access only to the features relevant to their role:
Receptionist:
o Can register patients, book appointments, generate bills.
o Cannot view prescriptions or lab reports.
Doctor:
o Can view their appointments, prescribe medicines, and upload lab
reports.
o Cannot modify billing or register patients.
Patient:
o Can only view their own appointments, prescriptions, lab results, and bill
status.
This structure prevents unauthorized access and ensures data privacy.
3. Input Validation
To prevent injection attacks and malformed data entry:
31
All input fields (registration, appointments, reports) are validated using:
o Character limit checks
o Email and phone format validation
o Date and time format enforcement
This reduces the risk of SQL injection, XSS, and other common attacks.
4. Secure Database Transactions
All database interactions are handled using PreparedStatements via JDBC.
This prevents SQL injection vulnerabilities, ensuring that user input cannot
directly manipulate database queries.
5. Password Protection
Although currently stored as plain text for demo purposes, the system is
designed to support hashed password storage using algorithms like SHA-256
or bcrypt.
This ensures that even if the database is compromised, user passwords remain
unreadable.
6. Session Control and Logout
Each user is assigned a session after login and redirected to their respective
dashboard.
A Logout option is provided for all roles to prevent session misuse.
Inactive users can be manually logged out or timed out in future updates.
7. User Data Integrity
System ensures that one user’s data cannot be modified or viewed by
another:
o Patients can only see their own data.
o Doctors can only access information related to their appointments.
Deleting patient records will automatically cascade and remove related reports
and bills to avoid data inconsistency.
8. Administrative Controls (Future Scope)
The system is designed to support admin dashboards for advanced monitoring.
Role creation, permission updates, and audit logs can be added to enhance
security further.
32
VALIDATION CHECKS
Validation checks are essential to ensure that the input data collected through the
application is accurate, reliable, and secure. In the Hospital Management System,
multiple validation mechanisms have been implemented at the user interface level and
the backend level to prevent invalid, incomplete, or malicious data from entering the
system.
Proper validation improves data quality, enhances user experience, and helps
prevent system crashes or security vulnerabilities.
1. Text Field Validations
Name Fields (Patient, Doctor, Receptionist):
o Must not be empty.
o Accepts only alphabets and spaces.
o Minimum 2 characters and maximum 100 characters.
Email Address:
o Must follow standard format (e.g., user@example.com).
o Must be unique across the database.
o Checked using regular expression (regex) pattern.
Phone Number:
o Must contain only digits.
o Length must be 10 digits.
o Cannot contain alphabets or special characters.
2. Numeric Field Validations
Age (in Patient Registration):
o Must be a valid integer between 0 and 120.
o Cannot be empty or contain letters.
Medicine Quantity & Unit Price (Inventory):
o Quantity must be a non-negative integer.
o Unit price must be a positive decimal (e.g., 10.50).
Billing Amounts:
o Checked to ensure non-zero, positive values only.
o Total must reflect correct calculation from services and medicines.
33
3. Password Field Validations
Password must not be empty.
Minimum length of 6 characters.
Can include alphabets, digits, and special characters.
Input is masked (shown as asterisks) for security.
4. Date and Time Validations
Appointment Date:
o Cannot be in the past.
o Must be a valid calendar date (e.g., no Feb 30).
Appointment Time:
o Must follow the proper format (HH:MM).
o Checked against doctor’s availability.
Prescription and Lab Report Dates:
o Cannot be future dates.
o Must match the format YYYY-MM-DD.
5. Drop-down and Enum Validations
Gender Selection:
o Only options: Male, Female, Other
o Cannot leave unselected.
Status Fields (e.g., Billing Status, Appointment Status):
o Must be chosen from predefined values (e.g., Paid, Unpaid, Confirmed,
Cancelled).
Payment Mode:
o Must be selected from: Cash, Card, or UPI.
o Prevents wrong data entry and improves report accuracy.
6. Duplicate Entry Prevention
Email addresses for patients, doctors, and receptionists must be unique.
Appointments cannot be double-booked (same patient, doctor, and time slot).
Inventory items must have unique medicine names.
7. Mandatory Fields
34
All critical fields are marked as required. The form does not proceed unless:
All required fields are filled
All formats are valid
All dropdowns are selected properly
An error dialog or message is shown if validation fails.
35
SYSTEM IMPLEMENTATION
System implementation is the stage where the developed and tested software is
deployed and made operational in a real-world environment. It involves converting
theoretical designs and code into a working solution that users can interact with. For the
Hospital Management System, the implementation phase focused on seamless
installation, user accessibility, and real-time interaction with the database and GUI
modules.
DATABASE CONNECTION
package hospital.database;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
public class DBConnection {
private static final String URL = "jdbc:mysql://localhost:3306/hospital_db";
private static final String USER = "root";
private static final String PASSWORD = "7070";
private DBConnection() {}
public static Connection getConnection() throws SQLException {
return DriverManager.getConnection(URL, USER, PASSWORD);
}
}
LOGIN PAGE
36
CODE
package hospital.ui.login;
import hospital.database.DBConnection;
import hospital.ui.doctor.DoctorContext;
import hospital.ui.doctor.DoctorDashboard;
import hospital.ui.patient.PatientDashboard;
import hospital.ui.receptionist.ReceptionistDashboard;
import javax.swing.*;
import javax.swing.border.EmptyBorder;
import javax.swing.border.MatteBorder;
import java.awt.*;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.sql.*;
/**
* Modernised login window (pure Swing, no external libs).
*/
public class LoginFrame extends JFrame {
/* ------------- THEME ------------- */
private static final Color BG_COLOR = new Color(0xF4F7FA);
private static final Color CARD_COLOR = Color.WHITE;
private static final Color PRIMARY_COLOR = new Color(0x1976D2); // blue
private static final Color PRIMARY_HOVER = new Color(0x1565C0);
private static final Color ACCENT_COLOR = new Color(0x455A64);
private static final Font FONT_HEADER = new Font("SansSerif", Font.BOLD, 22);
private static final Font FONT_SUB = new Font("SansSerif", Font.PLAIN, 14);
37
});
private final JTextField txtEmail = new JTextField(25);
private final JPasswordField txtPass = new JPasswordField(25);
public LoginFrame() {
setTitle("Hospital Management – Login");
setDefaultCloseOperation(EXIT_ON_CLOSE);
setBackground(BG_COLOR);
setResizable(false);
buildUI();
pack();
setLocationRelativeTo(null);
}
/* ------------- BUILD UI ------------- */
private void buildUI() {
/* outer background */
JPanel root = new JPanel(new GridBagLayout());
root.setBackground(BG_COLOR);
add(root);
/* inner card */
JPanel card = new JPanel();
card.setBorder(new MatteBorder(1,1,4,4,new Color(0xDDE3EB)));
card.setBackground(CARD_COLOR);
card.setLayout(new BoxLayout(card, BoxLayout.Y_AXIS));
card.setPreferredSize(new Dimension(380, 340));
root.add(card);
/* heading */
JLabel lblTitle = new JLabel("Welcome Back");
lblTitle.setFont(FONT_HEADER);
lblTitle.setAlignmentX(Component.CENTER_ALIGNMENT);
lblTitle.setBorder(new EmptyBorder(15,0,5,0));
38
JLabel lblSub = new JLabel("Login to continue");
lblSub.setFont(FONT_SUB);
lblSub.setForeground(ACCENT_COLOR);
lblSub.setAlignmentX(Component.CENTER_ALIGNMENT);
card.add(lblTitle);
card.add(lblSub);
card.add(Box.createRigidArea(new Dimension(0, 15)));
/* form panel */
JPanel form = new JPanel();
form.setOpaque(false);
form.setLayout(new BoxLayout(form, BoxLayout.Y_AXIS));
card.add(form);
form.add(field("Role", comboRole));
form.add(field("Email", txtEmail));
form.add(field("Password", txtPass));
/* buttons */
JButton btnLogin = primaryButton("Login");
JButton btnReg = textButton("New Patient Registration");
JButton btnForgot = textButton("Forgot Password");
btnLogin .addActionListener(e -> doLogin());
btnReg .addActionListener(e ->
new hospital.ui.patient.PatientRegistrationFrame(this).setVisible(true));
btnForgot.addActionListener(e ->
new ForgotPasswordDialog(this).setVisible(true));
card.add(Box.createVerticalStrut(10));
btnLogin.setAlignmentX(Component.CENTER_ALIGNMENT);
card.add(btnLogin);
card.add(Box.createVerticalStrut(10));
JPanel linkRow = new JPanel();
linkRow.setOpaque(false);
39
linkRow.add(btnReg);
linkRow.add(Box.createHorizontalStrut(10));
linkRow.add(btnForgot);
card.add(linkRow);
card.add(Box.createVerticalGlue());
}
/* helper to build a labelled field row */
private JPanel field(String label, JComponent comp) {
JLabel lbl = new JLabel(label);
lbl.setPreferredSize(new Dimension(80, 28));
lbl.setFont(FONT_SUB);
comp.setMaximumSize(comp.getPreferredSize());
comp.setAlignmentX(Component.LEFT_ALIGNMENT);
JPanel row = new JPanel(new FlowLayout(FlowLayout.LEFT, 8, 4));
row.setOpaque(false);
row.add(lbl);
row.add(comp);
return row;
}
/* UI helpers for buttons */
private JButton primaryButton(String text) {
JButton b = new JButton(text);
b.setForeground(Color.WHITE);
b.setBackground(PRIMARY_COLOR);
b.setFocusPainted(false);
b.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
b.setPreferredSize(new Dimension(160, 35));
b.addMouseListener(new Hover(b, PRIMARY_COLOR, PRIMARY_HOVER));
return b;
40
}
private JButton textButton(String text) {
JButton b = new JButton(text);
b.setForeground(PRIMARY_COLOR);
b.setBorderPainted(false);
b.setContentAreaFilled(false);
b.setFocusPainted(false);
b.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
b.setFont(FONT_SUB);
b.addMouseListener(new Hover(b, null, null));
return b;
}
private static class Hover extends MouseAdapter {
private final JButton btn;
private final Color base, hover;
Hover(JButton btn, Color base, Color hover) {
this.btn = btn; this.base = base; this.hover = hover;
}
@Override public void mouseEntered(MouseEvent e) {
if (hover != null) btn.setBackground(hover);
btn.setForeground(hover == null ? PRIMARY_HOVER : Color.WHITE);
}
@Override public void mouseExited(MouseEvent e) {
if (hover != null) btn.setBackground(base);
btn.setForeground(hover == null ? PRIMARY_COLOR : Color.WHITE);
}
}
/* ------------- LOGIN LOGIC (unchanged) ------------- */
private void doLogin() {
String role = comboRole.getSelectedItem().toString();
41
String email = txtEmail.getText().trim();
String pass = String.valueOf(txtPass.getPassword()).trim();
if (email.isEmpty() || pass.isEmpty()) {
JOptionPane.showMessageDialog(this, "Please fill all fields.");
return;
}
String sql = "SELECT * FROM " + role.toLowerCase() + " WHERE email=? AND
password=?";
try (Connection c = DBConnection.getConnection();
PreparedStatement ps = c.prepareStatement(sql)) {
ps.setString(1, email);
ps.setString(2, pass);
ResultSet rs = ps.executeQuery();
if (!rs.next()) {
JOptionPane.showMessageDialog(this, "Invalid credentials.");
return;
}
switch (role) {
case "Receptionist" -> {
new ReceptionistDashboard(rs.getString("name")).setVisible(true);
dispose();
}
case "Doctor" -> {
new DoctorDashboard(
new DoctorContext(rs.getInt("doctor_id"), rs.getString("name")))
.setVisible(true);
dispose();
}
case "Patient" -> {
42
new PatientDashboard(rs.getInt("patient_id"), rs.getString("name"))
.setVisible(true);
dispose();
}
}
} catch (SQLException ex) {
ex.printStackTrace();
JOptionPane.showMessageDialog(this, "DB Error:\n" + ex.getMessage());
}
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> new LoginFrame().setVisible(true));
}
}
FORGOT PASSWORD
43
CODE
package hospital.ui.login;
import hospital.database.DBConnection;
import javax.swing.*;
import javax.swing.border.EmptyBorder;
import javax.swing.border.MatteBorder;
import java.awt.*;
import java.sql.*;
/**
* Modern, full-width "Forgot Password" dialog (pure Swing).
*/
public class ForgotPasswordDialog extends JDialog {
private final JComboBox<String> comboRole = new JComboBox<>(new
String[]{"Doctor", "Patient"});
private final JTextField txtEmail = new JTextField();
private final JPasswordField txtPass = new JPasswordField();
/* ------ theme ------ */
private static final Color CARD_BG = Color.WHITE;
private static final Color BORDER = new Color(0xDDE3EB);
private static final Color PRIMARY = new Color(0x1976D2);
private static final Font FONT_LBL = new Font("SansSerif", Font.PLAIN, 14);
private static final Font FONT_HDR = new Font("SansSerif", Font.BOLD, 20);
public ForgotPasswordDialog(Window owner) {
super(owner, "Reset Password", ModalityType.APPLICATION_MODAL);
buildUI();
pack();
setLocationRelativeTo(owner);
setResizable(false);
}
/* ---------------- UI ---------------- */
44
private void buildUI() {
JPanel card = new JPanel();
card.setBackground(CARD_BG);
card.setBorder(new MatteBorder(1, 1, 4, 4, BORDER));
card.setLayout(new BoxLayout(card, BoxLayout.Y_AXIS));
card.setBorder(new EmptyBorder(25, 35, 25, 35));
add(card);
JLabel heading = new JLabel("Reset Your Password");
heading.setFont(FONT_HDR);
heading.setAlignmentX(Component.CENTER_ALIGNMENT);
card.add(heading);
card.add(Box.createRigidArea(new Dimension(0, 20)));
/* full-width fields */
card.add(field("Role", comboRole));
card.add(field("Registered Email", txtEmail));
card.add(field("New Password", txtPass));
card.add(Box.createRigidArea(new Dimension(0, 15)));
/* button */
JButton btnReset = new JButton("Reset Password");
btnReset.setBackground(PRIMARY);
btnReset.setForeground(Color.WHITE);
btnReset.setFocusPainted(false);
btnReset.setAlignmentX(Component.CENTER_ALIGNMENT);
btnReset.setPreferredSize(new Dimension(200, 38));
btnReset.addActionListener(e -> reset());
/* make Enter key activate button */
getRootPane().setDefaultButton(btnReset);
card.add(btnReset);
card.add(Box.createVerticalGlue());
}
45
/* helper: label + component block */
private JPanel field(String label, JComponent input) {
JLabel lbl = new JLabel(label);
lbl.setFont(FONT_LBL);
input.setMaximumSize(new Dimension(Integer.MAX_VALUE, 32));
input.setPreferredSize(new Dimension(300, 32));
JPanel panel = new JPanel();
panel.setOpaque(false);
panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));
panel.add(lbl);
panel.add(Box.createRigidArea(new Dimension(0, 6)));
panel.add(input);
panel.add(Box.createRigidArea(new Dimension(0, 15)));
return panel;
}
/* ---------------- logic ---------------- */
private void reset() {
String roleTable = comboRole.getSelectedItem().toString().toLowerCase(); // doctor
/ patient
String email = txtEmail.getText().trim();
String newPass = String.valueOf(txtPass.getPassword()).trim();
if (email.isEmpty() || newPass.isEmpty()) {
JOptionPane.showMessageDialog(this, "Please fill out every field.",
"Missing Information", JOptionPane.WARNING_MESSAGE);
return;
}
String sql = "UPDATE " + roleTable + " SET password=? WHERE email=?";
try (Connection con = DBConnection.getConnection();
PreparedStatement ps = con.prepareStatement(sql)) {
ps.setString(1, newPass);
46
ps.setString(2, email);
if (ps.executeUpdate() > 0) {
JOptionPane.showMessageDialog(this,
"Password updated – you can now log in.",
"Success", JOptionPane.INFORMATION_MESSAGE);
dispose();
} else {
JOptionPane.showMessageDialog(this,
"Email not found.", "Not Found",
JOptionPane.WARNING_MESSAGE);
}
} catch (SQLException ex) {
ex.printStackTrace();
JOptionPane.showMessageDialog(this,
"Database error:\n" + ex.getMessage(),
"Error", JOptionPane.ERROR_MESSAGE);
}}}
PATIENT REGISTRATION
47
CODE
package hospital.ui.patient;
import hospital.database.DBConnection;
import javax.swing.*;
import javax.swing.border.EmptyBorder;
import javax.swing.border.MatteBorder;
import java.awt.*;
import java.sql.*;
/**
* Fully modernized full-width patient registration form (Swing UI)
*/
public class PatientRegistrationFrame extends JFrame {
private final JTextField txtName = new JTextField();
private final JTextField txtAge = new JTextField();
private final JComboBox<String> comboGender = new JComboBox<>(new
String[]{"Male", "Female", "Other"});
private final JTextField txtEmail = new JTextField();
private final JTextField txtPhone = new JTextField();
private final JPasswordField txtPass = new JPasswordField();
private static final Color PRIMARY = new Color(0x1976D2);
private static final Color BORDER = new Color(0xDDE3EB);
public PatientRegistrationFrame(Window owner) {
super("New Patient Registration");
setDefaultCloseOperation(DISPOSE_ON_CLOSE);
setResizable(false);
buildUI();
pack();
setLocationRelativeTo(owner);
}
private void buildUI() {
48
JPanel content = new JPanel();
content.setLayout(new BoxLayout(content, BoxLayout.Y_AXIS));
content.setBorder(new EmptyBorder(25, 35, 25, 35));
content.setBackground(Color.WHITE);
JLabel heading = new JLabel("Patient Registration");
heading.setFont(new Font("SansSerif", Font.BOLD, 20));
heading.setAlignmentX(Component.CENTER_ALIGNMENT);
content.add(heading);
content.add(Box.createRigidArea(new Dimension(0, 20)));
content.add(createField("Full Name", txtName));
content.add(createField("Age", txtAge));
content.add(createField("Gender", comboGender));
content.add(createField("Email Address", txtEmail));
content.add(createField("Phone Number", txtPhone));
content.add(createField("Create Password", txtPass));
content.add(Box.createRigidArea(new Dimension(0, 20)));
JButton btnSave = new JButton("Register");
btnSave.setBackground(PRIMARY);
btnSave.setForeground(Color.WHITE);
btnSave.setFocusPainted(false);
btnSave.setAlignmentX(Component.CENTER_ALIGNMENT);
btnSave.setPreferredSize(new Dimension(200, 40));
btnSave.addActionListener(e -> register());
getRootPane().setDefaultButton(btnSave);
content.add(btnSave);
content.add(Box.createVerticalGlue());
add(content);
}
private JPanel createField(String label, JComponent input) {
JLabel lbl = new JLabel(label);
49
lbl.setFont(new Font("SansSerif", Font.PLAIN, 14));
input.setMaximumSize(new Dimension(Integer.MAX_VALUE, 32));
input.setPreferredSize(new Dimension(300, 32));
JPanel panel = new JPanel();
panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));
panel.setOpaque(false);
panel.add(lbl);
panel.add(Box.createRigidArea(new Dimension(0, 6)));
panel.add(input);
panel.add(Box.createRigidArea(new Dimension(0, 15)));
return panel;
}
private void register() {
String email = txtEmail.getText().trim();
50
}
// Insert new patient
try (PreparedStatement ps = con.prepareStatement(insertSql)) {
ps.setString(1, txtName.getText().trim());
ps.setInt(2, Integer.parseInt(txtAge.getText().trim()));
ps.setString(3, comboGender.getSelectedItem().toString());
ps.setString(4, email);
ps.setString(5, txtPhone.getText().trim());
ps.setString(6, String.valueOf(txtPass.getPassword()));
ps.executeUpdate();
}
JOptionPane.showMessageDialog(this,
"Registration successful! You can now log in.",
"Success", JOptionPane.INFORMATION_MESSAGE);
dispose();
} catch (SQLException | NumberFormatException ex) {
ex.printStackTrace();
JOptionPane.showMessageDialog(this,
"Error: " + ex.getMessage(),
"Error", JOptionPane.ERROR_MESSAGE);
}
}
}
51
PATIENT DASHBOARD
CODE
package hospital.ui.patient;
import hospital.ui.login.LoginFrame;
import javax.swing.*;
import java.awt.*;
/**
* Modern Patient Dashboard
* – My profile / appointments / prescriptions / bills
* – Clean top bar with welcome + logout
*/
public class PatientDashboard extends JFrame {
private final int patientId;
private final String patientName;
/* theme */
private static final Color HEADER_BG = Color.WHITE;
private static final Color HEADER_BRD = new Color(0xDDDDDD);
52
private static final Color PRIMARY = new Color(0x1976D2);
public PatientDashboard(int patientId, String name) {
this.patientId = patientId;
this.patientName = name;
setTitle("Patient Dashboard – " + name);
setSize(1000, 650);
setLocationRelativeTo(null);
setDefaultCloseOperation(DISPOSE_ON_CLOSE);
setResizable(false);
buildUI();
}
/* ---------- UI ---------- */
private void buildUI() {
setLayout(new BorderLayout());
/* --- top bar --- */
JPanel topBar = new JPanel(new BorderLayout());
topBar.setBackground(HEADER_BG);
topBar.setBorder(BorderFactory.createMatteBorder(0, 0, 1, 0, HEADER_BRD));
topBar.setPreferredSize(new Dimension(getWidth(), 50));
53
dispose();
new LoginFrame().setVisible(true);
});
topBar.add(lblWelcome, BorderLayout.WEST);
topBar.add(btnLogout, BorderLayout.EAST);
add(topBar, BorderLayout.NORTH);
/* --- tabbed panels --- */
JTabbedPane tabs = new JTabbedPane(JTabbedPane.TOP,
JTabbedPane.SCROLL_TAB_LAYOUT);
tabs.setFont(new Font("SansSerif", Font.PLAIN, 14));
tabs.setBackground(Color.WHITE);
tabs.addTab("Book Appointment", new BookAppointmentPanel(patientId));
tabs.addTab("My Appointments", new ViewAppointmentsPanel(patientId));
tabs.addTab("Prescriptions", new MyPrescriptionsPanel(patientId));
tabs.addTab("My Bills", new MyBillsPanel(patientId));
tabs.addTab("My Profile", new MyProfilePanel(patientId));
54
PATIENT BOOK APPOINTMENT
CODE
package hospital.ui.patient;
import hospital.database.DBConnection;
import javax.swing.*;
import javax.swing.border.EmptyBorder;
import javax.swing.border.MatteBorder;
import java.awt.*;
import java.sql.*;
import java.util.Date;
public class BookAppointmentPanel extends JPanel {
private final int patientId;
private final JComboBox<DoctorItem> cbDoctor = new JComboBox<>();
private final JSpinner spinDate = new JSpinner(
new SpinnerDateModel(new Date(), null, null,
java.util.Calendar.DAY_OF_MONTH));
private final JSpinner spinTime = new JSpinner(
55
new SpinnerDateModel(new Date(), null, null, java.util.Calendar.MINUTE));
private static final Color PRIMARY = new Color(0x1976D2);
private static final Color BORDER = new Color(0xDDE3EB);
public BookAppointmentPanel(int patientId) {
this.patientId = patientId;
buildUI();
loadDoctors();
}
private void buildUI() {
setLayout(new BorderLayout());
JPanel card = new JPanel();
card.setLayout(new BoxLayout(card, BoxLayout.Y_AXIS));
card.setBackground(Color.WHITE);
card.setBorder(new MatteBorder(1,1,4,4,BORDER));
card.setBorder(new EmptyBorder(25,35,25,35));
add(card);
JLabel hdr = new JLabel("Book Appointment");
hdr.setFont(new Font("SansSerif", Font.BOLD, 20));
hdr.setAlignmentX(Component.CENTER_ALIGNMENT);
card.add(hdr);
card.add(Box.createRigidArea(new Dimension(0,20)));
spinDate.setEditor(new JSpinner.DateEditor(spinDate,"yyyy-MM-dd"));
spinTime.setEditor(new JSpinner.DateEditor(spinTime,"HH:mm"));
card.add(field("Doctor", cbDoctor));
card.add(field("Date", spinDate));
card.add(field("Time", spinTime));
card.add(Box.createRigidArea(new Dimension(0,15)));
JButton btnBook = new JButton("Send Request");
btnBook.setBackground(PRIMARY);
btnBook.setForeground(Color.WHITE);
56
btnBook.setPreferredSize(new Dimension(180,38));
btnBook.setFocusPainted(false);
btnBook.setAlignmentX(Component.CENTER_ALIGNMENT);
btnBook.addActionListener(e -> book());
card.add(btnBook);
card.add(Box.createVerticalGlue());
/* SAFE default-button registration */
SwingUtilities.invokeLater(() -> {
JRootPane root = SwingUtilities.getRootPane(BookAppointmentPanel.this);
if (root != null) root.setDefaultButton(btnBook);
});
}
private JPanel field(String label,JComponent input){
JLabel lbl = new JLabel(label);
lbl.setFont(new Font("SansSerif",Font.PLAIN,14));
input.setMaximumSize(new Dimension(Integer.MAX_VALUE,32));
JPanel p = new JPanel();
p.setLayout(new BoxLayout(p,BoxLayout.Y_AXIS));
p.setOpaque(false);
p.add(lbl); p.add(Box.createRigidArea(new Dimension(0,6))); p.add(input);
p.add(Box.createRigidArea(new Dimension(0,15)));
return p;
}
/* ---------- DB helpers ---------- */
private void loadDoctors(){
try(Connection c=DBConnection.getConnection();
Statement st=c.createStatement();
ResultSet rs=st.executeQuery(
"SELECT doctor_id, name, specialization "
+ "FROM doctor ORDER BY name")){
57
while(rs.next()){
cbDoctor.addItem(new DoctorItem(
rs.getInt(1), rs.getString(2), rs.getString(3)));
}
}catch(SQLException ex){ showError(ex); }
}
private void book(){
DoctorItem doc = (DoctorItem) cbDoctor.getSelectedItem();
if(doc==null){
JOptionPane.showMessageDialog(this,"Please choose a doctor.");
return;
}
java.sql.Date dateSql =
new java.sql.Date(((java.util.Date)spinDate.getValue()).getTime());
java.sql.Time timeSql =
new java.sql.Time(((java.util.Date)spinTime.getValue()).getTime());
String sql = """
INSERT INTO appointment
(patient_id, doctor_id, appointment_date,
appointment_time, status, booked_by)
VALUES (?, ?, ?, ?, 'pending', 'patient')
""";
try(Connection c=DBConnection.getConnection();
PreparedStatement ps=c.prepareStatement(sql)){
ps.setInt(1, patientId);
ps.setInt(2, doc.id());
ps.setDate(3, dateSql);
ps.setTime(4, timeSql);
ps.executeUpdate();
JOptionPane.showMessageDialog(this,"Appointment request sent.");
58
}catch(SQLException ex){ showError(ex); }
}
VIEW APPOINTMENT
59
CODE
package hospital.ui.patient;
import hospital.database.DBConnection;
import javax.swing.*;
import javax.swing.event.DocumentEvent;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.JTableHeader;
import java.awt.*;
import java.sql.*;
/**
* Patient-side view of all appointments with:
* • live search by doctor name
* • cancel PENDING
* • REFRESH button to reload from DB
*/
public class ViewAppointmentsPanel extends JPanel {
/* ---------- theme ---------- */
private static final Color PRIMARY = new Color(0x1976D2);
private static final Color BORDER = new Color(0xDDE3EB);
/* ---------- model / table ---------- */
private final DefaultTableModel model = new DefaultTableModel(
new String[]{"ID", "Doctor", "Date", "Time", "Status"}, 0) {
@Override public boolean isCellEditable(int r, int c) { return false; }
};
private final JTable table = new JTable(model);
private final int patientId;
public ViewAppointmentsPanel(int patientId) {
this.patientId = patientId;
setLayout(new BorderLayout());
60
setBackground(new Color(0xF4F7FA));
buildUI();
refresh();
}
/* ---------- UI ---------- */
private void buildUI() {
/* card container */
JPanel card = new JPanel(new BorderLayout(10, 10));
card.setBackground(Color.WHITE);
card.setBorder(BorderFactory.createCompoundBorder(
BorderFactory.createMatteBorder(1, 1, 4, 4, BORDER),
BorderFactory.createEmptyBorder(15, 15, 15, 15)));
add(card, BorderLayout.CENTER);
/* table styling */
table.setRowHeight(24);
table.setGridColor(new Color(0xEEEEEE));
JTableHeader th = table.getTableHeader();
th.setReorderingAllowed(false);
th.setFont(new Font("SansSerif", Font.BOLD, 13));
61
/* toolbar */
JPanel bar = new JPanel(new FlowLayout(FlowLayout.LEFT, 8, 0));
bar.setOpaque(false);
JButton btnCancel = new JButton("Cancel Pending");
style(btnCancel);
btnCancel.addActionListener(e -> cancelSelected());
/* search box */
JTextField search = new JTextField();
search.setPreferredSize(new Dimension(220, 28));
search.setMaximumSize(new Dimension(220, 28));
search.setToolTipText("Search doctor name");
search.setFont(new Font("SansSerif", Font.PLAIN, 13));
search.getDocument().addDocumentListener(new
javax.swing.event.DocumentListener() {
@Override public void insertUpdate(DocumentEvent e) { filter(search.getText());
}
@Override public void removeUpdate(DocumentEvent e) {
filter(search.getText()); }
@Override public void changedUpdate(DocumentEvent e) {
filter(search.getText()); }
});
/* REFRESH button */
JButton btnRefresh = new JButton("Refresh");
style(btnRefresh);
btnRefresh.setToolTipText("Reload appointments list");
btnRefresh.addActionListener(e -> filter(search.getText())); // reload with current
filter
/* build toolbar */
bar.add(btnCancel);
bar.add(btnRefresh);
bar.add(Box.createHorizontalStrut(15));
bar.add(new JLabel("Search: "));
62
bar.add(search);
63
ORDER BY a.appointment_date DESC, a.appointment_time DESC
""", "%" + txt + "%");
}
private void loadQuery(String sql, String like) {
model.setRowCount(0);
try (Connection c = DBConnection.getConnection();
PreparedStatement ps = c.prepareStatement(sql)) {
ps.setInt(1, patientId);
if (like != null) ps.setString(2, like);
ResultSet rs = ps.executeQuery();
while (rs.next()) {
model.addRow(new Object[]{
rs.getInt(1),
rs.getString(2),
rs.getDate(3),
rs.getTime(4),
rs.getString(5)
});
}
} catch (SQLException ex) { showError(ex); }
}
/* ---------- cancel ---------- */
private void cancelSelected() {
int row = table.getSelectedRow();
if (row == -1) return;
int id = (int) model.getValueAt(row, 0);
String status = (String) model.getValueAt(row, 4);
if (!"pending".equalsIgnoreCase(status)) {
JOptionPane.showMessageDialog(this,
"Only PENDING appointments can be cancelled.");
64
return;
}
if (JOptionPane.showConfirmDialog(
this, "Cancel appointment " + id + "?", "Confirm",
JOptionPane.YES_NO_OPTION) != JOptionPane.YES_OPTION) return;
try (Connection c = DBConnection.getConnection();
PreparedStatement ps = c.prepareStatement(
"UPDATE appointment SET status='cancelled' "
+ "WHERE appointment_id=? AND patient_id=?")) {
ps.setInt(1, id);
ps.setInt(2, patientId);
ps.executeUpdate();
refresh();
} catch (SQLException ex) { showError(ex); }
}
/* ---------- util ---------- */
private void showError(Exception ex) {
ex.printStackTrace();
JOptionPane.showMessageDialog(this,
"DB Error: " + ex.getMessage(),
"Database Error", JOptionPane.ERROR_MESSAGE);
}
}
65
PATIENT PRESCRIPTIONS PAGE
CODE
package hospital.ui.patient;
import hospital.database.DBConnection;
import javax.swing.*;
import javax.swing.event.DocumentEvent;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.JTableHeader;
import java.awt.*;
import java.sql.*;
public class MyPrescriptionsPanel extends JPanel {
/* ---------- theme ---------- */
private static final Color PRIMARY = new Color(0x1976D2);
private static final Color BORDER = new Color(0xDDE3EB);
private static final Color BACK = new Color(0xF4F7FA);
/* ---------- model ---------- */
66
private final DefaultTableModel model = new DefaultTableModel(
new String[]{"App ID", "Doctor", "Date", "Medicines", "Notes"}, 0) {
@Override public boolean isCellEditable(int r,int c){ return false; }
};
private final JTable table = new JTable(model);
private final int patientId;
public MyPrescriptionsPanel(int patientId){
this.patientId = patientId;
setLayout(new BorderLayout());
setBackground(BACK);
buildUI();
load("");
}
/* ---------- build UI ---------- */
private void buildUI(){
/* card */
JPanel card = new JPanel(new BorderLayout(10,10));
card.setBackground(Color.WHITE);
card.setBorder(BorderFactory.createCompoundBorder(
BorderFactory.createMatteBorder(1,1,4,4,BORDER),
BorderFactory.createEmptyBorder(15,15,15,15)));
add(card,BorderLayout.CENTER);
/* table styling */
table.setRowHeight(24);
table.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
table.getColumnModel().getColumn(0).setPreferredWidth(70); // App ID
table.getColumnModel().getColumn(1).setPreferredWidth(120); // Doctor
table.getColumnModel().getColumn(2).setPreferredWidth(100); // Date
table.getColumnModel().getColumn(3).setPreferredWidth(220); // Medicines
table.getColumnModel().getColumn(4).setPreferredWidth(220); // Notes
67
table.setGridColor(new Color(0xEEEEEE));
JTableHeader th = table.getTableHeader();
th.setReorderingAllowed(false);
th.setFont(new Font("SansSerif", Font.BOLD, 13));
table.setDefaultRenderer(Object.class,new DefaultTableCellRenderer(){
@Override public Component getTableCellRendererComponent(
JTable t,Object v,boolean sel,boolean focus,int row,int col){
Component c = super.getTableCellRendererComponent(t,v,sel,focus,row,col);
c.setBackground(sel? t.getSelectionBackground()
:(row%2==0? Color.WHITE : new Color(0xF7F9FC)));
return c;
}
});
card.add(new JScrollPane(table),BorderLayout.CENTER);
/* search and refresh bar */
JTextField search = new JTextField();
search.setPreferredSize(new Dimension(250,28));
search.setMaximumSize(new Dimension(250,28));
search.setFont(new Font("SansSerif",Font.PLAIN,13));
search.setToolTipText("Search doctor name or medicine");
search.getDocument().addDocumentListener(new
javax.swing.event.DocumentListener() {
@Override public void insertUpdate(DocumentEvent e){ load(search.getText()); }
@Override public void removeUpdate(DocumentEvent e){ load(search.getText());
}
@Override public void changedUpdate(DocumentEvent e){
load(search.getText()); }
});
JButton btnRefresh = new JButton("Refresh");
style(btnRefresh);
68
btnRefresh.setToolTipText("Reload prescriptions");
btnRefresh.addActionListener(e -> load(search.getText()));
JPanel top = new JPanel(new FlowLayout(FlowLayout.LEFT,8,0));
top.setOpaque(false);
top.add(btnRefresh);
top.add(Box.createHorizontalStrut(12));
top.add(new JLabel("Search: "));
69
try (Connection c = DBConnection.getConnection();
PreparedStatement ps = c.prepareStatement(sql)) {
ps.setInt(1, patientId);
if(!filter.isBlank()){
String like = "%"+filter+"%";
ps.setString(2, like);
ps.setString(3, like);
}
ResultSet rs = ps.executeQuery();
while(rs.next()){
model.addRow(new Object[]{
rs.getInt(1), rs.getString(2),
rs.getDate(3), rs.getString(4),
rs.getString(5)});
}
} catch (SQLException ex){
ex.printStackTrace();
JOptionPane.showMessageDialog(this,
"Error loading prescriptions:\n"+ex.getMessage(),
"Database Error", JOptionPane.ERROR_MESSAGE);
}
}
}
70
PATIENT VIEW BILL
CODE
package hospital.ui.patient;
import hospital.database.DBConnection;
import javax.swing.*;
import javax.swing.event.DocumentEvent;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.JTableHeader;
import java.awt.*;
import java.sql.*;
public class MyBillsPanel extends JPanel {
/* ---------- theme ---------- */
private static final Color PRIMARY = new Color(0x1976D2);
private static final Color BORDER = new Color(0xDDE3EB);
private static final Color BACK = new Color(0xF4F7FA);
/* ---------- table model ---------- */
71
private final DefaultTableModel model = new DefaultTableModel(
new String[]{"Bill ID", "App ID", "Date", "Amount ₹",
"Status", "Payment Mode"}, 0) {
@Override public boolean isCellEditable(int r, int c) { return false; }
};
private final JTable table = new JTable(model);
private final int patientId;
public MyBillsPanel(int patientId) {
this.patientId = patientId;
setLayout(new BorderLayout());
setBackground(BACK);
buildUI();
load(""); // first load
}
/* ---------- UI build ---------- */
private void buildUI() {
/* card */
JPanel card = new JPanel(new BorderLayout(10, 10));
card.setBackground(Color.WHITE);
card.setBorder(BorderFactory.createCompoundBorder(
BorderFactory.createMatteBorder(1, 1, 4, 4, BORDER),
BorderFactory.createEmptyBorder(15, 15, 15, 15)));
add(card, BorderLayout.CENTER);
/* search + refresh bar */
JTextField search = new JTextField();
search.setPreferredSize(new Dimension(220, 28));
search.setMaximumSize(new Dimension(220, 28));
search.setToolTipText("Search status or payment mode");
search.setFont(new Font("SansSerif", Font.PLAIN, 13));
72
search.getDocument().addDocumentListener(new
javax.swing.event.DocumentListener() {
@Override public void insertUpdate(DocumentEvent e) { load(search.getText()); }
@Override public void removeUpdate(DocumentEvent e) {
load(search.getText()); }
@Override public void changedUpdate(DocumentEvent e) {
load(search.getText()); }
});
JButton btnRefresh = new JButton("Refresh");
style(btnRefresh);
btnRefresh.setToolTipText("Reload bills list");
btnRefresh.addActionListener(e -> load(search.getText()))
JPanel top = new JPanel(new FlowLayout(FlowLayout.LEFT, 8, 0));
top.setOpaque(false);
top.add(btnRefresh);
top.add(Box.createHorizontalStrut(12));
top.add(new JLabel("Search: "));
top.add(search);
73
c.setBackground(sel ? t.getSelectionBackground()
: (row % 2 == 0 ? Color.WHITE : new Color(0xF7F9FC)));
return c;
}
});
/* column widths */
table.getColumnModel().getColumn(0).setPreferredWidth(70); // Bill ID
table.getColumnModel().getColumn(1).setPreferredWidth(70); // App ID
table.getColumnModel().getColumn(2).setPreferredWidth(100); // Date
74
? ""
: "AND (b.status LIKE ? OR b.payment_mode LIKE ?)");
try (Connection c = DBConnection.getConnection();
PreparedStatement ps = c.prepareStatement(sql)) {
ps.setInt(1, patientId);
if (!filter.isBlank()) {
String like = "%" + filter + "%";
ps.setString(2, like);
ps.setString(3, like);
}
ResultSet rs = ps.executeQuery();
while (rs.next()) {
model.addRow(new Object[]{
rs.getInt(1), rs.getInt(2),
rs.getDate(3), rs.getBigDecimal(4),
rs.getString(5), rs.getString(6)});
}
} catch (SQLException ex) {
ex.printStackTrace();
JOptionPane.showMessageDialog(this,
"Error loading bills:\n" + ex.getMessage(),
"Database Error", JOptionPane.ERROR_MESSAGE);
}
}
}
75
PATIENT PROFILE
CODE
package hospital.ui.patient;
import hospital.database.DBConnection;
import javax.swing.*;
import javax.swing.border.EmptyBorder;
import javax.swing.border.MatteBorder;
import java.awt.*;
import java.sql.*;
public class MyProfilePanel extends JPanel {
private final int patientId;
private final JTextField txtName = new JTextField();
private final JTextField txtEmail = new JTextField();
private final JTextField txtPhone = new JTextField();
private final JPasswordField txtPass = new JPasswordField();
private static final Color PRIMARY = new Color(0x1976D2);
private static final Color BORDER = new Color(0xDDE3EB);
76
public MyProfilePanel(int patientId) {
this.patientId = patientId;
buildUI();
load();
}
/* ---------- UI ---------- */
private void buildUI() {
setLayout(new BorderLayout());
77
btnSave.setAlignmentX(Component.CENTER_ALIGNMENT);
btnSave.addActionListener(e -> save());
card.add(btnSave);
card.add(Box.createVerticalGlue());
/* SAFE default-button registration */
SwingUtilities.invokeLater(() -> {
JRootPane root = SwingUtilities.getRootPane(MyProfilePanel.this);
if (root != null) root.setDefaultButton(btnSave);
});
}
private JPanel field(String label, JComponent input) {
JLabel lbl = new JLabel(label);
lbl.setFont(new Font("SansSerif", Font.PLAIN, 14));
input.setMaximumSize(new Dimension(Integer.MAX_VALUE, 32));
JPanel p = new JPanel();
p.setLayout(new BoxLayout(p, BoxLayout.Y_AXIS));
p.setOpaque(false);
p.add(lbl);
p.add(Box.createRigidArea(new Dimension(0, 6)));
p.add(input);
p.add(Box.createRigidArea(new Dimension(0, 15)));
return p;
}
/* ---------- data ---------- */
private void load() {
String sql = "SELECT name, email, phone FROM patient WHERE patient_id=?";
try (Connection c = DBConnection.getConnection();
PreparedStatement ps = c.prepareStatement(sql)) {
ps.setInt(1, patientId);
ResultSet rs = ps.executeQuery();
78
if (rs.next()) {
txtName .setText(rs.getString(1));
txtEmail.setText(rs.getString(2));
txtPhone.setText(rs.getString(3));
}
} catch (SQLException ex) { error(ex); }
}
private void save() {
if (txtName.getText().trim().isEmpty() ||
txtEmail.getText().trim().isEmpty()) {
JOptionPane.showMessageDialog(this,"Name and Email cannot be empty.");
return;
}
boolean changePass = txtPass.getPassword().length>0;
String sql = "UPDATE patient SET name=?, email=?, phone=?"
+ (changePass? ", password=?":"")
+ " WHERE patient_id=?";
try(Connection c=DBConnection.getConnection();
PreparedStatement ps=c.prepareStatement(sql)){
ps.setString(1, txtName.getText().trim());
ps.setString(2, txtEmail.getText().trim());
ps.setString(3, txtPhone.getText().trim());
int idx = 4;
if(changePass){
ps.setString(4, String.valueOf(txtPass.getPassword()).trim());
idx = 5;
}
ps.setInt(idx, patientId);
ps.executeUpdate();
JOptionPane.showMessageDialog(this,"Profile updated.");
79
txtPass.setText("");
}catch(SQLException ex){ error(ex); }
}
private void error(Exception ex){
ex.printStackTrace();
JOptionPane.showMessageDialog(this,"DB Error: "+ex.getMessage());
}
}
DOCTOR DASHBOARD
CODE
package hospital.ui.doctor;
import hospital.ui.login.LoginFrame;
import javax.swing.*;
import java.awt.*;
public class DoctorDashboard extends JFrame {
private final DoctorContext ctx;
/* theme */
80
private static final Color HEADER_BG = Color.WHITE;
private static final Color HEADER_BRD = new Color(0xDDDDDD);
private static final Color PRIMARY = new Color(0x1976D2);
public DoctorDashboard(DoctorContext ctx) {
this.ctx = ctx;
setTitle("Doctor Dashboard – " + ctx.name());
setSize(1000, 650);
setLocationRelativeTo(null);
setDefaultCloseOperation(DISPOSE_ON_CLOSE);
setResizable(false);
buildUI();
}
/* ---------- UI ---------- */
private void buildUI() {
setLayout(new BorderLayout());
/* --- header bar --- */
JPanel header = new JPanel(new BorderLayout());
header.setBackground(HEADER_BG);
header.setBorder(BorderFactory.createMatteBorder(0, 0, 1, 0, HEADER_BRD));
header.setPreferredSize(new Dimension(getWidth(), 50));
JLabel lblWelcome = new JLabel("Welcome, Dr. " + ctx.name());
lblWelcome.setFont(new Font("SansSerif", Font.BOLD, 16));
lblWelcome.setBorder(BorderFactory.createEmptyBorder(0, 20, 0, 0));
JButton btnLogout = new JButton("Logout");
btnLogout.setBackground(new Color(0xD32F2F));
btnLogout.setForeground(Color.WHITE);
btnLogout.setFocusPainted(false);
btnLogout.setPreferredSize(new Dimension(100, 30));
btnLogout.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
btnLogout.addActionListener(e -> {
81
dispose();
new LoginFrame().setVisible(true);
});
header.add(lblWelcome, BorderLayout.WEST);
header.add(btnLogout, BorderLayout.EAST);
add(header, BorderLayout.NORTH);
/* --- tabbed pane --- */
JTabbedPane tabs = new JTabbedPane(JTabbedPane.TOP,
JTabbedPane.SCROLL_TAB_LAYOUT);
tabs.setFont(new Font("SansSerif", Font.PLAIN, 14));
tabs.setBackground(Color.WHITE);
tabs.addTab("My Appointments", new MyAppointmentsPanel(ctx));
tabs.addTab("My Profile", new MyProfilePanel(ctx));
JPanel center = new JPanel(new BorderLayout());
center.setBackground(Color.WHITE);
center.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));
center.add(tabs, BorderLayout.CENTER);
add(center, BorderLayout.CENTER);
}}
DOCTOR APPOINTMENT
82
CODE
package hospital.ui.doctor;
import hospital.database.DBConnection;
import javax.swing.*;
import javax.swing.event.DocumentEvent;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.JTableHeader;
import java.awt.*;
import java.sql.*;
public class MyAppointmentsPanel extends JPanel {
/* ---------- theme ---------- */
private static final Color PRIMARY = new Color(0x1976D2);
private static final Color DANGER = new Color(0xD32F2F);
private static final Color BORDER = new Color(0xDDE3EB);
private static final Color BACK = new Color(0xF4F7FA);
/* ---------- table ---------- */
private final DefaultTableModel model = new DefaultTableModel(
new String[]{"ID","Patient","Date","Time","Status"},0){
@Override public boolean isCellEditable(int r,int c){ return false; }
};
private final JTable table = new JTable(model);
private final DoctorContext ctx;
public MyAppointmentsPanel(DoctorContext ctx){
this.ctx = ctx;
setLayout(new BorderLayout());
setBackground(BACK);
buildUI();
load(""); // initial load
}
83
/* ---------- UI ---------- */
private void buildUI(){
/* card */
JPanel card = new JPanel(new BorderLayout(10,10));
card.setBackground(Color.WHITE);
card.setBorder(BorderFactory.createCompoundBorder(
BorderFactory.createMatteBorder(1,1,4,4,BORDER),
BorderFactory.createEmptyBorder(15,15,15,15)));
add(card,BorderLayout.CENTER);
/* table formatting */
table.setRowHeight(24);
table.setGridColor(new Color(0xEEEEEE));
table.getColumnModel().getColumn(0).setPreferredWidth(60);
JTableHeader th = table.getTableHeader();
th.setFont(new Font("SansSerif",Font.BOLD,13));
th.setReorderingAllowed(false);
/* zebra rows */
table.setDefaultRenderer(Object.class,new DefaultTableCellRenderer(){
@Override public Component getTableCellRendererComponent(
JTable t,Object v,boolean sel,boolean focus,int row,int col){
Component c=super.getTableCellRendererComponent(t,v,sel,focus,row,col);
c.setBackground(sel? t.getSelectionBackground()
:(row%2==0? Color.WHITE : new Color(0xF7F9FC)));
return c;
}
});
card.add(new JScrollPane(table),BorderLayout.CENTER);
/* toolbar */
JPanel bar = new JPanel(new FlowLayout(FlowLayout.LEFT,8,0));
bar.setOpaque(false);
84
JButton btnCancel = new JButton("Cancel");
JButton btnComplete = new JButton("Complete");
JButton btnRefresh = new JButton("Refresh");
style(btnCancel, DANGER, "Cancel selected appointment");
style(btnComplete, PRIMARY, "Mark selected CONFIRMED appointment as
completed");
style(btnRefresh, PRIMARY, "Reload appointments list");
btnCancel .addActionListener(e -> cancel());
btnComplete.addActionListener(e -> complete());
/* search box */
JTextField search = new JTextField();
search.setPreferredSize(new Dimension(220,28));
search.setMaximumSize(new Dimension(220,28));
search.setFont(new Font("SansSerif",Font.PLAIN,13));
search.setToolTipText("Search patient name or status");
/* search events */
search.getDocument().addDocumentListener(new
javax.swing.event.DocumentListener(){
@Override public void insertUpdate(DocumentEvent e){ load(search.getText()); }
@Override public void removeUpdate(DocumentEvent e){ load(search.getText());
}
@Override public void changedUpdate(DocumentEvent e){
load(search.getText()); }
});
/* refresh uses current search text */
btnRefresh.addActionListener(e -> load(search.getText()));
/* assemble bar */
bar.add(btnCancel);
bar.add(btnComplete);
bar.add(btnRefresh);
bar.add(Box.createHorizontalStrut(15));
85
bar.add(new JLabel("Search: "));
bar.add(search);
86
String like = "%"+filter+"%";
ps.setString(2, like);
ps.setString(3, like);
}
ResultSet rs = ps.executeQuery();
while(rs.next()){
model.addRow(new Object[]{
rs.getInt(1), rs.getString(2),
rs.getDate(3), rs.getTime(4),
rs.getString(5)});
}
}catch(SQLException ex){ error(ex);}
}
/* ---------- helpers ---------- */
private int selectedId(){
int r = table.getSelectedRow();
return r==-1 ? -1 : (int) model.getValueAt(r,0);
}
private void cancel(){
int id = selectedId(); if(id==-1) return;
String status = (String) model.getValueAt(table.getSelectedRow(),4);
if("completed".equalsIgnoreCase(status)){
JOptionPane.showMessageDialog(this,
"Completed appointments can’t be cancelled.",
"Invalid", JOptionPane.WARNING_MESSAGE);
return;
}
if(JOptionPane.showConfirmDialog(this,
"Cancel appointment "+id+"?","Confirm",
JOptionPane.YES_NO_OPTION)!=JOptionPane.YES_OPTION) return;
87
try(Connection c = DBConnection.getConnection();
PreparedStatement ps = c.prepareStatement(
"UPDATE appointment SET status='cancelled' WHERE appointment_id=?")){
ps.setInt(1,id);
ps.executeUpdate();
load(""); // full refresh
}catch(SQLException ex){ error(ex);}
}
private void complete(){
int id = selectedId(); if(id==-1) return;
String status = (String) model.getValueAt(table.getSelectedRow(),4);
if(!"confirmed".equalsIgnoreCase(status)){
JOptionPane.showMessageDialog(this,
"Only CONFIRMED appointments can be completed.",
"Invalid", JOptionPane.WARNING_MESSAGE);
return;
}
new PrescriptionDialog(
SwingUtilities.getWindowAncestor(this), ctx, id).setVisible(true);
load(""); // refresh list after prescription dialog closes
}
private void error(Exception ex){
ex.printStackTrace();
JOptionPane.showMessageDialog(this,
"Error: "+ex.getMessage(),
"Database Error", JOptionPane.ERROR_MESSAGE);
}
}
88
DOCTOR VIEW/EDIT OWN PROFILE
CODE
package hospital.ui.doctor;
import hospital.database.DBConnection;
import javax.swing.*;
import javax.swing.border.EmptyBorder;
import javax.swing.border.MatteBorder;
import java.awt.*;
import java.sql.*;
public class MyProfilePanel extends JPanel {
private final DoctorContext ctx;
private final JTextField txtName = new JTextField();
private final JTextField txtSpec = new JTextField();
private final JTextField txtPhone = new JTextField();
private final JPasswordField txtPass = new JPasswordField();
private static final Color PRIMARY = new Color(0x1976D2);
private static final Color BORDER = new Color(0xDDE3EB);
89
public MyProfilePanel(DoctorContext ctx){
this.ctx = ctx;
buildUI();
load();
}
private void buildUI(){
setLayout(new BorderLayout());
JPanel card = new JPanel();
card.setLayout(new BoxLayout(card, BoxLayout.Y_AXIS));
card.setBackground(Color.WHITE);
card.setBorder(new MatteBorder(1,1,4,4,BORDER));
card.setBorder(new EmptyBorder(25,35,25,35));
add(card);
JLabel hdr = new JLabel("My Profile");
hdr.setFont(new Font("SansSerif",Font.BOLD,20));
hdr.setAlignmentX(Component.CENTER_ALIGNMENT);
card.add(hdr);
card.add(Box.createRigidArea(new Dimension(0,20)));
card.add(field("Full Name", txtName));
card.add(field("Specialization", txtSpec));
card.add(field("Phone Number", txtPhone));
card.add(field("New Password", txtPass));
card.add(Box.createRigidArea(new Dimension(0,15)));
JButton btnSave = new JButton("Save Changes");
btnSave.setBackground(PRIMARY);
btnSave.setForeground(Color.WHITE);
btnSave.setPreferredSize(new Dimension(180,38));
btnSave.setFocusPainted(false);
btnSave.setAlignmentX(Component.CENTER_ALIGNMENT);
btnSave.addActionListener(e -> save());
90
card.add(btnSave);
card.add(Box.createVerticalGlue());
91
txtPhone.setText(rs.getString(3));
}
}catch(SQLException ex){ error(ex); }
}
private void save(){
boolean changePass = txtPass.getPassword().length>0;
String sql="UPDATE doctor SET name=?, specialization=?, phone=?"
+ (changePass?", password=?":"")
+ " WHERE doctor_id=?";
try(Connection c=DBConnection.getConnection();
PreparedStatement ps=c.prepareStatement(sql)){
ps.setString(1, txtName.getText().trim());
ps.setString(2, txtSpec.getText().trim());
ps.setString(3, txtPhone.getText().trim());
int idx=4;
if(changePass){
ps.setString(4,String.valueOf(txtPass.getPassword()).trim());
idx=5;
}
ps.setInt(idx, ctx.id());
ps.executeUpdate();
JOptionPane.showMessageDialog(this,"Profile updated.");
txtPass.setText("");
}catch(SQLException ex){ error(ex); }
}
private void error(Exception ex){
ex.printStackTrace();
JOptionPane.showMessageDialog(this,"Error: "+ex.getMessage(),
"Database Error", JOptionPane.ERROR_MESSAGE);
} }
92
DOCTOR COMPLETE APPOINTMENT + GIVE PRESCRIPTION
CODE
package hospital.ui.doctor;
import hospital.database.DBConnection;
import javax.swing.*;
import javax.swing.border.EmptyBorder;
import javax.swing.border.MatteBorder;
import javax.swing.table.DefaultTableModel;
import java.awt.*;
import java.math.BigDecimal;
import java.sql.*;
import java.time.LocalDate;
import java.util.HashMap;
import java.util.Map;
public class PrescriptionDialog extends JDialog {
/* ---------- theme ---------- */
93
private static final Color PRIMARY = new Color(0x1976D2);
private static final Color BORDER = new Color(0xDDE3EB);
/* ---------- ui components ---------- */
private final JTextArea txtNotes = new JTextArea(3, 30);
private final JComboBox<MedItem> cbMed = new JComboBox<>();
private final JTextField txtQty = new JTextField(5);
private final DefaultTableModel tblModel = new DefaultTableModel(
new String[]{"Medicine", "Qty", "Unit ₹", "Line ₹"}, 0) {
@Override public boolean isCellEditable(int r, int c) { return false; }
};
private final JTable tbl = new JTable(tblModel);
/* ---------- context ---------- */
private final DoctorContext ctx;
private final int appointmentId;
private final Map<Integer, Integer> selected = new HashMap<>(); // medId → qty
public PrescriptionDialog(Window owner, DoctorContext ctx, int appointmentId) {
super(owner, "Complete Appointment #" + appointmentId,
ModalityType.APPLICATION_MODAL);
this.ctx = ctx;
this.appointmentId = appointmentId;
loadMedicines();
buildUI();
pack();
setLocationRelativeTo(owner);
setResizable(false);
}
/* ---------- UI ---------- */
private void buildUI() {
setLayout(new BorderLayout());
/* card container */
94
JPanel card = new JPanel(new BorderLayout(10, 10));
card.setBackground(Color.WHITE);
card.setBorder(new MatteBorder(1, 1, 4, 4, BORDER));
card.setBorder(new EmptyBorder(20, 25, 20, 25));
add(card, BorderLayout.CENTER);
/* notes */
JPanel notesP = new JPanel(new BorderLayout(5, 5));
notesP.setOpaque(false);
JLabel lblNotes = new JLabel("Notes:");
txtNotes.setLineWrap(true);
txtNotes.setWrapStyleWord(true);
notesP.add(lblNotes, BorderLayout.NORTH);
notesP.add(new JScrollPane(txtNotes), BorderLayout.CENTER);
card.add(notesP, BorderLayout.NORTH);
/* medicine add bar */
JPanel medBar = new JPanel(new FlowLayout(FlowLayout.LEFT, 8, 0));
medBar.setOpaque(false);
medBar.add(cbMed);
medBar.add(new JLabel("Qty"));
medBar.add(txtQty);
JButton btnAdd = new JButton("Add");
btnAdd.setBackground(PRIMARY);
btnAdd.setForeground(Color.WHITE);
btnAdd.setFocusPainted(false);
btnAdd.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
btnAdd.addActionListener(e -> addMedicine());
medBar.add(btnAdd);
/* table styling */
tbl.setRowHeight(24);
tbl.setGridColor(new Color(0xEEEEEE));
95
tbl.getColumnModel().getColumn(0).setPreferredWidth(160);
JScrollPane tblScroll = new JScrollPane(tbl);
JPanel center = new JPanel(new BorderLayout(5, 5));
center.setOpaque(false);
center.add(medBar, BorderLayout.NORTH);
center.add(tblScroll, BorderLayout.CENTER);
card.add(center, BorderLayout.CENTER);
/* save button */
JButton btnSave = new JButton("Save & Complete");
btnSave.setBackground(PRIMARY);
btnSave.setForeground(Color.WHITE);
btnSave.setPreferredSize(new Dimension(180, 38));
btnSave.setFocusPainted(false);
btnSave.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
btnSave.addActionListener(e -> save());
JPanel south = new JPanel(new FlowLayout(FlowLayout.RIGHT));
south.setOpaque(false);
south.add(btnSave);
card.add(south, BorderLayout.SOUTH);
}
/* ---------- data helpers ---------- */
private void loadMedicines() {
try (Connection c = DBConnection.getConnection();
Statement st = c.createStatement();
ResultSet rs = st.executeQuery(
"SELECT medicine_id, name, price_per_unit, quantity "
+ "FROM inventory WHERE quantity > 0 ORDER BY name")) {
while (rs.next()) {
cbMed.addItem(new MedItem(
rs.getInt(1),
96
rs.getString(2),
rs.getBigDecimal(3),
rs.getInt(4)));
}
} catch (SQLException ex) { error(ex); }
}
private void addMedicine() {
MedItem med = (MedItem) cbMed.getSelectedItem();
if (med == null) return;
int qty;
try { qty = Integer.parseInt(txtQty.getText().trim()); }
catch (NumberFormatException ex) { qty = -1; }
if (qty <= 0) {
JOptionPane.showMessageDialog(this, "Enter a positive quantity.");
return;
}
if (qty > med.stock()) {
JOptionPane.showMessageDialog(this,
"Only " + med.stock() + " left in stock.");
return;
}
selected.merge(med.id(), qty, Integer::sum);
rebuildTable();
txtQty.setText("");
}
private void rebuildTable() {
tblModel.setRowCount(0);
for (var entry : selected.entrySet()) {
MedItem med = lookup(entry.getKey());
97
int q = entry.getValue();
BigDecimal line = med.price().multiply(BigDecimal.valueOf(q));
tblModel.addRow(new Object[]{med.name(), q, med.price(), line});
}
}
private MedItem lookup(int id) {
for (int i = 0; i < cbMed.getItemCount(); i++) {
MedItem m = cbMed.getItemAt(i);
if (m.id() == id) return m;
}
return null; // shouldn’t happen
}
/* ---------- save transaction ---------- */
private void save() {
if (selected.isEmpty()) {
JOptionPane.showMessageDialog(this,
"Add at least one medicine before saving.");
return;
}
98
Statement.RETURN_GENERATED_KEYS);
psP.setInt(1, appointmentId);
psP.setInt(2, ctx.id());
psP.setString(3, txtNotes.getText().trim());
psP.setString(4, medicineCsv());
psP.setDate (5, Date.valueOf(LocalDate.now()));
psP.setInt (6, appointmentId);
psP.executeUpdate();
ResultSet key = psP.getGeneratedKeys();
key.next();
int prescriptionId = key.getInt(1);
/* 2) insert prescription lines & update inventory */
PreparedStatement psLine = c.prepareStatement("""
INSERT INTO prescription_medicine
(prescription_id, medicine_id, quantity, unit_price)
VALUES (?,?,?,?)""");
PreparedStatement psInv = c.prepareStatement(
"UPDATE inventory SET quantity = quantity - ? WHERE medicine_id = ?");
for (var entry : selected.entrySet()) {
MedItem med = lookup(entry.getKey());
int qty = entry.getValue();
psLine.setInt(1, prescriptionId);
psLine.setInt(2, med.id());
psLine.setInt(3, qty);
psLine.setBigDecimal(4, med.price());
psLine.addBatch();
psInv.setInt(1, qty);
psInv.setInt(2, med.id());
psInv.addBatch();
}
99
psLine.executeBatch();
psInv.executeBatch();
/* 3) mark appointment completed */
try (PreparedStatement psA = c.prepareStatement(
"UPDATE appointment SET status='completed' WHERE appointment_id=?")) {
psA.setInt(1, appointmentId);
psA.executeUpdate();
}
/* 4) create bill */
try (PreparedStatement psBill = c.prepareStatement("""
INSERT INTO bill (patient_id, appointment_id, total_amount, status)
SELECT patient_id, appointment_id, ?, 'unpaid'
FROM appointment WHERE appointment_id = ?""")) {
psBill.setBigDecimal(1, total);
psBill.setInt(2, appointmentId);
psBill.executeUpdate();
}
c.commit();
JOptionPane.showMessageDialog(this,
"Prescription saved, stock updated, bill generated.",
"Success", JOptionPane.INFORMATION_MESSAGE);
dispose();
} catch (SQLException ex) { rollback(ex); }
}
/* ---------- helpers ---------- */
private BigDecimal totalCost() {
BigDecimal t = BigDecimal.ZERO;
for (var e : selected.entrySet()) {
MedItem m = lookup(e.getKey());
t = t.add(m.price().multiply(BigDecimal.valueOf(e.getValue())));
100
}
return t;
}
private String medicineCsv() {
StringBuilder sb = new StringBuilder();
for (var e : selected.entrySet()) {
MedItem m = lookup(e.getKey());
sb.append(m.name()).append(" x").append(e.getValue()).append(", ");
}
return sb.substring(0, sb.length() - 2); // drop trailing ", "
}
private record MedItem(int id, String name, BigDecimal price, int stock) {
@Override public String toString() { return name + " (₹" + price + ")"; }
}
/* ---------- error ---------- */
private void rollback(Exception ex) {
ex.printStackTrace();
JOptionPane.showMessageDialog(this,
"Error: " + ex.getMessage(),
"Database Error", JOptionPane.ERROR_MESSAGE);
}
private void error(Exception ex) { rollback(ex); }
}
101
RECEPTIONIST DASHBOARD
CODE
package hospital.ui.receptionist;
import hospital.ui.login.LoginFrame;
import javax.swing.*;
import java.awt.*;
public class ReceptionistDashboard extends JFrame {
public ReceptionistDashboard(String receptionistName) {
setTitle("Receptionist Dashboard – " + receptionistName);
setDefaultCloseOperation(DISPOSE_ON_CLOSE);
setSize(1000, 650);
setLocationRelativeTo(null);
setResizable(false);
buildUI(receptionistName);
}
private void buildUI(String name) {
setLayout(new BorderLayout());
102
/* ---------- Top Bar ---------- */
JPanel topBar = new JPanel(new BorderLayout());
topBar.setBackground(Color.WHITE);
topBar.setBorder(BorderFactory.createMatteBorder(0, 0, 1, 0, new
Color(0xDDDDDD)));
topBar.setPreferredSize(new Dimension(getWidth(), 50));
JLabel lblWelcome = new JLabel("Welcome, " + name);
lblWelcome.setFont(new Font("SansSerif", Font.BOLD, 16));
JButton btnLogout = new JButton("Logout");
btnLogout.setFocusPainted(false);
btnLogout.setBackground(new Color(0xD32F2F));
btnLogout.setForeground(Color.WHITE);
btnLogout.setPreferredSize(new Dimension(100, 30));
btnLogout.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
btnLogout.addActionListener(e -> {
dispose();
new LoginFrame().setVisible(true);
});
topBar.add(lblWelcome, BorderLayout.WEST);
topBar.add(btnLogout, BorderLayout.EAST);
topBar.setBorder(BorderFactory.createEmptyBorder(10, 20, 10, 20));
add(topBar, BorderLayout.NORTH);
/* ---------- Tabs ---------- */
JTabbedPane tabs = new JTabbedPane(JTabbedPane.TOP,
JTabbedPane.SCROLL_TAB_LAYOUT);
tabs.setFont(new Font("SansSerif", Font.PLAIN, 14));
tabs.setBackground(Color.WHITE);
tabs.addTab("Doctors", new ManageDoctorsPanel());
tabs.addTab("Patients", new ManagePatientsPanel());
tabs.addTab("Appointments", new ManageAppointmentsPanel());
tabs.addTab("Inventory", new ManageInventoryPanel());
103
tabs.addTab("Billing", new ManageBillingPanel());
JPanel centerPanel = new JPanel(new BorderLayout());
centerPanel.setBackground(Color.WHITE);
centerPanel.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));
centerPanel.add(tabs, BorderLayout.CENTER);
add(centerPanel, BorderLayout.CENTER);
}
}
CODE
package hospital.ui.receptionist;
import hospital.database.DBConnection;
import javax.swing.*;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.JTableHeader;
import java.awt.*;
104
import java.sql.*;
public class ManageDoctorsPanel extends JPanel {
/* ---------- theme ---------- */
private static final Color PRIMARY = new Color(0x1976D2);
private static final Color BORDER = new Color(0xDDE3EB);
/* ---------- table model ---------- */
private final DefaultTableModel model = new DefaultTableModel(
new String[]{"ID","Name","Specialization","Email","Phone"},0){
@Override public boolean isCellEditable(int r,int c){ return false; }
};
private final JTable table = new JTable(model);
/* search field needs field scope so Refresh can access it */
private final JTextField txtSearch = new JTextField();
public ManageDoctorsPanel() {
setLayout(new BorderLayout());
setBackground(new Color(0xF4F7FA));
buildUI();
load(""); // initial load
}
/* ---------- UI BUILD ---------- */
private void buildUI(){
/* card wrapper */
JPanel card = new JPanel(new BorderLayout(10,10));
card.setBackground(Color.WHITE);
card.setBorder(BorderFactory.createCompoundBorder(
BorderFactory.createMatteBorder(1,1,4,4,BORDER),
BorderFactory.createEmptyBorder(15,15,15,15)));
add(card,BorderLayout.CENTER);
/* table styling */
table.setRowHeight(24);
105
table.setGridColor(new Color(0xEEEEEE));
JTableHeader th = table.getTableHeader();
th.setReorderingAllowed(false);
th.setFont(new Font("SansSerif", Font.BOLD, 13));
table.setDefaultRenderer(Object.class,new Zebra());
card.add(new JScrollPane(table),BorderLayout.CENTER);
/* toolbar */
JPanel bar = new JPanel(new FlowLayout(FlowLayout.LEFT,8,0));
bar.setOpaque(false);
JButton btnAdd = blue("Add","Add new doctor");
JButton btnEdit = blue("Edit","Edit selected doctor");
JButton btnDelete = red ("Delete","Remove selected doctor");
JButton btnRefresh = blue("Refresh","Reload doctors");
btnAdd.addActionListener(e -> openDialog(null));
btnEdit.addActionListener(e -> {
int r=table.getSelectedRow();
if(r!=-1) openDialog((int)model.getValueAt(r,0));
});
btnDelete .addActionListener(e -> deleteSelected());
btnRefresh.addActionListener(e -> load(txtSearch.getText()));
bar.add(btnAdd); bar.add(btnEdit); bar.add(btnDelete); bar.add(btnRefresh);
/* search box */
txtSearch.setPreferredSize(new Dimension(200,28));
txtSearch.setMaximumSize(new Dimension(200,28));
txtSearch.setFont(new Font("SansSerif",Font.PLAIN,13));
txtSearch.setToolTipText("Search by name or specialization");
txtSearch.getDocument().addDocumentListener((Doc) e ->
load(txtSearch.getText()));
bar.add(Box.createHorizontalStrut(15));
bar.add(new JLabel("Search: "));
106
bar.add(txtSearch); bar.add(new JLabel(" "));
card.add(bar,BorderLayout.NORTH);
}
/* ---------- button helpers ---------- */
private JButton blue(String txt,String tip){ return styled(txt,PRIMARY,tip); }
private JButton red (String txt,String tip){ return styled(txt,new
Color(0xD32F2F),tip);}
private JButton styled(String txt,Color bg,String tip){
JButton b=new JButton(txt);
b.setBackground(bg); b.setForeground(Color.WHITE);
b.setFocusPainted(false);
b.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
b.setToolTipText(tip);
return b;
}
/* ---------- zebra renderer ---------- */
private static class Zebra extends DefaultTableCellRenderer{
@Override public Component getTableCellRendererComponent(
JTable t,Object v,boolean sel,boolean focus,int row,int col){
Component c=super.getTableCellRendererComponent(t,v,sel,focus,row,col);
c.setBackground(sel? t.getSelectionBackground()
:(row%2==0? Color.WHITE : new Color(0xF7F9FC)));
return c;
}
}
/* ---------- CRUD / LOAD ---------- */
private void load(String filter){
model.setRowCount(0);
String sql = """
SELECT doctor_id,name,specialization,email,phone
107
FROM doctor
%s
ORDER BY name
""".formatted(filter.isBlank()? ""
: "WHERE name LIKE ? OR specialization LIKE ?");
try(Connection c=DBConnection.getConnection();
PreparedStatement ps=c.prepareStatement(sql)){
if(!filter.isBlank()){
String like="%"+filter+"%";
ps.setString(1,like); ps.setString(2,like);
}
ResultSet rs=ps.executeQuery();
while(rs.next()){
model.addRow(new Object[]{
rs.getInt(1), rs.getString(2), rs.getString(3),
rs.getString(4), rs.getString(5)});
}
}catch(SQLException ex){ err(ex); }
}
private void openDialog(Integer id){
DoctorDialog dlg = new DoctorDialog(SwingUtilities.getWindowAncestor(this), id);
dlg.setVisible(true);
if(dlg.isSaved()) load(txtSearch.getText());
}
private void deleteSelected(){
int r=table.getSelectedRow(); if(r==-1) return;
int id=(int)model.getValueAt(r,0);
if(JOptionPane.showConfirmDialog(this,"Delete doctor "+id+"?","Confirm",
JOptionPane.YES_NO_OPTION)!=JOptionPane.YES_OPTION) return;
try(Connection c=DBConnection.getConnection();
108
PreparedStatement ps=c.prepareStatement(
"DELETE FROM doctor WHERE doctor_id=?")){
ps.setInt(1,id); ps.executeUpdate(); load(txtSearch.getText());
}catch(SQLException ex){ err(ex);}
}
/* ---------- util ---------- */
private void err(Exception ex){
ex.printStackTrace();
JOptionPane.showMessageDialog(this,
"Error: "+ex.getMessage(),
"Database Error",JOptionPane.ERROR_MESSAGE);
}
/* tiny document listener */
@FunctionalInterface
interface Doc extends javax.swing.event.DocumentListener{
void change(javax.swing.event.DocumentEvent e);
default void insertUpdate(javax.swing.event.DocumentEvent e){change(e);}
default void removeUpdate(javax.swing.event.DocumentEvent e){change(e);}
default void changedUpdate(javax.swing.event.DocumentEvent e){change(e);}
}
}
109
ADD/EDIT DOCTOR DIALOG
CODE
package hospital.ui.receptionist;
import hospital.database.DBConnection;
import javax.swing.*;
import javax.swing.border.EmptyBorder;
import javax.swing.border.MatteBorder;
import java.awt.*;
import java.sql.*;
public class DoctorDialog extends JDialog {
private final JTextField txtName = new JTextField();
private final JTextField txtSpec = new JTextField();
private final JTextField txtEmail = new JTextField();
private final JTextField txtPhone = new JTextField();
private final JPasswordField txtPass = new JPasswordField();
private final Integer doctorId;
private boolean saved = false;
public boolean isSaved() { return saved; }
110
/* theme */
private static final Color PRIMARY = new Color(0x1976D2);
private static final Color BORDER = new Color(0xDDE3EB);
public DoctorDialog(Window owner, Integer doctorId) {
super(owner, doctorId == null ? "Add Doctor" : "Edit Doctor",
ModalityType.APPLICATION_MODAL);
this.doctorId = doctorId;
buildUI();
if (doctorId != null) loadDoctor();
pack();
setLocationRelativeTo(owner);
setResizable(false);
}
/* -------- UI -------- */
private void buildUI() {
JPanel card = new JPanel();
card.setLayout(new BoxLayout(card, BoxLayout.Y_AXIS));
card.setBackground(Color.WHITE);
card.setBorder(new MatteBorder(1,1,4,4,BORDER));
card.setBorder(new EmptyBorder(25, 35, 25, 35));
JLabel heading = new JLabel(doctorId == null ? "Add New Doctor" : "Edit Doctor");
heading.setFont(new Font("SansSerif", Font.BOLD, 20));
heading.setAlignmentX(Component.CENTER_ALIGNMENT);
card.add(heading);
card.add(Box.createRigidArea(new Dimension(0, 20)));
card.add(field("Full Name", txtName));
card.add(field("Specialization", txtSpec));
card.add(field("Email Address", txtEmail));
card.add(field("Phone Number", txtPhone));
if (doctorId == null) { // password only on add
111
card.add(field("Create Password", txtPass));
}
card.add(Box.createRigidArea(new Dimension(0, 15)));
JButton btnSave = new JButton("Save");
btnSave.setBackground(PRIMARY);
btnSave.setForeground(Color.WHITE);
btnSave.setPreferredSize(new Dimension(180, 38));
btnSave.setFocusPainted(false);
btnSave.setAlignmentX(Component.CENTER_ALIGNMENT);
btnSave.addActionListener(e -> save());
getRootPane().setDefaultButton(btnSave);
card.add(btnSave);
card.add(Box.createVerticalGlue());
add(card);
}
private JPanel field(String label, JComponent input) {
JLabel lbl = new JLabel(label);
lbl.setFont(new Font("SansSerif", Font.PLAIN, 14));
input.setMaximumSize(new Dimension(Integer.MAX_VALUE, 32));
input.setPreferredSize(new Dimension(300, 32));
JPanel panel = new JPanel();
panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));
panel.setOpaque(false);
panel.add(lbl);
panel.add(Box.createRigidArea(new Dimension(0, 6)));
panel.add(input);
panel.add(Box.createRigidArea(new Dimension(0, 15)));
return panel;
}
/* -------- LOAD EXISTING -------- */
112
private void loadDoctor() {
String sql = "SELECT name, specialization, email, phone FROM doctor WHERE
doctor_id=?";
try (Connection con = DBConnection.getConnection();
PreparedStatement ps = con.prepareStatement(sql)) {
ps.setInt(1, doctorId);
ResultSet rs = ps.executeQuery();
if (rs.next()) {
txtName .setText(rs.getString(1));
txtSpec .setText(rs.getString(2));
txtEmail.setText(rs.getString(3));
txtPhone.setText(rs.getString(4));
txtPass .setEnabled(false); // keep old password
}
} catch (SQLException ex) { showError(ex); }
}
/* -------- SAVE -------- */
private void save() {
try (Connection con = DBConnection.getConnection()) {
if (doctorId == null) { // INSERT
String in = """
INSERT INTO doctor (name, specialization, email, phone, password)
VALUES (?,?,?,?,?)
""";
try (PreparedStatement ps = con.prepareStatement(in)) {
ps.setString(1, txtName .getText().trim());
ps.setString(2, txtSpec .getText().trim());
ps.setString(3, txtEmail.getText().trim());
ps.setString(4, txtPhone.getText().trim());
ps.setString(5, String.valueOf(txtPass.getPassword()));
113
ps.executeUpdate();
}
} else { // UPDATE
String up = """
UPDATE doctor
SET name=?, specialization=?, email=?, phone=?
WHERE doctor_id=?
""";
try (PreparedStatement ps = con.prepareStatement(up)) {
ps.setString(1, txtName .getText().trim());
ps.setString(2, txtSpec .getText().trim());
ps.setString(3, txtEmail.getText().trim());
ps.setString(4, txtPhone.getText().trim());
ps.setInt (5, doctorId);
ps.executeUpdate();
}
}
saved = true;
dispose();
} catch (SQLException ex) {
if (ex.getMessage().contains("Duplicate entry")) {
JOptionPane.showMessageDialog(this, "Email already exists.");
} else showError(ex);
} }
private void showError(Exception ex) {
ex.printStackTrace();
JOptionPane.showMessageDialog(this,
"Error: " + ex.getMessage(),
"Database Error", JOptionPane.ERROR_MESSAGE);
} }
114
MANAGE PATIENT
CODE
package hospital.ui.receptionist;
import hospital.database.DBConnection;
import javax.swing.*;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.JTableHeader;
import java.awt.*;
import java.sql.*;
public class ManagePatientsPanel extends JPanel {
/* ---------- theme ---------- */
private static final Color PRIMARY = new Color(0x1976D2);
private static final Color BORDER = new Color(0xDDE3EB);
/* ---------- table model ---------- */
private final DefaultTableModel model = new DefaultTableModel(
new String[]{"ID","Name","Age","Gender","Email",
115
"Phone","Illness"}, 0){
@Override public boolean isCellEditable(int r,int c){ return false; }
};
private final JTable table = new JTable(model);
public ManagePatientsPanel() {
setLayout(new BorderLayout());
setBackground(new Color(0xF4F7FA));
buildUI();
refresh();
}
/* ---------- UI ---------- */
private void buildUI() {
JPanel card = new JPanel(new BorderLayout(10,10));
card.setBackground(Color.WHITE);
card.setBorder(BorderFactory.createCompoundBorder(
BorderFactory.createMatteBorder(1,1,4,4,BORDER),
BorderFactory.createEmptyBorder(15,15,15,15)));
add(card, BorderLayout.CENTER);
/* table styling */
table.setRowHeight(24);
table.setGridColor(new Color(0xEEEEEE));
JTableHeader th = table.getTableHeader();
th.setReorderingAllowed(false);
th.setFont(new Font("SansSerif", Font.BOLD, 13));
table.setDefaultRenderer(Object.class,new Zebra());
card.add(new JScrollPane(table),BorderLayout.CENTER);
/* toolbar */
JPanel bar = new JPanel(new FlowLayout(FlowLayout.LEFT,8,0));
bar.setOpaque(false);
JButton btnAdd = blue("Add","Register new patient");
116
JButton btnEdit = blue("Edit","Edit selected patient");
JButton btnDelete = red("Delete","Remove selected patient");
JButton btnLab = blue("Add Lab Report","Upload lab report");
JButton btnRefresh= blue("Refresh","Reload patients");
btnAdd .addActionListener(e -> openDialog(null));
btnEdit .addActionListener(e -> {
int r=table.getSelectedRow(); if(r!=-1)
openDialog((int)model.getValueAt(r,0)); });
btnDelete.addActionListener(e -> deleteSelected());
btnLab .addActionListener(e -> addLabReport());
btnRefresh.addActionListener(e -> filter(search.getText()));
bar.add(btnAdd); bar.add(btnEdit); bar.add(btnDelete);
bar.add(btnLab); bar.add(btnRefresh);
/* search box */
search.setPreferredSize(new Dimension(200,28));
search.setMaximumSize(new Dimension(200,28));
search.getDocument().addDocumentListener((SimpleDocumentListener)
e -> filter(search.getText()));
bar.add(Box.createHorizontalStrut(15));
bar.add(new JLabel("Search: "));
117
b.setFocusPainted(false);
b.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
b.setToolTipText(tip); return b;
}
private static class Zebra extends DefaultTableCellRenderer{
@Override public Component getTableCellRendererComponent(
JTable t,Object v,boolean sel,boolean focus,int row,int col){
Component c=super.getTableCellRendererComponent(t,v,sel,focus,row,col);
c.setBackground(sel? t.getSelectionBackground()
:(row%2==0? Color.WHITE : new Color(0xF7F9FC)));
return c;
}
}
/* ---------- CRUD ---------- */
private void refresh(){ loadQuery(null); }
private void filter(String txt){
loadQuery(txt.isBlank() ? null : txt);
}
private void loadQuery(String like){
model.setRowCount(0);
String sql = "SELECT patient_id,name,age,gender,email,phone,illness "
+ "FROM patient "
+ (like==null? "" : "WHERE name LIKE ? OR email LIKE ?");
try(Connection c=DBConnection.getConnection();
PreparedStatement ps=c.prepareStatement(sql)){
if(like!=null){
like="%"+like+"%";
ps.setString(1,like); ps.setString(2,like);
}
ResultSet rs=ps.executeQuery();
118
while(rs.next()){
model.addRow(new Object[]{
rs.getInt(1), rs.getString(2), rs.getInt(3),
rs.getString(4), rs.getString(5),
rs.getString(6), rs.getString(7)});
}
}catch(SQLException ex){ showError(ex);}
}
private void openDialog(Integer id){
PatientDialog dlg=new PatientDialog(SwingUtilities.getWindowAncestor(this),id);
dlg.setVisible(true);
if(dlg.isSaved()) refresh();
}
private void deleteSelected(){
int r=table.getSelectedRow(); if(r==-1) return;
int id=(int)model.getValueAt(r,0);
if(JOptionPane.showConfirmDialog(this,"Delete patient "+id+"?","Confirm",
JOptionPane.YES_NO_OPTION)!=JOptionPane.YES_OPTION) return;
try(Connection c=DBConnection.getConnection();
PreparedStatement ps=c.prepareStatement(
"DELETE FROM patient WHERE patient_id=?")){
ps.setInt(1,id); ps.executeUpdate(); refresh();
}catch(SQLException ex){ showError(ex);}
}
private void addLabReport(){
int r=table.getSelectedRow(); if(r==-1) return;
int pid=(int)model.getValueAt(r,0);
new
LabReportDialog(SwingUtilities.getWindowAncestor(this),pid).setVisible(true);
}
119
/* ---------- util ---------- */
private void showError(Exception ex){
ex.printStackTrace();
JOptionPane.showMessageDialog(this,"Error: "+ex.getMessage(),
"Database Error",JOptionPane.ERROR_MESSAGE);
}
/* tiny doc-listener */
@FunctionalInterface
interface SimpleDocumentListener extends javax.swing.event.DocumentListener{
void update(javax.swing.event.DocumentEvent e);
default void insertUpdate(javax.swing.event.DocumentEvent e){update(e);}
default void removeUpdate(javax.swing.event.DocumentEvent e){update(e);}
default void changedUpdate(javax.swing.event.DocumentEvent e){update(e);}
}
}
120
CODE
package hospital.ui.receptionist;
import hospital.database.DBConnection;
import javax.swing.*;
import javax.swing.border.EmptyBorder;
import javax.swing.border.MatteBorder;
import java.awt.*;
import java.sql.*;
public class PatientDialog extends JDialog {
private final JTextField txtName = new JTextField();
private final JTextField txtAge = new JTextField();
private final JComboBox<String> cbGender = new JComboBox<>(new
String[]{"Male","Female","Other"});
private final JTextField txtEmail = new JTextField();
private final JTextField txtPhone = new JTextField();
private final JTextArea txtIll = new JTextArea(4, 20);
private final JPasswordField txtPass = new JPasswordField();
private final Integer patientId;
private boolean saved = false;
/* colour theme */
private static final Color BORDER = new Color(0xDDE3EB);
private static final Color PRIMARY = new Color(0x1976D2);
public PatientDialog(Window owner, Integer patientId) {
super(owner,
patientId == null ? "Add Patient" : "Edit Patient " + patientId,
ModalityType.APPLICATION_MODAL);
this.patientId = patientId;
buildUI();
if (patientId != null) load();
pack();
121
setLocationRelativeTo(owner);
setResizable(false);
}
public boolean isSaved() { return saved; }
/* ---------- UI ---------- */
private void buildUI() {
JPanel card = new JPanel();
card.setBackground(Color.WHITE);
card.setBorder(new MatteBorder(1,1,4,4,BORDER));
card.setLayout(new BoxLayout(card, BoxLayout.Y_AXIS));
card.setBorder(new EmptyBorder(25, 35, 25, 35));
add(card);
JLabel heading = new JLabel(patientId == null ? "Add New Patient" : "Edit Patient");
heading.setFont(new Font("SansSerif", Font.BOLD, 20));
heading.setAlignmentX(Component.CENTER_ALIGNMENT);
card.add(heading);
card.add(Box.createRigidArea(new Dimension(0, 20)));
card.add(field("Full Name", txtName));
card.add(field("Age", txtAge));
card.add(field("Gender", cbGender));
card.add(field("Email", txtEmail));
card.add(field("Phone", txtPhone));
/* Illness text area */
JLabel lblIll = new JLabel("Illness / Condition");
lblIll.setFont(new Font("SansSerif", Font.PLAIN, 14));
txtIll.setLineWrap(true);
txtIll.setWrapStyleWord(true);
txtIll.setMaximumSize(new Dimension(Integer.MAX_VALUE, 80));
card.add(lblIll);
card.add(Box.createRigidArea(new Dimension(0, 6)));
122
card.add(new JScrollPane(txtIll));
card.add(Box.createRigidArea(new Dimension(0, 15)));
/* Password (add-mode only) */
if (patientId == null) {
card.add(field("Create Password", txtPass));
}
card.add(Box.createRigidArea(new Dimension(0, 15)));
JButton btnSave = new JButton("Save");
btnSave.setBackground(PRIMARY);
btnSave.setForeground(Color.WHITE);
btnSave.setFocusPainted(false);
btnSave.setPreferredSize(new Dimension(180, 38));
btnSave.setAlignmentX(Component.CENTER_ALIGNMENT);
btnSave.addActionListener(e -> save());
getRootPane().setDefaultButton(btnSave);
card.add(btnSave);
card.add(Box.createVerticalGlue());
}
private JPanel field(String label, JComponent input) {
JLabel lbl = new JLabel(label);
lbl.setFont(new Font("SansSerif", Font.PLAIN, 14));
input.setMaximumSize(new Dimension(Integer.MAX_VALUE, 32));
input.setPreferredSize(new Dimension(300, 32));
JPanel panel = new JPanel();
panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));
panel.setOpaque(false);
panel.add(lbl);
panel.add(Box.createRigidArea(new Dimension(0, 6)));
panel.add(input);
panel.add(Box.createRigidArea(new Dimension(0, 15)));
123
return panel;
}
/* ---------- DB LOAD ---------- */
private void load() {
String sql = "SELECT name, age, gender, email, phone, illness FROM patient WHERE
patient_id=?";
try (Connection con = DBConnection.getConnection();
PreparedStatement ps = con.prepareStatement(sql)) {
ps.setInt(1, patientId);
ResultSet rs = ps.executeQuery();
if (rs.next()) {
txtName .setText(rs.getString(1));
txtAge .setText(String.valueOf(rs.getInt(2)));
cbGender.setSelectedItem(rs.getString(3));
txtEmail.setText(rs.getString(4));
txtPhone.setText(rs.getString(5));
txtIll .setText(rs.getString(6));
}
} catch (SQLException ex) { error(ex); }
}
/* ---------- DB SAVE ---------- */
private void save() {
try (Connection con = DBConnection.getConnection()) {
if (patientId == null) { // INSERT
String in = """
INSERT INTO patient
(name, age, gender, email, phone, illness, password)
VALUES (?,?,?,?,?,?,?)
""";
try (PreparedStatement ps = con.prepareStatement(in)) {
124
ps.setString(1, txtName.getText().trim());
ps.setInt (2, Integer.parseInt(txtAge.getText().trim()));
ps.setString(3, cbGender.getSelectedItem().toString());
ps.setString(4, txtEmail.getText().trim());
ps.setString(5, txtPhone.getText().trim());
ps.setString(6, txtIll.getText().trim());
ps.setString(7, String.valueOf(txtPass.getPassword()));
ps.executeUpdate();
}
} else { // UPDATE
String up = """
UPDATE patient
SET name=?, age=?, gender=?, email=?, phone=?, illness=?
WHERE patient_id=?
""";
try (PreparedStatement ps = con.prepareStatement(up)) {
ps.setString(1, txtName.getText().trim());
ps.setInt (2, Integer.parseInt(txtAge.getText().trim()));
ps.setString(3, cbGender.getSelectedItem().toString());
ps.setString(4, txtEmail.getText().trim());
ps.setString(5, txtPhone.getText().trim());
ps.setString(6, txtIll.getText().trim());
ps.setInt(7, patientId);
ps.executeUpdate();
}
}
saved = true;
dispose();
} catch (SQLException | NumberFormatException ex) { error(ex); }
}
125
private void error(Exception ex) {
ex.printStackTrace();
JOptionPane.showMessageDialog(this, "Error: " + ex.getMessage(),
"DB Error", JOptionPane.ERROR_MESSAGE);
}
}
MANAGE APPOINTMENTS
CODE
package hospital.ui.receptionist;
import hospital.database.DBConnection;
import javax.swing.*;
import javax.swing.event.DocumentEvent;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.JTableHeader;
import java.awt.*;
import java.sql.*;
126
public class ManageAppointmentsPanel extends JPanel {
/* ---------- theme ---------- */
private static final Color PRIMARY = new Color(0x1976D2);
private static final Color DANGER = new Color(0xD32F2F);
private static final Color BORDER = new Color(0xDDE3EB);
private static final Color BACK = new Color(0xF4F7FA);
/* ---------- table ---------- */
private final DefaultTableModel model = new DefaultTableModel(
new String[]{"ID","Patient","Doctor","Date","Time",
"Status","Booked By"},0){
@Override public boolean isCellEditable(int r,int c){ return false; }
};
private final JTable table = new JTable(model);
/* search box needs field-scope for refresh */
private final JTextField txtSearch = new JTextField();
public ManageAppointmentsPanel() {
setLayout(new BorderLayout());
setBackground(BACK);
buildUI();
load(""); // initial load
}
/* ---------- UI ---------- */
private void buildUI() {
JPanel card = new JPanel(new BorderLayout(10,10));
card.setBackground(Color.WHITE);
card.setBorder(BorderFactory.createCompoundBorder(
BorderFactory.createMatteBorder(1,1,4,4,BORDER),
BorderFactory.createEmptyBorder(15,15,15,15)));
add(card,BorderLayout.CENTER);
/* table style */
127
table.setRowHeight(24);
table.setGridColor(new Color(0xEEEEEE));
JTableHeader th = table.getTableHeader();
th.setReorderingAllowed(false);
th.setFont(new Font("SansSerif",Font.BOLD,13));
table.setDefaultRenderer(Object.class,new Zebra());
card.add(new JScrollPane(table),BorderLayout.CENTER);
/* toolbar */
JPanel bar = new JPanel(new FlowLayout(FlowLayout.LEFT,8,0));
bar.setOpaque(false);
JButton btnAdd = blue ("Add" ,"Create appointment");
JButton btnApprove = blue ("Approve Pending","Approve patient-pending");
JButton btnReject = red ("Reject Pending" ,"Reject patient-pending"); // NEW
JButton btnDelete = red ("Delete Done/Can","Delete completed / cancelled"); //
NEW
JButton btnRefresh = blue ("Refresh" ,"Reload list");
btnAdd .addActionListener(e -> openDialog());
btnApprove.addActionListener(e -> approveOrReject(true));
btnReject .addActionListener(e -> approveOrReject(false));
btnDelete .addActionListener(e -> deleteSelected());
btnRefresh.addActionListener(e -> load(txtSearch.getText()));
bar.add(btnAdd); bar.add(btnApprove); bar.add(btnReject);
bar.add(btnDelete); bar.add(btnRefresh);
/* search */
txtSearch.setPreferredSize(new Dimension(220,28));
txtSearch.setMaximumSize(new Dimension(220,28));
txtSearch.setFont(new Font("SansSerif",Font.PLAIN,13));
txtSearch.setToolTipText("Search patient or doctor");
txtSearch.getDocument().addDocumentListener(
(Doc) e -> load(txtSearch.getText()));
128
bar.add(Box.createHorizontalStrut(15));
bar.add(new JLabel("Search: "));
129
SELECT a.appointment_id, p.name, d.name,
a.appointment_date, a.appointment_time,
a.status, a.booked_by
FROM appointment a
JOIN patient p ON a.patient_id = p.patient_id
JOIN doctor d ON a.doctor_id = d.doctor_id
%s
ORDER BY a.appointment_date, a.appointment_time
""".formatted(filter.isBlank()? ""
: "WHERE p.name LIKE ? OR d.name LIKE ?");
try(Connection c=DBConnection.getConnection();
PreparedStatement ps=c.prepareStatement(sql)){
if(!filter.isBlank()){
String like="%"+filter+"%";
ps.setString(1,like); ps.setString(2,like);
}
ResultSet rs=ps.executeQuery();
while(rs.next()){
model.addRow(new Object[]{
rs.getInt(1), rs.getString(2), rs.getString(3),
rs.getDate(4), rs.getTime(5),
rs.getString(6), rs.getString(7)});
}
}catch(SQLException ex){ error(ex); }
}
/* ---------- add dialog ---------- */
private void openDialog(){
AppointmentDialog dlg =
new AppointmentDialog(SwingUtilities.getWindowAncestor(this));
dlg.setVisible(true);
130
if(dlg.isSaved()) load(txtSearch.getText());
}
/* ---------- approve OR reject ---------- */
private void approveOrReject(boolean approve){
int r = table.getSelectedRow(); if(r==-1) return;
String status =(String)model.getValueAt(r,5);
String booked =(String)model.getValueAt(r,6);
int id =(int) model.getValueAt(r,0);
if(!"pending".equalsIgnoreCase(status) || !"patient".equalsIgnoreCase(booked)){
JOptionPane.showMessageDialog(this,
"Action valid only for patient-booked PENDING appointments.");
return;
}
String newStatus = approve? "confirmed" : "cancelled";
try(Connection c=DBConnection.getConnection();
PreparedStatement ps=c.prepareStatement(
"UPDATE appointment SET status=? WHERE appointment_id=?")){
ps.setString(1,newStatus);
ps.setInt(2,id);
ps.executeUpdate();
load(txtSearch.getText());
JOptionPane.showMessageDialog(this,
approve? "Appointment approved." : "Appointment rejected.");
}catch(SQLException ex){ error(ex);}
}
/* ---------- delete completed / cancelled ---------- */
private void deleteSelected(){
int r = table.getSelectedRow(); if(r==-1) return;
String status =(String)model.getValueAt(r,5);
int id =(int) model.getValueAt(r,0);
131
if(!"completed".equalsIgnoreCase(status) &&
!"cancelled".equalsIgnoreCase(status)){
JOptionPane.showMessageDialog(this,
"Only COMPLETED or CANCELLED appointments can be deleted.");
return;
}
if(JOptionPane.showConfirmDialog(this,
"Delete appointment "+id+"?","Confirm",
JOptionPane.YES_NO_OPTION)!=JOptionPane.YES_OPTION) return;
try(Connection c=DBConnection.getConnection();
PreparedStatement ps=c.prepareStatement(
"DELETE FROM appointment WHERE appointment_id=?")){
ps.setInt(1,id);
ps.executeUpdate();
load(txtSearch.getText());
}catch(SQLException ex){ error(ex);}
}
/* ---------- util ---------- */
private void error(Exception ex){
ex.printStackTrace();
JOptionPane.showMessageDialog(this,
"Error: "+ex.getMessage(),
"Database Error", JOptionPane.ERROR_MESSAGE);
}
/* tiny doc listener */
@FunctionalInterface
interface Doc extends javax.swing.event.DocumentListener{
void change(javax.swing.event.DocumentEvent e);
default void insertUpdate(javax.swing.event.DocumentEvent e){change(e);}
default void removeUpdate(javax.swing.event.DocumentEvent e){change(e);}
132
default void changedUpdate(javax.swing.event.DocumentEvent e){change(e);}
}
}
CODE
package hospital.ui.receptionist;
import hospital.database.DBConnection;
import javax.swing.*;
import javax.swing.border.EmptyBorder;
import javax.swing.border.MatteBorder;
import java.awt.*;
import java.sql.*;
import java.time.LocalDate;
import java.time.LocalTime;
import java.util.Date;
public class AppointmentDialog extends JDialog {
133
private final JComboBox<PatientItem> cbPatient = new JComboBox<>();
private final JComboBox<DoctorItem> cbDoctor = new JComboBox<>();
/* Modern date/time spinners */
private final JSpinner spinDate = new JSpinner(
new SpinnerDateModel(new Date(), null, null,
java.util.Calendar.DAY_OF_MONTH));
private final JSpinner spinTime = new JSpinner(
new SpinnerDateModel(new Date(), null, null, java.util.Calendar.MINUTE));
private boolean saved = false;
public boolean isSaved() { return saved; }
/* theme */
private static final Color PRIMARY = new Color(0x1976D2);
private static final Color BORDER = new Color(0xDDE3EB);
public AppointmentDialog(Window owner) {
super(owner, "New Appointment", ModalityType.APPLICATION_MODAL);
loadPatients();
loadDoctors();
buildUI();
pack();
setLocationRelativeTo(owner);
setResizable(false);
}
/* ---------- UI ---------- */
private void buildUI() {
JPanel card = new JPanel();
card.setLayout(new BoxLayout(card, BoxLayout.Y_AXIS));
card.setBackground(Color.WHITE);
card.setBorder(new MatteBorder(1,1,4,4,BORDER));
card.setBorder(new EmptyBorder(25, 35, 25, 35));
add(card);
134
JLabel heading = new JLabel("Create Appointment");
heading.setFont(new Font("SansSerif", Font.BOLD, 20));
heading.setAlignmentX(Component.CENTER_ALIGNMENT);
card.add(heading);
card.add(Box.createRigidArea(new Dimension(0, 20)));
/* date/time spinner editors */
spinDate.setEditor(new JSpinner.DateEditor(spinDate, "yyyy-MM-dd"));
spinTime.setEditor(new JSpinner.DateEditor(spinTime, "HH:mm"));
card.add(field("Patient", cbPatient));
card.add(field("Doctor", cbDoctor));
card.add(field("Date", spinDate));
card.add(field("Time", spinTime));
card.add(Box.createRigidArea(new Dimension(0, 15)));
JButton btnSave = new JButton("Save");
btnSave.setBackground(PRIMARY);
btnSave.setForeground(Color.WHITE);
btnSave.setPreferredSize(new Dimension(180, 38));
btnSave.setFocusPainted(false);
btnSave.setAlignmentX(Component.CENTER_ALIGNMENT);
btnSave.addActionListener(e -> save());
getRootPane().setDefaultButton(btnSave);
card.add(btnSave);
card.add(Box.createVerticalGlue());
}
private JPanel field(String label, JComponent input) {
JLabel lbl = new JLabel(label);
lbl.setFont(new Font("SansSerif", Font.PLAIN, 14));
input.setMaximumSize(new Dimension(Integer.MAX_VALUE, 32));
input.setPreferredSize(new Dimension(260, 32));
JPanel panel = new JPanel();
135
panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));
panel.setOpaque(false);
panel.add(lbl);
panel.add(Box.createRigidArea(new Dimension(0, 6)));
panel.add(input);
panel.add(Box.createRigidArea(new Dimension(0, 15)));
return panel;
}
/* ---------- save logic ---------- */
private void save() {
try (Connection c = DBConnection.getConnection();
PreparedStatement ps = c.prepareStatement("""
INSERT INTO appointment
(patient_id, doctor_id, appointment_date,
appointment_time, status, booked_by)
VALUES (?, ?, ?, ?, 'confirmed', 'receptionist')
""")) {
ps.setInt(1, ((PatientItem) cbPatient.getSelectedItem()).id());
ps.setInt(2, ((DoctorItem) cbDoctor .getSelectedItem()).id());
java.util.Date d = (java.util.Date) spinDate.getValue();
java.util.Date t = (java.util.Date) spinTime.getValue();
ps.setDate (3, new java.sql.Date(d.getTime()));
ps.setTime (4, new java.sql.Time(t.getTime()));
ps.executeUpdate();
saved = true;
dispose();
} catch (Exception ex) { error(ex); }
}
/* ---------- load dropdowns ---------- */
private void loadPatients() {
136
try (Connection c = DBConnection.getConnection();
Statement st = c.createStatement();
ResultSet rs = st.executeQuery("SELECT patient_id, name FROM patient")) {
while (rs.next()) cbPatient.addItem(new PatientItem(rs.getInt(1),
rs.getString(2)));
} catch (SQLException ex) { error(ex); }
}
private void loadDoctors() {
try (Connection c = DBConnection.getConnection();
Statement st = c.createStatement();
ResultSet rs = st.executeQuery("SELECT doctor_id, name FROM doctor")) {
while (rs.next()) cbDoctor.addItem(new DoctorItem(rs.getInt(1),
rs.getString(2)));
} catch (SQLException ex) { error(ex); }
}
/* ---------- helper records ---------- */
private record PatientItem(int id, String name) {
@Override public String toString() { return name; }
}
private record DoctorItem(int id, String name) {
@Override public String toString() { return name; }
}
private void error(Exception ex) {
ex.printStackTrace();
JOptionPane.showMessageDialog(this,
"Error: " + ex.getMessage(),
"Database Error", JOptionPane.ERROR_MESSAGE);
}
}
137
MANAGE MEDICINE INVENTORY
CODE
package hospital.ui.receptionist;
import hospital.database.DBConnection;
import javax.swing.*;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.JTableHeader;
import java.awt.*;
import java.sql.*;
public class ManageInventoryPanel extends JPanel {
/* ---------- theme ---------- */
private static final Color PRIMARY = new Color(0x1976D2);
private static final Color BORDER = new Color(0xDDE3EB);
/* ---------- table model ---------- */
private final DefaultTableModel model = new DefaultTableModel(
new String[]{"ID","Medicine","Quantity","Unit ₹"}, 0) {
138
@Override public boolean isCellEditable(int r,int c){ return false; }
};
private final JTable table = new JTable(model);
/* search box must be field-scope so Refresh can read it */
private final JTextField search = new JTextField();
public ManageInventoryPanel() {
setLayout(new BorderLayout());
setBackground(new Color(0xF4F7FA));
buildUI();
refresh(); // initial load
}
/* ---------- build UI ---------- */
private void buildUI() {
JPanel card = new JPanel(new BorderLayout(10,10));
card.setBackground(Color.WHITE);
card.setBorder(BorderFactory.createCompoundBorder(
BorderFactory.createMatteBorder(1,1,4,4,BORDER),
BorderFactory.createEmptyBorder(15,15,15,15)));
add(card, BorderLayout.CENTER);
/* table styling */
table.setRowHeight(24);
table.setGridColor(new Color(0xEEEEEE));
JTableHeader th = table.getTableHeader();
th.setReorderingAllowed(false);
th.setFont(new Font("SansSerif", Font.BOLD, 13));
table.setDefaultRenderer(Object.class, new DefaultTableCellRenderer() {
@Override
public Component getTableCellRendererComponent(
JTable t,Object v,boolean sel,boolean focus,int row,int col){
Component c = super.getTableCellRendererComponent(t,v,sel,focus,row,col);
139
c.setBackground(sel ? t.getSelectionBackground()
: (row%2==0 ? Color.WHITE : new Color(0xF7F9FC)));
return c;
}
});
card.add(new JScrollPane(table), BorderLayout.CENTER);
/* toolbar */
JPanel bar = new JPanel(new FlowLayout(FlowLayout.LEFT, 8, 0));
bar.setOpaque(false);
JButton btnAdd = blueBtn("Add", "Add new medicine");
JButton btnEdit = blueBtn("Edit", "Edit selected medicine");
JButton btnDelete = redBtn ("Delete", "Remove selected medicine");
JButton btnRefresh = blueBtn("Refresh","Reload inventory"); // NEW
btnAdd .addActionListener(e -> openDialog(null));
btnEdit .addActionListener(e -> {
int r = table.getSelectedRow();
if (r != -1) openDialog((int) model.getValueAt(r, 0));
});
btnDelete.addActionListener(e -> deleteSelected());
btnRefresh.addActionListener(e -> filter(search.getText())); // reload
bar.add(btnAdd); bar.add(btnEdit); bar.add(btnDelete); bar.add(btnRefresh);
/* search box */
search.setPreferredSize(new Dimension(200,28));
search.setMaximumSize(new Dimension(200,28));
search.setFont(new Font("SansSerif", Font.PLAIN, 13));
search.setToolTipText("Search medicine name");
search.getDocument().addDocumentListener(
(Doc) e -> filter(search.getText()));
bar.add(Box.createHorizontalStrut(15));
bar.add(new JLabel("Search: "));
140
bar.add(search); bar.add(new JLabel(" "));
card.add(bar, BorderLayout.NORTH);
}
/* ---------- button helpers ---------- */
private JButton blueBtn(String text,String tip){
return styled(new JButton(text), PRIMARY, tip);
}
private JButton redBtn(String text,String tip){
return styled(new JButton(text), new Color(0xD32F2F), tip);
}
private JButton styled(JButton b,Color bg,String tip){
b.setBackground(bg);
b.setForeground(Color.WHITE);
b.setFocusPainted(false);
b.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
b.setToolTipText(tip);
return b;
}
/* ---------- data helpers ---------- */
private void refresh() { filter(""); }
141
if (JOptionPane.showConfirmDialog(this,"Delete medicine "+id+"?","Confirm",
JOptionPane.YES_NO_OPTION)!=JOptionPane.YES_OPTION) return;
try(Connection c = DBConnection.getConnection();
PreparedStatement ps = c.prepareStatement(
"DELETE FROM inventory WHERE medicine_id=?")){
ps.setInt(1, id);
ps.executeUpdate();
refresh();
} catch(SQLException ex){ showErr(ex); }
}
/* filter=="" means full refresh */
private void filter(String txt){
model.setRowCount(0);
String sql = txt.isBlank()
? "SELECT medicine_id,name,quantity,price_per_unit FROM inventory ORDER
BY name"
: "SELECT medicine_id,name,quantity,price_per_unit FROM inventory WHERE
name LIKE ? ORDER BY name";
try(Connection c = DBConnection.getConnection();
PreparedStatement ps = c.prepareStatement(sql)){
if(!txt.isBlank()) ps.setString(1,"%"+txt+"%");
ResultSet rs = ps.executeQuery();
while(rs.next()){
model.addRow(new Object[]{
rs.getInt(1), rs.getString(2),
rs.getInt(3), rs.getBigDecimal(4)});
}
}catch(SQLException ex){ showErr(ex);}
}
/* ---------- utilities ---------- */
private void showErr(Exception ex){
142
ex.printStackTrace();
JOptionPane.showMessageDialog(this,
"Error: "+ex.getMessage(),
"Database Error", JOptionPane.ERROR_MESSAGE);
}
/* tiny doc listener */
@FunctionalInterface
interface Doc extends javax.swing.event.DocumentListener{
void changed(javax.swing.event.DocumentEvent e);
default void insertUpdate(javax.swing.event.DocumentEvent e){changed(e);}
default void removeUpdate(javax.swing.event.DocumentEvent e){changed(e);}
default void changedUpdate(javax.swing.event.DocumentEvent e){changed(e);}
}
}
MEDICINE DIALOG
143
CODE
package hospital.ui.receptionist;
import hospital.database.DBConnection;
import javax.swing.*;
import javax.swing.border.EmptyBorder;
import javax.swing.border.MatteBorder;
import java.awt.*;
import java.math.BigDecimal;
import java.sql.*;
public class MedicineDialog extends JDialog {
private final JTextField txtName = new JTextField();
private final JTextField txtQty = new JTextField();
private final JTextField txtPrice = new JTextField();
private final Integer medId; // null = add | non-null = edit
private boolean saved = false;
public boolean isSaved() { return saved; }
/* theme */
private static final Color PRIMARY = new Color(0x1976D2);
private static final Color BORDER = new Color(0xDDE3EB);
public MedicineDialog(Window owner, Integer medId) {
super(owner, medId == null ? "Add Medicine" : "Edit Medicine",
ModalityType.APPLICATION_MODAL);
this.medId = medId;
buildUI();
if (medId != null) load();
pack();
setLocationRelativeTo(owner);
setResizable(false);
}
/* ---------------------- UI ---------------------- */
144
private void buildUI() {
JPanel card = new JPanel();
card.setBackground(Color.WHITE);
card.setBorder(new MatteBorder(1,1,4,4,BORDER));
card.setLayout(new BoxLayout(card, BoxLayout.Y_AXIS));
card.setBorder(new EmptyBorder(25, 35, 25, 35));
add(card);
JLabel heading = new JLabel(medId == null ? "Add New Medicine" : "Edit Medicine");
heading.setFont(new Font("SansSerif", Font.BOLD, 20));
heading.setAlignmentX(Component.CENTER_ALIGNMENT);
card.add(heading);
card.add(Box.createRigidArea(new Dimension(0, 20)));
card.add(field("Medicine Name", txtName));
card.add(field("Quantity in Stock", txtQty));
card.add(field("Unit Price (₹)", txtPrice));
card.add(Box.createRigidArea(new Dimension(0, 15)));
JButton btnSave = new JButton("Save");
btnSave.setBackground(PRIMARY);
btnSave.setForeground(Color.WHITE);
btnSave.setFocusPainted(false);
btnSave.setPreferredSize(new Dimension(180, 38));
btnSave.setAlignmentX(Component.CENTER_ALIGNMENT);
btnSave.addActionListener(e -> save());
getRootPane().setDefaultButton(btnSave);
card.add(btnSave);
card.add(Box.createVerticalGlue());
}
private JPanel field(String label, JComponent input) {
JLabel lbl = new JLabel(label);
lbl.setFont(new Font("SansSerif", Font.PLAIN, 14));
145
input.setMaximumSize(new Dimension(Integer.MAX_VALUE, 32));
input.setPreferredSize(new Dimension(300, 32));
JPanel panel = new JPanel();
panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));
panel.setOpaque(false);
panel.add(lbl);
panel.add(Box.createRigidArea(new Dimension(0, 6)));
panel.add(input);
panel.add(Box.createRigidArea(new Dimension(0, 15)));
return panel;
}
/* ---------------------- DATA LOAD ---------------------- */
private void load() {
String sql = "SELECT name, quantity, price_per_unit FROM inventory WHERE
medicine_id=?";
try (Connection c = DBConnection.getConnection();
PreparedStatement ps = c.prepareStatement(sql)) {
ps.setInt(1, medId);
ResultSet rs = ps.executeQuery();
if (rs.next()) {
txtName .setText(rs.getString(1));
txtQty .setText(String.valueOf(rs.getInt(2)));
txtPrice.setText(rs.getBigDecimal(3).toPlainString());
}
} catch (SQLException ex) { error(ex); }
}
/* ---------------------- SAVE ---------------------- */
private void save() {
/* validation */
int quantity;
146
BigDecimal price;
try {
quantity = Integer.parseInt(txtQty.getText().trim());
price = new BigDecimal(txtPrice.getText().trim());
if (quantity < 0 || price.compareTo(BigDecimal.ZERO) < 0)
throw new NumberFormatException();
} catch (NumberFormatException ex) {
JOptionPane.showMessageDialog(this, "Please enter positive numeric values.",
"Validation Error", JOptionPane.WARNING_MESSAGE);
return;
}
try (Connection c = DBConnection.getConnection()) {
if (medId == null) { // INSERT
String sql = "INSERT INTO inventory (name, quantity, price_per_unit) VALUES
(?,?,?)";
try (PreparedStatement ps = c.prepareStatement(sql)) {
ps.setString(1, txtName.getText().trim());
ps.setInt (2, quantity);
ps.setBigDecimal(3, price);
ps.executeUpdate();
}
} else { // UPDATE
String sql = """
UPDATE inventory
SET name=?, quantity=?, price_per_unit=?
WHERE medicine_id=?""";
try (PreparedStatement ps = c.prepareStatement(sql)) {
ps.setString(1, txtName.getText().trim());
ps.setInt (2, quantity);
ps.setBigDecimal(3, price);
147
ps.setInt(4, medId);
ps.executeUpdate();
}
}
saved = true;
dispose();
MANAGE BILLING
148
CODE
package hospital.ui.receptionist;
import hospital.database.DBConnection;
import javax.swing.*;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.JTableHeader;
import java.awt.*;
import java.sql.*;
public class ManageBillingPanel extends JPanel {
/* ---------- Colors ---------- */
private static final Color PRIMARY = new Color(0x1976D2);
private static final Color DANGER = new Color(0xD32F2F);
private static final Color BACK = new Color(0xF4F7FA);
private static final Color BORDER = new Color(0xDDE3EB);
/* ---------- Table ---------- */
private final DefaultTableModel model = new DefaultTableModel(
new String[]{
"Bill ID", "Patient", "Appt ID", "Appt Date",
"Total ₹", "Status", "Payment Mode"}, 0) {
@Override public boolean isCellEditable(int r, int c) { return false; }
};
private final JTable table = new JTable(model);
public ManageBillingPanel() {
setLayout(new BorderLayout());
setBackground(BACK);
buildUI();
refresh();
}
/* ---------- UI ---------- */
private void buildUI() {
149
JPanel card = new JPanel(new BorderLayout(10, 10));
card.setBackground(Color.WHITE);
card.setBorder(BorderFactory.createCompoundBorder(
BorderFactory.createMatteBorder(1, 1, 4, 4, BORDER),
BorderFactory.createEmptyBorder(15, 15, 15, 15)));
add(card, BorderLayout.CENTER);
/* toolbar */
JPanel bar = new JPanel(new FlowLayout(FlowLayout.LEFT, 8, 0));
bar.setOpaque(false);
JButton btnMarkPaid = blueButton("Mark as Paid");
JButton btnDelete = redButton("Delete");
JButton btnRefresh = blueButton("Refresh"); // NEW button
btnMarkPaid.addActionListener(e -> markPaid());
btnDelete .addActionListener(e -> delete());
btnRefresh .addActionListener(e -> refresh());
bar.add(btnMarkPaid);
bar.add(btnDelete);
bar.add(btnRefresh); // add refresh to bar
card.add(bar, BorderLayout.NORTH);
/* table styling */
table.setRowHeight(24);
table.setGridColor(new Color(0xEEEEEE));
JTableHeader th = table.getTableHeader();
th.setReorderingAllowed(false);
th.setFont(new Font("SansSerif", Font.BOLD, 13));
card.add(new JScrollPane(table), BorderLayout.CENTER);
}
/* ---------- button helpers ---------- */
private JButton blueButton(String text) {
150
JButton b = new JButton(text);
b.setBackground(PRIMARY);
b.setForeground(Color.WHITE);
b.setFocusPainted(false);
b.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
return b;
}
private JButton redButton(String text) {
JButton b = new JButton(text);
b.setBackground(DANGER);
b.setForeground(Color.WHITE);
b.setFocusPainted(false);
b.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
return b;
}
/* ---------- DB actions ---------- */
private void refresh() {
model.setRowCount(0);
String sql = """
SELECT b.bill_id, p.name, b.appointment_id, a.appointment_date,
b.total_amount, b.status, COALESCE(b.payment_mode,'-')
FROM bill b
JOIN patient p ON b.patient_id = p.patient_id
JOIN appointment a ON b.appointment_id = a.appointment_id
ORDER BY b.bill_id DESC
""";
try (Connection c = DBConnection.getConnection();
Statement st = c.createStatement();
ResultSet rs = st.executeQuery(sql)) {
while (rs.next()) {
151
model.addRow(new Object[]{
rs.getInt(1), rs.getString(2), rs.getInt(3),
rs.getDate(4), rs.getBigDecimal(5),
rs.getString(6), rs.getString(7)});
}
} catch (SQLException ex) { showError(ex); }
}
private void markPaid() {
int row = table.getSelectedRow();
if (row == -1) return;
if ("paid".equalsIgnoreCase((String) model.getValueAt(row, 5))) {
JOptionPane.showMessageDialog(this, "This bill is already paid.");
return;
}
String[] modes = {"cash", "card", "upi"};
String mode = (String) JOptionPane.showInputDialog(
this, "Select payment mode:", "Payment",
JOptionPane.PLAIN_MESSAGE, null, modes, modes[0]);
if (mode == null) return;
int billId = (int) model.getValueAt(row, 0);
try (Connection c = DBConnection.getConnection();
PreparedStatement ps = c.prepareStatement(
"UPDATE bill SET status='paid', payment_mode=? WHERE bill_id=?")) {
ps.setString(1, mode);
ps.setInt(2, billId);
ps.executeUpdate();
refresh();
} catch (SQLException ex) { showError(ex); }
}
private void delete() {
152
int row = table.getSelectedRow();
if (row == -1) return;
int billId = (int) model.getValueAt(row, 0);
if (JOptionPane.showConfirmDialog(
this, "Delete bill " + billId + "?", "Confirm",
JOptionPane.YES_NO_OPTION) != JOptionPane.YES_OPTION) return;
try (Connection c = DBConnection.getConnection();
PreparedStatement ps =
c.prepareStatement("DELETE FROM bill WHERE bill_id=?")) {
ps.setInt(1, billId);
ps.executeUpdate();
refresh();
} catch (SQLException ex) { showError(ex); }
}
private void showError(Exception ex) {
ex.printStackTrace();
JOptionPane.showMessageDialog(this,
"Error: " + ex.getMessage(),
"Database Error", JOptionPane.ERROR_MESSAGE);
}
}
153
SYSTEM TESTING
Testing is a crucial phase in the software development life cycle that ensures the system
meets its intended requirements and functions without errors or defects. For the
Hospital Management System, extensive testing was performed to verify the
correctness, reliability, and performance of each module. The goal was to identify bugs
early, validate features, and ensure smooth interaction between users and the system.
A combination of manual testing, unit testing, and integration testing was used
during the development process.
154
Feedback: The interface was user-friendly and the system behaved as expected.
155
FEASIBILITY STUDY
A feasibility study is an essential phase in software development that evaluates whether
a proposed system is practical and achievable in terms of cost, technology, operational
needs, and time constraints. Before beginning development of the Hospital
Management System, a detailed feasibility study was conducted to determine the
viability of building and deploying the system in a real-world healthcare environment.
The study considered multiple aspects of feasibility to ensure the solution would be
both effective and sustainable.
1. Technical Feasibility
This assesses whether the current technology and tools can support the design,
development, and deployment of the system.
Findings:
The system is developed using Java (Swing), which is well-suited for building
desktop GUI applications.
MySQL was chosen for the backend, which is robust, open-source, and widely
supported.
JDBC was used for seamless integration between Java and MySQL.
All technologies used are freely available, making it ideal for educational and
small-clinic use.
Conclusion: The technical stack is simple, well-documented, and feasible for the target
use case.
2. Operational Feasibility
This checks if the system can be accepted and used by the intended users in a practical
environment.
Findings:
The system offers role-based dashboards for Receptionist, Doctor, and Patient
— making it easy to use without confusion.
User interface is kept simple with proper form validation and field labels.
Operations such as booking, billing, and prescriptions follow real-life hospital
workflows.
Conclusion: The system aligns well with real-world hospital operations and can be
adopted with minimal training.
3. Economic Feasibility
156
This examines whether the system can be developed within an acceptable cost
structure.
Findings:
No expensive licenses or proprietary software was used.
Development tools (NetBeans, MySQL Workbench) are free and open-source.
Hardware requirements are minimal: standard PC or laptop.
Conclusion: The project is economically feasible for both development and deployment
at clinics, small hospitals, or institutions.
4. Schedule Feasibility
This focuses on whether the system can be completed within the planned academic
deadline.
Findings:
The development was completed within the given semester timeframe.
Each module was scheduled in weekly targets and executed accordingly.
Testing and documentation were completed on time.
Conclusion: The project was delivered within the planned academic schedule,
demonstrating effective time management.
5. Legal & Ethical Feasibility (Optional for Academic Projects)
Even though this is a student project, the system adheres to basic data privacy and
access control principles:
Sensitive patient information is protected using authentication.
Access is limited based on user roles (Doctor, Receptionist, Patient).
Passwords are stored securely, and unauthorized access is prevented.
Summary
The feasibility study confirms that the Hospital Management System is:
Technically sound
Operationally practical
Economically affordable
Time-wise achievable
Based on this analysis, the system was found to be fully feasible for academic and real-
world use.
157
FUTURE SCOPE
While the current version of the Hospital Management System (HMS) successfully
meets the basic operational needs of a small- to mid-sized hospital or clinic, there is
significant potential to enhance and extend the system in the future. As technology
continues to evolve, healthcare institutions require more automation, security, and
remote accessibility — all of which present opportunities for future development.
The future scope outlines the features, improvements, and integrations that can be
added to make the system more robust, scalable, and enterprise-ready.
1. Migration to Web-Based or Mobile Platform
Transform the current desktop-based system into a web application or mobile
app using technologies like Spring Boot, Angular, React, or Android.
This will allow doctors and patients to access the system remotely using
browsers or smartphones.
2. Integration with Health APIs and Devices
The system can be enhanced to connect with digital thermometers, ECG
machines, or lab equipment to automatically capture reports.
Integration with government health APIs or insurance services can be added
for faster patient data validation and claims.
3. Advanced Reporting and Analytics
Add a data analytics module to generate:
o Monthly patient visit summaries
o Medicine usage trends
o Revenue graphs and performance metrics
Use tools like JasperReports or Chart.js to visualize data within the system.
4. Enhanced Security and Encryption
Implement two-factor authentication (2FA) for added login security.
Apply end-to-end encryption for sensitive data such as prescriptions and lab
results.
Passwords can be encrypted using bcrypt or PBKDF2 instead of plain hashing.
5. Automated Appointment Reminders
Add a feature that sends automated email or SMS reminders to patients and
doctors before scheduled appointments.
Integrate with APIs like Twilio or SendGrid for this purpose.
6. Multi-User Access with Concurrency Control
158
Upgrade the system to support multiple concurrent users with database
locking or session management to avoid data conflicts during simultaneous
usage.
7. Audit Logs and Activity Tracking
Maintain logs for user actions such as login, logout, data modification, and
deletions.
Helps in tracking activity and improves system accountability.
8. Inventory Auto-Update and Notifications
Automate the inventory system so that medicine stock reduces automatically
when prescriptions are issued.
Notify receptionist or admin when medicine stock is low.
9. Cloud Deployment and Backup
Host the system on cloud platforms (e.g., AWS, Google Cloud) for 24/7
availability.
Add automated daily backups of the database to prevent data loss.
10. Multi-Language Support
Enable language options (Hindi, English, etc.) to make the system usable for non-
English-speaking staff and patients.
159
CONCLUSION
The Hospital Management System (HMS) project marks the successful development
of a robust and efficient desktop application designed to streamline hospital operations
and enhance the quality of healthcare service delivery. This project was undertaken with
the objective of minimizing paperwork, reducing human error, improving record
accessibility, and ensuring proper communication between patients, doctors, and
receptionists.
Throughout the course of this project, each phase of the Software Development Life
Cycle (SDLC) — from requirement gathering and system design to coding, testing, and
deployment — was followed diligently. The system was developed using Java (Swing
GUI) for the front end and MySQL as the backend database, connected using JDBC. All
core hospital functionalities, such as patient registration, doctor-patient
appointments, medical prescriptions, lab report uploads, inventory management,
and billing, have been successfully implemented and tested.
Special emphasis was placed on security, validation checks, and role-based access
control to ensure that the system is secure and reliable for daily hospital use. The
implementation also considered user-friendliness, providing intuitive interfaces for
patients, doctors, and reception staff.
This project not only helped us strengthen our technical and problem-solving skills but
also gave us valuable insight into how technology can be effectively applied in critical
sectors like healthcare. The feedback received from test users validated the practical
value of the system, and it is now fully prepared for use in real-world scenarios or future
deployment in clinics and healthcare centers.
Although the current version of the application meets the fundamental operational
requirements, the system is designed to be scalable and extendable. It offers great
future scope, including migrating to web or mobile platforms, adding advanced
analytics, and integrating with medical APIs or IoT devices.
160
REFERENCES
The development of this project involved consulting various online and offline resources
to gather technical information, resolve implementation challenges, and align the
system with real-world hospital workflows. Below is a list of the key references and
sources used throughout the design, development, and documentation phases of the
Hospital Management System:
Books & Academic Material
1. “Database System Concepts” by Abraham Silberschatz, Henry F. Korth, and S.
Sudarshan
→ For understanding database normalization, keys, and ER modeling.
2. “Object-Oriented Programming in Java” by E. Balagurusamy
→ For understanding core Java concepts and GUI development.
Online Resources
3. Oracle Java Documentation – https://docs.oracle.com/javase/
→ Official Java documentation used to implement Swing components, exception
handling, and JDBC.
4. MySQL Documentation – https://dev.mysql.com/doc/
→ Reference for MySQL syntax, table design, data types, and constraints.
5. GeeksforGeeks – https://www.geeksforgeeks.org
→ Used for examples related to Java Swing UI, JDBC connectivity, and form
validation.
6. Stack Overflow – https://stackoverflow.com
→ Helpful for resolving technical coding errors and debugging complex logic.
7. W3Schools – https://www.w3schools.com
→ For understanding basic SQL queries and database interaction patterns.
Industry Practices
8. Real hospital workflow understanding was based on observations, discussions
with medical staff, and reviewing digital practices in hospital systems.
9. Academic guidance was taken from college faculty and project guides during
analysis, system design, and evaluation.
Additional Resources
10. YouTube Tutorials on:
Java Swing GUI Design
MySQL Setup and JDBC Integration
Creating DFDs and ER Diagrams using tools like Draw.io and Creately
161