diff --git a/SmartClinicManagementSystem/app/build.gradle b/SmartClinicManagementSystem/app/build.gradle new file mode 100644 index 0000000..ce04590 --- /dev/null +++ b/SmartClinicManagementSystem/app/build.gradle @@ -0,0 +1,40 @@ +import org.springframework.boot.gradle.plugin.SpringBootPlugin + +apply plugin: 'java' +apply plugin: 'org.springframework.boot' + +version = "1.0.0" + +java { + sourceCompatibility = JavaVersion.VERSION_21 + targetCompatibility = JavaVersion.VERSION_21 +} + +repositories { + mavenCentral() +} + +dependencies { + implementation platform(SpringBootPlugin.BOM_COORDINATES) + implementation 'org.springframework.boot:spring-boot-starter-thymeleaf' + implementation 'org.springframework.boot:spring-boot-starter-data-jpa' + implementation 'org.springframework.boot:spring-boot-starter-data-mongodb' + implementation 'org.springframework.boot:spring-boot-starter-web' + implementation 'org.springframework.boot:spring-boot-starter-validation' + implementation 'io.jsonwebtoken:jjwt-api:0.12.6' + + runtimeOnly 'io.jsonwebtoken:jjwt-impl:0.12.6' + runtimeOnly 'org.springframework.boot:spring-boot-devtools' + runtimeOnly 'com.mysql:mysql-connector-j' + runtimeOnly 'io.jsonwebtoken:jjwt-jackson:0.12.6' + + testImplementation "org.junit.jupiter:junit-jupiter-api:${junitVersion}" + testImplementation "org.junit.jupiter:junit-jupiter-params:${junitVersion}" + testImplementation 'org.springframework.boot:spring-boot-starter-test' + + testRuntimeOnly "org.junit.jupiter:junit-jupiter-engine:${junitVersion}" +} + +test { + useJUnitPlatform() +} \ No newline at end of file diff --git a/SmartClinicManagementSystem/app/src/main/java/com/project/back_end/BackEndApplication.java b/SmartClinicManagementSystem/app/src/main/java/com/project/back_end/BackEndApplication.java new file mode 100644 index 0000000..e4b8139 --- /dev/null +++ b/SmartClinicManagementSystem/app/src/main/java/com/project/back_end/BackEndApplication.java @@ -0,0 +1,15 @@ +package com.project.back_end; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.context.annotation.ComponentScan; + +@SpringBootApplication +@ComponentScan("com.project.back_end") +public class BackEndApplication { + + public static void main(String[] args) { + SpringApplication.run(BackEndApplication.class, args); + } + +} diff --git a/SmartClinicManagementSystem/app/src/main/java/com/project/back_end/DTO/AppointmentDTO.java b/SmartClinicManagementSystem/app/src/main/java/com/project/back_end/DTO/AppointmentDTO.java new file mode 100644 index 0000000..cdf2417 --- /dev/null +++ b/SmartClinicManagementSystem/app/src/main/java/com/project/back_end/DTO/AppointmentDTO.java @@ -0,0 +1,90 @@ +package com.project.back_end.DTO; + +public class AppointmentDTO { +// 1. 'id' field: +// - Type: private Long +// - Description: +// - Represents the unique identifier for the appointment. +// - This is the primary key for identifying the appointment in the system. + +// 2. 'doctorId' field: +// - Type: private Long +// - Description: +// - Represents the ID of the doctor associated with the appointment. +// - This is a simplified field, capturing only the ID of the doctor (not the full Doctor object). + +// 3. 'doctorName' field: +// - Type: private String +// - Description: +// - Represents the name of the doctor associated with the appointment. +// - This is a simplified field for displaying the doctor's name. + +// 4. 'patientId' field: +// - Type: private Long +// - Description: +// - Represents the ID of the patient associated with the appointment. +// - This is a simplified field, capturing only the ID of the patient (not the full Patient object). + +// 5. 'patientName' field: +// - Type: private String +// - Description: +// - Represents the name of the patient associated with the appointment. +// - This is a simplified field for displaying the patient's name. + +// 6. 'patientEmail' field: +// - Type: private String +// - Description: +// - Represents the email of the patient associated with the appointment. +// - This is a simplified field for displaying the patient's email. + +// 7. 'patientPhone' field: +// - Type: private String +// - Description: +// - Represents the phone number of the patient associated with the appointment. +// - This is a simplified field for displaying the patient's phone number. + +// 8. 'patientAddress' field: +// - Type: private String +// - Description: +// - Represents the address of the patient associated with the appointment. +// - This is a simplified field for displaying the patient's address. + +// 9. 'appointmentTime' field: +// - Type: private LocalDateTime +// - Description: +// - Represents the scheduled date and time of the appointment. +// - The time when the appointment is supposed to happen, stored as a LocalDateTime object. + +// 10. 'status' field: +// - Type: private int +// - Description: +// - Represents the status of the appointment. +// - Status can indicate if the appointment is "Scheduled:0", "Completed:1", or other statuses (e.g., "Canceled") as needed. + +// 11. 'appointmentDate' field (Custom Getter): +// - Type: private LocalDate +// - Description: +// - A derived field representing only the date part of the appointment (without the time). +// - Extracted from the 'appointmentTime' field. + +// 12. 'appointmentTimeOnly' field (Custom Getter): +// - Type: private LocalTime +// - Description: +// - A derived field representing only the time part of the appointment (without the date). +// - Extracted from the 'appointmentTime' field. + +// 13. 'endTime' field (Custom Getter): +// - Type: private LocalDateTime +// - Description: +// - A derived field representing the end time of the appointment. +// - Calculated by adding 1 hour to the 'appointmentTime' field. + +// 14. Constructor: +// - The constructor accepts all the relevant fields for the AppointmentDTO, including simplified fields for the doctor and patient (ID, name, etc.). +// - It also calculates custom fields: 'appointmentDate', 'appointmentTimeOnly', and 'endTime' based on the 'appointmentTime' field. + +// 15. Getters: +// - Standard getter methods are provided for all fields: id, doctorId, doctorName, patientId, patientName, patientEmail, patientPhone, patientAddress, appointmentTime, status, appointmentDate, appointmentTimeOnly, and endTime. +// - These methods allow access to the values of the fields in the AppointmentDTO object. + +} diff --git a/SmartClinicManagementSystem/app/src/main/java/com/project/back_end/DTO/Login.java b/SmartClinicManagementSystem/app/src/main/java/com/project/back_end/DTO/Login.java new file mode 100644 index 0000000..e15babf --- /dev/null +++ b/SmartClinicManagementSystem/app/src/main/java/com/project/back_end/DTO/Login.java @@ -0,0 +1,30 @@ +package com.project.back_end.DTO; + +public class Login { + +// 1. 'email' field: +// - Type: private String +// - Description: +// - Represents the email address used for logging into the system. +// - The email field is expected to contain a valid email address for user authentication purposes. + +// 2. 'password' field: +// - Type: private String +// - Description: +// - Represents the password associated with the email address. +// - The password field is used for verifying the user's identity during login. +// - It is generally hashed before being stored and compared during authentication. + +// 3. Constructor: +// - No explicit constructor is defined for this class, as it relies on the default constructor provided by Java. +// - This class can be initialized with setters or directly via reflection, as per the application's needs. + +// 4. Getters and Setters: +// - Standard getter and setter methods are provided for both 'email' and 'password' fields. +// - The 'getEmail()' method allows access to the email value. +// - The 'setEmail(String email)' method sets the email value. +// - The 'getPassword()' method allows access to the password value. +// - The 'setPassword(String password)' method sets the password value. + + +} diff --git a/SmartClinicManagementSystem/app/src/main/java/com/project/back_end/config/WebConfig.java b/SmartClinicManagementSystem/app/src/main/java/com/project/back_end/config/WebConfig.java new file mode 100644 index 0000000..776c980 --- /dev/null +++ b/SmartClinicManagementSystem/app/src/main/java/com/project/back_end/config/WebConfig.java @@ -0,0 +1,21 @@ +package com.project.back_end.config; + + +import org.springframework.context.annotation.Configuration; +import org.springframework.lang.NonNull; + +import org.springframework.web.servlet.config.annotation.CorsRegistry; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; + +@Configuration +public class WebConfig implements WebMvcConfigurer { + + @Override + public void addCorsMappings(@NonNull CorsRegistry registry) { + // Allow CORS for all endpoints + registry.addMapping("/**") + .allowedOrigins("*") // Add your frontend URL here + .allowedMethods("GET", "POST", "PUT", "DELETE") // Specify allowed methods + .allowedHeaders("*"); // You can restrict headers if needed + } +} diff --git a/SmartClinicManagementSystem/app/src/main/java/com/project/back_end/controllers/AdminController.java b/SmartClinicManagementSystem/app/src/main/java/com/project/back_end/controllers/AdminController.java new file mode 100644 index 0000000..d63ba40 --- /dev/null +++ b/SmartClinicManagementSystem/app/src/main/java/com/project/back_end/controllers/AdminController.java @@ -0,0 +1,27 @@ + +package com.project.back_end.controllers; + +public class AdminController { + +// 1. Set Up the Controller Class: +// - Annotate the class with `@RestController` to indicate that it's a REST controller, used to handle web requests and return JSON responses. +// - Use `@RequestMapping("${api.path}admin")` to define a base path for all endpoints in this controller. +// - This allows the use of an external property (`api.path`) for flexible configuration of endpoint paths. + + +// 2. Autowire Service Dependency: +// - Use constructor injection to autowire the `Service` class. +// - The service handles core logic related to admin validation and token checking. +// - This promotes cleaner code and separation of concerns between the controller and business logic layer. + + +// 3. Define the `adminLogin` Method: +// - Handles HTTP POST requests for admin login functionality. +// - Accepts an `Admin` object in the request body, which contains login credentials. +// - Delegates authentication logic to the `validateAdmin` method in the service layer. +// - Returns a `ResponseEntity` with a `Map` containing login status or messages. + + + +} + diff --git a/SmartClinicManagementSystem/app/src/main/java/com/project/back_end/controllers/AppointmentController.java b/SmartClinicManagementSystem/app/src/main/java/com/project/back_end/controllers/AppointmentController.java new file mode 100644 index 0000000..4706eee --- /dev/null +++ b/SmartClinicManagementSystem/app/src/main/java/com/project/back_end/controllers/AppointmentController.java @@ -0,0 +1,48 @@ +package com.project.back_end.controllers; + + +public class AppointmentController { + +// 1. Set Up the Controller Class: +// - Annotate the class with `@RestController` to define it as a REST API controller. +// - Use `@RequestMapping("/appointments")` to set a base path for all appointment-related endpoints. +// - This centralizes all routes that deal with booking, updating, retrieving, and canceling appointments. + + +// 2. Autowire Dependencies: +// - Inject `AppointmentService` for handling the business logic specific to appointments. +// - Inject the general `Service` class, which provides shared functionality like token validation and appointment checks. + + +// 3. Define the `getAppointments` Method: +// - Handles HTTP GET requests to fetch appointments based on date and patient name. +// - Takes the appointment date, patient name, and token as path variables. +// - First validates the token for role `"doctor"` using the `Service`. +// - If the token is valid, returns appointments for the given patient on the specified date. +// - If the token is invalid or expired, responds with the appropriate message and status code. + + +// 4. Define the `bookAppointment` Method: +// - Handles HTTP POST requests to create a new appointment. +// - Accepts a validated `Appointment` object in the request body and a token as a path variable. +// - Validates the token for the `"patient"` role. +// - Uses service logic to validate the appointment data (e.g., check for doctor availability and time conflicts). +// - Returns success if booked, or appropriate error messages if the doctor ID is invalid or the slot is already taken. + + +// 5. Define the `updateAppointment` Method: +// - Handles HTTP PUT requests to modify an existing appointment. +// - Accepts a validated `Appointment` object and a token as input. +// - Validates the token for `"patient"` role. +// - Delegates the update logic to the `AppointmentService`. +// - Returns an appropriate success or failure response based on the update result. + + +// 6. Define the `cancelAppointment` Method: +// - Handles HTTP DELETE requests to cancel a specific appointment. +// - Accepts the appointment ID and a token as path variables. +// - Validates the token for `"patient"` role to ensure the user is authorized to cancel the appointment. +// - Calls `AppointmentService` to handle the cancellation process and returns the result. + + +} diff --git a/SmartClinicManagementSystem/app/src/main/java/com/project/back_end/controllers/DoctorController.java b/SmartClinicManagementSystem/app/src/main/java/com/project/back_end/controllers/DoctorController.java new file mode 100644 index 0000000..1c76fe5 --- /dev/null +++ b/SmartClinicManagementSystem/app/src/main/java/com/project/back_end/controllers/DoctorController.java @@ -0,0 +1,61 @@ +package com.project.back_end.controllers; + + +public class DoctorController { + +// 1. Set Up the Controller Class: +// - Annotate the class with `@RestController` to define it as a REST controller that serves JSON responses. +// - Use `@RequestMapping("${api.path}doctor")` to prefix all endpoints with a configurable API path followed by "doctor". +// - This class manages doctor-related functionalities such as registration, login, updates, and availability. + + +// 2. Autowire Dependencies: +// - Inject `DoctorService` for handling the core logic related to doctors (e.g., CRUD operations, authentication). +// - Inject the shared `Service` class for general-purpose features like token validation and filtering. + + +// 3. Define the `getDoctorAvailability` Method: +// - Handles HTTP GET requests to check a specific doctor’s availability on a given date. +// - Requires `user` type, `doctorId`, `date`, and `token` as path variables. +// - First validates the token against the user type. +// - If the token is invalid, returns an error response; otherwise, returns the availability status for the doctor. + + +// 4. Define the `getDoctor` Method: +// - Handles HTTP GET requests to retrieve a list of all doctors. +// - Returns the list within a response map under the key `"doctors"` with HTTP 200 OK status. + + +// 5. Define the `saveDoctor` Method: +// - Handles HTTP POST requests to register a new doctor. +// - Accepts a validated `Doctor` object in the request body and a token for authorization. +// - Validates the token for the `"admin"` role before proceeding. +// - If the doctor already exists, returns a conflict response; otherwise, adds the doctor and returns a success message. + + +// 6. Define the `doctorLogin` Method: +// - Handles HTTP POST requests for doctor login. +// - Accepts a validated `Login` DTO containing credentials. +// - Delegates authentication to the `DoctorService` and returns login status and token information. + + +// 7. Define the `updateDoctor` Method: +// - Handles HTTP PUT requests to update an existing doctor's information. +// - Accepts a validated `Doctor` object and a token for authorization. +// - Token must belong to an `"admin"`. +// - If the doctor exists, updates the record and returns success; otherwise, returns not found or error messages. + + +// 8. Define the `deleteDoctor` Method: +// - Handles HTTP DELETE requests to remove a doctor by ID. +// - Requires both doctor ID and an admin token as path variables. +// - If the doctor exists, deletes the record and returns a success message; otherwise, responds with a not found or error message. + + +// 9. Define the `filter` Method: +// - Handles HTTP GET requests to filter doctors based on name, time, and specialty. +// - Accepts `name`, `time`, and `speciality` as path variables. +// - Calls the shared `Service` to perform filtering logic and returns matching doctors in the response. + + +} diff --git a/SmartClinicManagementSystem/app/src/main/java/com/project/back_end/controllers/PatientController.java b/SmartClinicManagementSystem/app/src/main/java/com/project/back_end/controllers/PatientController.java new file mode 100644 index 0000000..9cbba5f --- /dev/null +++ b/SmartClinicManagementSystem/app/src/main/java/com/project/back_end/controllers/PatientController.java @@ -0,0 +1,52 @@ +package com.project.back_end.controllers; + +public class PatientController { + +// 1. Set Up the Controller Class: +// - Annotate the class with `@RestController` to define it as a REST API controller for patient-related operations. +// - Use `@RequestMapping("/patient")` to prefix all endpoints with `/patient`, grouping all patient functionalities under a common route. + + +// 2. Autowire Dependencies: +// - Inject `PatientService` to handle patient-specific logic such as creation, retrieval, and appointments. +// - Inject the shared `Service` class for tasks like token validation and login authentication. + + +// 3. Define the `getPatient` Method: +// - Handles HTTP GET requests to retrieve patient details using a token. +// - Validates the token for the `"patient"` role using the shared service. +// - If the token is valid, returns patient information; otherwise, returns an appropriate error message. + + +// 4. Define the `createPatient` Method: +// - Handles HTTP POST requests for patient registration. +// - Accepts a validated `Patient` object in the request body. +// - First checks if the patient already exists using the shared service. +// - If validation passes, attempts to create the patient and returns success or error messages based on the outcome. + + +// 5. Define the `login` Method: +// - Handles HTTP POST requests for patient login. +// - Accepts a `Login` DTO containing email/username and password. +// - Delegates authentication to the `validatePatientLogin` method in the shared service. +// - Returns a response with a token or an error message depending on login success. + + +// 6. Define the `getPatientAppointment` Method: +// - Handles HTTP GET requests to fetch appointment details for a specific patient. +// - Requires the patient ID, token, and user role as path variables. +// - Validates the token using the shared service. +// - If valid, retrieves the patient's appointment data from `PatientService`; otherwise, returns a validation error. + + +// 7. Define the `filterPatientAppointment` Method: +// - Handles HTTP GET requests to filter a patient's appointments based on specific conditions. +// - Accepts filtering parameters: `condition`, `name`, and a token. +// - Token must be valid for a `"patient"` role. +// - If valid, delegates filtering logic to the shared service and returns the filtered result. + + + +} + + diff --git a/SmartClinicManagementSystem/app/src/main/java/com/project/back_end/controllers/PrescriptionController.java b/SmartClinicManagementSystem/app/src/main/java/com/project/back_end/controllers/PrescriptionController.java new file mode 100644 index 0000000..8d8b94b --- /dev/null +++ b/SmartClinicManagementSystem/app/src/main/java/com/project/back_end/controllers/PrescriptionController.java @@ -0,0 +1,33 @@ +package com.project.back_end.controllers; + +public class PrescriptionController { + +// 1. Set Up the Controller Class: +// - Annotate the class with `@RestController` to define it as a REST API controller. +// - Use `@RequestMapping("${api.path}prescription")` to set the base path for all prescription-related endpoints. +// - This controller manages creating and retrieving prescriptions tied to appointments. + + +// 2. Autowire Dependencies: +// - Inject `PrescriptionService` to handle logic related to saving and fetching prescriptions. +// - Inject the shared `Service` class for token validation and role-based access control. +// - Inject `AppointmentService` to update appointment status after a prescription is issued. + + +// 3. Define the `savePrescription` Method: +// - Handles HTTP POST requests to save a new prescription for a given appointment. +// - Accepts a validated `Prescription` object in the request body and a doctor’s token as a path variable. +// - Validates the token for the `"doctor"` role. +// - If the token is valid, updates the status of the corresponding appointment to reflect that a prescription has been added. +// - Delegates the saving logic to `PrescriptionService` and returns a response indicating success or failure. + + +// 4. Define the `getPrescription` Method: +// - Handles HTTP GET requests to retrieve a prescription by its associated appointment ID. +// - Accepts the appointment ID and a doctor’s token as path variables. +// - Validates the token for the `"doctor"` role using the shared service. +// - If the token is valid, fetches the prescription using the `PrescriptionService`. +// - Returns the prescription details or an appropriate error message if validation fails. + + +} diff --git a/SmartClinicManagementSystem/app/src/main/java/com/project/back_end/controllers/ValidationFailed.java b/SmartClinicManagementSystem/app/src/main/java/com/project/back_end/controllers/ValidationFailed.java new file mode 100644 index 0000000..dd7161b --- /dev/null +++ b/SmartClinicManagementSystem/app/src/main/java/com/project/back_end/controllers/ValidationFailed.java @@ -0,0 +1,28 @@ +package com.project.back_end.controllers; + +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.MethodArgumentNotValidException; +import org.springframework.web.bind.annotation.ExceptionHandler; +import org.springframework.web.bind.annotation.RestControllerAdvice; +import org.springframework.validation.FieldError; + +import java.util.HashMap; +import java.util.Map; + +@RestControllerAdvice +public class ValidationFailed { + + @ExceptionHandler(MethodArgumentNotValidException.class) + public ResponseEntity> handleValidationException(MethodArgumentNotValidException ex) { + Map errors = new HashMap<>(); + + // Iterate through all the validation errors + for (FieldError error : ex.getBindingResult().getFieldErrors()) { + String errorMessage = error.getDefaultMessage(); + errors.put("message", "" + errorMessage); + } + + return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(errors); + } +} \ No newline at end of file diff --git a/SmartClinicManagementSystem/app/src/main/java/com/project/back_end/models/Admin.java b/SmartClinicManagementSystem/app/src/main/java/com/project/back_end/models/Admin.java new file mode 100644 index 0000000..58d9862 --- /dev/null +++ b/SmartClinicManagementSystem/app/src/main/java/com/project/back_end/models/Admin.java @@ -0,0 +1,37 @@ +package com.project.back_end.models; + +public class Admin { + +// @Entity annotation: +// - Marks the class as a JPA entity, which means it represents a table in the database. +// - It is required for persistence frameworks like Hibernate to map the class to a database table. + +// 1. 'id' field: +// - Type: private Long +// - Description: +// - Represents the unique identifier for the Admin entity. +// - This field is auto-generated by the database using @GeneratedValue with strategy GenerationType.IDENTITY. +// - It is the primary key of the entity, identified by @Id annotation. + +// 2. 'username' field: +// - Type: private String +// - Description: +// - Represents the username of the admin. +// - Used to log into the system. +// - @NotNull validation ensures that this field cannot be null when creating or updating an Admin. + +// 3. 'password' field: +// - Type: private String +// - Description: +// - Represents the password of the admin for authentication. +// - The field is marked with @JsonProperty(access = JsonProperty.Access.WRITE_ONLY) to prevent the password from being exposed in JSON responses. +// - @NotNull validation ensures the password cannot be null when creating or updating an Admin. + +// 4. Constructor(s): +// - A no-argument constructor is implicitly provided, required by JPA for entity creation. +// - A parameterized constructor can be added as needed. + +// 5. Getters and Setters: +// - Standard getter and setter methods are provided for accessing and modifying the fields. + +} diff --git a/SmartClinicManagementSystem/app/src/main/java/com/project/back_end/models/Appointment.java b/SmartClinicManagementSystem/app/src/main/java/com/project/back_end/models/Appointment.java new file mode 100644 index 0000000..b26be0d --- /dev/null +++ b/SmartClinicManagementSystem/app/src/main/java/com/project/back_end/models/Appointment.java @@ -0,0 +1,72 @@ +package com.project.back_end.models; + +public class Appointment { + + // @Entity annotation: +// - Marks the class as a JPA entity, meaning it represents a table in the database. +// - Required for persistence frameworks (e.g., Hibernate) to map the class to a database table. + +// 1. 'id' field: +// - Type: private Long +// - Description: +// - Represents the unique identifier for each appointment. +// - The @Id annotation marks it as the primary key. +// - The @GeneratedValue(strategy = GenerationType.IDENTITY) annotation auto-generates the ID value when a new record is inserted into the database. + +// 2. 'doctor' field: +// - Type: private Doctor +// - Description: +// - Represents the doctor assigned to this appointment. +// - The @ManyToOne annotation defines the relationship, indicating many appointments can be linked to one doctor. +// - The @NotNull annotation ensures that an appointment must be associated with a doctor when created. + +// 3. 'patient' field: +// - Type: private Patient +// - Description: +// - Represents the patient assigned to this appointment. +// - The @ManyToOne annotation defines the relationship, indicating many appointments can be linked to one patient. +// - The @NotNull annotation ensures that an appointment must be associated with a patient when created. + +// 4. 'appointmentTime' field: +// - Type: private LocalDateTime +// - Description: +// - Represents the date and time when the appointment is scheduled to occur. +// - The @Future annotation ensures that the appointment time is always in the future when the appointment is created. +// - It uses LocalDateTime, which includes both the date and time for the appointment. + +// 5. 'status' field: +// - Type: private int +// - Description: +// - Represents the current status of the appointment. It is an integer where: +// - 0 means the appointment is scheduled. +// - 1 means the appointment has been completed. +// - The @NotNull annotation ensures that the status field is not null. + +// 6. 'getEndTime' method: +// - Type: private LocalDateTime +// - Description: +// - This method is a transient field (not persisted in the database). +// - It calculates the end time of the appointment by adding one hour to the start time (appointmentTime). +// - It is used to get an estimated appointment end time for display purposes. + +// 7. 'getAppointmentDate' method: +// - Type: private LocalDate +// - Description: +// - This method extracts only the date part from the appointmentTime field. +// - It returns a LocalDate object representing just the date (without the time) of the scheduled appointment. + +// 8. 'getAppointmentTimeOnly' method: +// - Type: private LocalTime +// - Description: +// - This method extracts only the time part from the appointmentTime field. +// - It returns a LocalTime object representing just the time (without the date) of the scheduled appointment. + +// 9. Constructor(s): +// - A no-argument constructor is implicitly provided by JPA for entity creation. +// - A parameterized constructor can be added as needed to initialize fields. + +// 10. Getters and Setters: +// - Standard getter and setter methods are provided for accessing and modifying the fields: id, doctor, patient, appointmentTime, status, etc. + +} + diff --git a/SmartClinicManagementSystem/app/src/main/java/com/project/back_end/models/Doctor.java b/SmartClinicManagementSystem/app/src/main/java/com/project/back_end/models/Doctor.java new file mode 100644 index 0000000..8cb5d79 --- /dev/null +++ b/SmartClinicManagementSystem/app/src/main/java/com/project/back_end/models/Doctor.java @@ -0,0 +1,65 @@ +package com.project.back_end.models; + +public class Doctor { + +// @Entity annotation: +// - Marks the class as a JPA entity, meaning it represents a table in the database. +// - Required for persistence frameworks (e.g., Hibernate) to map the class to a database table. + +// 1. 'id' field: +// - Type: private Long +// - Description: +// - Represents the unique identifier for each doctor. +// - The @Id annotation marks it as the primary key. +// - The @GeneratedValue(strategy = GenerationType.IDENTITY) annotation auto-generates the ID value when a new record is inserted into the database. + +// 2. 'name' field: +// - Type: private String +// - Description: +// - Represents the doctor's name. +// - The @NotNull annotation ensures that the doctor's name is required. +// - The @Size(min = 3, max = 100) annotation ensures that the name length is between 3 and 100 characters. +// - Provides validation for correct input and user experience. + + +// 3. 'specialty' field: +// - Type: private String +// - Description: +// - Represents the medical specialty of the doctor. +// - The @NotNull annotation ensures that a specialty must be provided. +// - The @Size(min = 3, max = 50) annotation ensures that the specialty name is between 3 and 50 characters long. + +// 4. 'email' field: +// - Type: private String +// - Description: +// - Represents the doctor's email address. +// - The @NotNull annotation ensures that an email address is required. +// - The @Email annotation validates that the email address follows a valid email format (e.g., doctor@example.com). + +// 5. 'password' field: +// - Type: private String +// - Description: +// - Represents the doctor's password for login authentication. +// - The @NotNull annotation ensures that a password must be provided. +// - The @Size(min = 6) annotation ensures that the password must be at least 6 characters long. +// - The @JsonProperty(access = JsonProperty.Access.WRITE_ONLY) annotation ensures that the password is not serialized in the response (hidden from the frontend). + +// 6. 'phone' field: +// - Type: private String +// - Description: +// - Represents the doctor's phone number. +// - The @NotNull annotation ensures that a phone number must be provided. +// - The @Pattern(regexp = "^[0-9]{10}$") annotation validates that the phone number must be exactly 10 digits long. + +// 7. 'availableTimes' field: +// - Type: private List +// - Description: +// - Represents the available times for the doctor in a list of time slots. +// - Each time slot is represented as a string (e.g., "09:00-10:00", "10:00-11:00"). +// - The @ElementCollection annotation ensures that the list of time slots is stored as a separate collection in the database. + +// 8. Getters and Setters: +// - Standard getter and setter methods are provided for all fields: id, name, specialty, email, password, phone, and availableTimes. + +} + diff --git a/SmartClinicManagementSystem/app/src/main/java/com/project/back_end/models/Patient.java b/SmartClinicManagementSystem/app/src/main/java/com/project/back_end/models/Patient.java new file mode 100644 index 0000000..81b8c23 --- /dev/null +++ b/SmartClinicManagementSystem/app/src/main/java/com/project/back_end/models/Patient.java @@ -0,0 +1,59 @@ +package com.project.back_end.models; + +public class Patient { +// @Entity annotation: +// - Marks the class as a JPA entity, meaning it represents a table in the database. +// - Required for persistence frameworks (e.g., Hibernate) to map the class to a database table. + +// 1. 'id' field: +// - Type: private Long +// - Description: +// - Represents the unique identifier for each patient. +// - The @Id annotation marks it as the primary key. +// - The @GeneratedValue(strategy = GenerationType.IDENTITY) annotation auto-generates the ID value when a new record is inserted into the database. + +// 2. 'name' field: +// - Type: private String +// - Description: +// - Represents the patient's full name. +// - The @NotNull annotation ensures that the patient's name is required. +// - The @Size(min = 3, max = 100) annotation ensures that the name length is between 3 and 100 characters. +// - Provides validation for correct input and user experience. + + +// 3. 'email' field: +// - Type: private String +// - Description: +// - Represents the patient's email address. +// - The @NotNull annotation ensures that an email address must be provided. +// - The @Email annotation validates that the email address follows a valid email format (e.g., patient@example.com). + +// 4. 'password' field: +// - Type: private String +// - Description: +// - Represents the patient's password for login authentication. +// - The @NotNull annotation ensures that a password must be provided. +// - The @Size(min = 6) annotation ensures that the password must be at least 6 characters long. + +// 5. 'phone' field: +// - Type: private String +// - Description: +// - Represents the patient's phone number. +// - The @NotNull annotation ensures that a phone number must be provided. +// - The @Pattern(regexp = "^[0-9]{10}$") annotation validates that the phone number must be exactly 10 digits long. + +// 6. 'address' field: +// - Type: private String +// - Description: +// - Represents the patient's address. +// - The @NotNull annotation ensures that the address must be provided. +// - The @Size(max = 255) annotation ensures that the address does not exceed 255 characters in length, providing validation for the address input. + + +// 7. Getters and Setters: +// - Standard getter and setter methods are provided for all fields: id, name, email, password, phone, and address. +// - These methods allow access and modification of the fields of the Patient class. + + + +} diff --git a/SmartClinicManagementSystem/app/src/main/java/com/project/back_end/models/Prescription.java b/SmartClinicManagementSystem/app/src/main/java/com/project/back_end/models/Prescription.java new file mode 100644 index 0000000..89bc1a5 --- /dev/null +++ b/SmartClinicManagementSystem/app/src/main/java/com/project/back_end/models/Prescription.java @@ -0,0 +1,56 @@ +package com.project.back_end.models; + +public class Prescription { + + // @Document annotation: +// - Marks the class as a MongoDB document (a collection in MongoDB). +// - The collection name is specified as "prescriptions" to map this class to the "prescriptions" collection in MongoDB. + +// 1. 'id' field: +// - Type: private String +// - Description: +// - Represents the unique identifier for each prescription. +// - The @Id annotation marks it as the primary key in the MongoDB collection. +// - The id is of type String, which is commonly used for MongoDB's ObjectId as it stores IDs as strings in the database. + +// 2. 'patientName' field: +// - Type: private String +// - Description: +// - Represents the name of the patient receiving the prescription. +// - The @NotNull annotation ensures that the patient name is required. +// - The @Size(min = 3, max = 100) annotation ensures that the name length is between 3 and 100 characters, ensuring a reasonable name length. + +// 3. 'appointmentId' field: +// - Type: private Long +// - Description: +// - Represents the ID of the associated appointment where the prescription was given. +// - The @NotNull annotation ensures that the appointment ID is required for the prescription. + +// 4. 'medication' field: +// - Type: private String +// - Description: +// - Represents the medication prescribed to the patient. +// - The @NotNull annotation ensures that the medication name is required. +// - The @Size(min = 3, max = 100) annotation ensures that the medication name is between 3 and 100 characters, which ensures meaningful medication names. + +// 5. 'dosage' field: +// - Type: private String +// - Description: +// - Represents the dosage information for the prescribed medication. +// - The @NotNull annotation ensures that the dosage information is provided. + +// 6. 'doctorNotes' field: +// - Type: private String +// - Description: +// - Represents any additional notes or instructions from the doctor regarding the prescription. +// - The @Size(max = 200) annotation ensures that the doctor's notes do not exceed 200 characters, providing a reasonable limit for additional notes. + +// 7. Constructors: +// - The class includes a no-argument constructor (default constructor) and a parameterized constructor that initializes the fields: patientName, medication, dosage, doctorNotes, and appointmentId. + +// 8. Getters and Setters: +// - Standard getter and setter methods are provided for all fields: id, patientName, medication, dosage, doctorNotes, and appointmentId. +// - These methods allow access and modification of the fields of the Prescription class. + + +} diff --git a/SmartClinicManagementSystem/app/src/main/java/com/project/back_end/mvc/DashboardController.java b/SmartClinicManagementSystem/app/src/main/java/com/project/back_end/mvc/DashboardController.java new file mode 100644 index 0000000..b8cd357 --- /dev/null +++ b/SmartClinicManagementSystem/app/src/main/java/com/project/back_end/mvc/DashboardController.java @@ -0,0 +1,30 @@ +package com.project.back_end.mvc; + +public class DashboardController { + +// 1. Set Up the MVC Controller Class: +// - Annotate the class with `@Controller` to indicate that it serves as an MVC controller returning view names (not JSON). +// - This class handles routing to admin and doctor dashboard pages based on token validation. + + +// 2. Autowire the Shared Service: +// - Inject the common `Service` class, which provides the token validation logic used to authorize access to dashboards. + + +// 3. Define the `adminDashboard` Method: +// - Handles HTTP GET requests to `/adminDashboard/{token}`. +// - Accepts an admin's token as a path variable. +// - Validates the token using the shared service for the `"admin"` role. +// - If the token is valid (i.e., no errors returned), forwards the user to the `"admin/adminDashboard"` view. +// - If invalid, redirects to the root URL, likely the login or home page. + + +// 4. Define the `doctorDashboard` Method: +// - Handles HTTP GET requests to `/doctorDashboard/{token}`. +// - Accepts a doctor's token as a path variable. +// - Validates the token using the shared service for the `"doctor"` role. +// - If the token is valid, forwards the user to the `"doctor/doctorDashboard"` view. +// - If the token is invalid, redirects to the root URL. + + +} diff --git a/SmartClinicManagementSystem/app/src/main/java/com/project/back_end/repo/AdminRepository.java b/SmartClinicManagementSystem/app/src/main/java/com/project/back_end/repo/AdminRepository.java new file mode 100644 index 0000000..c9e7f5c --- /dev/null +++ b/SmartClinicManagementSystem/app/src/main/java/com/project/back_end/repo/AdminRepository.java @@ -0,0 +1,30 @@ +package com.project.back_end.repo; + +public interface AdminRepository { + + // 1. Extend JpaRepository: +// - The repository extends JpaRepository, which gives it basic CRUD functionality. +// - The methods such as save, delete, update, and find are inherited without the need for explicit implementation. +// - JpaRepository also includes pagination and sorting features. + +// Example: public interface AdminRepository extends JpaRepository {} + +// 2. Custom Query Method: +// - **findByUsername**: +// - This method allows you to find an Admin by their username. +// - Return type: Admin +// - Parameter: String username +// - It will return an Admin entity that matches the provided username. +// - If no Admin is found with the given username, it returns null. + +// Example: public Admin findByUsername(String username); + +// 3. Add @Repository annotation: +// - The @Repository annotation marks this interface as a Spring Data JPA repository. +// - While it is technically optional (since JpaRepository is a part of Spring Data), it's good practice to include it for clarity. +// - Spring Data JPA automatically implements the repository, providing the necessary CRUD functionality. + +// Example: @Repository +// public interface AdminRepository extends JpaRepository { ... } + +} diff --git a/SmartClinicManagementSystem/app/src/main/java/com/project/back_end/repo/AppointmentRepository.java b/SmartClinicManagementSystem/app/src/main/java/com/project/back_end/repo/AppointmentRepository.java new file mode 100644 index 0000000..f17c8c8 --- /dev/null +++ b/SmartClinicManagementSystem/app/src/main/java/com/project/back_end/repo/AppointmentRepository.java @@ -0,0 +1,66 @@ +package com.project.back_end.repo; + +public interface AppointmentRepository { + + // 1. Extend JpaRepository: +// - The repository extends JpaRepository, which gives it basic CRUD functionality. +// - The methods such as save, delete, update, and find are inherited without the need for explicit implementation. +// - JpaRepository also includes pagination and sorting features. + +// Example: public interface AppointmentRepository extends JpaRepository {} + +// 2. Custom Query Methods: + +// - **findByDoctorIdAndAppointmentTimeBetween**: +// - This method retrieves a list of appointments for a specific doctor within a given time range. +// - The doctor’s available times are eagerly fetched to avoid lazy loading. +// - Return type: List +// - Parameters: Long doctorId, LocalDateTime start, LocalDateTime end +// - It uses a LEFT JOIN to fetch the doctor’s available times along with the appointments. + +// - **findByDoctorIdAndPatient_NameContainingIgnoreCaseAndAppointmentTimeBetween**: +// - This method retrieves appointments for a specific doctor and patient name (ignoring case) within a given time range. +// - It performs a LEFT JOIN to fetch both the doctor and patient details along with the appointment times. +// - Return type: List +// - Parameters: Long doctorId, String patientName, LocalDateTime start, LocalDateTime end + +// - **deleteAllByDoctorId**: +// - This method deletes all appointments associated with a particular doctor. +// - It is marked as @Modifying and @Transactional, which makes it a modification query, ensuring that the operation is executed within a transaction. +// - Return type: void +// - Parameters: Long doctorId + +// - **findByPatientId**: +// - This method retrieves all appointments for a specific patient. +// - Return type: List +// - Parameters: Long patientId + +// - **findByPatient_IdAndStatusOrderByAppointmentTimeAsc**: +// - This method retrieves all appointments for a specific patient with a given status, ordered by the appointment time. +// - Return type: List +// - Parameters: Long patientId, int status + +// - **filterByDoctorNameAndPatientId**: +// - This method retrieves appointments based on a doctor’s name (using a LIKE query) and the patient’s ID. +// - Return type: List +// - Parameters: String doctorName, Long patientId + +// - **filterByDoctorNameAndPatientIdAndStatus**: +// - This method retrieves appointments based on a doctor’s name (using a LIKE query), patient’s ID, and a specific appointment status. +// - Return type: List +// - Parameters: String doctorName, Long patientId, int status + +// - **updateStatus**: +// - This method updates the status of a specific appointment based on its ID. +// - Return type: void +// - Parameters: int status, long id + +// 3. @Modifying and @Transactional annotations: +// - The @Modifying annotation is used to indicate that the method performs a modification operation (like DELETE or UPDATE). +// - The @Transactional annotation ensures that the modification is done within a transaction, meaning that if any exception occurs, the changes will be rolled back. + +// 4. @Repository annotation: +// - The @Repository annotation marks this interface as a Spring Data JPA repository. +// - Spring Data JPA automatically implements this repository, providing the necessary CRUD functionality and custom queries defined in the interface. + +} diff --git a/SmartClinicManagementSystem/app/src/main/java/com/project/back_end/repo/DoctorRepository.java b/SmartClinicManagementSystem/app/src/main/java/com/project/back_end/repo/DoctorRepository.java new file mode 100644 index 0000000..e302616 --- /dev/null +++ b/SmartClinicManagementSystem/app/src/main/java/com/project/back_end/repo/DoctorRepository.java @@ -0,0 +1,39 @@ +package com.project.back_end.repo; + +public interface DoctorRepository { + // 1. Extend JpaRepository: +// - The repository extends JpaRepository, which gives it basic CRUD functionality. +// - This allows the repository to perform operations like save, delete, update, and find without needing to implement these methods manually. +// - JpaRepository also includes features like pagination and sorting. + +// Example: public interface DoctorRepository extends JpaRepository {} + +// 2. Custom Query Methods: + +// - **findByEmail**: +// - This method retrieves a Doctor by their email. +// - Return type: Doctor +// - Parameters: String email + +// - **findByNameLike**: +// - This method retrieves a list of Doctors whose name contains the provided search string (case-sensitive). +// - The `CONCAT('%', :name, '%')` is used to create a pattern for partial matching. +// - Return type: List +// - Parameters: String name + +// - **findByNameContainingIgnoreCaseAndSpecialtyIgnoreCase**: +// - This method retrieves a list of Doctors where the name contains the search string (case-insensitive) and the specialty matches exactly (case-insensitive). +// - It combines both fields for a more specific search. +// - Return type: List +// - Parameters: String name, String specialty + +// - **findBySpecialtyIgnoreCase**: +// - This method retrieves a list of Doctors with the specified specialty, ignoring case sensitivity. +// - Return type: List +// - Parameters: String specialty + +// 3. @Repository annotation: +// - The @Repository annotation marks this interface as a Spring Data JPA repository. +// - Spring Data JPA automatically implements this repository, providing the necessary CRUD functionality and custom queries defined in the interface. + +} \ No newline at end of file diff --git a/SmartClinicManagementSystem/app/src/main/java/com/project/back_end/repo/PatientRepository.java b/SmartClinicManagementSystem/app/src/main/java/com/project/back_end/repo/PatientRepository.java new file mode 100644 index 0000000..dbecb5a --- /dev/null +++ b/SmartClinicManagementSystem/app/src/main/java/com/project/back_end/repo/PatientRepository.java @@ -0,0 +1,29 @@ +package com.project.back_end.repo; + +public interface PatientRepository { + // 1. Extend JpaRepository: +// - The repository extends JpaRepository, which provides basic CRUD functionality. +// - This allows the repository to perform operations like save, delete, update, and find without needing to implement these methods manually. +// - JpaRepository also includes features like pagination and sorting. + +// Example: public interface PatientRepository extends JpaRepository {} + +// 2. Custom Query Methods: + +// - **findByEmail**: +// - This method retrieves a Patient by their email address. +// - Return type: Patient +// - Parameters: String email + +// - **findByEmailOrPhone**: +// - This method retrieves a Patient by either their email or phone number, allowing flexibility for the search. +// - Return type: Patient +// - Parameters: String email, String phone + +// 3. @Repository annotation: +// - The @Repository annotation marks this interface as a Spring Data JPA repository. +// - Spring Data JPA automatically implements this repository, providing the necessary CRUD functionality and custom queries defined in the interface. + + +} + diff --git a/SmartClinicManagementSystem/app/src/main/java/com/project/back_end/repo/PrescriptionRepository.java b/SmartClinicManagementSystem/app/src/main/java/com/project/back_end/repo/PrescriptionRepository.java new file mode 100644 index 0000000..0c3345e --- /dev/null +++ b/SmartClinicManagementSystem/app/src/main/java/com/project/back_end/repo/PrescriptionRepository.java @@ -0,0 +1,21 @@ +package com.project.back_end.repo; + +public interface PrescriptionRepository { +// 1. Extend MongoRepository: +// - The repository extends MongoRepository, which provides basic CRUD functionality for MongoDB. +// - This allows the repository to perform operations like save, delete, update, and find without needing to implement these methods manually. +// - MongoRepository is tailored for working with MongoDB, unlike JpaRepository which is used for relational databases. + +// Example: public interface PrescriptionRepository extends MongoRepository {} + +// 2. Custom Query Method: + +// - **findByAppointmentId**: +// - This method retrieves a list of prescriptions associated with a specific appointment. +// - Return type: List +// - Parameters: Long appointmentId +// - MongoRepository automatically derives the query from the method name, in this case, it will find prescriptions by the appointment ID. + + +} + diff --git a/SmartClinicManagementSystem/app/src/main/java/com/project/back_end/services/AppointmentService.java b/SmartClinicManagementSystem/app/src/main/java/com/project/back_end/services/AppointmentService.java new file mode 100644 index 0000000..c43c207 --- /dev/null +++ b/SmartClinicManagementSystem/app/src/main/java/com/project/back_end/services/AppointmentService.java @@ -0,0 +1,45 @@ +package com.project.back_end.services; + +public class AppointmentService { +// 1. **Add @Service Annotation**: +// - To indicate that this class is a service layer class for handling business logic. +// - The `@Service` annotation should be added before the class declaration to mark it as a Spring service component. +// - Instruction: Add `@Service` above the class definition. + +// 2. **Constructor Injection for Dependencies**: +// - The `AppointmentService` class requires several dependencies like `AppointmentRepository`, `Service`, `TokenService`, `PatientRepository`, and `DoctorRepository`. +// - These dependencies should be injected through the constructor. +// - Instruction: Ensure constructor injection is used for proper dependency management in Spring. + +// 3. **Add @Transactional Annotation for Methods that Modify Database**: +// - The methods that modify or update the database should be annotated with `@Transactional` to ensure atomicity and consistency of the operations. +// - Instruction: Add the `@Transactional` annotation above methods that interact with the database, especially those modifying data. + +// 4. **Book Appointment Method**: +// - Responsible for saving the new appointment to the database. +// - If the save operation fails, it returns `0`; otherwise, it returns `1`. +// - Instruction: Ensure that the method handles any exceptions and returns an appropriate result code. + +// 5. **Update Appointment Method**: +// - This method is used to update an existing appointment based on its ID. +// - It validates whether the patient ID matches, checks if the appointment is available for updating, and ensures that the doctor is available at the specified time. +// - If the update is successful, it saves the appointment; otherwise, it returns an appropriate error message. +// - Instruction: Ensure proper validation and error handling is included for appointment updates. + +// 6. **Cancel Appointment Method**: +// - This method cancels an appointment by deleting it from the database. +// - It ensures the patient who owns the appointment is trying to cancel it and handles possible errors. +// - Instruction: Make sure that the method checks for the patient ID match before deleting the appointment. + +// 7. **Get Appointments Method**: +// - This method retrieves a list of appointments for a specific doctor on a particular day, optionally filtered by the patient's name. +// - It uses `@Transactional` to ensure that database operations are consistent and handled in a single transaction. +// - Instruction: Ensure the correct use of transaction boundaries, especially when querying the database for appointments. + +// 8. **Change Status Method**: +// - This method updates the status of an appointment by changing its value in the database. +// - It should be annotated with `@Transactional` to ensure the operation is executed in a single transaction. +// - Instruction: Add `@Transactional` before this method to ensure atomicity when updating appointment status. + + +} diff --git a/SmartClinicManagementSystem/app/src/main/java/com/project/back_end/services/DoctorService.java b/SmartClinicManagementSystem/app/src/main/java/com/project/back_end/services/DoctorService.java new file mode 100644 index 0000000..8c6149b --- /dev/null +++ b/SmartClinicManagementSystem/app/src/main/java/com/project/back_end/services/DoctorService.java @@ -0,0 +1,92 @@ +package com.project.back_end.services; + +public class DoctorService { + +// 1. **Add @Service Annotation**: +// - This class should be annotated with `@Service` to indicate that it is a service layer class. +// - The `@Service` annotation marks this class as a Spring-managed bean for business logic. +// - Instruction: Add `@Service` above the class declaration. + +// 2. **Constructor Injection for Dependencies**: +// - The `DoctorService` class depends on `DoctorRepository`, `AppointmentRepository`, and `TokenService`. +// - These dependencies should be injected via the constructor for proper dependency management. +// - Instruction: Ensure constructor injection is used for injecting dependencies into the service. + +// 3. **Add @Transactional Annotation for Methods that Modify or Fetch Database Data**: +// - Methods like `getDoctorAvailability`, `getDoctors`, `findDoctorByName`, `filterDoctorsBy*` should be annotated with `@Transactional`. +// - The `@Transactional` annotation ensures that database operations are consistent and wrapped in a single transaction. +// - Instruction: Add the `@Transactional` annotation above the methods that perform database operations or queries. + +// 4. **getDoctorAvailability Method**: +// - Retrieves the available time slots for a specific doctor on a particular date and filters out already booked slots. +// - The method fetches all appointments for the doctor on the given date and calculates the availability by comparing against booked slots. +// - Instruction: Ensure that the time slots are properly formatted and the available slots are correctly filtered. + +// 5. **saveDoctor Method**: +// - Used to save a new doctor record in the database after checking if a doctor with the same email already exists. +// - If a doctor with the same email is found, it returns `-1` to indicate conflict; `1` for success, and `0` for internal errors. +// - Instruction: Ensure that the method correctly handles conflicts and exceptions when saving a doctor. + +// 6. **updateDoctor Method**: +// - Updates an existing doctor's details in the database. If the doctor doesn't exist, it returns `-1`. +// - Instruction: Make sure that the doctor exists before attempting to save the updated record and handle any errors properly. + +// 7. **getDoctors Method**: +// - Fetches all doctors from the database. It is marked with `@Transactional` to ensure that the collection is properly loaded. +// - Instruction: Ensure that the collection is eagerly loaded, especially if dealing with lazy-loaded relationships (e.g., available times). + +// 8. **deleteDoctor Method**: +// - Deletes a doctor from the system along with all appointments associated with that doctor. +// - It first checks if the doctor exists. If not, it returns `-1`; otherwise, it deletes the doctor and their appointments. +// - Instruction: Ensure the doctor and their appointments are deleted properly, with error handling for internal issues. + +// 9. **validateDoctor Method**: +// - Validates a doctor's login by checking if the email and password match an existing doctor record. +// - It generates a token for the doctor if the login is successful, otherwise returns an error message. +// - Instruction: Make sure to handle invalid login attempts and password mismatches properly with error responses. + +// 10. **findDoctorByName Method**: +// - Finds doctors based on partial name matching and returns the list of doctors with their available times. +// - This method is annotated with `@Transactional` to ensure that the database query and data retrieval are properly managed within a transaction. +// - Instruction: Ensure that available times are eagerly loaded for the doctors. + + +// 11. **filterDoctorsByNameSpecilityandTime Method**: +// - Filters doctors based on their name, specialty, and availability during a specific time (AM/PM). +// - The method fetches doctors matching the name and specialty criteria, then filters them based on their availability during the specified time period. +// - Instruction: Ensure proper filtering based on both the name and specialty as well as the specified time period. + +// 12. **filterDoctorByTime Method**: +// - Filters a list of doctors based on whether their available times match the specified time period (AM/PM). +// - This method processes a list of doctors and their available times to return those that fit the time criteria. +// - Instruction: Ensure that the time filtering logic correctly handles both AM and PM time slots and edge cases. + + +// 13. **filterDoctorByNameAndTime Method**: +// - Filters doctors based on their name and the specified time period (AM/PM). +// - Fetches doctors based on partial name matching and filters the results to include only those available during the specified time period. +// - Instruction: Ensure that the method correctly filters doctors based on the given name and time of day (AM/PM). + +// 14. **filterDoctorByNameAndSpecility Method**: +// - Filters doctors by name and specialty. +// - It ensures that the resulting list of doctors matches both the name (case-insensitive) and the specified specialty. +// - Instruction: Ensure that both name and specialty are considered when filtering doctors. + + +// 15. **filterDoctorByTimeAndSpecility Method**: +// - Filters doctors based on their specialty and availability during a specific time period (AM/PM). +// - Fetches doctors based on the specified specialty and filters them based on their available time slots for AM/PM. +// - Instruction: Ensure the time filtering is accurately applied based on the given specialty and time period (AM/PM). + +// 16. **filterDoctorBySpecility Method**: +// - Filters doctors based on their specialty. +// - This method fetches all doctors matching the specified specialty and returns them. +// - Instruction: Make sure the filtering logic works for case-insensitive specialty matching. + +// 17. **filterDoctorsByTime Method**: +// - Filters all doctors based on their availability during a specific time period (AM/PM). +// - The method checks all doctors' available times and returns those available during the specified time period. +// - Instruction: Ensure proper filtering logic to handle AM/PM time periods. + + +} diff --git a/SmartClinicManagementSystem/app/src/main/java/com/project/back_end/services/PatientService.java b/SmartClinicManagementSystem/app/src/main/java/com/project/back_end/services/PatientService.java new file mode 100644 index 0000000..1be9520 --- /dev/null +++ b/SmartClinicManagementSystem/app/src/main/java/com/project/back_end/services/PatientService.java @@ -0,0 +1,58 @@ +package com.project.back_end.services; + +public class PatientService { +// 1. **Add @Service Annotation**: +// - The `@Service` annotation is used to mark this class as a Spring service component. +// - It will be managed by Spring's container and used for business logic related to patients and appointments. +// - Instruction: Ensure that the `@Service` annotation is applied above the class declaration. + +// 2. **Constructor Injection for Dependencies**: +// - The `PatientService` class has dependencies on `PatientRepository`, `AppointmentRepository`, and `TokenService`. +// - These dependencies are injected via the constructor to maintain good practices of dependency injection and testing. +// - Instruction: Ensure constructor injection is used for all the required dependencies. + +// 3. **createPatient Method**: +// - Creates a new patient in the database. It saves the patient object using the `PatientRepository`. +// - If the patient is successfully saved, the method returns `1`; otherwise, it logs the error and returns `0`. +// - Instruction: Ensure that error handling is done properly and exceptions are caught and logged appropriately. + +// 4. **getPatientAppointment Method**: +// - Retrieves a list of appointments for a specific patient, based on their ID. +// - The appointments are then converted into `AppointmentDTO` objects for easier consumption by the API client. +// - This method is marked as `@Transactional` to ensure database consistency during the transaction. +// - Instruction: Ensure that appointment data is properly converted into DTOs and the method handles errors gracefully. + +// 5. **filterByCondition Method**: +// - Filters appointments for a patient based on the condition (e.g., "past" or "future"). +// - Retrieves appointments with a specific status (0 for future, 1 for past) for the patient. +// - Converts the appointments into `AppointmentDTO` and returns them in the response. +// - Instruction: Ensure the method correctly handles "past" and "future" conditions, and that invalid conditions are caught and returned as errors. + +// 6. **filterByDoctor Method**: +// - Filters appointments for a patient based on the doctor's name. +// - It retrieves appointments where the doctor’s name matches the given value, and the patient ID matches the provided ID. +// - Instruction: Ensure that the method correctly filters by doctor's name and patient ID and handles any errors or invalid cases. + +// 7. **filterByDoctorAndCondition Method**: +// - Filters appointments based on both the doctor's name and the condition (past or future) for a specific patient. +// - This method combines filtering by doctor name and appointment status (past or future). +// - Converts the appointments into `AppointmentDTO` objects and returns them in the response. +// - Instruction: Ensure that the filter handles both doctor name and condition properly, and catches errors for invalid input. + +// 8. **getPatientDetails Method**: +// - Retrieves patient details using the `tokenService` to extract the patient's email from the provided token. +// - Once the email is extracted, it fetches the corresponding patient from the `patientRepository`. +// - It returns the patient's information in the response body. + // - Instruction: Make sure that the token extraction process works correctly and patient details are fetched properly based on the extracted email. + +// 9. **Handling Exceptions and Errors**: +// - The service methods handle exceptions using try-catch blocks and log any issues that occur. If an error occurs during database operations, the service responds with appropriate HTTP status codes (e.g., `500 Internal Server Error`). +// - Instruction: Ensure that error handling is consistent across the service, with proper logging and meaningful error messages returned to the client. + +// 10. **Use of DTOs (Data Transfer Objects)**: +// - The service uses `AppointmentDTO` to transfer appointment-related data between layers. This ensures that sensitive or unnecessary data (e.g., password or private patient information) is not exposed in the response. +// - Instruction: Ensure that DTOs are used appropriately to limit the exposure of internal data and only send the relevant fields to the client. + + + +} diff --git a/SmartClinicManagementSystem/app/src/main/java/com/project/back_end/services/PrescriptionService.java b/SmartClinicManagementSystem/app/src/main/java/com/project/back_end/services/PrescriptionService.java new file mode 100644 index 0000000..7ed0587 --- /dev/null +++ b/SmartClinicManagementSystem/app/src/main/java/com/project/back_end/services/PrescriptionService.java @@ -0,0 +1,34 @@ +package com.project.back_end.services; + +public class PrescriptionService { + + // 1. **Add @Service Annotation**: +// - The `@Service` annotation marks this class as a Spring service component, allowing Spring's container to manage it. +// - This class contains the business logic related to managing prescriptions in the healthcare system. +// - Instruction: Ensure the `@Service` annotation is applied to mark this class as a Spring-managed service. + +// 2. **Constructor Injection for Dependencies**: +// - The `PrescriptionService` class depends on the `PrescriptionRepository` to interact with the database. +// - It is injected through the constructor, ensuring proper dependency management and enabling testing. +// - Instruction: Constructor injection is a good practice, ensuring that all necessary dependencies are available at the time of service initialization. + +// 3. **savePrescription Method**: +// - This method saves a new prescription to the database. +// - Before saving, it checks if a prescription already exists for the same appointment (using the appointment ID). +// - If a prescription exists, it returns a `400 Bad Request` with a message stating the prescription already exists. +// - If no prescription exists, it saves the new prescription and returns a `201 Created` status with a success message. +// - Instruction: Handle errors by providing appropriate status codes and messages, ensuring that multiple prescriptions for the same appointment are not saved. + +// 4. **getPrescription Method**: +// - Retrieves a prescription associated with a specific appointment based on the `appointmentId`. +// - If a prescription is found, it returns it within a map wrapped in a `200 OK` status. +// - If there is an error while fetching the prescription, it logs the error and returns a `500 Internal Server Error` status with an error message. +// - Instruction: Ensure that this method handles edge cases, such as no prescriptions found for the given appointment, by returning meaningful responses. + +// 5. **Exception Handling and Error Responses**: +// - Both methods (`savePrescription` and `getPrescription`) contain try-catch blocks to handle exceptions that may occur during database interaction. +// - If an error occurs, the method logs the error and returns an HTTP `500 Internal Server Error` response with a corresponding error message. +// - Instruction: Ensure that all potential exceptions are handled properly, and meaningful responses are returned to the client. + + +} diff --git a/SmartClinicManagementSystem/app/src/main/java/com/project/back_end/services/Service.java b/SmartClinicManagementSystem/app/src/main/java/com/project/back_end/services/Service.java new file mode 100644 index 0000000..8c04994 --- /dev/null +++ b/SmartClinicManagementSystem/app/src/main/java/com/project/back_end/services/Service.java @@ -0,0 +1,66 @@ +package com.project.back_end.services; + +public class Service { +// 1. **@Service Annotation** +// The @Service annotation marks this class as a service component in Spring. This allows Spring to automatically detect it through component scanning +// and manage its lifecycle, enabling it to be injected into controllers or other services using @Autowired or constructor injection. + +// 2. **Constructor Injection for Dependencies** +// The constructor injects all required dependencies (TokenService, Repositories, and other Services). This approach promotes loose coupling, improves testability, +// and ensures that all required dependencies are provided at object creation time. + +// 3. **validateToken Method** +// This method checks if the provided JWT token is valid for a specific user. It uses the TokenService to perform the validation. +// If the token is invalid or expired, it returns a 401 Unauthorized response with an appropriate error message. This ensures security by preventing +// unauthorized access to protected resources. + +// 4. **validateAdmin Method** +// This method validates the login credentials for an admin user. +// - It first searches the admin repository using the provided username. +// - If an admin is found, it checks if the password matches. +// - If the password is correct, it generates and returns a JWT token (using the admin’s username) with a 200 OK status. +// - If the password is incorrect, it returns a 401 Unauthorized status with an error message. +// - If no admin is found, it also returns a 401 Unauthorized. +// - If any unexpected error occurs during the process, a 500 Internal Server Error response is returned. +// This method ensures that only valid admin users can access secured parts of the system. + +// 5. **filterDoctor Method** +// This method provides filtering functionality for doctors based on name, specialty, and available time slots. +// - It supports various combinations of the three filters. +// - If none of the filters are provided, it returns all available doctors. +// This flexible filtering mechanism allows the frontend or consumers of the API to search and narrow down doctors based on user criteria. + +// 6. **validateAppointment Method** +// This method validates if the requested appointment time for a doctor is available. +// - It first checks if the doctor exists in the repository. +// - Then, it retrieves the list of available time slots for the doctor on the specified date. +// - It compares the requested appointment time with the start times of these slots. +// - If a match is found, it returns 1 (valid appointment time). +// - If no matching time slot is found, it returns 0 (invalid). +// - If the doctor doesn’t exist, it returns -1. +// This logic prevents overlapping or invalid appointment bookings. + +// 7. **validatePatient Method** +// This method checks whether a patient with the same email or phone number already exists in the system. +// - If a match is found, it returns false (indicating the patient is not valid for new registration). +// - If no match is found, it returns true. +// This helps enforce uniqueness constraints on patient records and prevent duplicate entries. + +// 8. **validatePatientLogin Method** +// This method handles login validation for patient users. +// - It looks up the patient by email. +// - If found, it checks whether the provided password matches the stored one. +// - On successful validation, it generates a JWT token and returns it with a 200 OK status. +// - If the password is incorrect or the patient doesn't exist, it returns a 401 Unauthorized with a relevant error. +// - If an exception occurs, it returns a 500 Internal Server Error. +// This method ensures only legitimate patients can log in and access their data securely. + +// 9. **filterPatient Method** +// This method filters a patient's appointment history based on condition and doctor name. +// - It extracts the email from the JWT token to identify the patient. +// - Depending on which filters (condition, doctor name) are provided, it delegates the filtering logic to PatientService. +// - If no filters are provided, it retrieves all appointments for the patient. +// This flexible method supports patient-specific querying and enhances user experience on the client side. + + +} diff --git a/SmartClinicManagementSystem/app/src/main/java/com/project/back_end/services/TokenService.java b/SmartClinicManagementSystem/app/src/main/java/com/project/back_end/services/TokenService.java new file mode 100644 index 0000000..6681388 --- /dev/null +++ b/SmartClinicManagementSystem/app/src/main/java/com/project/back_end/services/TokenService.java @@ -0,0 +1,43 @@ +package com.project.back_end.services; + +public class TokenService { +// 1. **@Component Annotation** +// The @Component annotation marks this class as a Spring component, meaning Spring will manage it as a bean within its application context. +// This allows the class to be injected into other Spring-managed components (like services or controllers) where it's needed. + +// 2. **Constructor Injection for Dependencies** +// The constructor injects dependencies for `AdminRepository`, `DoctorRepository`, and `PatientRepository`, +// allowing the service to interact with the database and validate users based on their role (admin, doctor, or patient). +// Constructor injection ensures that the class is initialized with all required dependencies, promoting immutability and making the class testable. + +// 3. **getSigningKey Method** +// This method retrieves the HMAC SHA key used to sign JWT tokens. +// It uses the `jwt.secret` value, which is provided from an external source (like application properties). +// The `Keys.hmacShaKeyFor()` method converts the secret key string into a valid `SecretKey` for signing and verification of JWTs. + +// 4. **generateToken Method** +// This method generates a JWT token for a user based on their email. +// - The `subject` of the token is set to the user's email, which is used as an identifier. +// - The `issuedAt` is set to the current date and time. +// - The `expiration` is set to 7 days from the issue date, ensuring the token expires after one week. +// - The token is signed using the signing key generated by `getSigningKey()`, making it secure and tamper-proof. +// The method returns the JWT token as a string. + +// 5. **extractEmail Method** +// This method extracts the user's email (subject) from the provided JWT token. +// - The token is first verified using the signing key to ensure it hasn’t been tampered with. +// - After verification, the token is parsed, and the subject (which represents the email) is extracted. +// This method allows the application to retrieve the user's identity (email) from the token for further use. + +// 6. **validateToken Method** +// This method validates whether a provided JWT token is valid for a specific user role (admin, doctor, or patient). +// - It first extracts the email from the token using the `extractEmail()` method. +// - Depending on the role (`admin`, `doctor`, or `patient`), it checks the corresponding repository (AdminRepository, DoctorRepository, or PatientRepository) +// to see if a user with the extracted email exists. +// - If a match is found for the specified user role, it returns true, indicating the token is valid. +// - If the role or user does not exist, it returns false, indicating the token is invalid. +// - The method gracefully handles any errors by returning false if the token is invalid or an exception occurs. +// This ensures secure access control based on the user's role and their existence in the system. + + +} diff --git a/SmartClinicManagementSystem/app/src/main/resources/application.properties b/SmartClinicManagementSystem/app/src/main/resources/application.properties new file mode 100644 index 0000000..b6b721a --- /dev/null +++ b/SmartClinicManagementSystem/app/src/main/resources/application.properties @@ -0,0 +1,33 @@ +spring.application.name=back-end + +spring.datasource.url=jdbc:mysql:///cms?usessl=false +spring.datasource.username=root + +spring.datasource.password= +spring.jpa.hibernate.ddl-auto=update + +spring.jpa.show-sql=true +spring.jpa.properties.hibernate.format_sql=true +spring.jpa.open-in-view=false + +spring.data.mongodb.uri=mongodb://root:@:27017/prescriptions?authSource=admin" + +management.endpoint.health.show-details=always +management.health.db.enabled=true + + +api.path=/ +jwt.secret=$!@#$^%$$$%####$DDCPN0234FCFDPD8670M + + + +spring.web.resources.static-locations=classpath:/static/ + +# ------------------------- +# Thymeleaf Configuration +# ------------------------- +spring.thymeleaf.prefix=classpath:/templates/ +spring.thymeleaf.suffix=.html +spring.thymeleaf.mode=HTML +spring.thymeleaf.cache=false +spring.thymeleaf.encoding=UTF-8 \ No newline at end of file diff --git a/SmartClinicManagementSystem/app/src/main/resources/static/assets/css/addPrescription.css b/SmartClinicManagementSystem/app/src/main/resources/static/assets/css/addPrescription.css new file mode 100644 index 0000000..82d4cfa --- /dev/null +++ b/SmartClinicManagementSystem/app/src/main/resources/static/assets/css/addPrescription.css @@ -0,0 +1,91 @@ +/* This is the stylesheet for the addPrescription.html */ + +.form-container { + width: 100%; + max-width: 600px; + background: #ffffffc8; + margin: 50px auto; + padding: 30px; + border-radius: 15px; + box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1); + animation: fadeIn 0.5s ease-in-out; + } + + .container h2 { + text-align: center; + color: #222; + font-size: 28px; + margin-bottom: 25px; + } + + .container h2 span { + color: #A62B1F; + } + + label { + display: block; + margin-bottom: 6px; + font-weight: 500; + color: #333; + text-align: left; + font-size: 13px; + } + + input, textarea { + width: 100%; + padding: 12px; + resize: vertical; + margin-bottom: 20px; + border: 1px solid #cccccc6e; + border-radius: 8px; + font-size: 15px; + outline: none; + transition: 0.3s; + font-family: "Verdana"; + } + + input:focus, textarea:focus { + border-color: #015c5d; + box-shadow: 0 0 4px #a7f3d0; + filter: brightness(1.5); + } + + #patientName{ + background-color: #bdbcbc80; + } + .btn-primary { + background-color: #047857; + color: #fff; + padding: 14px; + width: 100%; + border: none; + border-radius: 8px; + font-size: 16px; + cursor: pointer; + transition: 0.3s; + } + + .btn-primary:hover { + background-color: #065f46; + } + + .btn-secondary { + background-color: transparent; + color: #333; + border: 1px solid #ccc; + padding: 12px; + width: 100%; + border-radius: 8px; + font-size: 15px; + margin-top: 12px; + cursor: pointer; + } + + .btn-secondary:hover{ + color: #fff; + } + + @keyframes fadeIn { + from { opacity: 0; transform: translateY(30px); } + to { opacity: 1; transform: translateY(0); } + } diff --git a/SmartClinicManagementSystem/app/src/main/resources/static/assets/css/adminDashboard.css b/SmartClinicManagementSystem/app/src/main/resources/static/assets/css/adminDashboard.css new file mode 100644 index 0000000..1a2b3c1 --- /dev/null +++ b/SmartClinicManagementSystem/app/src/main/resources/static/assets/css/adminDashboard.css @@ -0,0 +1,94 @@ +/*this is the style sheet for the adminDashboard. */ + +/* +Global Reset (`*`) + +* Purpose: Ensure consistent layout across all browsers. +* Properties: + + * `margin: 0` — removes default outer spacing from all elements. + * `padding: 0` — removes default inner spacing. + * `box-sizing: border-box` — ensures padding and borders are included within the total width/height of elements. + +Base HTML & Body (`html, body`) + +* Purpose: Establish a full-height layout and apply a standard font across the page. +* Properties: + + * `height: 100%` — allows containers to stretch to the full viewport height. + * `font-family: Arial, sans-serif` — applies a clean, readable sans-serif font. + +Main Layout Wrapper (`.wrapper`) + +* Purpose: Create a flexible, vertical layout that fills the entire screen. +* Properties: + + * `display: flex` — enables flexbox for layout control. + * `flex-direction: column` — stacks children vertically. + * `min-height: 100vh` — ensures the wrapper always covers full screen height. + +Section Heading (`h2`) + +* Purpose: Style the headings prominently for section separation. +* Properties: + + * `font-size: 32px` — makes the heading large and noticeable. + * `font-weight: bold` — emphasizes text. + * `margin-bottom: 50px` — creates space below the heading. + * `color: #003e3e` — uses a strong teal for visual anchoring. + +Main Content Section (`.main-content`) + +* Purpose: Layout the main content with padding and a background image. +* Properties: + + * `flex-grow: 1` — lets the content fill the available vertical space. + * `padding: 40px` — adds internal spacing around content. + * `display: flex` and `flex-direction: column` — organizes content in a vertical stack. + * `text-align: center` — centers the text. + * `background-image: url("index.png")` — sets a full-screen dashboard background. + * `background-size: cover` — ensures the image covers the whole section. + * `background-position: center` — centers the image. + * `background-repeat: no-repeat` — avoids tiling the image. + * `background-attachment: fixed` — fixes the image while scrolling. + +Primary Button (`button`) + +* Purpose: Design prominent, interactive buttons for main actions. + +* Properties: + + * `background-color: #A62B1F` — sets a bold red color. + * `color: white` — makes text stand out. + * `border: none` — removes any outline/border. + * `border-radius: 12px` — creates rounded corners. + * `padding: 10px 20px` — gives space inside the button. + * `margin-top: 20px` — adds spacing above the button. + * `width: 200px` — ensures consistent button width. + * `cursor: pointer` — shows a hand icon on hover. + * `font-size: 16px` — makes the text readable. + +* On Hover: + + * Retains the same red background to maintain branding. + +Admin Button (`.adminBtn`) + +* Purpose: Provide a secondary button style for admin-specific actions. + +* Properties: + + * `background-color: #f4f4f4` — uses a light grey background. + * `color: #333` — uses dark text for contrast. + * `font-weight: bold` — emphasizes text. + * `width: 110px` — smaller, compact width. + * `padding: 10px 0` — vertical padding only. + * `border: none` — clean look. + * `cursor: pointer` — indicates it's clickable. + +* On Hover**: + + Changes text color to `#A62B1F` for brand consistency while keeping the background same. + + +*/ \ No newline at end of file diff --git a/SmartClinicManagementSystem/app/src/main/resources/static/assets/css/doctorDashboard.css b/SmartClinicManagementSystem/app/src/main/resources/static/assets/css/doctorDashboard.css new file mode 100644 index 0000000..a7366f9 --- /dev/null +++ b/SmartClinicManagementSystem/app/src/main/resources/static/assets/css/doctorDashboard.css @@ -0,0 +1,65 @@ +/* This is the style sheet for the doctorDashboard.html */ +/* +**Table Header (`.table-header`)** + +* Set font size to `24px` for clear emphasis. +* Use a dark teal color (`#015c5d`) for consistency with the theme. +* Add `30px` bottom margin and remove right margin. + +**Table Styling (`table`)** + +* Make the table full width (`100%`). +* Collapse borders for clean lines. +* Use a `sans-serif` font. +* Add `20px` top margin for spacing. + +**Table Head (`thead`)** + +* Set a very light dark background (`#33333310`) for header row. +* Use white text color (`#fff`). + +**Table Cells (`td, th`)** + +* Apply padding of `12px 16px` for spacing. +* Center-align the text. +* Add a subtle bottom border (`1px solid #ddd`). + +**Table Row Styling** + +* Alternate row colors for better readability: + + * Even rows: semi-transparent light grey (`#f9f9f959`). + * Odd rows: soft white background (`#ffffffc0`). +* On hover: highlight row with a light teal overlay (`#015c5d39`). + +**Prescription Button (`.prescription-btn`)** + +* Set size to `30px x 30px`. +* Make it interactive with a pointer cursor. +* Add transition effects for scale and brightness on hover. +* On hover: + + * Slightly enlarge (`scale(1.1)`) + * Brighten appearance +* On click: slightly shrink (`scale(0.95)`). + +**No Record Message (`.noPatientRecord`)** + +* Use a `16px` italic grey font to indicate no data gently. + +**Today Button (`.today-btn`)** + +* Add right margin (`10px`). +* Add padding (`10px`). +* Set background color to teal green (`#015c5d`). + +**Date Picker (`.date-picker`)** + +* Add left margin (`10px`) and top margin (`13px`). +* Round corners with `8px` radius. +* Add padding (`10px`) and set fixed height (`30px`). + +--- + +Let me know if you'd like a consolidated style guide for the entire HospitalCRM frontend. + */ \ No newline at end of file diff --git a/SmartClinicManagementSystem/app/src/main/resources/static/assets/css/index.css b/SmartClinicManagementSystem/app/src/main/resources/static/assets/css/index.css new file mode 100644 index 0000000..3c35671 --- /dev/null +++ b/SmartClinicManagementSystem/app/src/main/resources/static/assets/css/index.css @@ -0,0 +1,53 @@ +/* this is the style sheet file for index.htlm */ + +/* +**Global Reset (`*`)** + +* Remove all default margin and padding. +* Use `border-box` for sizing to include padding and border in element size. + +**Base (`html, body`)** + +* Set height to 100% for full viewport layout. +* Use the `'Roboto'` sans-serif font for modern, clean typography. + +**Layout Wrapper (`.wrapper`)** + +* Use a vertical flexbox layout. +* Ensure the wrapper covers at least the full height of the screen (`min-height: 100vh`). + +**Heading (`h2`)** + +* Set a large font size (`48px`) for prominence. +* Add a bottom margin of `50px` for spacing. +* Use a dark teal color (`#003e3e`). +* Make the font bold and use a blended font stack (`'Alegreya', 'Roboto', sans-serif`) for elegant styling. + +**Main Section (`.main-content`)** + +* Allow the section to grow to fill space with `flex-grow: 1`. +* Add `40px` of internal padding. +* Center content both horizontally and vertically using `justify-content` and `align-items`. +* Display items in a column direction. +* Center all text. +* Apply a full-screen background image with: + + * `cover` size + * `center` positioning + * no repeat + * `fixed` attachment to keep image still during scroll + +**Buttons (`button`)** + +* Style with a teal green background (`#015c5d`) and white text. +* Remove borders and round the corners (`12px`). +* Use `10px 20px` padding and set width to `200px`. +* Add a top margin of `10px` for spacing. +* Enable pointer cursor and readable font size (`16px`). +* On hover, change background color to bold red (`#A62B1F`). + +**Dashboard Buttons (`.dashboard-btn`)** + +* Use the same base green background (`#015c5d`) as the default button. +* On hover, darken the background to deep teal (`#003e3e`) for visual feedback. + */ diff --git a/SmartClinicManagementSystem/app/src/main/resources/static/assets/css/patientDashboard.css b/SmartClinicManagementSystem/app/src/main/resources/static/assets/css/patientDashboard.css new file mode 100644 index 0000000..9504647 --- /dev/null +++ b/SmartClinicManagementSystem/app/src/main/resources/static/assets/css/patientDashboard.css @@ -0,0 +1,80 @@ +/* This is the style sheet for the patientDashboard.html */ + .card-actions { + background-color: #244557; + padding: 10px; + text-align: center; + } + + .card-actions:hover{ + background-color: #1c3745; + } + .ripple-overlay { + position: fixed; + width: 20px; + height: 20px; + background-color: #1c3745; + border-radius: 50%; + z-index: 9999; + transform: translate(-50%, -50%) scale(0); + transition: transform 1s ease-out, opacity 1s ease; + } + + .ripple-overlay.active { + transform: translate(-50%, -50%) scale(150); + opacity: 1; + } + + .modalApp { + position: fixed; + bottom: -100%; + left: 50%; + transform: translateX(-50%); + width: 50%; + background: #fff; + padding: 20px; + z-index: 10000; + transition: bottom 1.5s ease-in; + box-shadow: 0 -5px 10px rgba(0, 0, 0, 0.3); + border-radius: 10px 10px 0 0; + text-align: center; + } + + .modalApp.active { + bottom: 0; + } + + .modalApp h2 { + margin-top: 20px; + } + + .modalApp input { + display: block; + margin: 10px auto; + padding: 10px; + width: 90%; + margin-bottom: 40px; + } + + .modalApp select { + display: block; + margin: 10px auto; + padding: 10px; + width: 90%; + margin-bottom: 40px; + } + + .confirm-booking { + padding: 10px 20px; + background: #1c3745; + color: #fff; + border: none; + cursor: pointer; + + + + } + .confirm-booking:hover { + filter: brightness(1.2); + background-color: #1c3745; + } + diff --git a/SmartClinicManagementSystem/app/src/main/resources/static/assets/css/style.css b/SmartClinicManagementSystem/app/src/main/resources/static/assets/css/style.css new file mode 100644 index 0000000..7cb35c0 --- /dev/null +++ b/SmartClinicManagementSystem/app/src/main/resources/static/assets/css/style.css @@ -0,0 +1,382 @@ +/* This is the style sheet for global change across the files. */ + +/* style.css */ +.header { + display: flex; + justify-content: space-between; + align-items: center; + background-color: #f4f4f4; + color: #333; + padding: 10px 20px; + border-bottom: 2px solid #ccc; + flex-wrap: wrap; + min-height: 60px; + } + + /* Logo section with image + title */ + .logo-link{ + display: flex; + align-items: center; + gap: 10px; + + } + + .logo-img { + height: 40px; + width: auto; + max-width: 100%; + object-fit: contain; + } + + /* Logo text / slogan */ + .logo-title { + font-size: 20px; + font-weight: bold; + color: #333; + } + + /* Nav links styling */ + nav a { + margin-left: 20px; + margin-right: 20px; + text-decoration: none; + color: #333; + font-weight: bold; + } + + nav a:hover { + color: #003e3e; + } + + + /* Responsive behavior */ + @media (max-width: 600px) { + .header { + flex-direction: column; + align-items: flex-start; + } + + nav { + margin-top: 10px; + } + + nav a { + margin-left: 0; + margin-right: 10px; + } + + .logo-img { + height: 30px; + } + + .logo-title { + font-size: 18px; + } + } + + .doctorHeader{ + margin-right: 30px + } + .doctorHeader:hover{ + color:#A62B1F; + } +/* Footer Section */ +.footer { + background-color: #f4f4f4; + color: #fff; + padding: 40px 20px; + border-top: 2px solid #f4f4f4; + + } + + .footer-container { + display: flex; + flex-wrap: wrap; + justify-content: space-between; + gap: 30px; + max-width: 1200px; + margin: 0 auto; + } + + .footer-logo { + flex: 1 1 250px; + display: flex; + flex-direction: column; + align-items: flex-start; + gap: 15px; + } + + .footer-logo img { + height: 50px; + width: auto; + } + + .footer-logo p { + font-size: 14px; + color: #0a0a23; + } + + .footer-links { + display: flex; + flex: 2 1 500px; + justify-content: space-between; + flex-wrap: wrap; + gap: 20px; + } + + .footer-column { + display: flex; + flex-direction: column; + gap: 10px; + } + + .footer-column h4 { + font-size: 16px; + font-weight: bold; + margin-bottom: 8px; + color: #0a0a23; + } + + .footer-column a { + text-decoration: none; + color: #0a0a23; + font-size: 14px; + } + + .footer-column a:hover { + color: #003e3e; + transition: color 0.3s ease; + } + + /* Mobile Responsiveness */ + @media (max-width: 768px) { + .footer-container { + flex-direction: column; + align-items: flex-start; + } + + .footer-links { + flex-direction: column; + gap: 20px; + } + } + + + .modal { + display: none; + position: fixed; + z-index: 999; + padding-top: 60px; + left: 0; + top: 0; + width: 100%; + height: 100%; + background-color: rgba(0,0,0,0.6); + } + + .modal-content { + background-color: white; + margin: auto; + padding: 30px; + border-radius: 10px; + width: 400px; + position: relative; + } + + .modal-content h2{ + font-size: 32px; + } + + .close { + color: #aaa; + position: absolute; + right: 20px; + top: 15px; + font-size: 28px; + font-weight: bold; + cursor: pointer; + } + + .close:hover { + color: black; + } + + + + .dashboard-btn{ + width: 100%; + } + + .input-field { + padding: 10px; + border: 1px solid #ccc; + font-size: 16px; + margin-top: 10px; + margin-bottom: 20px; + width: 100%; + appearance: none; /* Remove default OS styles */ + background-color: #fff; + color: #333; + cursor: pointer; + border-radius: 8px; + } + + .input-field:hover { + border-color: #015c5d; + background-color: #f0fdfd; + } + + .input-field:focus { + outline: none; + border-color: #015c5d; + box-shadow: 0 0 5px rgba(1, 92, 93, 0.5); + filter: brightness(1.2); + } + + .select-dropdown option { + font-size: 16px; + padding: 10px; + } + + + #content { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(315px, 1fr)); + gap: 40px; + padding: 20px; + } + + .doctor-card { + display: flex; + flex-direction: column; + justify-content: space-between; + border: 1px solid #ddd; + border-radius: 10px; + width:auto; + overflow: hidden; + background-color: #fff; + box-shadow: 0 4px 6px rgba(0,0,0,0.1); + transition: transform 0.2s ease; + } + + .doctor-card:hover { + transform: scale(1.02); + } + + .doctor-info { + padding: 12px; + flex-grow: 1; + } + + .doctor-info h3 { + margin-top: 30px; + font-size: 24px; + color: #015c5d; + } + + .doctor-info p { + margin: 20px 0px; + font-size: 14px; + color: #555; + } + + .card-actions { + background-color: #e28282; + padding: 10px; + text-align: center; + } + + .card-actions:hover { + background-color: #d26969; + } + + .card-actions button { + background: transparent; + border: none; + color: #fff; + font-weight: bold; + cursor: pointer; + } + + .card-actions button:hover { + color: #fff; + border-color: #015c5d; + } + + #roleSelector { + width:auto; + border-radius: 10px; + } + + span { + color : #A62B1F; + } + + .searchBar{ + height: 30px; + padding:20px; + font-size: 16px; + margin-bottom: 30px; + border: 0.2px solid grey; +} + + .searchBar:focus{ + outline: none; + border-color: #015c5d; + box-shadow: 0 0 5px rgba(1, 92, 93, 0.697); +} + +.filter-wrapper { + width: 350px; + display: flex; + flex-direction: row; + +} + +.filter-select { + margin-right: 8px; + width: 100%; + padding: 8px 12px; + border: 1px solid #ccc; + border-radius: 6px; + background-color: #fff; + color: #333; + font-size: 14px; + background-position: right 10px center; + background-size: 16px 16px; + cursor: pointer; + transition: border-color 0.2s, box-shadow 0.2s; +} + +.filter-select:focus { + border-color: #015c5d; + box-shadow: 0 0 5px rgba(1, 92, 93, 0.697); + outline: none; +} + +.availabilityLabel{ + margin-bottom: 8px; +} + +.availability-container { + margin-bottom: 1rem; + +} + +.checkbox-group { + display: flex; + flex-direction: column; + gap: 1rem; + margin-top: 1rem; +} + +.checkbox-group label { + font-weight: 500; + cursor: pointer; +} + +.checkbox-group input[type="checkbox"] { + margin-right: 0.5rem; + accent-color: #015c5db8; +} + diff --git a/SmartClinicManagementSystem/app/src/main/resources/static/assets/css/updateAppointment.css b/SmartClinicManagementSystem/app/src/main/resources/static/assets/css/updateAppointment.css new file mode 100644 index 0000000..c72d99c --- /dev/null +++ b/SmartClinicManagementSystem/app/src/main/resources/static/assets/css/updateAppointment.css @@ -0,0 +1,89 @@ +/* This is the style sheet for the updateAppointment.html */ +.form-container { + max-width: 600px; + background: #ffffffc8; + margin: 10px auto; + padding: 30px; + border-radius: 15px; + box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1); + animation: fadeIn 0.5s ease-in-out; + } + + .container h2 { + text-align: center; + color: #222; + font-size: 28px; + margin-bottom: 25px; + } + + .container h2 span { + color: #A62B1F; + } + + label { + display: block; + margin-bottom: 6px; + font-weight: 500; + color: #333; + text-align: left; + font-size: 13px; + } + + input, textarea ,select { + width: 100%; + padding: 12px; + resize: vertical; + margin-bottom: 20px; + border: 1px solid #cccccc6e; + border-radius: 8px; + font-size: 15px; + outline: none; + transition: 0.3s; + font-family: "Verdana"; + } + + input:focus, textarea:focus { + border-color: #015c5d; + box-shadow: 0 0 4px #a7f3d0; + filter: brightness(1.5); + } + + #patientName{ + background-color: #bdbcbc80; + } + .btn-primary { + background-color: #047857; + color: #fff; + padding: 14px; + width: 100%; + border: none; + border-radius: 8px; + font-size: 16px; + cursor: pointer; + transition: 0.3s; + } + + .btn-primary:hover { + background-color: #065f46; + } + + .btn-secondary { + background-color: transparent; + color: #333; + border: 1px solid #ccc; + padding: 12px; + width: 100%; + border-radius: 8px; + font-size: 15px; + margin-top: 12px; + cursor: pointer; + } + + .btn-secondary:hover{ + color: #fff; + } + + @keyframes fadeIn { + from { opacity: 0; transform: translateY(30px); } + to { opacity: 1; transform: translateY(0); } + } diff --git a/SmartClinicManagementSystem/app/src/main/resources/static/assets/images/addPrescriptionIcon/addPrescription.png b/SmartClinicManagementSystem/app/src/main/resources/static/assets/images/addPrescriptionIcon/addPrescription.png new file mode 100644 index 0000000..dd2daf5 Binary files /dev/null and b/SmartClinicManagementSystem/app/src/main/resources/static/assets/images/addPrescriptionIcon/addPrescription.png differ diff --git a/SmartClinicManagementSystem/app/src/main/resources/static/assets/images/defineRole/index.png b/SmartClinicManagementSystem/app/src/main/resources/static/assets/images/defineRole/index.png new file mode 100644 index 0000000..a16183d Binary files /dev/null and b/SmartClinicManagementSystem/app/src/main/resources/static/assets/images/defineRole/index.png differ diff --git a/SmartClinicManagementSystem/app/src/main/resources/static/assets/images/edit/edit.png b/SmartClinicManagementSystem/app/src/main/resources/static/assets/images/edit/edit.png new file mode 100644 index 0000000..038a4dd Binary files /dev/null and b/SmartClinicManagementSystem/app/src/main/resources/static/assets/images/edit/edit.png differ diff --git a/SmartClinicManagementSystem/app/src/main/resources/static/assets/images/logo/logo.png b/SmartClinicManagementSystem/app/src/main/resources/static/assets/images/logo/logo.png new file mode 100644 index 0000000..75a119c Binary files /dev/null and b/SmartClinicManagementSystem/app/src/main/resources/static/assets/images/logo/logo.png differ diff --git a/SmartClinicManagementSystem/app/src/main/resources/static/index.html b/SmartClinicManagementSystem/app/src/main/resources/static/index.html new file mode 100644 index 0000000..238c126 --- /dev/null +++ b/SmartClinicManagementSystem/app/src/main/resources/static/index.html @@ -0,0 +1,104 @@ + + \ No newline at end of file diff --git a/SmartClinicManagementSystem/app/src/main/resources/static/js/addPrescription.js b/SmartClinicManagementSystem/app/src/main/resources/static/js/addPrescription.js new file mode 100644 index 0000000..e7bea96 --- /dev/null +++ b/SmartClinicManagementSystem/app/src/main/resources/static/js/addPrescription.js @@ -0,0 +1,80 @@ +import { savePrescription, getPrescription } from "./services/prescriptionServices.js"; + +document.addEventListener('DOMContentLoaded', async () => { + const savePrescriptionBtn = document.getElementById("savePrescription"); + const patientNameInput = document.getElementById("patientName"); + const medicinesInput = document.getElementById("medicines"); + const dosageInput = document.getElementById("dosage"); + const notesInput = document.getElementById("notes"); + const heading = document.getElementById("heading") + + + const urlParams = new URLSearchParams(window.location.search); + const appointmentId = urlParams.get("appointmentId"); + const mode = urlParams.get("mode"); + const token = localStorage.getItem("token"); + const patientName = urlParams.get("patientName") + + if (heading) { + if (mode === "view") { + heading.innerHTML = `View Prescription`; + } else { + heading.innerHTML = `Add Prescription`; + } + } + + + // Pre-fill patient name + if (patientNameInput && patientName) { + patientNameInput.value = patientName; + } + + // Fetch and pre-fill existing prescription if it exists + if (appointmentId && token) { + try { + const response = await getPrescription(appointmentId, token); + console.log("getPrescription :: ", response); + + // Now, check if the prescription exists in the response and access it from the array + if (response.prescription && response.prescription.length > 0) { + const existingPrescription = response.prescription[0]; // Access first prescription object + patientNameInput.value = existingPrescription.patientName || YOU; + medicinesInput.value = existingPrescription.medication || ""; + dosageInput.value = existingPrescription.dosage || ""; + notesInput.value = existingPrescription.doctorNotes || ""; + } + + } catch (error) { + console.warn("No existing prescription found or failed to load:", error); + } + } + if (mode === 'view') { + // Make fields read-only + patientNameInput.disabled = true; + medicinesInput.disabled = true; + dosageInput.disabled = true; + notesInput.disabled = true; + savePrescriptionBtn.style.display = "none"; // Hide the save button + } + // Save prescription on button click + savePrescriptionBtn.addEventListener('click', async (e) => { + e.preventDefault(); + + const prescription = { + patientName: patientNameInput.value, + medication: medicinesInput.value, + dosage: dosageInput.value, + doctorNotes: notesInput.value, + appointmentId + }; + + const { success, message } = await savePrescription(prescription, token); + + if (success) { + alert("✅ Prescription saved successfully."); + selectRole('doctor'); + } else { + alert("❌ Failed to save prescription. " + message); + } + }); +}); diff --git a/SmartClinicManagementSystem/app/src/main/resources/static/js/adminDashboard.js b/SmartClinicManagementSystem/app/src/main/resources/static/js/adminDashboard.js new file mode 100644 index 0000000..a930352 --- /dev/null +++ b/SmartClinicManagementSystem/app/src/main/resources/static/js/adminDashboard.js @@ -0,0 +1,72 @@ +/* + This script handles the admin dashboard functionality for managing doctors: + - Loads all doctor cards + - Filters doctors by name, time, or specialty + - Adds a new doctor via modal form + + + Attach a click listener to the "Add Doctor" button + When clicked, it opens a modal form using openModal('addDoctor') + + + When the DOM is fully loaded: + - Call loadDoctorCards() to fetch and display all doctors + + + Function: loadDoctorCards + Purpose: Fetch all doctors and display them as cards + + Call getDoctors() from the service layer + Clear the current content area + For each doctor returned: + - Create a doctor card using createDoctorCard() + - Append it to the content div + + Handle any fetch errors by logging them + + + Attach 'input' and 'change' event listeners to the search bar and filter dropdowns + On any input change, call filterDoctorsOnChange() + + + Function: filterDoctorsOnChange + Purpose: Filter doctors based on name, available time, and specialty + + Read values from the search bar and filters + Normalize empty values to null + Call filterDoctors(name, time, specialty) from the service + + If doctors are found: + - Render them using createDoctorCard() + If no doctors match the filter: + - Show a message: "No doctors found with the given filters." + + Catch and display any errors with an alert + + + Function: renderDoctorCards + Purpose: A helper function to render a list of doctors passed to it + + Clear the content area + Loop through the doctors and append each card to the content area + + + Function: adminAddDoctor + Purpose: Collect form data and add a new doctor to the system + + Collect input values from the modal form + - Includes name, email, phone, password, specialty, and available times + + Retrieve the authentication token from localStorage + - If no token is found, show an alert and stop execution + + Build a doctor object with the form values + + Call saveDoctor(doctor, token) from the service + + If save is successful: + - Show a success message + - Close the modal and reload the page + + If saving fails, show an error message +*/ diff --git a/SmartClinicManagementSystem/app/src/main/resources/static/js/appointmentRecord.js b/SmartClinicManagementSystem/app/src/main/resources/static/js/appointmentRecord.js new file mode 100644 index 0000000..67580d1 --- /dev/null +++ b/SmartClinicManagementSystem/app/src/main/resources/static/js/appointmentRecord.js @@ -0,0 +1,44 @@ +// appointmentRecord.js +import { getAppointments } from "./components/appointmentRow.js"; +import { getAppointmentRecord } from "./services/appointmentRecordService.js"; + +const tableBody = document.getElementById("patientTableBody"); +const filterSelect = document.getElementById("appointmentFilter"); + +async function loadAppointments(filter = "upcoming") { + const appointments = await getAppointmentRecord(); + + if (!appointments || appointments.length === 0) { + tableBody.innerHTML = `No appointments found.`; + return; + } + + const today = new Date().setHours(0, 0, 0, 0); + let filteredAppointments = appointments; + + if (filter === "upcoming") { + filteredAppointments = appointments.filter(app => new Date(app.date) >= today); + } else if (filter === "past") { + filteredAppointments = appointments.filter(app => new Date(app.date) < today); + } + + if (filteredAppointments.length === 0) { + tableBody.innerHTML = `No ${filter} appointments found.`; + return; + } + + tableBody.innerHTML = ""; + filteredAppointments.forEach(appointment => { + const row = getAppointments(appointment); + tableBody.appendChild(row); + }); +} + +// Handle filter change +filterSelect.addEventListener("change", (e) => { + const selectedFilter = e.target.value; + loadAppointments(selectedFilter); +}); + +// Load upcoming appointments by default +loadAppointments("upcoming"); diff --git a/SmartClinicManagementSystem/app/src/main/resources/static/js/components/appointmentRow.js b/SmartClinicManagementSystem/app/src/main/resources/static/js/components/appointmentRow.js new file mode 100644 index 0000000..9f7591b --- /dev/null +++ b/SmartClinicManagementSystem/app/src/main/resources/static/js/components/appointmentRow.js @@ -0,0 +1,19 @@ +// appointmentRow.js +export function getAppointments(appointment) { + const tr = document.createElement("tr"); + + tr.innerHTML = ` + ${appointment.patientName} + ${appointment.doctorName} + ${appointment.date} + ${appointment.time} + action + `; + + // Attach event listeners + tr.querySelector(".prescription-btn").addEventListener("click", () => { + window.location.href = `addPrescription.html?id=${patient.id}`; + }); + + return tr; +} diff --git a/SmartClinicManagementSystem/app/src/main/resources/static/js/components/doctorCard.js b/SmartClinicManagementSystem/app/src/main/resources/static/js/components/doctorCard.js new file mode 100644 index 0000000..f32d36c --- /dev/null +++ b/SmartClinicManagementSystem/app/src/main/resources/static/js/components/doctorCard.js @@ -0,0 +1,41 @@ +/* +Import the overlay function for booking appointments from loggedPatient.js + + Import the deleteDoctor API function to remove doctors (admin role) from docotrServices.js + + Import function to fetch patient details (used during booking) from patientServices.js + + Function to create and return a DOM element for a single doctor card + Create the main container for the doctor card + Retrieve the current user role from localStorage + Create a div to hold doctor information + Create and set the doctor’s name + Create and set the doctor's specialization + Create and set the doctor's email + Create and list available appointment times + Append all info elements to the doctor info container + Create a container for card action buttons + === ADMIN ROLE ACTIONS === + Create a delete button + Add click handler for delete button + Get the admin token from localStorage + Call API to delete the doctor + Show result and remove card if successful + Add delete button to actions container + + === PATIENT (NOT LOGGED-IN) ROLE ACTIONS === + Create a book now button + Alert patient to log in before booking + Add button to actions container + + === LOGGED-IN PATIENT ROLE ACTIONS === + Create a book now button + Handle booking logic for logged-in patient + Redirect if token not available + Fetch patient data with token + Show booking overlay UI with doctor and patient info + Add button to actions container + + Append doctor info and action buttons to the car + Return the complete doctor card element +*/ diff --git a/SmartClinicManagementSystem/app/src/main/resources/static/js/components/footer.js b/SmartClinicManagementSystem/app/src/main/resources/static/js/components/footer.js new file mode 100644 index 0000000..4739856 --- /dev/null +++ b/SmartClinicManagementSystem/app/src/main/resources/static/js/components/footer.js @@ -0,0 +1,104 @@ +/* + Function to render the footer content into the page + Select the footer element from the DOM + Set the inner HTML of the footer element to include the footer content + This section dynamically generates the footer content for the web page, including the hospital's logo, copyright information, and various helpful links. + + 1. Insert Footer HTML Content + + * The content is inserted into the `footer` element with the ID "footer" using `footer.innerHTML`. + * This is done dynamically via JavaScript to ensure that the footer is properly rendered across different pages. + + 2. Create the Footer Wrapper + + * The `