6 changed files with 2371 additions and 7 deletions
-
17src/main/java/com/gcc/commissionerreview/configuration/DataSourceConfig.java
-
73src/main/java/com/gcc/commissionerreview/controller/CoworkspaceApicontroller.java
-
12src/main/java/com/gcc/commissionerreview/controller/MainController.java
-
461src/main/java/com/gcc/commissionerreview/service/CoworkspaceService.java
-
1112src/main/resources/templates/modules/coworkspace.html
-
695src/main/resources/templates/modules/coworkspacereport.html
@ -0,0 +1,73 @@ |
|||
package com.gcc.commissionerreview.controller; |
|||
|
|||
import java.util.HashMap; |
|||
import java.util.List; |
|||
import java.util.Map; |
|||
|
|||
import org.springframework.beans.factory.annotation.Autowired; |
|||
import org.springframework.http.HttpStatus; |
|||
import org.springframework.http.ResponseEntity; |
|||
import org.springframework.web.bind.annotation.GetMapping; |
|||
import org.springframework.web.bind.annotation.RequestMapping; |
|||
import org.springframework.web.bind.annotation.RequestParam; |
|||
import org.springframework.web.bind.annotation.RestController; |
|||
|
|||
import com.gcc.commissionerreview.service.CommunityHallService; |
|||
import com.gcc.commissionerreview.service.CoworkspaceService; |
|||
|
|||
@RestController |
|||
@RequestMapping("/commissionerreview/api/coworkspace") |
|||
public class CoworkspaceApicontroller { |
|||
|
|||
@Autowired |
|||
private CoworkspaceService reportService; |
|||
|
|||
// ak |
|||
@GetMapping("/performance-report") |
|||
public ResponseEntity<List<Map<String, Object>>> getPerformanceReport( |
|||
@RequestParam(required = false) String fromDate, |
|||
@RequestParam(required = false) String toDate) { |
|||
|
|||
return ResponseEntity.ok( |
|||
reportService.getPerformanceReport(fromDate, toDate)); |
|||
} |
|||
|
|||
@GetMapping("/building-bookings") |
|||
public ResponseEntity<List<Map<String, Object>>> getBuildingBookings( |
|||
@RequestParam Integer bid, |
|||
@RequestParam Integer cid, |
|||
@RequestParam(required = false) String fromDate, |
|||
@RequestParam(required = false) String toDate, |
|||
@RequestParam(required = false) String filterBy) { |
|||
|
|||
return ResponseEntity.ok( |
|||
reportService.getBuildingBookings(bid, cid, fromDate, toDate, filterBy)); |
|||
} |
|||
|
|||
@GetMapping("/category-summary") |
|||
public ResponseEntity<List<Map<String, Object>>> getCategorySummary( |
|||
@RequestParam Integer bid, |
|||
@RequestParam(required = false) String fromDate, |
|||
@RequestParam(required = false) String toDate) { |
|||
|
|||
return ResponseEntity.ok( |
|||
reportService.getCategorySummary( |
|||
bid, fromDate, toDate)); |
|||
} |
|||
|
|||
@GetMapping("/dashboard") |
|||
public ResponseEntity<Map<String, Object>> getDashboard() { |
|||
return ResponseEntity.ok(reportService.getDashboard()); |
|||
} |
|||
|
|||
@GetMapping("/getReport") |
|||
public ResponseEntity<List<Map<String, Object>>> getReport( |
|||
@RequestParam(required = false) String fromDate, |
|||
@RequestParam(required = false) String toDate, |
|||
@RequestParam(required = false) String filterBy) { |
|||
|
|||
return ResponseEntity.ok( |
|||
reportService.getReport(fromDate, toDate, filterBy)); |
|||
} |
|||
|
|||
} |
|||
@ -0,0 +1,461 @@ |
|||
package com.gcc.commissionerreview.service; |
|||
|
|||
import java.util.ArrayList; |
|||
import java.util.HashMap; |
|||
import java.util.List; |
|||
import java.util.Map; |
|||
|
|||
import javax.sql.DataSource; |
|||
|
|||
import org.springframework.beans.factory.annotation.Autowired; |
|||
import org.springframework.beans.factory.annotation.Qualifier; |
|||
import org.springframework.beans.factory.annotation.Value; |
|||
import org.springframework.jdbc.core.JdbcTemplate; |
|||
import org.springframework.stereotype.Service; |
|||
|
|||
@Service |
|||
public class CoworkspaceService { |
|||
|
|||
@Autowired |
|||
private JdbcTemplate jdbcTemplate; |
|||
|
|||
@Autowired |
|||
public void setFeedbackDataSource(@Qualifier("mysqlcowrspaceDataSource") DataSource dataSource) { |
|||
this.jdbcTemplate = new JdbcTemplate(dataSource); |
|||
} |
|||
|
|||
public List<Map<String, Object>> getPerformanceReport(String fromDate, String toDate) { |
|||
|
|||
StringBuilder sql = new StringBuilder(); |
|||
|
|||
sql.append(""" |
|||
SELECT |
|||
b.bid, |
|||
b.name AS building_name, |
|||
|
|||
COUNT(bk.booking_id) AS total_bookings, |
|||
|
|||
IFNULL(SUM(bk.amount),0) AS total_revenue, |
|||
|
|||
SUM( |
|||
CASE |
|||
WHEN CURDATE() BETWEEN bk.from_date AND bk.to_date |
|||
THEN 1 ELSE 0 |
|||
END |
|||
) AS ongoing_bookings, |
|||
|
|||
SUM( |
|||
CASE |
|||
WHEN bk.to_date < CURDATE() |
|||
THEN 1 ELSE 0 |
|||
END |
|||
) AS completed_bookings, |
|||
|
|||
SUM( |
|||
CASE |
|||
WHEN bk.from_date > CURDATE() |
|||
THEN 1 ELSE 0 |
|||
END |
|||
) AS future_bookings |
|||
|
|||
FROM booking bk |
|||
LEFT JOIN buildings b |
|||
ON bk.bid = b.bid |
|||
|
|||
WHERE 1=1 |
|||
"""); |
|||
|
|||
List<Object> params = new ArrayList<>(); |
|||
|
|||
if (fromDate != null && !fromDate.isBlank() |
|||
&& toDate != null && !toDate.isBlank()) { |
|||
|
|||
sql.append(" AND bk.from_date BETWEEN ? AND ? "); |
|||
params.add(fromDate); |
|||
params.add(toDate); |
|||
} |
|||
|
|||
sql.append(""" |
|||
GROUP BY b.bid, b.name |
|||
ORDER BY b.bid |
|||
"""); |
|||
|
|||
return jdbcTemplate.queryForList(sql.toString(), params.toArray()); |
|||
} |
|||
|
|||
public List<Map<String, Object>> getBuildingBookings( |
|||
Integer bid, |
|||
Integer cid, |
|||
String fromDate, |
|||
String toDate, |
|||
String filterBy) { |
|||
|
|||
StringBuilder sql = new StringBuilder(); |
|||
|
|||
sql.append(""" |
|||
SELECT |
|||
bk.booking_id, |
|||
bk.user_name, |
|||
bk.mobile, |
|||
bk.from_date, |
|||
bk.to_date, |
|||
bk.no_of_person, |
|||
bk.amount, |
|||
bk.cdate AS booking_date |
|||
FROM booking bk |
|||
WHERE bk.bid = ? |
|||
AND bk.cid = ? |
|||
AND bk.booking_status = 'success' |
|||
"""); |
|||
|
|||
List<Object> params = new ArrayList<>(); |
|||
params.add(bid); |
|||
params.add(cid); |
|||
|
|||
if (fromDate != null && !fromDate.isBlank() |
|||
&& toDate != null && !toDate.isBlank()) { |
|||
|
|||
if ("slot_date".equals(filterBy)) { |
|||
|
|||
sql.append(""" |
|||
AND EXISTS ( |
|||
SELECT 1 |
|||
FROM calendar cl |
|||
WHERE cl.bookingid = bk.booking_id |
|||
AND DATE(cl.bdate) BETWEEN ? AND ? |
|||
) |
|||
"""); |
|||
|
|||
params.add(fromDate); |
|||
params.add(toDate); |
|||
|
|||
} else if ("current_date".equals(filterBy)) { |
|||
|
|||
sql.append(""" |
|||
AND DATE(bk.cdate) BETWEEN ? AND ? |
|||
"""); |
|||
|
|||
params.add(fromDate); |
|||
params.add(toDate); |
|||
|
|||
} else { |
|||
|
|||
sql.append(""" |
|||
AND bk.from_date BETWEEN ? AND ? |
|||
"""); |
|||
|
|||
params.add(fromDate); |
|||
params.add(toDate); |
|||
} |
|||
} |
|||
|
|||
sql.append(""" |
|||
ORDER BY bk.cdate |
|||
"""); |
|||
|
|||
return jdbcTemplate.queryForList(sql.toString(), params.toArray()); |
|||
} |
|||
|
|||
public List<Map<String, Object>> getBuildingBookingswithoutfilterby(Integer bid, Integer cid, |
|||
String fromDate, |
|||
String toDate) { |
|||
|
|||
StringBuilder sql = new StringBuilder(); |
|||
|
|||
sql.append(""" |
|||
SELECT |
|||
booking_id, |
|||
user_name, |
|||
mobile, |
|||
from_date, |
|||
to_date, |
|||
no_of_person, |
|||
amount, |
|||
cdate AS booking_date |
|||
FROM booking |
|||
WHERE bid = ? AND cid = ? |
|||
"""); |
|||
|
|||
List<Object> params = new ArrayList<>(); |
|||
params.add(bid); |
|||
params.add(cid); |
|||
|
|||
if (fromDate != null && !fromDate.isBlank() |
|||
&& toDate != null && !toDate.isBlank()) { |
|||
|
|||
sql.append(" AND from_date BETWEEN ? AND ? "); |
|||
params.add(fromDate); |
|||
params.add(toDate); |
|||
} |
|||
|
|||
sql.append(" ORDER BY cdate "); |
|||
|
|||
return jdbcTemplate.queryForList(sql.toString(), params.toArray()); |
|||
} |
|||
|
|||
public List<Map<String, Object>> getCategorySummary(Integer bid, |
|||
String fromDate, |
|||
String toDate) { |
|||
|
|||
StringBuilder sql = new StringBuilder(); |
|||
|
|||
sql.append(""" |
|||
SELECT |
|||
c.cid, |
|||
c.bid, |
|||
c.display_name AS category_name, |
|||
|
|||
COUNT(bk.booking_id) AS total_bookings, |
|||
|
|||
IFNULL(SUM(bk.amount),0) AS total_revenue, |
|||
|
|||
SUM( |
|||
CASE |
|||
WHEN CURDATE() BETWEEN bk.from_date AND bk.to_date |
|||
THEN 1 |
|||
ELSE 0 |
|||
END |
|||
) AS ongoing_bookings, |
|||
|
|||
SUM( |
|||
CASE |
|||
WHEN bk.to_date < CURDATE() |
|||
THEN 1 |
|||
ELSE 0 |
|||
END |
|||
) AS completed_bookings, |
|||
|
|||
SUM( |
|||
CASE |
|||
WHEN bk.from_date > CURDATE() |
|||
THEN 1 |
|||
ELSE 0 |
|||
END |
|||
) AS future_bookings |
|||
|
|||
FROM category c |
|||
|
|||
LEFT JOIN booking bk |
|||
ON c.cid = bk.cid |
|||
AND c.bid = bk.bid |
|||
|
|||
WHERE c.bid = ? |
|||
"""); |
|||
|
|||
List<Object> params = new ArrayList<>(); |
|||
params.add(bid); |
|||
|
|||
if (fromDate != null && !fromDate.isBlank() |
|||
&& toDate != null && !toDate.isBlank()) { |
|||
|
|||
sql.append(" AND bk.from_date BETWEEN ? AND ? "); |
|||
|
|||
params.add(fromDate); |
|||
params.add(toDate); |
|||
} |
|||
|
|||
sql.append(""" |
|||
GROUP BY c.cid,c.name |
|||
ORDER BY c.name |
|||
"""); |
|||
|
|||
return jdbcTemplate.queryForList(sql.toString(), params.toArray()); |
|||
} |
|||
|
|||
public Map<String, Object> getDashboard() { |
|||
|
|||
Map<String, Object> dashboard = new HashMap<>(); |
|||
|
|||
// Card 1 |
|||
Integer totalBuildings = jdbcTemplate.queryForObject( |
|||
"SELECT COUNT(bid) FROM buildings where isactive = 1 and isdelete = 0", |
|||
Integer.class); |
|||
|
|||
// Card 2 |
|||
Integer totalBookings = jdbcTemplate.queryForObject( |
|||
"SELECT COUNT(booking_id) FROM booking ", |
|||
Integer.class); |
|||
|
|||
// Card 3 |
|||
Double totalRevenue = jdbcTemplate.queryForObject( |
|||
"SELECT IFNULL(SUM(amount),0) FROM booking", |
|||
Double.class); |
|||
|
|||
// Card 4 |
|||
List<Map<String, Object>> categories = jdbcTemplate.queryForList(""" |
|||
SELECT |
|||
display_name, |
|||
COUNT(display_name) AS total |
|||
FROM category |
|||
GROUP BY display_name |
|||
ORDER BY display_name |
|||
"""); |
|||
|
|||
// Card 5 |
|||
List<Map<String, Object>> slotDetails = jdbcTemplate.queryForList(""" |
|||
SELECT DISTINCT |
|||
s.display_name AS subcategory_name, |
|||
c.display_name AS category_name, |
|||
sl.name AS slot_name |
|||
FROM category c |
|||
LEFT JOIN subcategory s |
|||
ON c.cid = s.cid |
|||
LEFT JOIN slots sl |
|||
ON s.scid = sl.scid |
|||
ORDER BY |
|||
c.display_name, |
|||
s.display_name, |
|||
sl.name |
|||
"""); |
|||
|
|||
dashboard.put("totalBuildings", totalBuildings); |
|||
dashboard.put("totalBookings", totalBookings); |
|||
dashboard.put("totalRevenue", totalRevenue); |
|||
|
|||
dashboard.put("categories", categories); |
|||
|
|||
dashboard.put("slotCount", slotDetails.size()); |
|||
dashboard.put("slotDetails", slotDetails); |
|||
|
|||
return dashboard; |
|||
} |
|||
|
|||
// new requirement |
|||
public List<Map<String, Object>> getReport(String fromDate, String toDate, String filterBy) { |
|||
|
|||
StringBuilder sql = new StringBuilder(); |
|||
|
|||
sql.append(""" |
|||
SELECT |
|||
b.bid, |
|||
|
|||
|
|||
b.name AS building_name, |
|||
b.inauguration_date, |
|||
DATEDIFF(CURDATE(), DATE(b.inauguration_date)) AS operational_days, |
|||
|
|||
COUNT(bk.booking_id) AS total_bookings, |
|||
|
|||
|
|||
IFNULL(SUM(bk.amount), 0) AS total_revenue, |
|||
|
|||
IFNULL(cs.total_slot, 0) AS total_slot, |
|||
|
|||
COUNT(CASE |
|||
WHEN cat.display_name = 'Desk Space' |
|||
THEN bk.booking_id |
|||
END) AS desk_space, |
|||
|
|||
COUNT(CASE |
|||
WHEN cat.display_name = 'Learning Centre' |
|||
THEN bk.booking_id |
|||
END) AS learning_centre, |
|||
|
|||
COUNT(CASE |
|||
WHEN cat.display_name = 'Meeting Rooms' |
|||
THEN bk.booking_id |
|||
END) AS meeting_rooms, |
|||
MAX(CASE |
|||
WHEN cat.display_name = 'Desk Space' |
|||
THEN cat.cid |
|||
END) AS desk_space_cid, |
|||
|
|||
MAX(CASE |
|||
WHEN cat.display_name = 'Learning Centre' |
|||
THEN cat.cid |
|||
END) AS learning_centre_cid, |
|||
|
|||
MAX(CASE |
|||
WHEN cat.display_name = 'Meeting Rooms' |
|||
THEN cat.cid |
|||
END) AS meeting_rooms_cid |
|||
|
|||
FROM buildings b |
|||
|
|||
LEFT JOIN booking bk |
|||
ON b.bid = bk.bid |
|||
|
|||
LEFT JOIN category cat |
|||
ON bk.cid = cat.cid |
|||
AND bk.bid = cat.bid |
|||
|
|||
LEFT JOIN ( |
|||
SELECT |
|||
c.bid, |
|||
COUNT(c.bookingid) AS total_slot |
|||
FROM calendar c |
|||
LEFT JOIN booking b |
|||
ON c.bookingid = b.booking_id |
|||
GROUP BY c.bid |
|||
|
|||
) cs |
|||
ON b.bid = cs.bid |
|||
|
|||
|
|||
"""); |
|||
sql.append(" WHERE 1=1 AND bk.booking_status = 'success' "); |
|||
|
|||
List<Object> params = new ArrayList<>(); |
|||
|
|||
if (fromDate != null && !fromDate.isBlank() |
|||
&& toDate != null && !toDate.isBlank()) { |
|||
|
|||
if ("slot_date".equals(filterBy)) { |
|||
|
|||
sql.append(""" |
|||
AND EXISTS ( |
|||
SELECT 1 |
|||
FROM calendar cl |
|||
WHERE cl.bookingid = bk.booking_id |
|||
AND DATE(cl.bdate) BETWEEN ? AND ? |
|||
) |
|||
"""); |
|||
|
|||
params.add(fromDate); |
|||
params.add(toDate); |
|||
|
|||
} else if ("current_date".equals(filterBy)) { |
|||
|
|||
sql.append(""" |
|||
AND DATE(bk.cdate) BETWEEN ? AND ? |
|||
"""); |
|||
|
|||
params.add(fromDate); |
|||
params.add(toDate); |
|||
|
|||
} else { |
|||
|
|||
sql.append(""" |
|||
AND bk.from_date BETWEEN ? AND ? |
|||
"""); |
|||
|
|||
params.add(fromDate); |
|||
params.add(toDate); |
|||
} |
|||
} |
|||
/* |
|||
* List<Object> params = new ArrayList<>(); |
|||
* if (fromDate != null && !fromDate.isBlank() |
|||
* && toDate != null && !toDate.isBlank()) { |
|||
* |
|||
* sql.append(" AND bk.from_date BETWEEN ? AND ? "); |
|||
* params.add(fromDate); |
|||
* params.add(toDate); |
|||
* } |
|||
*/ |
|||
|
|||
sql.append(""" |
|||
GROUP BY |
|||
b.bid, |
|||
b.name, |
|||
b.inauguration_date, |
|||
cs.total_slot |
|||
|
|||
ORDER BY |
|||
b.bid |
|||
"""); |
|||
|
|||
return jdbcTemplate.queryForList(sql.toString(), params.toArray()); |
|||
} |
|||
|
|||
} |
|||
1112
src/main/resources/templates/modules/coworkspace.html
File diff suppressed because it is too large
View File
File diff suppressed because it is too large
View File
@ -0,0 +1,695 @@ |
|||
<!DOCTYPE html> |
|||
<html lang="en" xmlns:th="http://www.thymeleaf.org"> |
|||
|
|||
<head> |
|||
<title>Coworkspace Performance Report</title> |
|||
|
|||
<!-- Bootstrap 5 CSS --> |
|||
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha1/dist/css/bootstrap.min.css" rel="stylesheet"> |
|||
<!-- FontAwesome CSS for icons --> |
|||
<link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css" rel="stylesheet"> |
|||
<!-- DataTables CSS --> |
|||
<link href="https://cdn.datatables.net/1.13.4/css/jquery.dataTables.min.css" rel="stylesheet" /> |
|||
<link href="https://cdn.datatables.net/buttons/2.3.6/css/buttons.dataTables.min.css" rel="stylesheet" /> |
|||
<link href="https://cdn.datatables.net/fixedcolumns/4.2.2/css/fixedColumns.dataTables.min.css" rel="stylesheet" /> |
|||
|
|||
|
|||
<style> |
|||
body { |
|||
background-color: #f8f9fa; |
|||
} |
|||
|
|||
.report-container { |
|||
overflow-x: auto; |
|||
} |
|||
|
|||
/*#hallBookingTable { |
|||
width: 100% !important; |
|||
}*/ |
|||
|
|||
.page-header-title h4 { |
|||
margin: 20px 0; |
|||
text-align: center; |
|||
font-weight: bold; |
|||
color: #003366; |
|||
text-transform: uppercase; |
|||
} |
|||
|
|||
.filter-section { |
|||
background: #fff; |
|||
padding: 15px; |
|||
border-radius: 8px; |
|||
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.05); |
|||
margin-bottom: 20px; |
|||
} |
|||
|
|||
.report-container { |
|||
background: #fff; |
|||
padding: 15px; |
|||
border-radius: 8px; |
|||
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.05); |
|||
} |
|||
|
|||
|
|||
|
|||
/* table.dataTable th, |
|||
table.dataTable td { |
|||
text-align: center; |
|||
vertical-align: middle; |
|||
border: 1px solid #dee2e6 !important; |
|||
white-space: nowrap; |
|||
}*/ |
|||
|
|||
|
|||
thead th { |
|||
background-color: #003366 !important; |
|||
color: white !important; |
|||
} |
|||
|
|||
/* Horizontal Scroll */ |
|||
.dataTables_scrollBody { |
|||
overflow-x: auto !important; |
|||
overflow-y: auto !important; |
|||
} |
|||
|
|||
/* Fixed Column Background */ |
|||
table.dataTable tbody tr td.dtfc-fixed-left { |
|||
background-color: #fff !important; |
|||
} |
|||
|
|||
table.dataTable.table-striped tbody tr:nth-of-type(odd) td.dtfc-fixed-left { |
|||
background-color: #f9f9f9 !important; |
|||
} |
|||
|
|||
.dataTables_scrollBody { |
|||
overflow-x: auto !important; |
|||
overflow-y: auto !important; |
|||
} |
|||
|
|||
.select2-container { |
|||
width: 100% !important; |
|||
} |
|||
|
|||
.select2-results__options { |
|||
max-height: 400px !important; |
|||
/* increase height */ |
|||
} |
|||
|
|||
.select2-dropdown { |
|||
z-index: 9999 !important; |
|||
} |
|||
|
|||
/*.dataTables_scrollHeadInner, |
|||
#hallBookingTable { |
|||
width: max-content !important; |
|||
}*/ |
|||
|
|||
/* table.dataTable th, |
|||
table.dataTable td { |
|||
white-space: nowrap; |
|||
}*/ |
|||
/* table.dataTable th, |
|||
table.dataTable td { |
|||
text-align: center; |
|||
vertical-align: middle; |
|||
border: 1px solid #dee2e6 !important; |
|||
} |
|||
|
|||
#hallBookingTable th:nth-child(8), |
|||
#hallBookingTable td:nth-child(8) { |
|||
white-space: nowrap !important; |
|||
min-width: 180px; |
|||
} |
|||
|
|||
|
|||
|
|||
#hallBookingTable th:nth-child(5), |
|||
#hallBookingTable td:nth-child(5) { |
|||
|
|||
min-width: 220px; |
|||
max-width: 220px; |
|||
|
|||
white-space: normal !important; |
|||
word-wrap: break-word; |
|||
word-break: break-word; |
|||
} |
|||
|
|||
#hallBookingTable th:nth-child(20), |
|||
#hallBookingTable td:nth-child(20) { |
|||
width: 80px !important; |
|||
max-width: 80px !important; |
|||
min-width: 80px !important; |
|||
|
|||
white-space: normal !important; |
|||
word-break: break-word !important; |
|||
}*/ |
|||
.hall-name-wrap { |
|||
min-width: 220px !important; |
|||
max-width: 220px !important; |
|||
white-space: normal !important; |
|||
word-break: break-word; |
|||
} |
|||
|
|||
|
|||
|
|||
/* #hallBookingTable th:not(:nth-child(4)), |
|||
#hallBookingTable td:not(:nth-child(4)) { |
|||
white-space: nowrap; |
|||
}*/ |
|||
|
|||
/* Wrap selected columns */ |
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
/* Scrollbar */ |
|||
.dataTables_scrollBody::-webkit-scrollbar { |
|||
height: 8px; |
|||
} |
|||
|
|||
.dataTables_scrollBody::-webkit-scrollbar-thumb { |
|||
background: #c1c1c1; |
|||
border-radius: 4px; |
|||
} |
|||
|
|||
.dataTables_scrollBody::-webkit-scrollbar-track { |
|||
background: #f1f1f1; |
|||
} |
|||
</style> |
|||
</head> |
|||
|
|||
<body> |
|||
|
|||
<div class="container-fluid py-4"> |
|||
<div class="page-header-title"> |
|||
<h4> Coworkspace Performance Report</h4> |
|||
</div> |
|||
|
|||
<!-- Filter Section --> |
|||
<div class="row"> |
|||
|
|||
<div class="col-md-3"> |
|||
<label>From Date</label> |
|||
<input type="date" id="fromDate" class="form-control"> |
|||
</div> |
|||
|
|||
<div class="col-md-3"> |
|||
<label>To Date</label> |
|||
<input type="date" id="toDate" class="form-control"> |
|||
</div> |
|||
|
|||
<div class="col-md-6 mt-4"> |
|||
|
|||
<button class="btn btn-primary" id="searchBtn"> |
|||
Search |
|||
</button> |
|||
|
|||
<button class="btn btn-secondary" id="resetBtn"> |
|||
Reset |
|||
</button> |
|||
|
|||
</div> |
|||
|
|||
</div> |
|||
|
|||
<!--<div class="col-md-2 mt-4"> |
|||
<button class="btn btn-primary" id="searchBtn"> |
|||
Search |
|||
</button> |
|||
<button class="btn btn-primary" id="resetBtn"> |
|||
Reset |
|||
</button> |
|||
|
|||
</div>--> |
|||
|
|||
|
|||
|
|||
<div class="report-container"> |
|||
<table id="reportTable" class="table table-bordered table-striped nowrap" width="100%"> |
|||
|
|||
<thead> |
|||
|
|||
<tr> |
|||
|
|||
<th>S.No</th> |
|||
<th>Building Name</th> |
|||
<th>Total Bookings</th> |
|||
<th>Total Revenue</th> |
|||
<th>Ongoing</th> |
|||
<th>Completed</th> |
|||
<th>Future</th> |
|||
|
|||
</tr> |
|||
|
|||
</thead> |
|||
|
|||
<tbody></tbody> |
|||
|
|||
</table> |
|||
</div> |
|||
<div class="modal fade" id="categoryModal"> |
|||
|
|||
<div class="modal-dialog modal-xl"> |
|||
|
|||
<div class="modal-content"> |
|||
|
|||
<div class="modal-header"> |
|||
<h5>Category Summary</h5> |
|||
|
|||
<button class="btn-close" data-bs-dismiss="modal"></button> |
|||
</div> |
|||
|
|||
<div class="modal-body"> |
|||
|
|||
<table id="categoryTable" class="table table-bordered"> |
|||
|
|||
<thead> |
|||
|
|||
<tr> |
|||
|
|||
<th>S.No</th> |
|||
<th>Category Name</th> |
|||
<th>Total Bookings</th> |
|||
<th>Total Revenue</th> |
|||
<th>Ongoing</th> |
|||
<th>Completed</th> |
|||
<th>Future</th> |
|||
|
|||
</tr> |
|||
|
|||
</thead> |
|||
|
|||
</table> |
|||
|
|||
</div> |
|||
|
|||
</div> |
|||
|
|||
</div> |
|||
|
|||
</div> |
|||
|
|||
<!-- Details Modal --> |
|||
<div class="modal fade" id="bookingModal"> |
|||
|
|||
<div class="modal-dialog modal-xl"> |
|||
|
|||
<div class="modal-content"> |
|||
|
|||
<div class="modal-header"> |
|||
|
|||
<h5>Booking Details</h5> |
|||
|
|||
<button class="btn-close" data-bs-dismiss="modal"></button> |
|||
|
|||
</div> |
|||
|
|||
<div class="modal-body"> |
|||
|
|||
<table id="bookingTable" class="table table-bordered"> |
|||
|
|||
<thead> |
|||
|
|||
<tr> |
|||
|
|||
<th>S.No</th> |
|||
<th>Booking Id</th> |
|||
<th>Booking Date</th> |
|||
<th>User Name</th> |
|||
<th>Mobile</th> |
|||
<th>From Date</th> |
|||
<th>To Date</th> |
|||
<th>No Of Person</th> |
|||
<th>Amount</th> |
|||
|
|||
|
|||
|
|||
</tr> |
|||
|
|||
</thead> |
|||
|
|||
</table> |
|||
|
|||
</div> |
|||
|
|||
</div> |
|||
|
|||
</div> |
|||
|
|||
</div> |
|||
|
|||
<!-- Media Modal --> |
|||
<div class="modal fade" id="mediaModal" tabindex="-1" aria-labelledby="mediaModalLabel" aria-hidden="true" |
|||
style="z-index: 1060;"> |
|||
<div class="modal-dialog modal-lg modal-dialog-centered"> |
|||
<div class="modal-content"> |
|||
<div class="modal-header"> |
|||
<h5 class="modal-title" id="mediaModalLabel">Media Viewer</h5> |
|||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button> |
|||
</div> |
|||
<div class="modal-body text-center" id="mediaModalBody"> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
<div id="pageLoader" |
|||
style="display: none; position: fixed; top: 0; left: 0; width: 100%; height: 100%; background: rgba(255, 255, 255, 0.8); z-index: 9999; text-align: center;"> |
|||
<div style="position: relative; top: 50%; transform: translateY(-50%);"> |
|||
<div class="spinner-border text-primary" role="status" style="width: 3rem; height: 3rem;"> |
|||
<span class="sr-only"></span> |
|||
</div> |
|||
<!-- Add the 'Please wait' text below the spinner --> |
|||
<p style="margin-top: 1rem; font-size: 1.2rem; color: #007bff;">Please wait...</p> |
|||
</div> |
|||
</div> |
|||
|
|||
<!-- Scripts --> |
|||
|
|||
<script src="https://cdn.jsdelivr.net/npm/jquery@3.6.0/dist/jquery.min.js"></script> |
|||
<link href="https://cdn.jsdelivr.net/npm/select2@4.1.0-rc.0/dist/css/select2.min.css" rel="stylesheet" /> |
|||
<script src="https://cdn.jsdelivr.net/npm/select2@4.1.0-rc.0/dist/js/select2.min.js"></script> |
|||
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha1/dist/js/bootstrap.bundle.min.js"></script> |
|||
|
|||
|
|||
<!-- DataTables JS --> |
|||
<script src="https://cdn.datatables.net/1.13.4/js/jquery.dataTables.min.js"></script> |
|||
<script src="https://cdn.datatables.net/buttons/2.3.6/js/dataTables.buttons.min.js"></script> |
|||
<script src="https://cdn.datatables.net/buttons/2.3.6/js/buttons.html5.min.js"></script> |
|||
<script src="https://cdn.datatables.net/buttons/2.3.6/js/buttons.print.min.js"></script> |
|||
<script src="https://cdnjs.cloudflare.com/ajax/libs/jszip/3.1.3/jszip.min.js"></script> |
|||
<script src="https://cdnjs.cloudflare.com/ajax/libs/pdfmake/0.2.7/pdfmake.min.js"></script> |
|||
<script src="https://cdnjs.cloudflare.com/ajax/libs/pdfmake/0.2.7/vfs_fonts.js"></script> |
|||
<script src="https://cdn.jsdelivr.net/npm/xlsx@0.18.5/dist/xlsx.full.min.js"></script> |
|||
<script src="https://cdn.datatables.net/fixedcolumns/4.2.2/js/dataTables.fixedColumns.min.js"></script> |
|||
|
|||
<!-- SweetAlert --> |
|||
<script src="https://cdn.jsdelivr.net/npm/sweetalert2@11"></script> |
|||
|
|||
<script th:inline="none"> |
|||
$(document).ready(function () { |
|||
let today = new Date().toISOString().split('T')[0]; |
|||
|
|||
// Restrict both date fields to today |
|||
$("#fromDate").attr("max", today); |
|||
$("#toDate").attr("max", today); |
|||
|
|||
$("#fromDate").on("change", function () { |
|||
|
|||
let fromDate = $(this).val(); |
|||
|
|||
// To Date cannot be before From Date |
|||
$("#toDate").attr("min", fromDate); |
|||
|
|||
// To Date cannot be after today |
|||
$("#toDate").attr("max", today); |
|||
|
|||
// Clear To Date if it is outside the valid range |
|||
let toDate = $("#toDate").val(); |
|||
if (toDate && (toDate < fromDate || toDate > today)) { |
|||
$("#toDate").val(""); |
|||
} |
|||
|
|||
}); |
|||
|
|||
|
|||
|
|||
loadReport(); |
|||
|
|||
}); |
|||
let bookingTable; |
|||
|
|||
function viewBookings(bid, cid) { |
|||
|
|||
if ($.fn.DataTable.isDataTable('#bookingTable')) { |
|||
$('#bookingTable').DataTable().destroy(); |
|||
} |
|||
$('#pageLoader').show(); |
|||
|
|||
$('#bookingTable').DataTable({ |
|||
|
|||
ajax: { |
|||
url: "/commissionerreview/api/coworkspace/building-bookings", |
|||
type: "GET", |
|||
data: { |
|||
bid: bid, |
|||
cid: cid, |
|||
fromDate: $("#fromDate").val(), |
|||
toDate: $("#toDate").val() |
|||
}, |
|||
|
|||
dataSrc: "", |
|||
complete: function () { |
|||
$('#pageLoader').hide(); |
|||
}, |
|||
|
|||
error: function () { |
|||
$('#pageLoader').hide(); |
|||
alert("Failed to load booking details."); |
|||
} |
|||
}, |
|||
|
|||
|
|||
destroy: true, |
|||
|
|||
columns: [ |
|||
|
|||
|
|||
{ |
|||
data: null, |
|||
render: function (data, type, row, meta) { |
|||
return meta.row + 1; |
|||
} |
|||
}, |
|||
{ data: "booking_id" }, |
|||
{ |
|||
data: "booking_date", |
|||
render: function (data) { |
|||
return formatDate(data); |
|||
} |
|||
}, |
|||
|
|||
{ data: "user_name" }, |
|||
{ data: "mobile" }, |
|||
{ data: "from_date" }, |
|||
{ data: "to_date" }, |
|||
{ data: "no_of_person" }, |
|||
{ data: "amount" } |
|||
|
|||
|
|||
] |
|||
|
|||
}); |
|||
|
|||
$("#bookingModal").modal("show"); |
|||
} |
|||
function formatDate(dateStr) { |
|||
if (!dateStr) return '-'; |
|||
|
|||
// Remove time part if present |
|||
dateStr = dateStr.split('T')[0]; |
|||
|
|||
const [y, m, d] = dateStr.split('-'); |
|||
return `${d}-${m}-${y}`; |
|||
} |
|||
|
|||
function initializeTable() { |
|||
|
|||
table = $("#reportTable").DataTable({ |
|||
destroy: true, |
|||
processing: true, |
|||
columns: [ |
|||
{ |
|||
data: null, |
|||
render: function (data, type, row, meta) { |
|||
return meta.row + 1; |
|||
} |
|||
}, |
|||
{ data: "building_name" }, |
|||
{ data: "total_bookings" }, |
|||
{ data: "total_revenue" }, |
|||
{ data: "ongoing_bookings" }, |
|||
{ data: "completed_bookings" }, |
|||
{ data: "future_bookings" } |
|||
], |
|||
dom: 'Bfrtip', |
|||
paging: false, |
|||
buttons: ['excel', 'pdf'] |
|||
}); |
|||
|
|||
} |
|||
function viewCategorySummary(bid) { |
|||
|
|||
$('#pageLoader').show(); |
|||
|
|||
if ($.fn.DataTable.isDataTable("#categoryTable")) { |
|||
$("#categoryTable").DataTable().destroy(); |
|||
} |
|||
|
|||
$("#categoryTable").DataTable({ |
|||
|
|||
destroy: true, |
|||
|
|||
ajax: { |
|||
|
|||
url: "/commissionerreview/api/coworkspace/category-summary", |
|||
|
|||
type: "GET", |
|||
|
|||
data: { |
|||
bid: bid, |
|||
fromDate: $("#fromDate").val(), |
|||
toDate: $("#toDate").val() |
|||
}, |
|||
|
|||
dataSrc: "", |
|||
|
|||
complete: function () { |
|||
|
|||
$('#pageLoader').hide(); |
|||
|
|||
} |
|||
|
|||
}, |
|||
|
|||
columns: [ |
|||
|
|||
{ |
|||
data: null, |
|||
render: function (data, type, row, meta) { |
|||
|
|||
return meta.row + 1; |
|||
|
|||
} |
|||
}, |
|||
|
|||
{ |
|||
|
|||
data: null, |
|||
|
|||
render: function (data) { |
|||
|
|||
return '<a href="javascript:void(0)" onclick="viewBookings(' |
|||
+ data.bid + ',' + data.cid + ')">' |
|||
+ data.category_name + |
|||
'</a>'; |
|||
|
|||
} |
|||
|
|||
}, |
|||
|
|||
{ data: "total_bookings" }, |
|||
{ data: "total_revenue" }, |
|||
{ data: "ongoing_bookings" }, |
|||
{ data: "completed_bookings" }, |
|||
{ data: "future_bookings" } |
|||
|
|||
] |
|||
|
|||
}); |
|||
|
|||
$("#categoryModal").modal("show"); |
|||
|
|||
} |
|||
|
|||
|
|||
function loadReport() { |
|||
$('#pageLoader').show(); |
|||
|
|||
|
|||
$.ajax({ |
|||
|
|||
url: "/commissionerreview/api/coworkspace/performance-report", |
|||
|
|||
type: "GET", |
|||
|
|||
data: { |
|||
|
|||
fromDate: $("#fromDate").val(), |
|||
toDate: $("#toDate").val() |
|||
|
|||
}, |
|||
|
|||
success: function (response) { |
|||
$('#pageLoader').hide(); |
|||
|
|||
if ($.fn.DataTable.isDataTable('#reportTable')) { |
|||
$('#reportTable').DataTable().destroy(); |
|||
} |
|||
|
|||
$('#reportTable tbody').empty(); |
|||
|
|||
table = $('#reportTable').DataTable({ |
|||
|
|||
destroy: true, |
|||
|
|||
data: response, |
|||
|
|||
processing: true, |
|||
|
|||
columns: [ |
|||
|
|||
{ |
|||
data: null, |
|||
render: function (data, type, row, meta) { |
|||
return meta.row + 1; |
|||
} |
|||
}, |
|||
|
|||
{ |
|||
data: null, |
|||
render: function (data) { |
|||
|
|||
return '<a href="javascript:void(0)" ' + |
|||
'onclick="viewCategorySummary(' + data.bid + ')">' + |
|||
data.building_name + |
|||
'</a>'; |
|||
} |
|||
}, |
|||
{ data: "total_bookings" }, |
|||
{ data: "total_revenue" }, |
|||
{ data: "ongoing_bookings" }, |
|||
{ data: "completed_bookings" }, |
|||
{ data: "future_bookings" } |
|||
|
|||
], |
|||
|
|||
dom: 'Bfrtip', |
|||
paging: false, |
|||
|
|||
buttons: [ |
|||
'excel', |
|||
'pdf' |
|||
] |
|||
|
|||
}); |
|||
|
|||
} |
|||
|
|||
}); |
|||
|
|||
} |
|||
$("#searchBtn").click(function () { |
|||
|
|||
loadReport(); |
|||
|
|||
}); |
|||
/*$('#bookingModal').on('hidden.bs.modal', function () { |
|||
window.location.reload(); |
|||
});*/ |
|||
$("#resetBtn").click(function () { |
|||
|
|||
$("#fromDate").val(""); |
|||
$("#toDate").val(""); |
|||
|
|||
loadReport(); |
|||
|
|||
}); |
|||
</script> |
|||
|
|||
</body> |
|||
|
|||
</html> |
|||
Write
Preview
Loading…
Cancel
Save
Reference in new issue