No commits in common. '3281fd4055295a0770d3bbe5818cb17c77d6284d' and '31300a03703348f520ac337a16cd6a79f2a76c96' have entirely different histories.
3281fd4055
...
31300a0370
34 changed files with 2449 additions and 1127 deletions
-
BIN.mvn/wrapper/maven-wrapper.jar
-
2.mvn/wrapper/maven-wrapper.properties
-
3src/main/java/com/feedback/it_asset/ItAssetApplication.java
-
118src/main/java/com/feedback/it_asset/component/UserSessionInterceptor.java
-
397src/main/java/com/feedback/it_asset/controller/APIController.java
-
4src/main/java/com/feedback/it_asset/controller/AssetController.java
-
80src/main/java/com/feedback/it_asset/controller/FeedbackController.java
-
83src/main/java/com/feedback/it_asset/controller/MainController.java
-
18src/main/java/com/feedback/it_asset/dto/FeedbackCountResponse.java
-
6src/main/java/com/feedback/it_asset/dto/ItAssetDashboardDto.java
-
34src/main/java/com/feedback/it_asset/dto/MonthWiseCountsDTO.java
-
4src/main/java/com/feedback/it_asset/entity/AssetCategory.java
-
8src/main/java/com/feedback/it_asset/entity/AssetCategoryQuestions.java
-
10src/main/java/com/feedback/it_asset/entity/GccAssetDetails.java
-
4src/main/java/com/feedback/it_asset/entity/GccFeedbackData.java
-
40src/main/java/com/feedback/it_asset/entity/Role.java
-
160src/main/java/com/feedback/it_asset/entity/User.java
-
57src/main/java/com/feedback/it_asset/entity/UserRole.java
-
8src/main/java/com/feedback/it_asset/repository/GccAssetDetailsRep.java
-
50src/main/java/com/feedback/it_asset/repository/GccFeedbackDataRep.java
-
13src/main/java/com/feedback/it_asset/repository/GccFeedbackRep.java
-
14src/main/java/com/feedback/it_asset/repository/UserRepository.java
-
78src/main/java/com/feedback/it_asset/service/AssetDetailsService.java
-
81src/main/java/com/feedback/it_asset/service/GccAssetService.java
-
3src/main/resources/application.properties
-
452src/main/resources/templates/closedchart.html
-
394src/main/resources/templates/dashboard.html
-
54src/main/resources/templates/gcc-asset-list.html
-
21src/main/resources/templates/gcc-complaint.html
-
409src/main/resources/templates/old-dashboard.html
-
2src/main/resources/templates/pending-complaint.html
-
455src/main/resources/templates/pendingchart.html
-
62src/main/resources/templates/testdashboard.html
-
452src/main/resources/templates/totalchart.html
@ -0,0 +1,2 @@ |
|||||
|
distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.5/apache-maven-3.9.5-bin.zip |
||||
|
wrapperUrl=https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar |
||||
@ -1,59 +1,59 @@ |
|||||
package com.feedback.it_asset.component; |
|
||||
|
|
||||
import java.util.Arrays; |
|
||||
import java.util.List; |
|
||||
|
|
||||
import org.springframework.beans.factory.annotation.Autowired; |
|
||||
import org.springframework.stereotype.Component; |
|
||||
import org.springframework.web.servlet.HandlerInterceptor; |
|
||||
|
|
||||
import com.feedback.it_asset.AppConfig; |
|
||||
import com.feedback.it_asset.UserSession; |
|
||||
import jakarta.servlet.http.HttpServletRequest; |
|
||||
import jakarta.servlet.http.HttpServletResponse; |
|
||||
|
|
||||
@Component |
|
||||
public class UserSessionInterceptor implements HandlerInterceptor { |
|
||||
|
|
||||
@Autowired |
|
||||
private UserSession userSession; |
|
||||
@Autowired |
|
||||
private AppConfig appConfig; |
|
||||
|
|
||||
private static final List<String> EXCLUDED_URLS = Arrays.asList("/login", "/", "/api"); |
|
||||
@Override |
|
||||
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { |
|
||||
// Get the current request URL |
|
||||
String requestUrl = request.getRequestURI(); |
|
||||
|
|
||||
// Exclude static resources from the check |
|
||||
if (requestUrl.startsWith("/assets/") || requestUrl.startsWith("/css/") || requestUrl.startsWith("/js/") || requestUrl.startsWith("/images/") || requestUrl.startsWith("/api/")) { |
|
||||
return true; // Allow the request to proceed without checking the login status |
|
||||
} |
|
||||
|
|
||||
// Exclude the login page from the check |
|
||||
// Exclude specific URLs from the check |
|
||||
if (EXCLUDED_URLS.contains(requestUrl)) { |
|
||||
return true; // Allow the request to proceed without checking the login status |
|
||||
} |
|
||||
// Check if the user is logged in |
|
||||
// If logged in, add the userSession to the model |
|
||||
// Return true to allow the request to proceed |
|
||||
//if (isLoggedIn()) { |
|
||||
if(userSession.getUserId() != null && userSession.getUserType() != null) { |
|
||||
request.setAttribute("userSession", userSession); |
|
||||
} else { |
|
||||
request.setAttribute("title", "Login"); |
|
||||
request.setAttribute("baseURL", appConfig.getBaseUrl()); |
|
||||
response.sendRedirect("/login"); |
|
||||
return false; // Stop further processing of the request |
|
||||
} |
|
||||
return true; // Allow the request to proceed |
|
||||
} |
|
||||
|
|
||||
private boolean isLoggedIn() { |
|
||||
// Implement your login check logic here |
|
||||
// For example, check if the userSession contains the necessary information |
|
||||
return userSession.getUserId() != null && userSession.getUserType() != null; |
|
||||
} |
|
||||
} |
|
||||
|
//package com.feedback.it_asset.component; |
||||
|
// |
||||
|
//import java.util.Arrays; |
||||
|
//import java.util.List; |
||||
|
// |
||||
|
//import org.springframework.beans.factory.annotation.Autowired; |
||||
|
//import org.springframework.stereotype.Component; |
||||
|
//import org.springframework.web.servlet.HandlerInterceptor; |
||||
|
// |
||||
|
//import com.feedback.it_asset.AppConfig; |
||||
|
//import com.feedback.it_asset.UserSession; |
||||
|
//import jakarta.servlet.http.HttpServletRequest; |
||||
|
//import jakarta.servlet.http.HttpServletResponse; |
||||
|
// |
||||
|
//@Component |
||||
|
//public class UserSessionInterceptor implements HandlerInterceptor { |
||||
|
// |
||||
|
// @Autowired |
||||
|
// private UserSession userSession; |
||||
|
// @Autowired |
||||
|
// private AppConfig appConfig; |
||||
|
// |
||||
|
// private static final List<String> EXCLUDED_URLS = Arrays.asList("/login", "/", "/api"); |
||||
|
// @Override |
||||
|
// public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { |
||||
|
// // Get the current request URL |
||||
|
// String requestUrl = request.getRequestURI(); |
||||
|
// |
||||
|
// // Exclude static resources from the check |
||||
|
// if (requestUrl.startsWith("/assets/") || requestUrl.startsWith("/css/") || requestUrl.startsWith("/js/") || requestUrl.startsWith("/images/") || requestUrl.startsWith("/api/")) { |
||||
|
// return true; // Allow the request to proceed without checking the login status |
||||
|
// } |
||||
|
// |
||||
|
// // Exclude the login page from the check |
||||
|
// // Exclude specific URLs from the check |
||||
|
// if (EXCLUDED_URLS.contains(requestUrl)) { |
||||
|
// return true; // Allow the request to proceed without checking the login status |
||||
|
// } |
||||
|
// // Check if the user is logged in |
||||
|
// // If logged in, add the userSession to the model |
||||
|
// // Return true to allow the request to proceed |
||||
|
// //if (isLoggedIn()) { |
||||
|
// if(userSession.getUserId() != null && userSession.getUserType() != null) { |
||||
|
// request.setAttribute("userSession", userSession); |
||||
|
// } else { |
||||
|
// request.setAttribute("title", "Login"); |
||||
|
// request.setAttribute("baseURL", appConfig.getBaseUrl()); |
||||
|
// response.sendRedirect("/login"); |
||||
|
// return false; // Stop further processing of the request |
||||
|
// } |
||||
|
// return true; // Allow the request to proceed |
||||
|
// } |
||||
|
// |
||||
|
// private boolean isLoggedIn() { |
||||
|
// // Implement your login check logic here |
||||
|
// // For example, check if the userSession contains the necessary information |
||||
|
// return userSession.getUserId() != null && userSession.getUserType() != null; |
||||
|
// } |
||||
|
//} |
||||
@ -0,0 +1,18 @@ |
|||||
|
package com.feedback.it_asset.dto; |
||||
|
|
||||
|
public class FeedbackCountResponse { |
||||
|
|
||||
|
private long[] counts; |
||||
|
|
||||
|
public long[] getCounts() { |
||||
|
return counts; |
||||
|
} |
||||
|
|
||||
|
public void setCounts(long[] counts) { |
||||
|
this.counts = counts; |
||||
|
} |
||||
|
|
||||
|
|
||||
|
|
||||
|
|
||||
|
} |
||||
@ -0,0 +1,6 @@ |
|||||
|
package com.feedback.it_asset.dto; |
||||
|
|
||||
|
public class ItAssetDashboardDto { |
||||
|
|
||||
|
|
||||
|
} |
||||
@ -0,0 +1,34 @@ |
|||||
|
package com.feedback.it_asset.dto; |
||||
|
public class MonthWiseCountsDTO { |
||||
|
private long onlyYesCount; |
||||
|
private long onlyNoCount; |
||||
|
|
||||
|
// Constructors, getters, setters, etc. |
||||
|
|
||||
|
public MonthWiseCountsDTO() { |
||||
|
// default constructor |
||||
|
} |
||||
|
|
||||
|
public MonthWiseCountsDTO(long onlyYesCount, long onlyNoCount) { |
||||
|
this.onlyYesCount = onlyYesCount; |
||||
|
this.onlyNoCount = onlyNoCount; |
||||
|
} |
||||
|
|
||||
|
public long getOnlyYesCount() { |
||||
|
return onlyYesCount; |
||||
|
} |
||||
|
|
||||
|
public void setOnlyYesCount(long onlyYesCount) { |
||||
|
this.onlyYesCount = onlyYesCount; |
||||
|
} |
||||
|
|
||||
|
public long getOnlyNoCount() { |
||||
|
return onlyNoCount; |
||||
|
} |
||||
|
|
||||
|
public void setOnlyNoCount(long onlyNoCount) { |
||||
|
this.onlyNoCount = onlyNoCount; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
|
||||
@ -0,0 +1,40 @@ |
|||||
|
package com.feedback.it_asset.entity; |
||||
|
|
||||
|
import com.fasterxml.jackson.annotation.JsonIgnoreProperties; |
||||
|
|
||||
|
import jakarta.persistence.Column; |
||||
|
import jakarta.persistence.Entity; |
||||
|
import jakarta.persistence.GeneratedValue; |
||||
|
import jakarta.persistence.GenerationType; |
||||
|
import jakarta.persistence.Id; |
||||
|
import jakarta.persistence.Table; |
||||
|
|
||||
|
@Entity |
||||
|
@JsonIgnoreProperties({ "hibernateLazyInitializer", "handler"}) |
||||
|
@Table(name = "roles") |
||||
|
public class Role { |
||||
|
@Id |
||||
|
@Column(name = "role_id") |
||||
|
@GeneratedValue(strategy = GenerationType.IDENTITY) |
||||
|
private Integer id; |
||||
|
|
||||
|
private String name; |
||||
|
public Integer getId() { |
||||
|
return id; |
||||
|
} |
||||
|
|
||||
|
public Role() { |
||||
|
} |
||||
|
|
||||
|
public void setId(Integer id) { |
||||
|
this.id = id; |
||||
|
} |
||||
|
|
||||
|
public String getName() { |
||||
|
return name; |
||||
|
} |
||||
|
|
||||
|
public void setName(String name) { |
||||
|
this.name = name; |
||||
|
} |
||||
|
} |
||||
@ -1,43 +1,133 @@ |
|||||
package com.feedback.it_asset.entity; |
package com.feedback.it_asset.entity; |
||||
|
|
||||
|
import java.util.HashSet; |
||||
|
import java.util.Set; |
||||
|
|
||||
|
import com.fasterxml.jackson.annotation.JsonIgnoreProperties; |
||||
|
|
||||
|
import jakarta.persistence.CascadeType; |
||||
|
import jakarta.persistence.Column; |
||||
import jakarta.persistence.Entity; |
import jakarta.persistence.Entity; |
||||
import jakarta.persistence.GeneratedValue; |
|
||||
import jakarta.persistence.GenerationType; |
|
||||
|
import jakarta.persistence.FetchType; |
||||
import jakarta.persistence.Id; |
import jakarta.persistence.Id; |
||||
|
import jakarta.persistence.JoinColumn; |
||||
|
import jakarta.persistence.JoinTable; |
||||
|
import jakarta.persistence.ManyToMany; |
||||
|
import jakarta.persistence.Table; |
||||
|
|
||||
@Entity |
@Entity |
||||
|
@JsonIgnoreProperties({ "hibernateLazyInitializer", "handler"}) |
||||
|
@Table(name = "users") |
||||
public class User { |
public class User { |
||||
|
|
||||
@Id |
@Id |
||||
@GeneratedValue(strategy = GenerationType.IDENTITY) |
|
||||
private int id; |
|
||||
private String username; |
|
||||
private String password; |
|
||||
private String usertype; |
|
||||
public int getId() { |
|
||||
return id; |
|
||||
} |
|
||||
public void setId(int id) { |
|
||||
this.id = id; |
|
||||
} |
|
||||
public String getUsername() { |
|
||||
return username; |
|
||||
} |
|
||||
public void setUsername(String username) { |
|
||||
this.username = username; |
|
||||
} |
|
||||
public String getPassword() { |
|
||||
return password; |
|
||||
} |
|
||||
public void setPassword(String password) { |
|
||||
this.password = password; |
|
||||
} |
|
||||
public String getUsertype() { |
|
||||
return usertype; |
|
||||
} |
|
||||
public void setUsertype(String usertype) { |
|
||||
this.usertype = usertype; |
|
||||
} |
|
||||
|
|
||||
|
|
||||
} |
|
||||
|
@Column(name = "user_id") |
||||
|
private Long id; |
||||
|
@Column(name = "first_name") |
||||
|
private String firstName; |
||||
|
@Column(name = "last_name") |
||||
|
private String lastName; |
||||
|
@Column(name = "display_name") |
||||
|
private String displayName; |
||||
|
@Column(name = "uname") |
||||
|
private String userameTxt; |
||||
|
@Column(name = "pword") |
||||
|
private String passwordTxt; |
||||
|
|
||||
|
@Column(name = "isdelete",nullable = false, columnDefinition = "Boolean default false") |
||||
|
private Boolean isDelete; |
||||
|
@Column(name = "isactive",nullable = false, columnDefinition = "Boolean default true") |
||||
|
private Boolean isActive; |
||||
|
@Column(name = "cdate",nullable = false, columnDefinition = "DATETIME DEFAULT CURRENT_TIMESTAMP") |
||||
|
private String cDate; |
||||
|
|
||||
|
@ManyToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER) |
||||
|
@JoinTable( |
||||
|
name = "users_roles", |
||||
|
joinColumns = @JoinColumn(name = "user_id"), |
||||
|
inverseJoinColumns = @JoinColumn(name = "role_id") |
||||
|
) |
||||
|
private Set<Role> roles = new HashSet<>(); |
||||
|
|
||||
|
public User() { |
||||
|
} |
||||
|
|
||||
|
public Long getId() { |
||||
|
return id; |
||||
|
} |
||||
|
|
||||
|
public void setId(Long id) { |
||||
|
this.id = id; |
||||
|
} |
||||
|
|
||||
|
public String getFirstName() { |
||||
|
return firstName; |
||||
|
} |
||||
|
|
||||
|
public void setFirstName(String firstName) { |
||||
|
this.firstName = firstName; |
||||
|
} |
||||
|
|
||||
|
public String getLastName() { |
||||
|
return lastName; |
||||
|
} |
||||
|
|
||||
|
public void setLastName(String lastName) { |
||||
|
this.lastName = lastName; |
||||
|
} |
||||
|
|
||||
|
public String getDisplayName() { |
||||
|
return displayName; |
||||
|
} |
||||
|
|
||||
|
public void setDisplayName(String displayName) { |
||||
|
this.displayName = displayName; |
||||
|
} |
||||
|
|
||||
|
public String getUserameTxt() { |
||||
|
return userameTxt; |
||||
|
} |
||||
|
|
||||
|
public void setUserameTxt(String userameTxt) { |
||||
|
this.userameTxt = userameTxt; |
||||
|
} |
||||
|
|
||||
|
public String getPasswordTxt() { |
||||
|
return passwordTxt; |
||||
|
} |
||||
|
|
||||
|
public void setPasswordTxt(String passwordTxt) { |
||||
|
this.passwordTxt = passwordTxt; |
||||
|
} |
||||
|
|
||||
|
public Boolean getDelete() { |
||||
|
return isDelete; |
||||
|
} |
||||
|
|
||||
|
public void setDelete(Boolean delete) { |
||||
|
isDelete = delete; |
||||
|
} |
||||
|
|
||||
|
public Boolean getActive() { |
||||
|
return isActive; |
||||
|
} |
||||
|
|
||||
|
public void setActive(Boolean active) { |
||||
|
isActive = active; |
||||
|
} |
||||
|
|
||||
|
public String getcDate() { |
||||
|
return cDate; |
||||
|
} |
||||
|
|
||||
|
public void setcDate(String cDate) { |
||||
|
this.cDate = cDate; |
||||
|
} |
||||
|
|
||||
|
public Set<Role> getRoles() { |
||||
|
return roles; |
||||
|
} |
||||
|
|
||||
|
public void setRoles(Set<Role> roles) { |
||||
|
this.roles = roles; |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,57 @@ |
|||||
|
package com.feedback.it_asset.entity; |
||||
|
|
||||
|
import com.fasterxml.jackson.annotation.JsonIgnoreProperties; |
||||
|
|
||||
|
import jakarta.persistence.Entity; |
||||
|
import jakarta.persistence.GeneratedValue; |
||||
|
import jakarta.persistence.GenerationType; |
||||
|
import jakarta.persistence.Id; |
||||
|
import jakarta.persistence.JoinColumn; |
||||
|
import jakarta.persistence.ManyToOne; |
||||
|
import jakarta.persistence.Table; |
||||
|
|
||||
|
@Entity |
||||
|
@JsonIgnoreProperties({ "hibernateLazyInitializer", "handler"}) |
||||
|
@Table(name = "users_roles") |
||||
|
public class UserRole { |
||||
|
@Id |
||||
|
@GeneratedValue(strategy = GenerationType.IDENTITY) |
||||
|
private Long id; |
||||
|
|
||||
|
@ManyToOne |
||||
|
@JoinColumn(name = "user_id", referencedColumnName = "user_id") |
||||
|
private User user; |
||||
|
|
||||
|
@ManyToOne |
||||
|
@JoinColumn(name = "role_id", referencedColumnName = "role_id") |
||||
|
private Role role; |
||||
|
|
||||
|
// constructor, getters, and setters |
||||
|
|
||||
|
public UserRole() { |
||||
|
} |
||||
|
|
||||
|
public Long getId() { |
||||
|
return id; |
||||
|
} |
||||
|
|
||||
|
public void setId(Long id) { |
||||
|
this.id = id; |
||||
|
} |
||||
|
|
||||
|
public User getUser() { |
||||
|
return user; |
||||
|
} |
||||
|
|
||||
|
public void setUser(User user) { |
||||
|
this.user = user; |
||||
|
} |
||||
|
|
||||
|
public Role getRole() { |
||||
|
return role; |
||||
|
} |
||||
|
|
||||
|
public void setRole(Role role) { |
||||
|
this.role = role; |
||||
|
} |
||||
|
} |
||||
@ -1,78 +0,0 @@ |
|||||
package com.feedback.it_asset.service; |
|
||||
|
|
||||
import java.sql.Connection; |
|
||||
import java.sql.DriverManager; |
|
||||
import java.sql.PreparedStatement; |
|
||||
import java.sql.SQLException; |
|
||||
|
|
||||
import org.springframework.stereotype.Service; |
|
||||
|
|
||||
|
|
||||
@Service |
|
||||
public class AssetDetailsService { |
|
||||
|
|
||||
|
|
||||
private static final String SOURCE_JDBC_URL = "jdbc:mysql://localhost:3306/gcc_asset_details"; |
|
||||
private static final String DESTINATION_JDBC_URL = "jdbc:mysql://localhost:3306/it_assets"; |
|
||||
private static final String SOURCE_USERNAME = "root"; |
|
||||
private static final String SOURCE_PASSWORD = "root"; |
|
||||
private static final String DESTINATION_USERNAME = "root"; |
|
||||
private static final String DESTINATION_PASSWORD = "root"; |
|
||||
|
|
||||
public void migrateData() { |
|
||||
try { |
|
||||
// Load the JDBC driver |
|
||||
Class.forName("com.mysql.cj.jdbc.Driver"); |
|
||||
|
|
||||
// Establish connections for source and destination databases |
|
||||
try ( |
|
||||
Connection sourceConnection = DriverManager.getConnection(SOURCE_JDBC_URL, SOURCE_USERNAME, SOURCE_PASSWORD); |
|
||||
Connection destinationConnection = DriverManager.getConnection(DESTINATION_JDBC_URL, DESTINATION_USERNAME, DESTINATION_PASSWORD) |
|
||||
) { |
|
||||
// SQL query to fetch data from the source schema |
|
||||
String sqlQuery = "SELECT ta.ASSET_ID, ta.ASSET_NO, td.DEPT_NAME, tl.LOC_NAME, tsu.SEC_USER_NAME " + |
|
||||
"FROM tbl_asset ta " + |
|
||||
"JOIN tbl_mas_dept td ON ta.DEPT_ID = td.DEPT_ID " + |
|
||||
"JOIN tbl_mas_loc tl ON ta.LOC_ID = tl.LOC_ID " + |
|
||||
"JOIN tbl_mas_sec_user tsu ON ta.SECUSER_ID = tsu.SEC_USER_ID "; |
|
||||
|
|
||||
|
|
||||
// Create a prepared statement for the source database |
|
||||
try (PreparedStatement preparedStatementSource = sourceConnection.prepareStatement(sqlQuery)) { |
|
||||
|
|
||||
// Execute the query in the source database |
|
||||
try (var resultSet = preparedStatementSource.executeQuery()) { |
|
||||
// SQL query to insert data into the destination schema for asset_data |
|
||||
String insertAssetDataQuery = "INSERT INTO gcc_asset_details (asset_id, asset_code, department_name, position, assign_person) VALUES (?, ?, ?, ?, ?)"; |
|
||||
|
|
||||
// SQL query to insert data into the destination schema for asset_category |
|
||||
// String insertAssetCategoryQuery = "INSERT INTO asset_category (category_name) VALUES (?)"; |
|
||||
|
|
||||
// Create prepared statements for the destination database |
|
||||
try (PreparedStatement preparedStatementDestinationAssetData = destinationConnection.prepareStatement(insertAssetDataQuery)) { |
|
||||
|
|
||||
// Process the result set and insert data into the destination schema |
|
||||
while (resultSet.next()) { |
|
||||
// Insert data into asset_data table |
|
||||
preparedStatementDestinationAssetData.setString(1, resultSet.getString("ASSET_ID")); |
|
||||
preparedStatementDestinationAssetData.setString(2, resultSet.getString("ASSET_NO")); |
|
||||
preparedStatementDestinationAssetData.setString(3, resultSet.getString("DEPT_NAME")); |
|
||||
preparedStatementDestinationAssetData.setString(4, resultSet.getString("LOC_NAME")); |
|
||||
preparedStatementDestinationAssetData.setString(5, resultSet.getString("SEC_USER_NAME")); |
|
||||
int rowsAffectedAssetData = preparedStatementDestinationAssetData.executeUpdate(); |
|
||||
System.out.println("Rows affected for asset_data: " + rowsAffectedAssetData); |
|
||||
|
|
||||
// Insert data into asset_category table |
|
||||
// preparedStatementDestinationAssetCategory.setString(1, resultSet.getString("category_name")); |
|
||||
// int rowsAffectedAssetCategory = preparedStatementDestinationAssetCategory.executeUpdate(); |
|
||||
// System.out.println("Rows affected for asset_category: " + rowsAffectedAssetCategory); |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
} catch (ClassNotFoundException | SQLException e) { |
|
||||
e.printStackTrace(); // Handle the exception appropriately |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
@ -0,0 +1,452 @@ |
|||||
|
<!doctype html> |
||||
|
<html xmlns:th="http://www.thymeleaf.org"> |
||||
|
<head th:replace="fragments/head :: head"></head> |
||||
|
|
||||
|
<body> |
||||
|
<!-- Page Container --> |
||||
|
<div id="page-container" class="sidebar-o sidebar-dark enable-page-overlay side-scroll page-header-fixed page-header-dark"> |
||||
|
<!-- Side Overlay aside (right)--> |
||||
|
<aside th:replace="fragments/aside-right :: aside"></aside> |
||||
|
<!-- END Side Overlay (right)--> |
||||
|
|
||||
|
<!-- Sidebar Nav--> |
||||
|
<nav th:replace="fragments/nav :: nav"></nav> |
||||
|
<!-- END Sidebar --> |
||||
|
|
||||
|
<!-- Header --> |
||||
|
<header th:replace="fragments/header :: header"></header> |
||||
|
<!-- END Header --> |
||||
|
|
||||
|
<!-- Main Container --> |
||||
|
<main id="main-container"> |
||||
|
<!-- Hero --> |
||||
|
<div class=""> |
||||
|
<div class="content content-full"> |
||||
|
<div class="d-flex flex-column flex-sm-row justify-content-sm-between align-items-sm-center"> |
||||
|
<h3 class="flex-grow-1 fs-5 fw-semibold my-2 my-sm-3">Welcome</h3> |
||||
|
<nav class="flex-shrink-0 my-2 my-sm-0 ms-sm-3" aria-label="breadcrumb"> |
||||
|
<ol class="breadcrumb"> |
||||
|
<li class="breadcrumb-item">Home</li> |
||||
|
<li class="breadcrumb-item active" aria-current="page">Dashboard</li> |
||||
|
</ol> |
||||
|
</nav> |
||||
|
</div> |
||||
|
</div> |
||||
|
</div> |
||||
|
<!-- END Hero --> |
||||
|
|
||||
|
<!-- Page Content --> |
||||
|
<div class="content"> |
||||
|
<!-- Overview --> |
||||
|
<div class="row items-push"> |
||||
|
<div class="col-sm-6 col-xl-3"> |
||||
|
<div class="block block-rounded text-center d-flex flex-column h-100 mb-0"> |
||||
|
<div class="block-content block-content-full flex-grow-1"> |
||||
|
<div class="item rounded-3 bg-body mx-auto my-3"> |
||||
|
<i class="fa fa-qrcode fa-lg text-primary"></i> |
||||
|
</div> |
||||
|
<div class="fs-2 fw-bold text-success" th:utext="${totalAssets}">000</div> |
||||
|
<div class="text-muted mb-1 fs-5">Total Asset</div> |
||||
|
|
||||
|
</div> |
||||
|
<div class="block-content block-content-full block-content-sm bg-body-light fs-sm"> |
||||
|
<a class="fw-medium" href="/gcc-asset-list"> |
||||
|
View all Assets |
||||
|
<i class="fa fa-arrow-right ms-1 opacity-25"></i> |
||||
|
</a> |
||||
|
</div> |
||||
|
</div> |
||||
|
</div> |
||||
|
<div class="col-sm-6 col-xl-3"> |
||||
|
<div class="block block-rounded text-center d-flex flex-column h-100 mb-0"> |
||||
|
<div class="block-content block-content-full flex-grow-1"> |
||||
|
<div class="item rounded-3 bg-body mx-auto my-3"> |
||||
|
<i class="fa fa-comments fa-lg text-primary"></i> |
||||
|
</div> |
||||
|
<div class="fs-2 fw-bold text-info" th:utext="${totalFeedbacks}">000</div> |
||||
|
<div class="text-muted mb-1 fs-5">Total Complaints</div> |
||||
|
|
||||
|
</div> |
||||
|
<div class="block-content block-content-full block-content-sm bg-body-light fs-sm"> |
||||
|
<a class="fw-medium" href="/complaint-list"> |
||||
|
View all Complaints |
||||
|
<i class="fa fa-arrow-right ms-1 opacity-25"></i> |
||||
|
</a> |
||||
|
</div> |
||||
|
</div> |
||||
|
</div> |
||||
|
<div class="col-sm-6 col-xl-3"> |
||||
|
<div class="block block-rounded text-center d-flex flex-column h-100 mb-0"> |
||||
|
<div class="block-content block-content-full flex-grow-1"> |
||||
|
<div class="item rounded-3 bg-body mx-auto my-3"> |
||||
|
<i class="fa fa-thumbs-up fa-lg text-primary"></i> |
||||
|
</div> |
||||
|
<div class="fs-2 fw-bold text-success" th:utext="${totalYesFeedbacks}">000</div> |
||||
|
<div class="text-muted mb-1 fs-5">Total closed Complaints</div> |
||||
|
|
||||
|
</div> |
||||
|
<div class="block-content block-content-full block-content-sm bg-body-light fs-sm"> |
||||
|
<a class="fw-medium" href="/closed-complaint"> |
||||
|
View all Closed Complaints |
||||
|
<i class="fa fa-arrow-right ms-1 opacity-25"></i> |
||||
|
</a> |
||||
|
</div> |
||||
|
</div> |
||||
|
</div> |
||||
|
<div class="col-sm-6 col-xl-3"> |
||||
|
<div class="block block-rounded text-center d-flex flex-column h-100 mb-0"> |
||||
|
<div class="block-content block-content-full"> |
||||
|
<div class="item rounded-3 bg-body mx-auto my-3"> |
||||
|
<i class="fa fa-thumbs-down fa-lg text-primary"></i> |
||||
|
</div> |
||||
|
<div class="fs-2 fw-bold text-warning" th:utext="${totalNoFeedbacks}">000</div> |
||||
|
<div class="text-muted mb-1 fs-5">Total Pending Complaints</div> |
||||
|
|
||||
|
</div> |
||||
|
<div class="block-content block-content-full block-content-sm bg-body-light fs-sm"> |
||||
|
<a class="fw-medium" href="/pending-complaint"> |
||||
|
View all Pending Complaint |
||||
|
<i class="fa fa-arrow-right ms-1 opacity-25"></i> |
||||
|
</a> |
||||
|
</div> |
||||
|
</div> |
||||
|
</div> |
||||
|
</div> |
||||
|
<!-- END Overview --> |
||||
|
|
||||
|
<!-- Store Growth --> |
||||
|
|
||||
|
<div class="row"> |
||||
|
<div class="col-12 col-md-6 col-xl-6"> |
||||
|
<div class="p-md-2 p-lg-3 w-100" style="height: 400px;"> |
||||
|
<!-- Chart 1 Container --> |
||||
|
<canvas id="myChart1"></canvas> |
||||
|
</div> |
||||
|
</div> |
||||
|
|
||||
|
<div class="col-12 col-md-6 col-xl-6"> |
||||
|
<div class="p-md-2 p-lg-3 w-100" style="height: 500px;"> |
||||
|
<!-- Chart 2 Container --> |
||||
|
<canvas id="myChart"></canvas> |
||||
|
</div> |
||||
|
</div> |
||||
|
</div> |
||||
|
|
||||
|
|
||||
|
</div> |
||||
|
</div> |
||||
|
|
||||
|
</div> |
||||
|
<!-- END Store Growth --> |
||||
|
|
||||
|
<!-- Latest Orders + Stats --> |
||||
|
|
||||
|
<!-- END Latest Orders + Stats --> |
||||
|
</div> |
||||
|
<!-- END Page Content --> |
||||
|
</main> |
||||
|
<!-- END Main Container --> |
||||
|
|
||||
|
<!-- Footer --> |
||||
|
<footer th:replace="fragments/footer :: footer"></footer> |
||||
|
<!-- END Footer --> |
||||
|
</div> |
||||
|
<!-- END Page Container --> |
||||
|
|
||||
|
<!-- Scripts --> |
||||
|
<!-- Include jQuery --> |
||||
|
<script src="https://code.jquery.com/jquery-3.6.4.min.js"></script> |
||||
|
<!-- Your existing script tag follows --> |
||||
|
<script th:replace="fragments/script :: script"></script> |
||||
|
<!-- Page JS Plugins --> |
||||
|
<script src="assets/js/plugins/chart.js/chart.umd.js"></script> |
||||
|
<!-- Include Date Range Picker --> |
||||
|
<script type="text/javascript" src="assets/js/plugins/bootstrap-daterangepicker/daterangepicker.js"></script> |
||||
|
<link rel="stylesheet" type="text/css" href="assets/js/plugins/bootstrap-daterangepicker/daterangepicker.css" /> |
||||
|
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script> |
||||
|
|
||||
|
<script> |
||||
|
var dash = {}; |
||||
|
|
||||
|
function convert() { |
||||
|
// Ensure proper initialization logic for feedbackAnalysisData |
||||
|
dash.feedbackAnalysisData = /*[[${dashboard}]]*/ {}; |
||||
|
} |
||||
|
|
||||
|
convert(); |
||||
|
|
||||
|
|
||||
|
var pageDashboard = { |
||||
|
chartBars: undefined, |
||||
|
chartLinesBarsData: { |
||||
|
datasets: [ |
||||
|
{ data: [] }, // Assuming totalYesFeedbacks is an array |
||||
|
{ data: [] }, |
||||
|
{data:[] } // Assuming totalNoFeedbacks is an array |
||||
|
] |
||||
|
}, |
||||
|
|
||||
|
initChart: function (feedbackAnalysis) { |
||||
|
// Set Global Chart.js configuration |
||||
|
Chart.defaults.color = '#818d96'; |
||||
|
Chart.defaults.scale.grid.color = 'transparent'; |
||||
|
Chart.defaults.scale.grid.zeroLineColor = 'transparent'; |
||||
|
Chart.defaults.scale.beginAtZero = true; |
||||
|
Chart.defaults.elements.line.borderWidth = 1; |
||||
|
Chart.defaults.plugins.legend.labels.boxWidth = 12; |
||||
|
|
||||
|
// Get Chart Container |
||||
|
let chartBarsCon = document.getElementById('myChart'); |
||||
|
|
||||
|
var data = { |
||||
|
labels: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'], |
||||
|
datasets: [ |
||||
|
{ |
||||
|
label: 'Pending Complaint', |
||||
|
data: [], |
||||
|
fill: true, |
||||
|
backgroundColor: '#e74c3c', |
||||
|
borderColor: 'transparent', |
||||
|
pointBackgroundColor: '#c2d7ab', |
||||
|
pointBorderColor: '#fff', |
||||
|
pointHoverBackgroundColor: '#c0392b', |
||||
|
pointHoverBorderColor: '#c2d7ab', |
||||
|
}, |
||||
|
|
||||
|
] |
||||
|
}; |
||||
|
|
||||
|
|
||||
|
var options = { |
||||
|
responsive: true, |
||||
|
scales: { |
||||
|
x: { beginAtZero: true }, |
||||
|
y: { beginAtZero: true } |
||||
|
}, |
||||
|
plugins: { |
||||
|
datalabels: { |
||||
|
anchor: 'end', |
||||
|
align: 'end', |
||||
|
color: 'black', |
||||
|
formatter: function (value, context) { |
||||
|
// Display the value only if it's greater than 0 |
||||
|
return value > 0 ? value : ''; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
}; |
||||
|
|
||||
|
// Create the chart |
||||
|
this.chartBars = new Chart(chartBarsCon, { |
||||
|
type: 'bar', |
||||
|
data: data, |
||||
|
options: options |
||||
|
}); |
||||
|
}, |
||||
|
updateChartLinesBarsData: function (newData) { |
||||
|
// Ensure the chart is initialized before updating |
||||
|
if (this.chartBars) { |
||||
|
// Assuming labels for the chart are ['Jan', 'Feb', 'Mar', ..., 'Dec'] |
||||
|
var labels = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']; |
||||
|
|
||||
|
// Initialize arrays with values from dataArray |
||||
|
var totalFeedbacksData = Array.from({ length: labels.length }, (_, index) => { |
||||
|
return newData.reduce((sum, item) => { |
||||
|
const key = Object.keys(item)[0]; |
||||
|
const dataArray = item[key]; |
||||
|
// console.log(totalFeedbacksData[${index}]: ${dataArray[index]}); |
||||
|
return sum + dataArray[index]; |
||||
|
}, 0); |
||||
|
}); |
||||
|
|
||||
|
var totalYesFeedbacksData = Array.from({ length: labels.length }, (_, index) => { |
||||
|
return newData.reduce((sum, item) => { |
||||
|
const key = Object.keys(item)[0]; |
||||
|
const dataArray = item[key]; |
||||
|
// console.log(totalYesFeedbacksData[${index}]: ${dataArray[index]}); |
||||
|
return dataArray[index]; |
||||
|
}, 0); |
||||
|
}); |
||||
|
|
||||
|
// Subtract totalYesFeedbacksData from totalFeedbacksData |
||||
|
var totalNoFeedbacksData = totalFeedbacksData.map((value, index) => value - totalYesFeedbacksData[index]); |
||||
|
|
||||
|
// Update the chart data |
||||
|
// this.chartBars.data.datasets[0].data = totalFeedbacksData; |
||||
|
this.chartBars.data.datasets[0].data = totalYesFeedbacksData; |
||||
|
//this.chartBars.data.datasets[0].data = totalNoFeedbacksData; |
||||
|
|
||||
|
// Log the updated chart data |
||||
|
// console.log('Updated chart data (totalFeedbacksData):', this.chartBars.data.datasets[0].data); |
||||
|
//console.log('Updated chart data (totalYesFeedbacksData):', this.chartBars.data.datasets[1].data); |
||||
|
//console.log('Updated chart data (totalNoFeedbacksData):', this.chartBars.data.datasets[2].data); |
||||
|
|
||||
|
// Update the chart |
||||
|
this.chartBars.update(); |
||||
|
} else { |
||||
|
console.error('Chart is not initialized. Unable to update data.'); |
||||
|
} |
||||
|
}, |
||||
|
|
||||
|
|
||||
|
|
||||
|
getAndPushData: function (cdate) { |
||||
|
// Ensure convert() is called before accessing dash.feedbackAnalysisData |
||||
|
convert(); |
||||
|
|
||||
|
var self = this; |
||||
|
|
||||
|
$.ajax({ |
||||
|
url: 'api/cou/' + cdate, |
||||
|
method: 'GET', |
||||
|
dataType: 'json', |
||||
|
success: function (response) { |
||||
|
console.log('Data fetched successfully:', response); |
||||
|
self.updateChartLinesBarsData(response); |
||||
|
}, |
||||
|
error: function (xhr, status, error) { |
||||
|
console.error('Error:', error); |
||||
|
} |
||||
|
}); |
||||
|
} |
||||
|
}; |
||||
|
|
||||
|
// Call the initChart function with the feedbackAnalysis data |
||||
|
pageDashboard.initChart(dash.feedbackAnalysisData || {}); |
||||
|
|
||||
|
// Call the getAndPushData method to fetch and update chart data |
||||
|
pageDashboard.getAndPushData(); |
||||
|
|
||||
|
pageDashboard.getAndPushData(); |
||||
|
var pageDashboard = { |
||||
|
chartPie: undefined, |
||||
|
chartPieData: { |
||||
|
labels: ['Total Complaints', 'Closed Complaint', 'Pending Complaint'], |
||||
|
datasets: [ |
||||
|
{ |
||||
|
data: [], |
||||
|
backgroundColor: ['#3498db', '#e74c3c', '#cc6633'], |
||||
|
hoverBackgroundColor: ['#2980b9', '#c0392b', '#A35128'] |
||||
|
} |
||||
|
] |
||||
|
}, |
||||
|
|
||||
|
initChart: function () { |
||||
|
// Get Chart Container |
||||
|
let chartPieCon = document.getElementById('myChart1'); |
||||
|
|
||||
|
var options = { |
||||
|
responsive: true, |
||||
|
plugins: { |
||||
|
datalabels: { |
||||
|
color: 'black', |
||||
|
formatter: function (value) { |
||||
|
// Display the value only if it's greater than 0 |
||||
|
return value > 0 ? value : ''; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
}; |
||||
|
|
||||
|
// Create the chart |
||||
|
this.chartPie = new Chart(chartPieCon, { |
||||
|
type: 'pie', |
||||
|
data: this.chartPieData, |
||||
|
options: options |
||||
|
}); |
||||
|
|
||||
|
// Add click event listener to the chart container |
||||
|
chartPieCon.onclick = function (event) { |
||||
|
var elements = pageDashboard.chartPie.getElementsAtEventForMode(event, 'point', pageDashboard.chartPie.options); |
||||
|
|
||||
|
if (elements && elements.length > 0) { |
||||
|
var clickedIndex = elements[0].index; |
||||
|
console.log('Clicked Index:', clickedIndex); |
||||
|
console.log('Elements:', elements); |
||||
|
console.log('Labels:', pageDashboard.chartPieData.labels); |
||||
|
|
||||
|
} else { |
||||
|
console.error('No elements found at the click event.'); |
||||
|
} |
||||
|
if (clickedIndex >= 0 && clickedIndex < pageDashboard.chartPieData.labels.length) { |
||||
|
var clickedLabel = pageDashboard.chartPieData.labels[clickedIndex]; |
||||
|
|
||||
|
// Log the clicked label for debugging |
||||
|
console.log('Clicked Label:', clickedLabel); |
||||
|
|
||||
|
// Navigate based on the clicked label |
||||
|
switch (clickedLabel) { |
||||
|
case 'Total Complaints': |
||||
|
console.log('Navigating to pendingchart.html'); |
||||
|
window.location.href = 'pendingchart.html'; |
||||
|
break; |
||||
|
case 'Pending Complaint': |
||||
|
console.log('Navigating to nofeedbacks.html'); |
||||
|
window.location.href = 'closedchart.html'; |
||||
|
break; |
||||
|
case 'Closed Complaint': |
||||
|
console.log('Navigating to yesfeedbacks.html'); |
||||
|
window.location.href = 'totalchart.html'; |
||||
|
break; |
||||
|
// Add more cases for other labels if needed |
||||
|
default: |
||||
|
console.log('No action defined for clicked label:', clickedLabel); |
||||
|
} |
||||
|
} else { |
||||
|
console.error('Invalid clicked index:', clickedIndex); |
||||
|
} |
||||
|
|
||||
|
}; |
||||
|
}, |
||||
|
|
||||
|
updateChartPieData: function (data) { |
||||
|
if (this.chartPie) { |
||||
|
var totalFeedbacks = data.totalFeedbacks || 0; |
||||
|
var totalYesFeedbacks = data.totalYesFeedbacks || 0; |
||||
|
var totalNoFeedbacks = data.totalNoFeedbacks || 0; |
||||
|
|
||||
|
// Update the chart data |
||||
|
this.chartPieData.datasets[0].data = [totalFeedbacks, totalYesFeedbacks, totalNoFeedbacks]; |
||||
|
|
||||
|
// Update the chart |
||||
|
this.chartPie.update(); |
||||
|
} else { |
||||
|
console.error('Chart is not initialized. Unable to update data.'); |
||||
|
} |
||||
|
}, |
||||
|
|
||||
|
getAndPushData: function () { |
||||
|
// Assume you have a function named 'convert' |
||||
|
convert(); |
||||
|
var self = this; |
||||
|
|
||||
|
// Fetch data from the actual API |
||||
|
$.ajax({ |
||||
|
url: 'http://localhost:8071/api/dashboard-summary', |
||||
|
method: 'GET', |
||||
|
dataType: 'json', |
||||
|
success: function (response) { |
||||
|
console.log('Data fetched successfully:', response); |
||||
|
|
||||
|
// Call the function to process the API response |
||||
|
self.updateChartPieData(response); |
||||
|
}, |
||||
|
error: function (xhr, status, error) { |
||||
|
console.error('Error:', error); |
||||
|
} |
||||
|
}); |
||||
|
} |
||||
|
}; |
||||
|
|
||||
|
// Call the initChart function |
||||
|
pageDashboard.initChart(); |
||||
|
|
||||
|
// Call the getAndPushData method to fetch and update chart data |
||||
|
pageDashboard.getAndPushData(); |
||||
|
|
||||
|
|
||||
|
|
||||
|
|
||||
|
</script> |
||||
|
</body> |
||||
|
</html> |
||||
@ -1,409 +0,0 @@ |
|||||
<!doctype html> |
|
||||
<html xmlns:th="http://www.thymeleaf.org"> |
|
||||
<head th:replace="fragments/head :: head"></head> |
|
||||
|
|
||||
<body> |
|
||||
<!-- Page Container --> |
|
||||
<div id="page-container" class="sidebar-o sidebar-dark enable-page-overlay side-scroll page-header-fixed page-header-dark"> |
|
||||
<!-- Side Overlay aside (right)--> |
|
||||
<aside th:replace="fragments/aside-right :: aside"></aside> |
|
||||
<!-- END Side Overlay (right)--> |
|
||||
|
|
||||
<!-- Sidebar Nav--> |
|
||||
<nav th:replace="fragments/nav :: nav"></nav> |
|
||||
<!-- END Sidebar --> |
|
||||
|
|
||||
<!-- Header --> |
|
||||
<header th:replace="fragments/header :: header"></header> |
|
||||
<!-- END Header --> |
|
||||
|
|
||||
<!-- Main Container --> |
|
||||
<main id="main-container"> |
|
||||
<!-- Hero --> |
|
||||
<div class=""> |
|
||||
<div class="content content-full"> |
|
||||
<div class="d-flex flex-column flex-sm-row justify-content-sm-between align-items-sm-center"> |
|
||||
<h3 class="flex-grow-1 fs-5 fw-semibold my-2 my-sm-3">Welcome</h3> |
|
||||
<nav class="flex-shrink-0 my-2 my-sm-0 ms-sm-3" aria-label="breadcrumb"> |
|
||||
<ol class="breadcrumb"> |
|
||||
<li class="breadcrumb-item">Home</li> |
|
||||
<li class="breadcrumb-item active" aria-current="page">Dashboard</li> |
|
||||
</ol> |
|
||||
</nav> |
|
||||
</div> |
|
||||
</div> |
|
||||
</div> |
|
||||
<!-- END Hero --> |
|
||||
|
|
||||
<!-- Page Content --> |
|
||||
<div class="content"> |
|
||||
<!-- Overview --> |
|
||||
<div class="row items-push"> |
|
||||
<div class="col-sm-6 col-xl-3"> |
|
||||
<div class="block block-rounded text-center d-flex flex-column h-100 mb-0"> |
|
||||
<div class="block-content block-content-full flex-grow-1"> |
|
||||
<div class="item rounded-3 bg-body mx-auto my-3"> |
|
||||
<i class="fa fa-qrcode fa-lg text-primary"></i> |
|
||||
</div> |
|
||||
<div class="fs-2 fw-bold text-success" th:utext="${totalAssets}">000</div> |
|
||||
<div class="text-muted mb-1 fs-5">Total Asset</div> |
|
||||
|
|
||||
</div> |
|
||||
<div class="block-content block-content-full block-content-sm bg-body-light fs-sm"> |
|
||||
<a class="fw-medium" href="/gcc-asset-list"> |
|
||||
View all Assets |
|
||||
<i class="fa fa-arrow-right ms-1 opacity-25"></i> |
|
||||
</a> |
|
||||
</div> |
|
||||
</div> |
|
||||
</div> |
|
||||
<div class="col-sm-6 col-xl-3"> |
|
||||
<div class="block block-rounded text-center d-flex flex-column h-100 mb-0"> |
|
||||
<div class="block-content block-content-full flex-grow-1"> |
|
||||
<div class="item rounded-3 bg-body mx-auto my-3"> |
|
||||
<i class="fa fa-comments fa-lg text-primary"></i> |
|
||||
</div> |
|
||||
<div class="fs-2 fw-bold text-info" th:utext="${totalFeedbacks}">000</div> |
|
||||
<div class="text-muted mb-1 fs-5">Total Complaints</div> |
|
||||
|
|
||||
</div> |
|
||||
<div class="block-content block-content-full block-content-sm bg-body-light fs-sm"> |
|
||||
<a class="fw-medium" href="/complaint-list"> |
|
||||
View all Complaints |
|
||||
<i class="fa fa-arrow-right ms-1 opacity-25"></i> |
|
||||
</a> |
|
||||
</div> |
|
||||
</div> |
|
||||
</div> |
|
||||
<div class="col-sm-6 col-xl-3"> |
|
||||
<div class="block block-rounded text-center d-flex flex-column h-100 mb-0"> |
|
||||
<div class="block-content block-content-full flex-grow-1"> |
|
||||
<div class="item rounded-3 bg-body mx-auto my-3"> |
|
||||
<i class="fa fa-thumbs-up fa-lg text-primary"></i> |
|
||||
</div> |
|
||||
<div class="fs-2 fw-bold text-success" th:utext="${totalYesFeedbacks}">000</div> |
|
||||
<div class="text-muted mb-1 fs-5">Total closed Complaints</div> |
|
||||
|
|
||||
</div> |
|
||||
<div class="block-content block-content-full block-content-sm bg-body-light fs-sm"> |
|
||||
<a class="fw-medium" href="/closed-complaint"> |
|
||||
View all Closed Complaints |
|
||||
<i class="fa fa-arrow-right ms-1 opacity-25"></i> |
|
||||
</a> |
|
||||
</div> |
|
||||
</div> |
|
||||
</div> |
|
||||
<div class="col-sm-6 col-xl-3"> |
|
||||
<div class="block block-rounded text-center d-flex flex-column h-100 mb-0"> |
|
||||
<div class="block-content block-content-full"> |
|
||||
<div class="item rounded-3 bg-body mx-auto my-3"> |
|
||||
<i class="fa fa-thumbs-down fa-lg text-primary"></i> |
|
||||
</div> |
|
||||
<div class="fs-2 fw-bold text-warning" th:utext="${totalNoFeedbacks}">000</div> |
|
||||
<div class="text-muted mb-1 fs-5">Total Pending Complaints</div> |
|
||||
|
|
||||
</div> |
|
||||
<div class="block-content block-content-full block-content-sm bg-body-light fs-sm"> |
|
||||
<a class="fw-medium" href="/pending-complaint"> |
|
||||
View all Pending Complaint |
|
||||
<i class="fa fa-arrow-right ms-1 opacity-25"></i> |
|
||||
</a> |
|
||||
</div> |
|
||||
</div> |
|
||||
</div> |
|
||||
</div> |
|
||||
<!-- END Overview --> |
|
||||
|
|
||||
<!-- Store Growth --> |
|
||||
<div class="block block-rounded"> |
|
||||
<div class="block-header block-header-default"> |
|
||||
<h3 class="block-title"> |
|
||||
Monthly Summary |
|
||||
</h3> |
|
||||
<div class="block-options"> |
|
||||
<button type="button" class="btn-block-option" data-toggle="block-option" data-action="state_toggle" data-action-mode="demo"> |
|
||||
<i class="si si-refresh"></i> |
|
||||
</button> |
|
||||
<button type="button" class="btn-block-option"> |
|
||||
<i class="si si-wrench"></i> |
|
||||
</button> |
|
||||
<button type="button" class="btn-block-option" id="reportrange"> |
|
||||
<span></span> |
|
||||
</button> |
|
||||
|
|
||||
</div> |
|
||||
</div> |
|
||||
<div class="block-content block-content-full"> |
|
||||
<div class="row"> |
|
||||
<div class="col-md-5 col-xl-4 d-md-flex align-items-md-center"> |
|
||||
<div class="p-md-2 p-lg-3"> |
|
||||
<div class="py-3"> |
|
||||
<div class="fs-1 fw-bold" th:utext="${totalFeedbacks}">000</div> |
|
||||
<div class="fw-semibold text-info">Total Complaints</div> |
|
||||
|
|
||||
</div> |
|
||||
<div class="py-3"> |
|
||||
<div class="fs-1 fw-bold" th:utext="${totalYesFeedbacks}">000</div> |
|
||||
<div class="fw-semibold text-success">Closed Complaints</div> |
|
||||
|
|
||||
</div> |
|
||||
<div class="py-3"> |
|
||||
<div class="fs-1 fw-bold" th:utext="${totalNoFeedbacks}">000</div> |
|
||||
<div class="fw-semibold text-warning">Pending Complaints</div> |
|
||||
|
|
||||
</div> |
|
||||
</div> |
|
||||
</div> |
|
||||
<div class="col-md-7 col-xl-8 d-md-flex align-items-md-center"> |
|
||||
<div class="p-md-2 p-lg-3 w-100" style="height: 450px;"> |
|
||||
<!-- Bars Chart Container --> |
|
||||
<!-- Chart.js Chart is initialized in js/pages/be_pages_dashboard.min.js which was auto compiled from _js/pages/be_pages_dashboard.js --> |
|
||||
<!-- For more info and examples you can check out http://www.chartjs.org/docs/ --> |
|
||||
<canvas id="js-chartjs-analytics-bars"></canvas> |
|
||||
</div> |
|
||||
</div> |
|
||||
</div> |
|
||||
</div> |
|
||||
</div> |
|
||||
<!-- END Store Growth --> |
|
||||
|
|
||||
<!-- Latest Orders + Stats --> |
|
||||
|
|
||||
<!-- END Latest Orders + Stats --> |
|
||||
</div> |
|
||||
<!-- END Page Content --> |
|
||||
</main> |
|
||||
<!-- END Main Container --> |
|
||||
|
|
||||
<!-- Footer --> |
|
||||
<footer th:replace="fragments/footer :: footer"></footer> |
|
||||
<!-- END Footer --> |
|
||||
</div> |
|
||||
<!-- END Page Container --> |
|
||||
|
|
||||
<!-- Scripts --> |
|
||||
<script th:replace="fragments/script :: script"></script> |
|
||||
<!-- Page JS Plugins --> |
|
||||
<script src="assets/js/plugins/chart.js/chart.umd.js"></script> |
|
||||
<!-- Include Date Range Picker --> |
|
||||
<script type="text/javascript" src="assets/js/plugins/bootstrap-daterangepicker/daterangepicker.js"></script> |
|
||||
<link rel="stylesheet" type="text/css" href="assets/js/plugins/bootstrap-daterangepicker/daterangepicker.css" /> |
|
||||
<script> |
|
||||
var dash; |
|
||||
function convert(){ |
|
||||
dash=/*[[${dashboard}]]*/{}; |
|
||||
} |
|
||||
convert(); |
|
||||
alert("hi board"); |
|
||||
console.log(dash); |
|
||||
// Chart.js Charts, for more examples you can check out http://www.chartjs.org/docs |
|
||||
class pageDashboard { |
|
||||
/* |
|
||||
* Init Charts |
|
||||
* |
|
||||
*/ |
|
||||
static initChartsBars() { |
|
||||
// Set Global Chart.js configuration |
|
||||
Chart.defaults.color = '#818d96'; |
|
||||
Chart.defaults.scale.grid.color = 'transparent'; |
|
||||
Chart.defaults.scale.grid.zeroLineColor = 'transparent'; |
|
||||
Chart.defaults.scale.beginAtZero = true; |
|
||||
Chart.defaults.elements.line.borderWidth = 1; |
|
||||
Chart.defaults.plugins.legend.labels.boxWidth = 12; |
|
||||
|
|
||||
// Get Chart Containers |
|
||||
let chartBarsCon = document.getElementById('js-chartjs-analytics-bars'); |
|
||||
|
|
||||
// Set Chart and Chart Data variables |
|
||||
let chartBars, chartLinesBarsData; |
|
||||
|
|
||||
// Bars Chart Data |
|
||||
chartLinesBarsData = { |
|
||||
//labels: ['MON', 'TUE', 'WED', 'THU', 'FRI', 'SAT', 'SUN'], |
|
||||
labels: ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'], |
|
||||
|
|
||||
datasets: [ |
|
||||
{ |
|
||||
label: 'Total Complaints', |
|
||||
fill: true, |
|
||||
backgroundColor: '#c7d7e6', |
|
||||
borderColor: 'transparent', |
|
||||
pointBackgroundColor: '#c7d7e6', |
|
||||
pointBorderColor: '#fff', |
|
||||
pointHoverBackgroundColor: '#fff', |
|
||||
pointHoverBorderColor: '#c7d7e6', |
|
||||
data: [0, 0, 0, 1, 0, 0, 2] |
|
||||
}, |
|
||||
{ |
|
||||
label: 'Closed Complaint', |
|
||||
fill: true, |
|
||||
backgroundColor: '#c2d7ab', |
|
||||
borderColor: 'transparent', |
|
||||
pointBackgroundColor: '#c2d7ab', |
|
||||
pointBorderColor: '#fff', |
|
||||
pointHoverBackgroundColor: '#fff', |
|
||||
pointHoverBorderColor: '#c2d7ab', |
|
||||
data: [0, 0, 0, 1, 0, 0, 0] |
|
||||
}, |
|
||||
{ |
|
||||
label: 'Pending Complaint', |
|
||||
fill: true, |
|
||||
backgroundColor: '#e9cb91', |
|
||||
borderColor: 'transparent', |
|
||||
pointBackgroundColor: '#e9cb91', |
|
||||
pointBorderColor: '#fff', |
|
||||
pointHoverBackgroundColor: '#fff', |
|
||||
pointHoverBorderColor: '#e9cb91', |
|
||||
data: [0, 0, 0, 0, 0, 0, 2] |
|
||||
} |
|
||||
] |
|
||||
}; |
|
||||
|
|
||||
// Init Chart |
|
||||
if (chartBarsCon !== null) { |
|
||||
chartBars = new Chart(chartBarsCon, { |
|
||||
type: 'bar', |
|
||||
data: chartLinesBarsData, |
|
||||
options: { |
|
||||
responsive: true, |
|
||||
maintainAspectRatio: false, |
|
||||
plugins: { |
|
||||
tooltip: { |
|
||||
callbacks: { |
|
||||
label: function (context) { |
|
||||
return context.dataset.label + ': ' + context.parsed.y + ''; |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
}); |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
/* |
|
||||
* Init functionality |
|
||||
* |
|
||||
*/ |
|
||||
static init() { |
|
||||
this.initChartsBars(); |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
// Initialize when page loads |
|
||||
Dashmix.onLoad(() => pageDashboard.init()); |
|
||||
|
|
||||
</script> |
|
||||
|
|
||||
<script type="text/javascript"> |
|
||||
$(function() { |
|
||||
|
|
||||
var start = moment().subtract(29, 'days'); |
|
||||
var end = moment(); |
|
||||
|
|
||||
function cb(start, end) { |
|
||||
$('#reportrange span').html(start.format('MMMM D, YYYY') + ' - ' + end.format('MMMM D, YYYY')); |
|
||||
} |
|
||||
|
|
||||
$('#reportrange').daterangepicker({ |
|
||||
startDate: start, |
|
||||
endDate: end, |
|
||||
ranges: { |
|
||||
'Today': [moment(), moment()], |
|
||||
'Yesterday': [moment().subtract(1, 'days'), moment().subtract(1, 'days')], |
|
||||
'Last 7 Days': [moment().subtract(6, 'days'), moment()], |
|
||||
'Last 30 Days': [moment().subtract(29, 'days'), moment()], |
|
||||
'This Month': [moment().startOf('month'), moment().endOf('month')], |
|
||||
'Last Month': [moment().subtract(1, 'month').startOf('month'), moment().subtract(1, 'month').endOf('month')] |
|
||||
} |
|
||||
}, cb); |
|
||||
|
|
||||
cb(start, end); |
|
||||
|
|
||||
}); |
|
||||
</script> |
|
||||
|
|
||||
<script type="text/javascript"> |
|
||||
//Chart Update data |
|
||||
/* static updateChartLinesBarsData(newData) { |
|
||||
// Update the chart data; |
|
||||
pageDashboard.chartLinesBarsData.datasets[0].data = newData.totalFeedbacks; |
|
||||
pageDashboard.chartLinesBarsData.datasets[1].data = newData.positiveFeedbacks; |
|
||||
pageDashboard.chartLinesBarsData.datasets[2].data = newData.negativeFeedbacks; |
|
||||
|
|
||||
// Update the chart |
|
||||
if (pageDashboard.chartBars !== undefined) { |
|
||||
pageDashboard.chartBars.data = pageDashboard.chartLinesBarsData; |
|
||||
pageDashboard.chartBars.update(); |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
function getAndpushdata(){ |
|
||||
$.ajax({ |
|
||||
url: 'api/dashboard', // Replace with the URL to fetch the updated data |
|
||||
method: 'GET', // Replace with the appropriate HTTP method |
|
||||
dataType: 'json', // Replace with the data type you are expecting |
|
||||
success: function (response) { |
|
||||
// Assuming the response contains the updated chart data in the expected format |
|
||||
pageDashboard.updateChartLinesBarsData(response); |
|
||||
}, |
|
||||
error: function (xhr, status, error) { |
|
||||
// Handle the error scenario |
|
||||
console.error('Error:', error); |
|
||||
} |
|
||||
}); |
|
||||
} */ |
|
||||
|
|
||||
|
|
||||
// Assuming pageDashboard is an object or class instance |
|
||||
var pageDashboard = { |
|
||||
chartLinesBarsData: { |
|
||||
datasets: [ |
|
||||
{ data: [] }, // Assuming totalFeedbacks is an array |
|
||||
{ data: [] }, // Assuming positiveFeedbacks is an array |
|
||||
{ data: [] } // Assuming negativeFeedbacks is an array |
|
||||
] |
|
||||
}, |
|
||||
chartBars: undefined, // Assuming chartBars is initially undefined |
|
||||
|
|
||||
updateChartLinesBarsData: function(newData) { |
|
||||
// Update the chart data |
|
||||
this.chartLinesBarsData.datasets[0].data = newData.totalFeedbacks; |
|
||||
this.chartLinesBarsData.datasets[1].data = newData.positiveFeedbacks; |
|
||||
this.chartLinesBarsData.datasets[2].data = newData.negativeFeedbacks; |
|
||||
|
|
||||
// Update the chart |
|
||||
if (this.chartBars !== undefined) { |
|
||||
this.chartBars.data = this.chartLinesBarsData; |
|
||||
this.chartBars.update(); |
|
||||
} |
|
||||
}, |
|
||||
|
|
||||
getAndPushData: function() { |
|
||||
var self = this; // Store a reference to the current object |
|
||||
|
|
||||
$.ajax({ |
|
||||
url: 'api/dashboard', // Replace with the URL to fetch the updated data |
|
||||
method: 'GET', // Replace with the appropriate HTTP method |
|
||||
dataType: 'json', // Replace with the data type you are expecting |
|
||||
success: function(response) { |
|
||||
// Assuming the response contains the updated chart data in the expected format |
|
||||
self.updateChartLinesBarsData(response); |
|
||||
}, |
|
||||
error: function(xhr, status, error) { |
|
||||
// Handle the error scenario |
|
||||
console.error('Error:', error); |
|
||||
} |
|
||||
}); |
|
||||
} |
|
||||
}; |
|
||||
|
|
||||
// Call the getAndPushData method to fetch and update chart data |
|
||||
pageDashboard.getAndPushData(); |
|
||||
|
|
||||
|
|
||||
|
|
||||
|
|
||||
</script> |
|
||||
</body> |
|
||||
</html> |
|
||||
@ -0,0 +1,455 @@ |
|||||
|
<!doctype html> |
||||
|
<html xmlns:th="http://www.thymeleaf.org"> |
||||
|
<head th:replace="fragments/head :: head"></head> |
||||
|
|
||||
|
<body> |
||||
|
<!-- Page Container --> |
||||
|
<div id="page-container" class="sidebar-o sidebar-dark enable-page-overlay side-scroll page-header-fixed page-header-dark"> |
||||
|
<!-- Side Overlay aside (right)--> |
||||
|
<aside th:replace="fragments/aside-right :: aside"></aside> |
||||
|
<!-- END Side Overlay (right)--> |
||||
|
|
||||
|
<!-- Sidebar Nav--> |
||||
|
<nav th:replace="fragments/nav :: nav"></nav> |
||||
|
<!-- END Sidebar --> |
||||
|
|
||||
|
<!-- Header --> |
||||
|
<header th:replace="fragments/header :: header"></header> |
||||
|
<!-- END Header --> |
||||
|
|
||||
|
<!-- Main Container --> |
||||
|
<main id="main-container"> |
||||
|
<!-- Hero --> |
||||
|
<div class=""> |
||||
|
<div class="content content-full"> |
||||
|
<div class="d-flex flex-column flex-sm-row justify-content-sm-between align-items-sm-center"> |
||||
|
<h3 class="flex-grow-1 fs-5 fw-semibold my-2 my-sm-3">Welcome</h3> |
||||
|
<nav class="flex-shrink-0 my-2 my-sm-0 ms-sm-3" aria-label="breadcrumb"> |
||||
|
<ol class="breadcrumb"> |
||||
|
<li class="breadcrumb-item">Home</li> |
||||
|
<li class="breadcrumb-item active" aria-current="page">Dashboard</li> |
||||
|
</ol> |
||||
|
</nav> |
||||
|
</div> |
||||
|
</div> |
||||
|
</div> |
||||
|
<!-- END Hero --> |
||||
|
|
||||
|
<!-- Page Content --> |
||||
|
<div class="content"> |
||||
|
<!-- Overview --> |
||||
|
<div class="row items-push"> |
||||
|
<div class="col-sm-6 col-xl-3"> |
||||
|
<div class="block block-rounded text-center d-flex flex-column h-100 mb-0"> |
||||
|
<div class="block-content block-content-full flex-grow-1"> |
||||
|
<div class="item rounded-3 bg-body mx-auto my-3"> |
||||
|
<i class="fa fa-qrcode fa-lg text-primary"></i> |
||||
|
</div> |
||||
|
<div class="fs-2 fw-bold text-success" th:utext="${totalAssets}">000</div> |
||||
|
<div class="text-muted mb-1 fs-5">Total Asset</div> |
||||
|
|
||||
|
</div> |
||||
|
<div class="block-content block-content-full block-content-sm bg-body-light fs-sm"> |
||||
|
<a class="fw-medium" href="/gcc-asset-list"> |
||||
|
View all Assets |
||||
|
<i class="fa fa-arrow-right ms-1 opacity-25"></i> |
||||
|
</a> |
||||
|
</div> |
||||
|
</div> |
||||
|
</div> |
||||
|
<div class="col-sm-6 col-xl-3"> |
||||
|
<div class="block block-rounded text-center d-flex flex-column h-100 mb-0"> |
||||
|
<div class="block-content block-content-full flex-grow-1"> |
||||
|
<div class="item rounded-3 bg-body mx-auto my-3"> |
||||
|
<i class="fa fa-comments fa-lg text-primary"></i> |
||||
|
</div> |
||||
|
<div class="fs-2 fw-bold text-info" th:utext="${totalFeedbacks}">000</div> |
||||
|
<div class="text-muted mb-1 fs-5">Total Complaints</div> |
||||
|
|
||||
|
</div> |
||||
|
<div class="block-content block-content-full block-content-sm bg-body-light fs-sm"> |
||||
|
<a class="fw-medium" href="/complaint-list"> |
||||
|
View all Complaints |
||||
|
<i class="fa fa-arrow-right ms-1 opacity-25"></i> |
||||
|
</a> |
||||
|
</div> |
||||
|
</div> |
||||
|
</div> |
||||
|
<div class="col-sm-6 col-xl-3"> |
||||
|
<div class="block block-rounded text-center d-flex flex-column h-100 mb-0"> |
||||
|
<div class="block-content block-content-full flex-grow-1"> |
||||
|
<div class="item rounded-3 bg-body mx-auto my-3"> |
||||
|
<i class="fa fa-thumbs-up fa-lg text-primary"></i> |
||||
|
</div> |
||||
|
<div class="fs-2 fw-bold text-success" th:utext="${totalYesFeedbacks}">000</div> |
||||
|
<div class="text-muted mb-1 fs-5">Total closed Complaints</div> |
||||
|
|
||||
|
</div> |
||||
|
<div class="block-content block-content-full block-content-sm bg-body-light fs-sm"> |
||||
|
<a class="fw-medium" href="/closed-complaint"> |
||||
|
View all Closed Complaints |
||||
|
<i class="fa fa-arrow-right ms-1 opacity-25"></i> |
||||
|
</a> |
||||
|
</div> |
||||
|
</div> |
||||
|
</div> |
||||
|
<div class="col-sm-6 col-xl-3"> |
||||
|
<div class="block block-rounded text-center d-flex flex-column h-100 mb-0"> |
||||
|
<div class="block-content block-content-full"> |
||||
|
<div class="item rounded-3 bg-body mx-auto my-3"> |
||||
|
<i class="fa fa-thumbs-down fa-lg text-primary"></i> |
||||
|
</div> |
||||
|
<div class="fs-2 fw-bold text-warning" th:utext="${totalNoFeedbacks}">000</div> |
||||
|
<div class="text-muted mb-1 fs-5">Total Pending Complaints</div> |
||||
|
|
||||
|
</div> |
||||
|
<div class="block-content block-content-full block-content-sm bg-body-light fs-sm"> |
||||
|
<a class="fw-medium" href="/pending-complaint"> |
||||
|
View all Pending Complaint |
||||
|
<i class="fa fa-arrow-right ms-1 opacity-25"></i> |
||||
|
</a> |
||||
|
</div> |
||||
|
</div> |
||||
|
</div> |
||||
|
</div> |
||||
|
<!-- END Overview --> |
||||
|
|
||||
|
<!-- Store Growth --> |
||||
|
|
||||
|
<div class="row"> |
||||
|
<div class="col-12 col-md-6 col-xl-6"> |
||||
|
<div class="p-md-2 p-lg-3 w-100" style="height: 400px;"> |
||||
|
<!-- Chart 1 Container --> |
||||
|
<canvas id="myChart1"></canvas> |
||||
|
</div> |
||||
|
</div> |
||||
|
|
||||
|
<div class="col-12 col-md-6 col-xl-6"> |
||||
|
<div class="p-md-2 p-lg-3 w-100" style="height: 500px;"> |
||||
|
<!-- Chart 2 Container --> |
||||
|
<canvas id="myChart"></canvas> |
||||
|
</div> |
||||
|
</div> |
||||
|
</div> |
||||
|
|
||||
|
|
||||
|
</div> |
||||
|
|
||||
|
|
||||
|
|
||||
|
<!-- END Store Growth --> |
||||
|
|
||||
|
<!-- Latest Orders + Stats --> |
||||
|
|
||||
|
<!-- END Latest Orders + Stats --> |
||||
|
|
||||
|
<!-- END Page Content --> |
||||
|
</main> |
||||
|
<!-- END Main Container --> |
||||
|
|
||||
|
<!-- Footer --> |
||||
|
<footer th:replace="fragments/footer :: footer"></footer> |
||||
|
<!-- END Footer --> |
||||
|
</div> |
||||
|
<!-- END Page Container --> |
||||
|
|
||||
|
<!-- Scripts --> |
||||
|
<!-- Include jQuery --> |
||||
|
<script src="https://code.jquery.com/jquery-3.6.4.min.js"></script> |
||||
|
<!-- Your existing script tag follows --> |
||||
|
<script th:replace="fragments/script :: script"></script> |
||||
|
<!-- Page JS Plugins --> |
||||
|
<script src="assets/js/plugins/chart.js/chart.umd.js"></script> |
||||
|
<!-- Include Date Range Picker --> |
||||
|
<script type="text/javascript" src="assets/js/plugins/bootstrap-daterangepicker/daterangepicker.js"></script> |
||||
|
<link rel="stylesheet" type="text/css" href="assets/js/plugins/bootstrap-daterangepicker/daterangepicker.css" /> |
||||
|
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script> |
||||
|
|
||||
|
<script> |
||||
|
var dash = {}; |
||||
|
|
||||
|
function convert() { |
||||
|
// Ensure proper initialization logic for feedbackAnalysisData |
||||
|
dash.feedbackAnalysisData = /*[[${dashboard}]]*/ {}; |
||||
|
} |
||||
|
|
||||
|
convert(); |
||||
|
|
||||
|
|
||||
|
var pageDashboard = { |
||||
|
chartBars: undefined, |
||||
|
chartLinesBarsData: { |
||||
|
datasets: [ |
||||
|
{ data: [] }, // Assuming totalYesFeedbacks is an array |
||||
|
{ data: [] }, |
||||
|
{data:[] } // Assuming totalNoFeedbacks is an array |
||||
|
] |
||||
|
}, |
||||
|
|
||||
|
initChart: function (feedbackAnalysis) { |
||||
|
// Set Global Chart.js configuration |
||||
|
Chart.defaults.color = '#818d96'; |
||||
|
Chart.defaults.scale.grid.color = 'transparent'; |
||||
|
Chart.defaults.scale.grid.zeroLineColor = 'transparent'; |
||||
|
Chart.defaults.scale.beginAtZero = true; |
||||
|
Chart.defaults.elements.line.borderWidth = 1; |
||||
|
Chart.defaults.plugins.legend.labels.boxWidth = 12; |
||||
|
|
||||
|
// Get Chart Container |
||||
|
let chartBarsCon = document.getElementById('myChart'); |
||||
|
|
||||
|
var data = { |
||||
|
labels: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'], |
||||
|
datasets: [ |
||||
|
{ |
||||
|
label: 'Total Complaints', |
||||
|
data: [], |
||||
|
fill: true, |
||||
|
backgroundColor: '#3498db', |
||||
|
borderColor: 'transparent', |
||||
|
pointBackgroundColor: '#c7d7e6', |
||||
|
pointBorderColor: '#fff', |
||||
|
pointHoverBackgroundColor: '#2980b9', |
||||
|
pointHoverBorderColor: '#c7d7e6', |
||||
|
}, |
||||
|
|
||||
|
] |
||||
|
}; |
||||
|
|
||||
|
|
||||
|
var options = { |
||||
|
responsive: true, |
||||
|
scales: { |
||||
|
x: { beginAtZero: true }, |
||||
|
y: { beginAtZero: true } |
||||
|
}, |
||||
|
plugins: { |
||||
|
datalabels: { |
||||
|
anchor: 'end', |
||||
|
align: 'end', |
||||
|
color: 'black', |
||||
|
formatter: function (value, context) { |
||||
|
// Display the value only if it's greater than 0 |
||||
|
return value > 0 ? value : ''; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
}; |
||||
|
|
||||
|
// Create the chart |
||||
|
this.chartBars = new Chart(chartBarsCon, { |
||||
|
type: 'bar', |
||||
|
data: data, |
||||
|
options: options |
||||
|
}); |
||||
|
}, |
||||
|
updateChartLinesBarsData: function (newData) { |
||||
|
// Ensure the chart is initialized before updating |
||||
|
if (this.chartBars) { |
||||
|
// Assuming labels for the chart are ['Jan', 'Feb', 'Mar', ..., 'Dec'] |
||||
|
var labels = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']; |
||||
|
|
||||
|
// Initialize arrays with values from dataArray |
||||
|
var totalFeedbacksData = Array.from({ length: labels.length }, (_, index) => { |
||||
|
return newData.reduce((sum, item) => { |
||||
|
const key = Object.keys(item)[0]; |
||||
|
const dataArray = item[key]; |
||||
|
// console.log(totalFeedbacksData[${index}]: ${dataArray[index]}); |
||||
|
return sum + dataArray[index]; |
||||
|
}, 0); |
||||
|
}); |
||||
|
|
||||
|
var totalYesFeedbacksData = Array.from({ length: labels.length }, (_, index) => { |
||||
|
return newData.reduce((sum, item) => { |
||||
|
const key = Object.keys(item)[0]; |
||||
|
const dataArray = item[key]; |
||||
|
// console.log(totalYesFeedbacksData[${index}]: ${dataArray[index]}); |
||||
|
return dataArray[index]; |
||||
|
}, 0); |
||||
|
}); |
||||
|
|
||||
|
// Subtract totalYesFeedbacksData from totalFeedbacksData |
||||
|
var totalNoFeedbacksData = totalFeedbacksData.map((value, index) => value - totalYesFeedbacksData[index]); |
||||
|
|
||||
|
// Update the chart data |
||||
|
this.chartBars.data.datasets[0].data = totalFeedbacksData; |
||||
|
// this.chartBars.data.datasets[1].data = totalYesFeedbacksData; |
||||
|
// this.chartBars.data.datasets[2].data = totalNoFeedbacksData; |
||||
|
|
||||
|
// Log the updated chart data |
||||
|
// console.log('Updated chart data (totalFeedbacksData):', this.chartBars.data.datasets[0].data); |
||||
|
//console.log('Updated chart data (totalYesFeedbacksData):', this.chartBars.data.datasets[1].data); |
||||
|
//console.log('Updated chart data (totalNoFeedbacksData):', this.chartBars.data.datasets[2].data); |
||||
|
|
||||
|
// Update the chart |
||||
|
this.chartBars.update(); |
||||
|
} else { |
||||
|
console.error('Chart is not initialized. Unable to update data.'); |
||||
|
} |
||||
|
}, |
||||
|
|
||||
|
|
||||
|
|
||||
|
getAndPushData: function (cdate) { |
||||
|
|
||||
|
// Ensure convert() is called before accessing dash.feedbackAnalysisData |
||||
|
convert(); |
||||
|
|
||||
|
|
||||
|
var self = this; |
||||
|
|
||||
|
$.ajax({ |
||||
|
url: 'api/cou/' + cdate, |
||||
|
method: 'GET', |
||||
|
dataType: 'json', |
||||
|
success: function (response) { |
||||
|
console.log('Data fetched successfully:', response); |
||||
|
self.updateChartLinesBarsData(response); |
||||
|
}, |
||||
|
error: function (xhr, status, error) { |
||||
|
console.error('Error:', error); |
||||
|
} |
||||
|
}); |
||||
|
} |
||||
|
}; |
||||
|
|
||||
|
// Call the initChart function with the feedbackAnalysis data |
||||
|
pageDashboard.initChart(dash.feedbackAnalysisData || {}); |
||||
|
|
||||
|
// Call the getAndPushData method to fetch and update chart data |
||||
|
pageDashboard.getAndPushData(); |
||||
|
pageDashboard.getAndPushData(); |
||||
|
var pageDashboard = { |
||||
|
chartPie: undefined, |
||||
|
chartPieData: { |
||||
|
labels: ['Total Complaints', 'Closed Complaint', 'Pending Complaint'], |
||||
|
datasets: [ |
||||
|
{ |
||||
|
data: [], |
||||
|
backgroundColor: ['#3498db', '#e74c3c', '#cc6633'], |
||||
|
hoverBackgroundColor: ['#2980b9', '#c0392b', '#A35128'] |
||||
|
} |
||||
|
] |
||||
|
}, |
||||
|
|
||||
|
initChart: function () { |
||||
|
// Get Chart Container |
||||
|
let chartPieCon = document.getElementById('myChart1'); |
||||
|
|
||||
|
var options = { |
||||
|
responsive: true, |
||||
|
plugins: { |
||||
|
datalabels: { |
||||
|
color: 'black', |
||||
|
formatter: function (value) { |
||||
|
// Display the value only if it's greater than 0 |
||||
|
return value > 0 ? value : ''; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
}; |
||||
|
|
||||
|
// Create the chart |
||||
|
this.chartPie = new Chart(chartPieCon, { |
||||
|
type: 'pie', |
||||
|
data: this.chartPieData, |
||||
|
options: options |
||||
|
}); |
||||
|
|
||||
|
// Add click event listener to the chart container |
||||
|
chartPieCon.onclick = function (event) { |
||||
|
var elements = pageDashboard.chartPie.getElementsAtEventForMode(event, 'point', pageDashboard.chartPie.options); |
||||
|
|
||||
|
if (elements && elements.length > 0) { |
||||
|
var clickedIndex = elements[0].index; |
||||
|
console.log('Clicked Index:', clickedIndex); |
||||
|
console.log('Elements:', elements); |
||||
|
console.log('Labels:', pageDashboard.chartPieData.labels); |
||||
|
|
||||
|
// Continue with the rest of your code... |
||||
|
} else { |
||||
|
console.error('No elements found at the click event.'); |
||||
|
} |
||||
|
if (clickedIndex >= 0 && clickedIndex < pageDashboard.chartPieData.labels.length) { |
||||
|
var clickedLabel = pageDashboard.chartPieData.labels[clickedIndex]; |
||||
|
|
||||
|
// Log the clicked label for debugging |
||||
|
console.log('Clicked Label:', clickedLabel); |
||||
|
|
||||
|
// Navigate based on the clicked label |
||||
|
switch (clickedLabel) { |
||||
|
case 'Total Complaints': |
||||
|
console.log('Navigating to pendingchart.html'); |
||||
|
window.location.href = 'pendingchart.html'; |
||||
|
break; |
||||
|
case 'Pending Complaint': |
||||
|
console.log('Navigating to nofeedbacks.html'); |
||||
|
window.location.href = 'closedchart.html'; |
||||
|
break; |
||||
|
case 'Closed Complaint': |
||||
|
console.log('Navigating to yesfeedbacks.html'); |
||||
|
window.location.href = 'totalchart.html'; |
||||
|
break; |
||||
|
// Add more cases for other labels if needed |
||||
|
default: |
||||
|
console.log('No action defined for clicked label:', clickedLabel); |
||||
|
} |
||||
|
} else { |
||||
|
console.error('Invalid clicked index:', clickedIndex); |
||||
|
} |
||||
|
|
||||
|
}; |
||||
|
}, |
||||
|
|
||||
|
updateChartPieData: function (data) { |
||||
|
if (this.chartPie) { |
||||
|
var totalFeedbacks = data.totalFeedbacks || 0; |
||||
|
var totalYesFeedbacks = data.totalYesFeedbacks || 0; |
||||
|
var totalNoFeedbacks = data.totalNoFeedbacks || 0; |
||||
|
|
||||
|
// Update the chart data |
||||
|
this.chartPieData.datasets[0].data = [totalFeedbacks, totalYesFeedbacks, totalNoFeedbacks]; |
||||
|
|
||||
|
// Update the chart |
||||
|
this.chartPie.update(); |
||||
|
} else { |
||||
|
console.error('Chart is not initialized. Unable to update data.'); |
||||
|
} |
||||
|
}, |
||||
|
|
||||
|
getAndPushData: function () { |
||||
|
// Assume you have a function named 'convert' |
||||
|
convert(); |
||||
|
var self = this; |
||||
|
|
||||
|
// Fetch data from the actual API |
||||
|
$.ajax({ |
||||
|
url: 'http://localhost:8071/api/dashboard-summary', |
||||
|
method: 'GET', |
||||
|
dataType: 'json', |
||||
|
success: function (response) { |
||||
|
console.log('Data fetched successfully:', response); |
||||
|
|
||||
|
// Call the function to process the API response |
||||
|
self.updateChartPieData(response); |
||||
|
}, |
||||
|
error: function (xhr, status, error) { |
||||
|
console.error('Error:', error); |
||||
|
} |
||||
|
}); |
||||
|
} |
||||
|
}; |
||||
|
|
||||
|
// Call the initChart function |
||||
|
pageDashboard.initChart(); |
||||
|
|
||||
|
// Call the getAndPushData method to fetch and update chart data |
||||
|
pageDashboard.getAndPushData(); |
||||
|
|
||||
|
|
||||
|
|
||||
|
|
||||
|
|
||||
|
</script> |
||||
|
</body> |
||||
|
</html> |
||||
@ -0,0 +1,62 @@ |
|||||
|
<!DOCTYPE html> |
||||
|
<html lang="en"> |
||||
|
<head> |
||||
|
<meta charset="UTF-8"> |
||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0"> |
||||
|
<title>Feedback Chart</title> |
||||
|
<!-- Include Chart.js from CDN --> |
||||
|
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script> |
||||
|
</head> |
||||
|
<body> |
||||
|
<canvas id="feedbackChart" width="400" height="400"></canvas> |
||||
|
|
||||
|
<script> |
||||
|
var dash=[[${dashboard}]]; |
||||
|
console.log(dash); |
||||
|
// Assume your API endpoint returns a JSON object with the data |
||||
|
// Modify the URL accordingly based on your server setup |
||||
|
const apiUrl = 'api/cou/{cdate}'; // Replace with your actual API endpoint |
||||
|
|
||||
|
// Fetch data from the API |
||||
|
fetch(apiUrl) |
||||
|
.then(response => response.json()) |
||||
|
.then(data => { |
||||
|
// Extract data for chart |
||||
|
const labels = ['Yes', 'No', 'Total']; |
||||
|
const values = [data.yes, data.no, data.total]; |
||||
|
|
||||
|
// Create a Chart.js chart |
||||
|
const ctx = document.getElementById('feedbackChart').getContext('2d'); |
||||
|
const myChart = new Chart(ctx, { |
||||
|
type: 'bar', |
||||
|
data: { |
||||
|
labels: labels, |
||||
|
datasets: [{ |
||||
|
label: 'Feedback Data', |
||||
|
data: values, |
||||
|
backgroundColor: [ |
||||
|
'rgba(75, 192, 192, 0.2)', |
||||
|
'rgba(255, 99, 132, 0.2)', |
||||
|
'rgba(255, 255, 255, 0.2)' |
||||
|
], |
||||
|
borderColor: [ |
||||
|
'rgba(75, 192, 192, 1)', |
||||
|
'rgba(255, 99, 132, 1)', |
||||
|
'rgba(255, 255, 255, 1)' |
||||
|
], |
||||
|
borderWidth: 1 |
||||
|
}] |
||||
|
}, |
||||
|
options: { |
||||
|
scales: { |
||||
|
y: { |
||||
|
beginAtZero: true |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
}); |
||||
|
}) |
||||
|
.catch(error => console.error('Error fetching data:', error)); |
||||
|
</script> |
||||
|
</body> |
||||
|
</html> |
||||
@ -0,0 +1,452 @@ |
|||||
|
<!doctype html> |
||||
|
<html xmlns:th="http://www.thymeleaf.org"> |
||||
|
<head th:replace="fragments/head :: head"></head> |
||||
|
|
||||
|
<body> |
||||
|
<!-- Page Container --> |
||||
|
<div id="page-container" class="sidebar-o sidebar-dark enable-page-overlay side-scroll page-header-fixed page-header-dark"> |
||||
|
<!-- Side Overlay aside (right)--> |
||||
|
<aside th:replace="fragments/aside-right :: aside"></aside> |
||||
|
<!-- END Side Overlay (right)--> |
||||
|
|
||||
|
<!-- Sidebar Nav--> |
||||
|
<nav th:replace="fragments/nav :: nav"></nav> |
||||
|
<!-- END Sidebar --> |
||||
|
|
||||
|
<!-- Header --> |
||||
|
<header th:replace="fragments/header :: header"></header> |
||||
|
<!-- END Header --> |
||||
|
|
||||
|
<!-- Main Container --> |
||||
|
<main id="main-container"> |
||||
|
<!-- Hero --> |
||||
|
<div class=""> |
||||
|
<div class="content content-full"> |
||||
|
<div class="d-flex flex-column flex-sm-row justify-content-sm-between align-items-sm-center"> |
||||
|
<h3 class="flex-grow-1 fs-5 fw-semibold my-2 my-sm-3">Welcome</h3> |
||||
|
<nav class="flex-shrink-0 my-2 my-sm-0 ms-sm-3" aria-label="breadcrumb"> |
||||
|
<ol class="breadcrumb"> |
||||
|
<li class="breadcrumb-item">Home</li> |
||||
|
<li class="breadcrumb-item active" aria-current="page">Dashboard</li> |
||||
|
</ol> |
||||
|
</nav> |
||||
|
</div> |
||||
|
</div> |
||||
|
</div> |
||||
|
<!-- END Hero --> |
||||
|
|
||||
|
<!-- Page Content --> |
||||
|
<div class="content"> |
||||
|
<!-- Overview --> |
||||
|
<div class="row items-push"> |
||||
|
<div class="col-sm-6 col-xl-3"> |
||||
|
<div class="block block-rounded text-center d-flex flex-column h-100 mb-0"> |
||||
|
<div class="block-content block-content-full flex-grow-1"> |
||||
|
<div class="item rounded-3 bg-body mx-auto my-3"> |
||||
|
<i class="fa fa-qrcode fa-lg text-primary"></i> |
||||
|
</div> |
||||
|
<div class="fs-2 fw-bold text-success" th:utext="${totalAssets}">000</div> |
||||
|
<div class="text-muted mb-1 fs-5">Total Asset</div> |
||||
|
</div> |
||||
|
<div class="block-content block-content-full block-content-sm bg-body-light fs-sm"> |
||||
|
<a class="fw-medium" href="/gcc-asset-list"> |
||||
|
View all Assets |
||||
|
<i class="fa fa-arrow-right ms-1 opacity-25"></i> |
||||
|
</a> |
||||
|
</div> |
||||
|
</div> |
||||
|
</div> |
||||
|
<div class="col-sm-6 col-xl-3"> |
||||
|
<div class="block block-rounded text-center d-flex flex-column h-100 mb-0"> |
||||
|
<div class="block-content block-content-full flex-grow-1"> |
||||
|
<div class="item rounded-3 bg-body mx-auto my-3"> |
||||
|
<i class="fa fa-comments fa-lg text-primary"></i> |
||||
|
</div> |
||||
|
<div class="fs-2 fw-bold text-info" th:utext="${totalFeedbacks}">000</div> |
||||
|
<div class="text-muted mb-1 fs-5">Total Complaints</div> |
||||
|
|
||||
|
</div> |
||||
|
<div class="block-content block-content-full block-content-sm bg-body-light fs-sm"> |
||||
|
<a class="fw-medium" href="/complaint-list"> |
||||
|
View all Complaints |
||||
|
<i class="fa fa-arrow-right ms-1 opacity-25"></i> |
||||
|
</a> |
||||
|
</div> |
||||
|
</div> |
||||
|
</div> |
||||
|
<div class="col-sm-6 col-xl-3"> |
||||
|
<div class="block block-rounded text-center d-flex flex-column h-100 mb-0"> |
||||
|
<div class="block-content block-content-full flex-grow-1"> |
||||
|
<div class="item rounded-3 bg-body mx-auto my-3"> |
||||
|
<i class="fa fa-thumbs-up fa-lg text-primary"></i> |
||||
|
</div> |
||||
|
<div class="fs-2 fw-bold text-success" th:utext="${totalYesFeedbacks}">000</div> |
||||
|
<div class="text-muted mb-1 fs-5">Total closed Complaints</div> |
||||
|
|
||||
|
</div> |
||||
|
<div class="block-content block-content-full block-content-sm bg-body-light fs-sm"> |
||||
|
<a class="fw-medium" href="/closed-complaint"> |
||||
|
View all Closed Complaints |
||||
|
<i class="fa fa-arrow-right ms-1 opacity-25"></i> |
||||
|
</a> |
||||
|
</div> |
||||
|
</div> |
||||
|
</div> |
||||
|
<div class="col-sm-6 col-xl-3"> |
||||
|
<div class="block block-rounded text-center d-flex flex-column h-100 mb-0"> |
||||
|
<div class="block-content block-content-full"> |
||||
|
<div class="item rounded-3 bg-body mx-auto my-3"> |
||||
|
<i class="fa fa-thumbs-down fa-lg text-primary"></i> |
||||
|
</div> |
||||
|
<div class="fs-2 fw-bold text-warning" th:utext="${totalNoFeedbacks}">000</div> |
||||
|
<div class="text-muted mb-1 fs-5">Total Pending Complaints</div> |
||||
|
|
||||
|
</div> |
||||
|
<div class="block-content block-content-full block-content-sm bg-body-light fs-sm"> |
||||
|
<a class="fw-medium" href="/pending-complaint"> |
||||
|
View all Pending Complaint |
||||
|
<i class="fa fa-arrow-right ms-1 opacity-25"></i> |
||||
|
</a> |
||||
|
</div> |
||||
|
</div> |
||||
|
</div> |
||||
|
</div> |
||||
|
<!-- END Overview --> |
||||
|
|
||||
|
<!-- Store Growth --> |
||||
|
|
||||
|
<div class="row"> |
||||
|
<div class="col-12 col-md-6 col-xl-6"> |
||||
|
<div class="p-md-2 p-lg-3 w-100" style="height: 400px;"> |
||||
|
<!-- Chart 1 Container --> |
||||
|
<canvas id="myChart1"></canvas> |
||||
|
</div> |
||||
|
</div> |
||||
|
|
||||
|
<div class="col-12 col-md-6 col-xl-6"> |
||||
|
<div class="p-md-2 p-lg-3 w-100" style="height: 500px;"> |
||||
|
<!-- Chart 2 Container --> |
||||
|
<canvas id="myChart"></canvas> |
||||
|
</div> |
||||
|
</div> |
||||
|
</div> |
||||
|
|
||||
|
|
||||
|
</div> |
||||
|
</div> |
||||
|
|
||||
|
</div> |
||||
|
<!-- END Store Growth --> |
||||
|
|
||||
|
<!-- Latest Orders + Stats --> |
||||
|
|
||||
|
<!-- END Latest Orders + Stats --> |
||||
|
</div> |
||||
|
<!-- END Page Content --> |
||||
|
</main> |
||||
|
<!-- END Main Container --> |
||||
|
|
||||
|
<!-- Footer --> |
||||
|
<footer th:replace="fragments/footer :: footer"></footer> |
||||
|
<!-- END Footer --> |
||||
|
</div> |
||||
|
<!-- END Page Container --> |
||||
|
|
||||
|
<!-- Scripts --> |
||||
|
<!-- Include jQuery --> |
||||
|
<script src="https://code.jquery.com/jquery-3.6.4.min.js"></script> |
||||
|
<!-- Your existing script tag follows --> |
||||
|
<script th:replace="fragments/script :: script"></script> |
||||
|
<!-- Page JS Plugins --> |
||||
|
<script src="assets/js/plugins/chart.js/chart.umd.js"></script> |
||||
|
<!-- Include Date Range Picker --> |
||||
|
<script type="text/javascript" src="assets/js/plugins/bootstrap-daterangepicker/daterangepicker.js"></script> |
||||
|
<link rel="stylesheet" type="text/css" href="assets/js/plugins/bootstrap-daterangepicker/daterangepicker.css" /> |
||||
|
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script> |
||||
|
|
||||
|
<script> |
||||
|
var dash = {}; |
||||
|
|
||||
|
function convert() { |
||||
|
// Ensure proper initialization logic for feedbackAnalysisData |
||||
|
dash.feedbackAnalysisData = /*[[${dashboard}]]*/ {}; |
||||
|
} |
||||
|
|
||||
|
convert(); |
||||
|
|
||||
|
|
||||
|
var pageDashboard = { |
||||
|
chartBars: undefined, |
||||
|
chartLinesBarsData: { |
||||
|
datasets: [ |
||||
|
{ data: [] }, // Assuming totalYesFeedbacks is an array |
||||
|
{ data: [] }, |
||||
|
{data:[] } // Assuming totalNoFeedbacks is an array |
||||
|
] |
||||
|
}, |
||||
|
|
||||
|
initChart: function (feedbackAnalysis) { |
||||
|
// Set Global Chart.js configuration |
||||
|
Chart.defaults.color = '#818d96'; |
||||
|
Chart.defaults.scale.grid.color = 'transparent'; |
||||
|
Chart.defaults.scale.grid.zeroLineColor = 'transparent'; |
||||
|
Chart.defaults.scale.beginAtZero = true; |
||||
|
Chart.defaults.elements.line.borderWidth = 1; |
||||
|
Chart.defaults.plugins.legend.labels.boxWidth = 12; |
||||
|
|
||||
|
// Get Chart Container |
||||
|
let chartBarsCon = document.getElementById('myChart'); |
||||
|
|
||||
|
var data = { |
||||
|
labels: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'], |
||||
|
datasets: [ |
||||
|
{ |
||||
|
label: 'Closed Complaint', |
||||
|
data: [], |
||||
|
fill: true, |
||||
|
backgroundColor: '#cc6633', |
||||
|
borderColor: 'transparent', |
||||
|
pointBackgroundColor: '#e9cb91', |
||||
|
pointBorderColor: '#fff', |
||||
|
pointHoverBackgroundColor: '#A35128', |
||||
|
pointHoverBorderColor: '#e9cb91', |
||||
|
}, |
||||
|
|
||||
|
] |
||||
|
}; |
||||
|
|
||||
|
|
||||
|
var options = { |
||||
|
responsive: true, |
||||
|
scales: { |
||||
|
x: { beginAtZero: true }, |
||||
|
y: { beginAtZero: true } |
||||
|
}, |
||||
|
plugins: { |
||||
|
datalabels: { |
||||
|
anchor: 'end', |
||||
|
align: 'end', |
||||
|
color: 'black', |
||||
|
formatter: function (value, context) { |
||||
|
// Display the value only if it's greater than 0 |
||||
|
return value > 0 ? value : ''; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
}; |
||||
|
|
||||
|
// Create the chart |
||||
|
this.chartBars = new Chart(chartBarsCon, { |
||||
|
type: 'bar', |
||||
|
data: data, |
||||
|
options: options |
||||
|
}); |
||||
|
}, |
||||
|
updateChartLinesBarsData: function (newData) { |
||||
|
// Ensure the chart is initialized before updating |
||||
|
if (this.chartBars) { |
||||
|
// Assuming labels for the chart are ['Jan', 'Feb', 'Mar', ..., 'Dec'] |
||||
|
var labels = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']; |
||||
|
|
||||
|
// Initialize arrays with values from dataArray |
||||
|
var totalFeedbacksData = Array.from({ length: labels.length }, (_, index) => { |
||||
|
return newData.reduce((sum, item) => { |
||||
|
const key = Object.keys(item)[0]; |
||||
|
const dataArray = item[key]; |
||||
|
// console.log(totalFeedbacksData[${index}]: ${dataArray[index]}); |
||||
|
return sum + dataArray[index]; |
||||
|
}, 0); |
||||
|
}); |
||||
|
|
||||
|
var totalYesFeedbacksData = Array.from({ length: labels.length }, (_, index) => { |
||||
|
return newData.reduce((sum, item) => { |
||||
|
const key = Object.keys(item)[0]; |
||||
|
const dataArray = item[key]; |
||||
|
// console.log(totalYesFeedbacksData[${index}]: ${dataArray[index]}); |
||||
|
return dataArray[index]; |
||||
|
}, 0); |
||||
|
}); |
||||
|
|
||||
|
// Subtract totalYesFeedbacksData from totalFeedbacksData |
||||
|
var totalNoFeedbacksData = totalFeedbacksData.map((value, index) => value - totalYesFeedbacksData[index]); |
||||
|
|
||||
|
// Update the chart data |
||||
|
// this.chartBars.data.datasets[0].data = totalFeedbacksData; |
||||
|
// this.chartBars.data.datasets[0].data = totalYesFeedbacksData; |
||||
|
this.chartBars.data.datasets[0].data = totalNoFeedbacksData; |
||||
|
|
||||
|
// Log the updated chart data |
||||
|
// console.log('Updated chart data (totalFeedbacksData):', this.chartBars.data.datasets[0].data); |
||||
|
//console.log('Updated chart data (totalYesFeedbacksData):', this.chartBars.data.datasets[1].data); |
||||
|
//console.log('Updated chart data (totalNoFeedbacksData):', this.chartBars.data.datasets[2].data); |
||||
|
|
||||
|
// Update the chart |
||||
|
this.chartBars.update(); |
||||
|
} else { |
||||
|
console.error('Chart is not initialized. Unable to update data.'); |
||||
|
} |
||||
|
}, |
||||
|
|
||||
|
|
||||
|
|
||||
|
getAndPushData: function (cdate) { |
||||
|
// Ensure convert() is called before accessing dash.feedbackAnalysisData |
||||
|
convert(); |
||||
|
|
||||
|
var self = this; |
||||
|
|
||||
|
$.ajax({ |
||||
|
url: 'api/cou/' + cdate, |
||||
|
method: 'GET', |
||||
|
dataType: 'json', |
||||
|
success: function (response) { |
||||
|
console.log('Data fetched successfully:', response); |
||||
|
self.updateChartLinesBarsData(response); |
||||
|
}, |
||||
|
error: function (xhr, status, error) { |
||||
|
console.error('Error:', error); |
||||
|
} |
||||
|
}); |
||||
|
} |
||||
|
}; |
||||
|
|
||||
|
// Call the initChart function with the feedbackAnalysis data |
||||
|
pageDashboard.initChart(dash.feedbackAnalysisData || {}); |
||||
|
|
||||
|
// Call the getAndPushData method to fetch and update chart data |
||||
|
pageDashboard.getAndPushData(); |
||||
|
|
||||
|
pageDashboard.getAndPushData(); |
||||
|
var pageDashboard = { |
||||
|
chartPie: undefined, |
||||
|
chartPieData: { |
||||
|
labels: ['Total Complaints', 'Closed Complaint', 'Pending Complaint'], |
||||
|
datasets: [ |
||||
|
{ |
||||
|
data: [], |
||||
|
backgroundColor: ['#3498db', '#e74c3c', '#cc6633'], |
||||
|
hoverBackgroundColor: ['#2980b9', '#c0392b', '#A35128'] |
||||
|
} |
||||
|
] |
||||
|
}, |
||||
|
|
||||
|
initChart: function () { |
||||
|
// Get Chart Container |
||||
|
let chartPieCon = document.getElementById('myChart1'); |
||||
|
|
||||
|
var options = { |
||||
|
responsive: true, |
||||
|
plugins: { |
||||
|
datalabels: { |
||||
|
color: 'black', |
||||
|
formatter: function (value) { |
||||
|
// Display the value only if it's greater than 0 |
||||
|
return value > 0 ? value : ''; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
}; |
||||
|
|
||||
|
// Create the chart |
||||
|
this.chartPie = new Chart(chartPieCon, { |
||||
|
type: 'pie', |
||||
|
data: this.chartPieData, |
||||
|
options: options |
||||
|
}); |
||||
|
|
||||
|
// Add click event listener to the chart container |
||||
|
chartPieCon.onclick = function (event) { |
||||
|
var elements = pageDashboard.chartPie.getElementsAtEventForMode(event, 'point', pageDashboard.chartPie.options); |
||||
|
|
||||
|
if (elements && elements.length > 0) { |
||||
|
var clickedIndex = elements[0].index; |
||||
|
console.log('Clicked Index:', clickedIndex); |
||||
|
console.log('Elements:', elements); |
||||
|
console.log('Labels:', pageDashboard.chartPieData.labels); |
||||
|
|
||||
|
// Continue with the rest of your code... |
||||
|
} else { |
||||
|
console.error('No elements found at the click event.'); |
||||
|
} |
||||
|
if (clickedIndex >= 0 && clickedIndex < pageDashboard.chartPieData.labels.length) { |
||||
|
var clickedLabel = pageDashboard.chartPieData.labels[clickedIndex]; |
||||
|
|
||||
|
// Log the clicked label for debugging |
||||
|
console.log('Clicked Label:', clickedLabel); |
||||
|
|
||||
|
// Navigate based on the clicked label |
||||
|
switch (clickedLabel) { |
||||
|
case 'Total Complaints': |
||||
|
console.log('Navigating to pendingchart.html'); |
||||
|
window.location.href = 'pendingchart.html'; |
||||
|
break; |
||||
|
case 'Pending Complaint': |
||||
|
console.log('Navigating to nofeedbacks.html'); |
||||
|
window.location.href = 'closedchart.html'; |
||||
|
break; |
||||
|
case 'Closed Complaint': |
||||
|
console.log('Navigating to yesfeedbacks.html'); |
||||
|
window.location.href = 'totalchart.html'; |
||||
|
break; |
||||
|
// Add more cases for other labels if needed |
||||
|
default: |
||||
|
console.log('No action defined for clicked label:', clickedLabel); |
||||
|
} |
||||
|
} else { |
||||
|
console.error('Invalid clicked index:', clickedIndex); |
||||
|
} |
||||
|
|
||||
|
}; |
||||
|
}, |
||||
|
|
||||
|
updateChartPieData: function (data) { |
||||
|
if (this.chartPie) { |
||||
|
var totalFeedbacks = data.totalFeedbacks || 0; |
||||
|
var totalYesFeedbacks = data.totalYesFeedbacks || 0; |
||||
|
var totalNoFeedbacks = data.totalNoFeedbacks || 0; |
||||
|
|
||||
|
// Update the chart data |
||||
|
this.chartPieData.datasets[0].data = [totalFeedbacks, totalYesFeedbacks, totalNoFeedbacks]; |
||||
|
|
||||
|
// Update the chart |
||||
|
this.chartPie.update(); |
||||
|
} else { |
||||
|
console.error('Chart is not initialized. Unable to update data.'); |
||||
|
} |
||||
|
}, |
||||
|
|
||||
|
getAndPushData: function () { |
||||
|
// Assume you have a function named 'convert' |
||||
|
convert(); |
||||
|
var self = this; |
||||
|
|
||||
|
// Fetch data from the actual API |
||||
|
$.ajax({ |
||||
|
url: 'http://localhost:8071/api/dashboard-summary', |
||||
|
method: 'GET', |
||||
|
dataType: 'json', |
||||
|
success: function (response) { |
||||
|
console.log('Data fetched successfully:', response); |
||||
|
|
||||
|
// Call the function to process the API response |
||||
|
self.updateChartPieData(response); |
||||
|
}, |
||||
|
error: function (xhr, status, error) { |
||||
|
console.error('Error:', error); |
||||
|
} |
||||
|
}); |
||||
|
} |
||||
|
}; |
||||
|
|
||||
|
// Call the initChart function |
||||
|
pageDashboard.initChart(); |
||||
|
|
||||
|
// Call the getAndPushData method to fetch and update chart data |
||||
|
pageDashboard.getAndPushData(); |
||||
|
|
||||
|
|
||||
|
|
||||
|
|
||||
|
</script> |
||||
|
</body> |
||||
|
</html> |
||||
Write
Preview
Loading…
Cancel
Save
Reference in new issue