diff --git a/src/main/java/com/cardiff/client_project/controller/nursinghome/NursingHomeController.java b/src/main/java/com/cardiff/client_project/controller/nursinghome/NursingHomeController.java index f1ba66c1ac7651c84ca146f9531f1d6b484e5c61..59d82833cf7a33ea190edba4285072452340d158 100644 --- a/src/main/java/com/cardiff/client_project/controller/nursinghome/NursingHomeController.java +++ b/src/main/java/com/cardiff/client_project/controller/nursinghome/NursingHomeController.java @@ -68,14 +68,37 @@ public class NursingHomeController { @GetMapping("/search") public Result<List<HospitalDTO>> searchHospitals(@RequestParam(required = false) String name) { try { - log.info("Searching hospitals with name: {}", name); if (name == null || name.trim().isEmpty()) { return nursingHomeService.getAvailableBeds(); } return nursingHomeService.searchHospitals(name.trim()); } catch (Exception e) { - log.error("Error searching hospitals: ", e); - return Result.error("Error searching hospitals: " + e.getMessage()); + log.error("Search error: ", e); + return Result.error("Search failed: " + e.getMessage()); + } + } + + @PutMapping("/{id}/approval") + public Result<String> updateApprovalStatus( + @PathVariable Integer id, + @RequestParam String status) { + try { + log.info("Updating approval status for hospital {}: {}", id, status); + return nursingHomeService.updateApprovalStatus(id, status); + } catch (Exception e) { + log.error("Error updating approval status: ", e); + return Result.error("Failed to update approval status"); + } + } + + @GetMapping("/pending") + public Result<List<HospitalDTO>> getPendingApprovals() { + try { + log.info("Fetching pending approvals"); + return nursingHomeService.getPendingApprovals(); + } catch (Exception e) { + log.error("Error fetching pending approvals: ", e); + return Result.error("Failed to fetch pending approvals"); } } } diff --git a/src/main/java/com/cardiff/client_project/mapper/NursingHomeMapper.java b/src/main/java/com/cardiff/client_project/mapper/NursingHomeMapper.java index 612c72d3116eb2b1799c959028ef2c1b3749ab53..612feb553b47e2a8d1d9507aabbbc12d8fcfa5c2 100644 --- a/src/main/java/com/cardiff/client_project/mapper/NursingHomeMapper.java +++ b/src/main/java/com/cardiff/client_project/mapper/NursingHomeMapper.java @@ -5,6 +5,8 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.stereotype.Repository; +import java.sql.ResultSet; +import java.sql.SQLException; import java.util.List; @Repository @@ -13,33 +15,64 @@ public class NursingHomeMapper { @Autowired private JdbcTemplate jdbcTemplate; + public List<HospitalDTO> searchHospitals(String name) { + String sql = """ + SELECT + id, name, address, phone, maxAmount, + amountPatient, status, approval_status + FROM hospital + WHERE status = 1 + AND name LIKE CONCAT('%', ?, '%') + ORDER BY name ASC + """; + + return jdbcTemplate.query(sql, + ps -> ps.setString(1, name), + this::mapToDTO); + } + public List<HospitalDTO> findAllNursingHomes() { String sql = """ SELECT - id, - name, - address, - phone, - maxAmount, - amountPatient, - status + id, name, address, phone, maxAmount, + amountPatient, status, approval_status FROM hospital WHERE status = 1 """; - return jdbcTemplate.query(sql, (rs, rowNum) -> { - HospitalDTO dto = new HospitalDTO(); - dto.setId(rs.getInt("id")); - dto.setName(rs.getString("name")); - dto.setLocation(rs.getString("address")); - dto.setPhone(rs.getString("phone")); - dto.setTotalBeds(rs.getInt("maxAmount")); - int maxAmount = rs.getInt("maxAmount"); - int amountPatient = rs.getInt("amountPatient"); - dto.setAvailableBeds(maxAmount - amountPatient); - dto.setOccupancyRate(calculateOccupancy(maxAmount, amountPatient)); - return dto; - }); + return jdbcTemplate.query(sql, this::mapToDTO); + } + + public List<HospitalDTO> getPendingApprovals() { + String sql = """ + SELECT + id, name, address, phone, maxAmount, + amountPatient, status, approval_status + FROM hospital + WHERE approval_status = 'PENDING' + """; + + return jdbcTemplate.query(sql, this::mapToDTO); + } + + public int updateApprovalStatus(int id, String status) { + String sql = "UPDATE hospital SET approval_status = ? WHERE id = ?"; + return jdbcTemplate.update(sql, status, id); + } + + private HospitalDTO mapToDTO(ResultSet rs, int rowNum) throws SQLException { + HospitalDTO dto = new HospitalDTO(); + dto.setId(rs.getInt("id")); + dto.setName(rs.getString("name")); + dto.setLocation(rs.getString("address")); + dto.setPhone(rs.getString("phone")); + int maxAmount = rs.getInt("maxAmount"); + int amountPatient = rs.getInt("amountPatient"); + dto.setTotalBeds(maxAmount); + dto.setAvailableBeds(maxAmount - amountPatient); + dto.setOccupancyRate(calculateOccupancy(maxAmount, amountPatient)); + dto.setApprovalStatus(rs.getString("approval_status")); + return dto; } private double calculateOccupancy(int maxAmount, int amountPatient) { @@ -49,15 +82,10 @@ public class NursingHomeMapper { public int insertHospital(HospitalDTO dto) { String sql = """ INSERT INTO hospital ( - name, - address, - phone, - maxAmount, - amountPatient, - status, - type, - roleId - ) VALUES (?, ?, ?, ?, ?, 1, 'hospital', 3) + name, address, phone, maxAmount, + amountPatient, status, type, roleId, + approval_status + ) VALUES (?, ?, ?, ?, ?, 1, 'hospital', 3, 'PENDING') """; return jdbcTemplate.update(sql, diff --git a/src/main/java/com/cardiff/client_project/pojo/dto/HospitalDTO.java b/src/main/java/com/cardiff/client_project/pojo/dto/HospitalDTO.java index 0bc6896473690451937cacd5b0b4fd12b2147005..9bb0df21c749649cfa0b64a4ff9029b36f93d257 100644 --- a/src/main/java/com/cardiff/client_project/pojo/dto/HospitalDTO.java +++ b/src/main/java/com/cardiff/client_project/pojo/dto/HospitalDTO.java @@ -12,4 +12,5 @@ public class HospitalDTO { private int totalBeds; private int availableBeds; private double occupancyRate; + private String approvalStatus; } \ No newline at end of file diff --git a/src/main/java/com/cardiff/client_project/pojo/vo/HospitalVO.java b/src/main/java/com/cardiff/client_project/pojo/vo/HospitalVO.java index 3e673b8b8a28227dd626cf424453391420edeb9d..a12f13c974e19c257bbf296a4dba4a7c15787528 100644 --- a/src/main/java/com/cardiff/client_project/pojo/vo/HospitalVO.java +++ b/src/main/java/com/cardiff/client_project/pojo/vo/HospitalVO.java @@ -15,4 +15,6 @@ public class HospitalVO { private String status_str; private int maxAmount; private int amountPatient; + private String approvalStatus; + private String approvalStatus_str; } diff --git a/src/main/java/com/cardiff/client_project/service/NursingHomeService.java b/src/main/java/com/cardiff/client_project/service/NursingHomeService.java index 48bcfe9ce20e173608b2653861ed9f628e531698..f31c3ba660315d3d190f80f5e5d2fde364a84e9c 100644 --- a/src/main/java/com/cardiff/client_project/service/NursingHomeService.java +++ b/src/main/java/com/cardiff/client_project/service/NursingHomeService.java @@ -12,4 +12,6 @@ public interface NursingHomeService { Result<List<HospitalDTO>> getAllPatients(); Result<String> updateBedCount(int hospitalId, int currentPatients); Result<List<HospitalDTO>> searchHospitals(String name); + Result<String> updateApprovalStatus(Integer hospitalId, String status); + Result<List<HospitalDTO>> getPendingApprovals(); } \ No newline at end of file diff --git a/src/main/java/com/cardiff/client_project/service/imp/NursingHomeServiceImp.java b/src/main/java/com/cardiff/client_project/service/imp/NursingHomeServiceImp.java index 731f46c38d976816cb87ee14e0eb8d1b5d062de1..a9708a47e891713a6f48ebfd237980f215462871 100644 --- a/src/main/java/com/cardiff/client_project/service/imp/NursingHomeServiceImp.java +++ b/src/main/java/com/cardiff/client_project/service/imp/NursingHomeServiceImp.java @@ -11,9 +11,9 @@ import org.springframework.transaction.annotation.Transactional; import lombok.extern.slf4j.Slf4j; import java.util.List; +import java.util.stream.Collectors; @Service -@Transactional @Slf4j public class NursingHomeServiceImp implements NursingHomeService { @@ -28,14 +28,19 @@ public class NursingHomeServiceImp implements NursingHomeService { public Result<List<HospitalDTO>> getAvailableBeds() { try { List<HospitalDTO> hospitals = nursingHomeMapper.findAllNursingHomes(); - if (hospitals == null || hospitals.isEmpty()) { - return Result.error("No hospitals available"); + hospitals = hospitals.stream() + .filter(h -> "APPROVED".equals(h.getApprovalStatus())) + .collect(Collectors.toList()); + + if (hospitals.isEmpty()) { + return Result.error("No approved hospitals available"); } return Result.success(hospitals); } catch (DataAccessException e) { return Result.error("Database error: " + e.getMessage()); } catch (Exception e) { - return Result.error("Internal server error"); + log.error("Error fetching available beds: {}", e.getMessage(), e); + return Result.error("Failed to fetch available beds"); } } @@ -108,22 +113,73 @@ public class NursingHomeServiceImp implements NursingHomeService { @Transactional(readOnly = true) public Result<List<HospitalDTO>> searchHospitals(String name) { try { - log.info("Searching hospitals with name: {}", name); if (name == null || name.trim().isEmpty()) { return Result.error("Search term cannot be empty"); } + List<HospitalDTO> hospitals = nursingHomeMapper.searchHospitals(name); + return hospitals.isEmpty() ? + Result.error("No hospitals found") : + Result.success(hospitals); + } catch (Exception e) { + log.error("Search error: ", e); + return Result.error("Search failed"); + } + } - List<HospitalDTO> hospitals = nursingHomeMapper.searchHospitals(name.trim()); - if (hospitals.isEmpty()) { - log.info("No hospitals found matching: {}", name); - return Result.error("No hospitals found"); + @Override + @Transactional + public Result<String> updateApprovalStatus(Integer hospitalId, String status) { + try { + log.info("Updating approval status for hospital {}: {}", hospitalId, status); + + if (hospitalId == null || hospitalId <= 0) { + log.warn("Invalid hospital ID: {}", hospitalId); + return Result.error("Invalid hospital ID"); + } + + if (!isValidApprovalStatus(status)) { + log.warn("Invalid approval status: {}", status); + return Result.error("Invalid approval status"); + } + + int result = nursingHomeMapper.updateApprovalStatus(hospitalId, status); + if (result > 0) { + log.info("Successfully updated approval status for hospital {}", hospitalId); + return Result.success("Approval status updated successfully"); } + + log.warn("Hospital not found with ID: {}", hospitalId); + return Result.error("Hospital not found"); + + } catch (DataAccessException e) { + log.error("Database error while updating approval status: {}", e.getMessage(), e); + return Result.error("Database error occurred"); + } catch (Exception e) { + log.error("Unexpected error while updating approval status: {}", e.getMessage(), e); + return Result.error("Failed to update approval status"); + } + } - log.info("Found {} hospitals matching search term", hospitals.size()); - return Result.success(hospitals); + @Override + @Transactional(readOnly = true) + public Result<List<HospitalDTO>> getPendingApprovals() { + try { + log.info("Fetching pending approval hospitals"); + List<HospitalDTO> pendingHospitals = nursingHomeMapper.getPendingApprovals(); + + if (pendingHospitals.isEmpty()) { + log.info("No pending approvals found"); + return Result.error("No pending approvals"); + } + + log.info("Found {} pending approvals", pendingHospitals.size()); + return Result.success(pendingHospitals); + } catch (DataAccessException e) { + log.error("Database error while fetching pending approvals: {}", e.getMessage(), e); + return Result.error("Database error occurred"); } catch (Exception e) { - log.error("Error searching hospitals: ", e); - return Result.error("Failed to search hospitals"); + log.error("Unexpected error while fetching pending approvals: {}", e.getMessage(), e); + return Result.error("Failed to fetch pending approvals"); } } @@ -139,4 +195,17 @@ public class NursingHomeServiceImp implements NursingHomeService { hospitalDTO.getAvailableBeds() >= 0 && hospitalDTO.getAvailableBeds() <= hospitalDTO.getTotalBeds(); } + + private boolean isValidStatus(String status) { + return status != null && + (status.equals("APPROVED") || + status.equals("REJECTED") || + status.equals("PENDING")); + } + + private boolean isValidApprovalStatus(String status) { + if (status == null) return false; + return List.of("PENDING", "APPROVED", "REJECTED") + .contains(status.toUpperCase()); + } } \ No newline at end of file diff --git a/src/main/resources/static/css/beds.css b/src/main/resources/static/css/beds.css index 18f829e7a573ab424a9572096675a4128b8f594f..4f8405295d46afdad50d7d6f69023765cabd8473 100644 --- a/src/main/resources/static/css/beds.css +++ b/src/main/resources/static/css/beds.css @@ -342,3 +342,20 @@ footer { padding: 1rem; } +.approval-pending { + background-color: var(--warning-color); + color: white; + padding: 0.25rem 0.5rem; + border-radius: 4px; +} + +.approval-rejected { + background-color: var(--danger-color); + color: white; +} + +.approval-approved { + background-color: var(--success-color); + color: white; +} + diff --git a/src/main/resources/static/js/beds.js b/src/main/resources/static/js/beds.js index 301f5232dfe86beaf9262c38b5ba85cedcd40851..f9b37375513d88a8722ad7811ef0ce451d228020 100644 --- a/src/main/resources/static/js/beds.js +++ b/src/main/resources/static/js/beds.js @@ -52,29 +52,43 @@ $(document).ready(function () { function updateTable(hospitals) { const tbody = $('#hospitalTable tbody'); tbody.empty(); - + + if (!hospitals || hospitals.length === 0) { + showNoDataMessage(); + return; + } + hospitals.forEach(function(hospital) { - const tr = ` - <tr> - <td>${hospital.id}</td> - <td>${hospital.name || ''}</td> - <td>${hospital.location || ''}</td> - <td>${hospital.phone || ''}</td> - <td>${hospital.totalBeds || 0}</td> - <td>${hospital.availableBeds || 0}</td> - <td>${Math.round(hospital.occupancyRate)}%</td> - <td> - <button class="btn edit-btn" data-id="${hospital.id}"> - <i class="fas fa-edit"></i> - </button> - <button class="btn delete-btn" data-id="${hospital.id}"> - <i class="fas fa-trash"></i> - </button> - </td> - </tr> - `; - tbody.append(tr); + // Only show approved hospitals + if (hospital.approvalStatus === 'APPROVED') { + const tr = $('<tr>').append( + $('<td>').text(hospital.name), + $('<td>').text(hospital.location), + $('<td>').text(hospital.phone), + $('<td>').text(hospital.totalBeds), + $('<td>').text(hospital.availableBeds), + $('<td>').text(hospital.occupancyRate + '%'), + $('<td>').append( + $('<span>') + .addClass('status-badge') + .addClass('approval-' + hospital.approvalStatus.toLowerCase()) + .text(hospital.approvalStatus) + ) + ); + tbody.append(tr); + } }); + + if (tbody.children().length === 0) { + tbody.append( + $('<tr>').append( + $('<td>') + .attr('colspan', '7') + .addClass('no-data') + .text('No approved hospitals found') + ) + ); + } } function initializeEventHandlers() { @@ -334,6 +348,24 @@ $(document).ready(function () { // Add fade effects for smoother transitions $('.table-container').hide().fadeIn(); + + // Add new function for admin approval handling + function handleApproval(hospitalId, status) { + $.ajax({ + url: `${API_BASE_URL}/approval/${hospitalId}`, + method: 'PUT', + data: { status: status }, + success: function(response) { + if(response.code === 1) { + showSuccess(`Hospital ${status.toLowerCase()} successfully`); + loadHospitals(); + } else { + showError(response.msg || DEFAULT_ERROR); + } + }, + error: handleAjaxError + }); + } }); function handleSignOut() {