31 changed files with 6448 additions and 1117 deletions
-
19.mvn/wrapper/maven-wrapper.properties
-
12pom.xml
-
45src/main/java/com/gcc/publicgrievance/Service/ComplaintService.java
-
47src/main/java/com/gcc/publicgrievance/config/AppConfigur.java
-
28src/main/java/com/gcc/publicgrievance/configuration/AppConfig.java
-
73src/main/java/com/gcc/publicgrievance/configuration/DataSourceConfig.java
-
24src/main/java/com/gcc/publicgrievance/configuration/SecurityConfig.java
-
33src/main/java/com/gcc/publicgrievance/configuration/UserSessionInterceptor.java
-
123src/main/java/com/gcc/publicgrievance/controller/APIController.java
-
887src/main/java/com/gcc/publicgrievance/controller/ComplaintController.java
-
18src/main/java/com/gcc/publicgrievance/controller/UserController.java
-
20src/main/resources/application-dev.properties
-
24src/main/resources/application-prod.properties
-
9src/main/resources/application.properties
-
BINsrc/main/resources/static/images/message.png
-
BINsrc/main/resources/static/images/otp.png
-
BINsrc/main/resources/static/images/output-onlinepngtools.png
-
65src/main/resources/static/js/screenreader.js
-
82src/main/resources/templates/User/home.html
-
0src/main/resources/templates/User/kin.html
-
2120src/main/resources/templates/User/registercomplaints.html
-
320src/main/resources/templates/checklistofficer/checklistofficer.html
-
4src/main/resources/templates/fragments/accessibility.html
-
5src/main/resources/templates/fragments/footer.html
-
113src/main/resources/templates/fragments/header.html
-
258src/main/resources/templates/officer/checkofficerhome.html
-
528src/main/resources/templates/officer/checkofficerstatus.html
-
614src/main/resources/templates/staff/staffcheckstatus.html
-
1538src/main/resources/templates/staff/staffcomplaint.html
-
543src/main/resources/templates/staff/staffhome.html
-
13src/test/java/com/gcc/publicgrievance/PublicgrievanceApplicationTests.java
@ -1,19 +0,0 @@ |
|||||
# Licensed to the Apache Software Foundation (ASF) under one |
|
||||
# or more contributor license agreements. See the NOTICE file |
|
||||
# distributed with this work for additional information |
|
||||
# regarding copyright ownership. The ASF licenses this file |
|
||||
# to you under the Apache License, Version 2.0 (the |
|
||||
# "License"); you may not use this file except in compliance |
|
||||
# with the License. You may obtain a copy of the License at |
|
||||
# |
|
||||
# https://www.apache.org/licenses/LICENSE-2.0 |
|
||||
# |
|
||||
# Unless required by applicable law or agreed to in writing, |
|
||||
# software distributed under the License is distributed on an |
|
||||
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
|
||||
# KIND, either express or implied. See the License for the |
|
||||
# specific language governing permissions and limitations |
|
||||
# under the License. |
|
||||
wrapperVersion=3.3.2 |
|
||||
distributionType=only-script |
|
||||
distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.7/apache-maven-3.9.7-bin.zip |
|
||||
@ -0,0 +1,47 @@ |
|||||
|
package com.gcc.publicgrievance.config; |
||||
|
|
||||
|
import org.springframework.boot.context.properties.ConfigurationProperties; |
||||
|
import org.springframework.stereotype.Component; |
||||
|
|
||||
|
@Component |
||||
|
@ConfigurationProperties(prefix = "app") |
||||
|
public class AppConfigur { |
||||
|
|
||||
|
private String title; |
||||
|
private String baseUrl; |
||||
|
private String getOtpUrl; |
||||
|
private String erpUrl; |
||||
|
|
||||
|
public String getTitle() { |
||||
|
return title; |
||||
|
} |
||||
|
|
||||
|
public void setTitle(String title) { |
||||
|
this.title = title; |
||||
|
} |
||||
|
|
||||
|
public String getBaseUrl() { |
||||
|
return baseUrl; |
||||
|
} |
||||
|
|
||||
|
public void setBaseUrl(String baseUrl) { |
||||
|
this.baseUrl = baseUrl; |
||||
|
} |
||||
|
|
||||
|
public String getGetOtpUrl() { |
||||
|
return getOtpUrl; |
||||
|
} |
||||
|
|
||||
|
public void setGetOtpUrl(String getOtpUrl) { |
||||
|
this.getOtpUrl = getOtpUrl; |
||||
|
} |
||||
|
|
||||
|
public String getErpUrl() { |
||||
|
return erpUrl; |
||||
|
} |
||||
|
|
||||
|
public void setErpUrl(String erpUrl) { |
||||
|
this.erpUrl = erpUrl; |
||||
|
} |
||||
|
|
||||
|
} |
||||
@ -1,15 +1,15 @@ |
|||||
package com.gcc.publicgrievance.configuration; |
|
||||
|
|
||||
import org.springframework.context.annotation.Bean; |
|
||||
import org.springframework.context.annotation.Configuration; |
|
||||
import org.springframework.web.client.RestTemplate; |
|
||||
|
|
||||
@Configuration |
|
||||
public class AppConfig { |
|
||||
|
|
||||
@Bean |
|
||||
public RestTemplate restTemplate() { |
|
||||
return new RestTemplate(); |
|
||||
} |
|
||||
|
|
||||
} |
|
||||
|
package com.gcc.publicgrievance.configuration; |
||||
|
|
||||
|
import org.springframework.context.annotation.Bean; |
||||
|
import org.springframework.context.annotation.Configuration; |
||||
|
import org.springframework.web.client.RestTemplate; |
||||
|
|
||||
|
@Configuration public class AppConfig { |
||||
|
|
||||
|
@Bean |
||||
|
public RestTemplate restTemplate() { |
||||
|
return new RestTemplate(); |
||||
|
} |
||||
|
|
||||
|
} |
||||
@ -0,0 +1,73 @@ |
|||||
|
package com.gcc.publicgrievance.configuration; |
||||
|
|
||||
|
import java.util.Properties; |
||||
|
|
||||
|
import org.hibernate.jpa.HibernatePersistenceProvider; |
||||
|
import org.springframework.beans.factory.annotation.Qualifier; |
||||
|
import org.springframework.context.annotation.Bean; |
||||
|
import org.springframework.context.annotation.Configuration; |
||||
|
import org.springframework.context.annotation.Primary; |
||||
|
import org.springframework.data.jpa.repository.config.EnableJpaRepositories; |
||||
|
import org.springframework.jdbc.datasource.DriverManagerDataSource; |
||||
|
import org.springframework.orm.jpa.JpaTransactionManager; |
||||
|
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean; |
||||
|
import org.springframework.transaction.PlatformTransactionManager; |
||||
|
import org.springframework.transaction.annotation.EnableTransactionManagement; |
||||
|
import org.springframework.web.client.RestTemplate; |
||||
|
|
||||
|
import javax.sql.DataSource; |
||||
|
|
||||
|
@Configuration |
||||
|
@EnableTransactionManagement |
||||
|
public class DataSourceConfig { |
||||
|
|
||||
|
private static String host = "localhost"; |
||||
|
//private static String dbpassword = "gccroot"; |
||||
|
private static String dbpassword = "password"; |
||||
|
|
||||
|
@Configuration |
||||
|
@EnableTransactionManagement |
||||
|
@EnableJpaRepositories( |
||||
|
entityManagerFactoryRef = "appEntityManagerFactory", |
||||
|
transactionManagerRef = "appTransactionManager", |
||||
|
basePackages = {"com.gcc.publicgrievance"} |
||||
|
) |
||||
|
|
||||
|
public static class MysqlAppDataSourceConfig { |
||||
|
@Primary |
||||
|
@Bean(name = "mysqlAppDataSource") |
||||
|
public DataSource mysqlAppDataSource() { |
||||
|
DriverManagerDataSource dataSource = new DriverManagerDataSource(); |
||||
|
dataSource.setDriverClassName("com.mysql.cj.jdbc.Driver"); |
||||
|
dataSource.setUrl("jdbc:mysql://"+host+"/gcc_rest_services"); |
||||
|
dataSource.setUsername("root"); |
||||
|
dataSource.setPassword(dbpassword); |
||||
|
return dataSource; |
||||
|
} |
||||
|
|
||||
|
@Primary |
||||
|
@Bean(name="appEntityManagerFactory") |
||||
|
public LocalContainerEntityManagerFactoryBean entityManagerFactory( |
||||
|
@Qualifier("mysqlAppDataSource") DataSource dataSource) { |
||||
|
LocalContainerEntityManagerFactoryBean entityManagerFactoryBean = new LocalContainerEntityManagerFactoryBean(); |
||||
|
entityManagerFactoryBean.setDataSource(dataSource); |
||||
|
entityManagerFactoryBean.setPackagesToScan("com.gcc.publicgrievance"); |
||||
|
entityManagerFactoryBean.setPersistenceProviderClass(HibernatePersistenceProvider.class); |
||||
|
Properties properties = new Properties(); |
||||
|
properties.setProperty("hibernate.hbm2ddl.auto", "update"); |
||||
|
entityManagerFactoryBean.setJpaProperties(properties); |
||||
|
|
||||
|
return entityManagerFactoryBean; |
||||
|
} |
||||
|
|
||||
|
@Primary |
||||
|
@Bean(name = "appTransactionManager") |
||||
|
public PlatformTransactionManager transactionManager(@Qualifier("appEntityManagerFactory") jakarta.persistence.EntityManagerFactory entityManagerFactory) { |
||||
|
return new JpaTransactionManager(entityManagerFactory); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
|
||||
|
|
||||
|
|
||||
|
} |
||||
@ -0,0 +1,24 @@ |
|||||
|
package com.gcc.publicgrievance.configuration; |
||||
|
|
||||
|
import org.springframework.context.annotation.Bean; |
||||
|
import org.springframework.context.annotation.Configuration; |
||||
|
import org.springframework.security.config.annotation.web.builders.HttpSecurity; |
||||
|
import org.springframework.security.web.SecurityFilterChain; |
||||
|
|
||||
|
@Configuration |
||||
|
public class SecurityConfig { |
||||
|
|
||||
|
@Bean |
||||
|
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception { |
||||
|
http |
||||
|
.csrf(csrf -> csrf.disable()) |
||||
|
.authorizeHttpRequests(auth -> auth |
||||
|
.requestMatchers("/pgr/api/**").permitAll() |
||||
|
.anyRequest().permitAll() |
||||
|
) |
||||
|
.formLogin(form -> form.disable()) |
||||
|
.httpBasic(httpBasic -> httpBasic.disable()); |
||||
|
|
||||
|
return http.build(); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,33 @@ |
|||||
|
package com.gcc.publicgrievance.configuration; |
||||
|
|
||||
|
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.gcc.publicgrievance.config.AppConfigur; |
||||
|
|
||||
|
import jakarta.servlet.http.HttpServletRequest; |
||||
|
import jakarta.servlet.http.HttpServletResponse; |
||||
|
|
||||
|
@Component |
||||
|
public class UserSessionInterceptor implements HandlerInterceptor { |
||||
|
|
||||
|
|
||||
|
|
||||
|
@Autowired |
||||
|
private AppConfigur appConfig; |
||||
|
|
||||
|
@Override |
||||
|
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { |
||||
|
// Get the current request URL |
||||
|
String requestUrl = request.getRequestURI(); |
||||
|
request.setAttribute("baseURL", appConfig.getBaseUrl()); |
||||
|
|
||||
|
return true; // Allow the request to proceed |
||||
|
} |
||||
|
|
||||
|
|
||||
|
} |
||||
@ -0,0 +1,123 @@ |
|||||
|
package com.gcc.publicgrievance.controller; |
||||
|
|
||||
|
import java.io.BufferedReader; |
||||
|
import java.io.IOException; |
||||
|
import java.io.InputStreamReader; |
||||
|
import java.io.OutputStream; |
||||
|
import java.net.HttpURLConnection; |
||||
|
import java.net.URL; |
||||
|
import java.net.URLEncoder; |
||||
|
import java.time.LocalDateTime; |
||||
|
import java.time.format.DateTimeFormatter; |
||||
|
import java.util.Date; |
||||
|
import java.util.Random; |
||||
|
|
||||
|
import org.springframework.beans.factory.annotation.Autowired; |
||||
|
import org.springframework.http.HttpMethod; |
||||
|
import org.springframework.http.HttpStatus; |
||||
|
import org.springframework.http.ResponseEntity; |
||||
|
import org.springframework.web.bind.annotation.GetMapping; |
||||
|
import org.springframework.web.bind.annotation.PostMapping; |
||||
|
import org.springframework.web.bind.annotation.RequestMapping; |
||||
|
import org.springframework.web.bind.annotation.RequestParam; |
||||
|
import org.springframework.web.bind.annotation.RequestPart; |
||||
|
import org.springframework.web.bind.annotation.RestController; |
||||
|
import org.springframework.web.client.RestTemplate; |
||||
|
import org.springframework.web.multipart.MultipartFile; |
||||
|
|
||||
|
import com.fasterxml.jackson.databind.JsonNode; |
||||
|
import com.fasterxml.jackson.databind.ObjectMapper; // Import Jackson's ObjectMapper |
||||
|
import com.fasterxml.jackson.databind.node.ObjectNode; |
||||
|
import com.gcc.publicgrievance.config.AppConfigur; |
||||
|
|
||||
|
import jakarta.servlet.http.HttpServletRequest; |
||||
|
import jakarta.servlet.http.HttpSession; |
||||
|
|
||||
|
@RequestMapping("/pgr/api") |
||||
|
@RestController |
||||
|
public class APIController { |
||||
|
|
||||
|
@Autowired |
||||
|
private AppConfigur appConfig; |
||||
|
|
||||
|
@GetMapping(value = "/sendOTP") |
||||
|
public String sendOtp(HttpServletRequest request, |
||||
|
@RequestParam String mobileNo, |
||||
|
@RequestParam(defaultValue = "5") int otpLength, |
||||
|
@RequestParam(defaultValue = "false") boolean mobilenocheck) { |
||||
|
|
||||
|
String bodyMessage = ""; |
||||
|
|
||||
|
try { |
||||
|
// Validate Mobile Number |
||||
|
if (mobileNo.length() != 10) { |
||||
|
throw new IllegalArgumentException("Invalid Mobile Number. It must be 10 digits."); |
||||
|
} |
||||
|
|
||||
|
// New SMS API URL |
||||
|
String urlString = "https://gccservices.in/gccofficialapp/api/sendOTP?mobileNo=" + mobileNo + |
||||
|
"&otpLength=" + otpLength + "&mobilenocheck=" + mobilenocheck; |
||||
|
|
||||
|
System.out.println("\nurlString---: " + urlString); |
||||
|
|
||||
|
// Send the OTP using the new SMS API |
||||
|
RestTemplate restTemplate = new RestTemplate(); |
||||
|
ResponseEntity<String> response = restTemplate.exchange(urlString, HttpMethod.GET, null, String.class); |
||||
|
|
||||
|
// Log full response and status code |
||||
|
System.out.println("\nResponse Status Code: " + response.getStatusCode()); |
||||
|
System.out.println("\nResponse Body: " + response.getBody()); |
||||
|
|
||||
|
// Parse the response to extract the OTP from the API response |
||||
|
ObjectMapper objectMapper = new ObjectMapper(); |
||||
|
JsonNode jsonResponse = objectMapper.readTree(response.getBody()); |
||||
|
String apiOtp = jsonResponse.get(0).get("OTP").asText(); // Extract OTP from the response |
||||
|
int statusCode = jsonResponse.get(0).get("status").asInt(); // Extract status code |
||||
|
String message = jsonResponse.get(0).get("message").asText(); // Extract message |
||||
|
|
||||
|
// Store the OTP in the session |
||||
|
HttpSession session = request.getSession(); |
||||
|
session.setAttribute("otp", apiOtp); // Use the OTP from the API response |
||||
|
|
||||
|
// Construct the bodyMessage with status, mobileNo, and OTP |
||||
|
bodyMessage = "[{\"Status\": " + statusCode + " , \"Mobile No\": " + mobileNo + " , \"OTP\": " + apiOtp + " , \"Message\": \"" + message + "\"}]"; |
||||
|
System.out.println("OTP sent successfully!"); |
||||
|
|
||||
|
} catch (IllegalArgumentException e) { |
||||
|
// Catch validation error for mobile number |
||||
|
System.out.println("ERROR---: " + e.getMessage()); |
||||
|
bodyMessage = "Error: " + e.getMessage(); |
||||
|
} catch (Exception e) { |
||||
|
// Catch general errors |
||||
|
System.out.println("ERROR---: " + e); |
||||
|
bodyMessage = "There was a problem sending OTP. Try again."; |
||||
|
} |
||||
|
|
||||
|
return bodyMessage; |
||||
|
} |
||||
|
|
||||
|
@GetMapping(value = "/verifyOTP") |
||||
|
public String verifyOtp(HttpServletRequest request, @RequestParam String otp) { |
||||
|
HttpSession session = request.getSession(); |
||||
|
try { |
||||
|
String sessionOtp = (String) session.getAttribute("otp"); // Get OTP from session |
||||
|
System.out.println("sessionOtp---:" + sessionOtp); |
||||
|
String enteredOtp = otp.trim(); // OTP entered by user |
||||
|
|
||||
|
if (sessionOtp != null && sessionOtp.equals(enteredOtp)) { |
||||
|
System.out.println("Entered OTP Correct"); |
||||
|
session.setAttribute("verifiedotp", "success"); |
||||
|
return "Success"; // OTP is correct |
||||
|
} else { |
||||
|
System.out.println("Incorrect OTP. Please enter correct OTP."); |
||||
|
session.setAttribute("verifiedotp", "error"); |
||||
|
return "Error"; // OTP mismatch |
||||
|
} |
||||
|
} catch (Exception e) { |
||||
|
System.out.println("Error verifying OTP: " + e.getMessage()); |
||||
|
return "Error"; // Handle any exceptions |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
|
||||
|
} |
||||
@ -0,0 +1,20 @@ |
|||||
|
spring.application.name=publicgrievance |
||||
|
# Sets the session timeout to 60 seconds |
||||
|
#server.servlet.session.timeout=60s |
||||
|
|
||||
|
# Sets the async request timeout to 5000 milliseconds (5 seconds) |
||||
|
#spring.mvc.async.request-timeout=5000ms |
||||
|
|
||||
|
server.port=8072 |
||||
|
#server.port=8061 |
||||
|
|
||||
|
app.baseUrl=http://localhost:8072 |
||||
|
|
||||
|
#For development |
||||
|
#assets.baseUrl=/ |
||||
|
|
||||
|
|
||||
|
app.getOtpUrl=https://tmegov.onex-aura.com/api/sms? |
||||
|
|
||||
|
app.erpUrl=https://erp.chennaicorporation.gov.in/pgr/newmobileservice? |
||||
|
app.title=GREATER CHENNAI CORPORATION - PGR |
||||
@ -0,0 +1,24 @@ |
|||||
|
spring.application.name=publicgrievance |
||||
|
# Sets the session timeout to 60 seconds |
||||
|
#server.servlet.session.timeout=60s |
||||
|
|
||||
|
# Sets the async request timeout to 5000 milliseconds (5 seconds) |
||||
|
#spring.mvc.async.request-timeout=5000ms |
||||
|
|
||||
|
server.port=8072 |
||||
|
#server.port=8061 |
||||
|
|
||||
|
app.baseUrl=https://gccservices.chennaicorporation.gov.in/pgr/ |
||||
|
|
||||
|
#For Production |
||||
|
#assets.baseUrl=/pgr |
||||
|
|
||||
|
|
||||
|
app.getOtpUrl=https://tmegov.onex-aura.com/api/sms? |
||||
|
|
||||
|
app.erpUrl=https://erp.chennaicorporation.gov.in/pgr/newmobileservice? |
||||
|
app.title=GREATER CHENNAI CORPORATION - PGR |
||||
|
|
||||
|
# Disable DataSource auto-configuration since no database is being used |
||||
|
spring.autoconfigure.exclude=org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration |
||||
|
|
||||
@ -1,8 +1 @@ |
|||||
spring.application.name=publicgrievance |
|
||||
# Sets the session timeout to 60 seconds |
|
||||
server.servlet.session.timeout=60s |
|
||||
|
|
||||
# Sets the async request timeout to 5000 milliseconds (5 seconds) |
|
||||
spring.mvc.async.request-timeout=5000ms |
|
||||
|
|
||||
|
|
||||
|
spring.profiles.active= prod |
||||
|
After Width: 512 | Height: 512 | Size: 16 KiB |
|
After Width: 1102 | Height: 1020 | Size: 234 KiB |
|
After Width: 512 | Height: 512 | Size: 4.6 KiB |
@ -1,33 +1,44 @@ |
|||||
// screenReader.js
|
|
||||
|
// speech.js
|
||||
|
|
||||
let isReading = false; |
|
||||
let speechSynthesisUtterance; |
|
||||
|
let isSpeechEnabled = false; // Start with speech disabled
|
||||
|
|
||||
function readScreenContent() { |
|
||||
const content = document.body.innerText; |
|
||||
speechSynthesisUtterance = new SpeechSynthesisUtterance(content); |
|
||||
window.speechSynthesis.speak(speechSynthesisUtterance); |
|
||||
isReading = true; |
|
||||
|
// Function to handle the speech synthesis
|
||||
|
function speakText(text) { |
||||
|
if (isSpeechEnabled) { |
||||
|
const speech = new SpeechSynthesisUtterance(text); |
||||
|
speech.lang = 'en-US'; // Set language as needed
|
||||
|
window.speechSynthesis.speak(speech); |
||||
|
} |
||||
} |
} |
||||
|
|
||||
function stopReading() { |
|
||||
if (speechSynthesisUtterance) { |
|
||||
window.speechSynthesis.cancel(); |
|
||||
isReading = false; |
|
||||
} |
|
||||
|
// Function to add event listeners to all relevant elements for speech
|
||||
|
function addSpeechListeners() { |
||||
|
const elementsToRead = document.querySelectorAll('label, button, input, h1, h2, h3, h4,h5,h6, p, .card-footer'); // Add any additional selectors as needed
|
||||
|
elementsToRead.forEach(function(element) { |
||||
|
element.addEventListener('mouseover', function() { |
||||
|
// Check if it's an input field and read the placeholder if it exists
|
||||
|
if (element.tagName.toLowerCase() === 'input') { |
||||
|
const placeholder = element.getAttribute('placeholder'); |
||||
|
if (placeholder) { |
||||
|
speakText(placeholder.trim()); |
||||
|
} |
||||
|
} else { |
||||
|
speakText(element.textContent.trim()); // Speak the element's text when hovered
|
||||
|
} |
||||
|
}); |
||||
|
}); |
||||
} |
} |
||||
|
|
||||
function toggleScreenReader(buttonId) { |
|
||||
const button = document.getElementById(buttonId); |
|
||||
if (button) { |
|
||||
button.addEventListener('click', function() { |
|
||||
if (isReading) { |
|
||||
stopReading(); |
|
||||
button.innerText = "Read Screen"; // Update button text when stopped
|
|
||||
} else { |
|
||||
readScreenContent(); |
|
||||
button.innerText = "Stop Reading"; // Update button text when reading
|
|
||||
} |
|
||||
}); |
|
||||
} |
|
||||
} |
|
||||
|
document.addEventListener('DOMContentLoaded', function() { |
||||
|
addSpeechListeners(); // Add speech listeners when the document is loaded
|
||||
|
|
||||
|
// Add event listener to the toggle button
|
||||
|
const toggleButton = document.getElementById('toggleSpeech'); |
||||
|
toggleButton.addEventListener('click', function() { |
||||
|
isSpeechEnabled = !isSpeechEnabled; // Toggle the speech feature
|
||||
|
|
||||
|
// Update button text based on the state, preserving the image
|
||||
|
const buttonText = isSpeechEnabled ? 'Turn Off Speech' : 'Turn On Speech'; |
||||
|
toggleButton.innerHTML = `<img src="images/output-onlinepngtools.png" alt="Accessibility Icon" style="height: 30px;"> ${buttonText}`; |
||||
|
}); |
||||
|
}); |
||||
2120
src/main/resources/templates/User/registercomplaints.html
File diff suppressed because it is too large
View File
File diff suppressed because it is too large
View File
@ -0,0 +1,258 @@ |
|||||
|
<!DOCTYPE html> |
||||
|
<html xmlns:th="http://www.thymeleaf.org"> |
||||
|
|
||||
|
<head> |
||||
|
<meta charset="UTF-8"> |
||||
|
<title>Main Page</title> |
||||
|
<!--Google Font --> |
||||
|
<link href="https://fonts.googleapis.com/css2?family=Lato:wght@400;700&display=swap" rel="stylesheet"> |
||||
|
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.6.0/css/all.min.css" |
||||
|
integrity="sha512-Kc323vGBEqzTmouAECnVceyQqyqdsSiqLQISBL29aUW4U/M7pSPA/gEUZQqv1cwx4OnYxTxve5UMg5GT6L4JJg==" |
||||
|
crossorigin="anonymous" referrerpolicy="no-referrer" /> |
||||
|
<!--Bootstrap CSS--> |
||||
|
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css" rel="stylesheet"> |
||||
|
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.7.1/jquery.min.js"></script> |
||||
|
<script th:src="@{/js/invertcolor.js}"></script> |
||||
|
<style> |
||||
|
body { |
||||
|
font-family: 'Lato', sans-serif; |
||||
|
background-color: white; |
||||
|
} |
||||
|
|
||||
|
body.inverted { |
||||
|
background-color: black; |
||||
|
color: white; |
||||
|
filter: invert(1); |
||||
|
} |
||||
|
|
||||
|
.card { |
||||
|
border-radius: 15px; |
||||
|
border: none; |
||||
|
padding: 20px; |
||||
|
background-color: #f0f4ff; |
||||
|
text-align: center; |
||||
|
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1); |
||||
|
display: flex; |
||||
|
flex-direction: column; |
||||
|
height: 100%; |
||||
|
/* Make sure cards take up full height of the column */ |
||||
|
} |
||||
|
|
||||
|
.card-body { |
||||
|
flex: 1; |
||||
|
/* Allow card-body to grow and take up available space */ |
||||
|
} |
||||
|
|
||||
|
.card-img { |
||||
|
width: 40px; |
||||
|
margin-bottom: 15px; |
||||
|
} |
||||
|
|
||||
|
.card-title { |
||||
|
font-size: 1.2rem; |
||||
|
font-weight: bold; |
||||
|
} |
||||
|
|
||||
|
.card-text { |
||||
|
color: #666; |
||||
|
margin-bottom: 20px; |
||||
|
} |
||||
|
|
||||
|
.card-footer { |
||||
|
font-weight: bold; |
||||
|
color: #007bff; |
||||
|
display: flex; |
||||
|
align-items: center; |
||||
|
justify-content: center; |
||||
|
} |
||||
|
|
||||
|
.card-footer i { |
||||
|
margin-left: 5px; |
||||
|
} |
||||
|
|
||||
|
.row { |
||||
|
display: flex; |
||||
|
flex-wrap: wrap; |
||||
|
margin-bottom: 30px; |
||||
|
} |
||||
|
|
||||
|
.col-md-4 { |
||||
|
display: flex; |
||||
|
/* Ensure columns use Flexbox to distribute space evenly */ |
||||
|
padding: 0 15px; |
||||
|
/* Adjust padding to fit full width */ |
||||
|
} |
||||
|
|
||||
|
.container { |
||||
|
max-width: 1200px; |
||||
|
} |
||||
|
|
||||
|
.container .row .col-md-4 { |
||||
|
padding: 0 15px; |
||||
|
/* Adjust padding to fit full width */ |
||||
|
display: flex; |
||||
|
flex-direction: column; |
||||
|
} |
||||
|
|
||||
|
.card { |
||||
|
flex-grow: 1; |
||||
|
/* Ensure all cards have the same height */ |
||||
|
} |
||||
|
|
||||
|
.container .row .col-md-12 { |
||||
|
padding: 0 15px; |
||||
|
} |
||||
|
|
||||
|
.card-link { |
||||
|
text-decoration: none; |
||||
|
/* Remove the underline from the link */ |
||||
|
color: inherit; |
||||
|
/* Inherit the text color */ |
||||
|
display: block; |
||||
|
/* Make the link cover the entire card */ |
||||
|
} |
||||
|
|
||||
|
.card-link:hover .card { |
||||
|
box-shadow: 0 6px 12px rgba(0, 0, 0, 0.2); |
||||
|
/* Optional: add hover effect */ |
||||
|
} |
||||
|
|
||||
|
/* Style for reader button */ |
||||
|
|
||||
|
|
||||
|
#reader-btn.active { |
||||
|
background-color: #28a745; |
||||
|
} |
||||
|
|
||||
|
/*header css*/ |
||||
|
.header { |
||||
|
background-color: #3b4858; |
||||
|
padding: 10px 20px; |
||||
|
display: flex; |
||||
|
align-items: center; |
||||
|
justify-content: space-between; |
||||
|
color: white; |
||||
|
} |
||||
|
|
||||
|
.header .logo-left img { |
||||
|
height: 60px; |
||||
|
} |
||||
|
|
||||
|
.header .title { |
||||
|
text-align: center; |
||||
|
flex-grow: 1; |
||||
|
} |
||||
|
|
||||
|
.header .title h2 { |
||||
|
margin: 0; |
||||
|
font-size: 1.5rem; |
||||
|
} |
||||
|
|
||||
|
.header .logos-right img { |
||||
|
height: 60px; |
||||
|
margin-left: 10px; |
||||
|
} |
||||
|
|
||||
|
/*header buttons*/ |
||||
|
.header { |
||||
|
display: flex; |
||||
|
align-items: center; |
||||
|
justify-content: space-between; |
||||
|
/* Space out the items within the header */ |
||||
|
} |
||||
|
|
||||
|
.header-buttons { |
||||
|
padding-left: 5px; |
||||
|
display: flex; |
||||
|
align-items: center; |
||||
|
gap: 10px; |
||||
|
/* Adjust spacing between buttons */ |
||||
|
} |
||||
|
|
||||
|
#reader-btn, |
||||
|
#invertColorBtn { |
||||
|
padding: 5px 10px; |
||||
|
font-size: 14px; |
||||
|
cursor: pointer; |
||||
|
} |
||||
|
|
||||
|
/*for radio button style*/ |
||||
|
.radio-group { |
||||
|
display: flex; |
||||
|
align-items: center; |
||||
|
/* Ensures all items are aligned to the center */ |
||||
|
} |
||||
|
|
||||
|
.radio-item { |
||||
|
display: flex; |
||||
|
align-items: center; |
||||
|
margin-right: 20px; |
||||
|
/* Adds space between each radio item */ |
||||
|
} |
||||
|
|
||||
|
.radio-item input[type="radio"] { |
||||
|
margin-right: 10px; |
||||
|
/* Adds space between the radio button and its label */ |
||||
|
vertical-align: middle; |
||||
|
/* Ensures vertical alignment */ |
||||
|
} |
||||
|
|
||||
|
.radio-item label { |
||||
|
margin: 0; |
||||
|
/* Removes any default margins that might affect alignment */ |
||||
|
} |
||||
|
</style> |
||||
|
</head> |
||||
|
|
||||
|
|
||||
|
<body> |
||||
|
<div th:insert="~{fragments/accessibility :: accessibility}"></div> |
||||
|
|
||||
|
<!-- Insert the header fragment --> |
||||
|
<div th:insert="fragments/header :: headerFragment"></div> |
||||
|
|
||||
|
|
||||
|
|
||||
|
<!-- Cards Section --> |
||||
|
<!-- Cards Section --> |
||||
|
<div class="container d-flex justify-content-center align-items-center" style="height: 100vh;"> |
||||
|
<!--card to register complaint--> |
||||
|
<div class="col-md-12"> |
||||
|
<a href="/pgr/registercomplaints" class="card-link"> |
||||
|
<div class="card content" style="margin-bottom: 12%;"> |
||||
|
<div class="card-body"> |
||||
|
<img src="images/register.png" alt="register" class="card-img"> |
||||
|
<div class="card-content"> |
||||
|
<h5 class="card-title">Register Your<br> Complaints</h5> |
||||
|
<p class="card-text">Register Complaints<br> Via Internet</p> |
||||
|
</div> |
||||
|
</div> |
||||
|
<div class="card-footer"> |
||||
|
Get Started <i class="fa fa-arrow-right"></i> |
||||
|
</div> |
||||
|
</div> |
||||
|
</a> |
||||
|
</div> |
||||
|
</div> |
||||
|
|
||||
|
|
||||
|
|
||||
|
<div th:insert="fragments/footer :: footerFragment"></div> |
||||
|
|
||||
|
<script th:src="@{/js/screenreader.js}"></script> |
||||
|
|
||||
|
<!-- Replace Slim jQuery with Full jQuery --> |
||||
|
<script src="https://code.jquery.com/jquery-3.2.1.min.js"></script> |
||||
|
|
||||
|
<!-- Popper.js (for Bootstrap tooltips, popovers, etc.) --> |
||||
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.11.0/umd/popper.min.js"></script> |
||||
|
|
||||
|
<!-- Bootstrap JS --> |
||||
|
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/js/bootstrap.min.js"></script> |
||||
|
|
||||
|
<!-- Font Awesome for Icons --> |
||||
|
<script src="https://kit.fontawesome.com/a076d05399.js"></script> |
||||
|
|
||||
|
</body> |
||||
|
|
||||
|
</html> |
||||
@ -0,0 +1,528 @@ |
|||||
|
<!DOCTYPE html> |
||||
|
<html xmlns:th="http://www.thymeleaf.org"> |
||||
|
|
||||
|
<head> |
||||
|
<meta charset="UTF-8"> |
||||
|
<title>CheckList User</title> |
||||
|
<!-- Google Font --> |
||||
|
<link href="https://fonts.googleapis.com/css2?family=Lato:wght@400;700&display=swap" rel="stylesheet"> |
||||
|
<!-- Bootstrap CSS --> |
||||
|
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css" rel="stylesheet"> |
||||
|
|
||||
|
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.7.1/jquery.min.js"></script> |
||||
|
<link rel="stylesheet" href="https://unpkg.com/leaflet/dist/leaflet.css" /> |
||||
|
<script src="https://unpkg.com/leaflet/dist/leaflet.js"></script> |
||||
|
<style> |
||||
|
/*rating style for css*/ |
||||
|
.rating { |
||||
|
direction: rtl; |
||||
|
display: inline-flex; |
||||
|
font-size: 24px; |
||||
|
} |
||||
|
|
||||
|
.rating input { |
||||
|
display: none; |
||||
|
} |
||||
|
|
||||
|
.rating label { |
||||
|
color: #ddd; |
||||
|
cursor: pointer; |
||||
|
margin: 0; |
||||
|
} |
||||
|
|
||||
|
.rating input:checked~label { |
||||
|
color: #414f69; |
||||
|
} |
||||
|
|
||||
|
.rating label:hover, |
||||
|
.rating label:hover~label { |
||||
|
color: #414f69; |
||||
|
} |
||||
|
|
||||
|
/* Style for resizing content */ |
||||
|
.resizable-content { |
||||
|
font-size: medium; |
||||
|
transition: font-size 0.3s ease; |
||||
|
} |
||||
|
|
||||
|
|
||||
|
.comment-table { |
||||
|
width: 100%; |
||||
|
border-collapse: collapse; |
||||
|
} |
||||
|
|
||||
|
.comment-table td { |
||||
|
padding: 0.5rem; |
||||
|
border: 1px solid #ddd; |
||||
|
/* Light border color */ |
||||
|
} |
||||
|
|
||||
|
.comment-table td:first-child { |
||||
|
width: 25%; |
||||
|
/* Adjust as needed for label column width */ |
||||
|
font-weight: bold; |
||||
|
} |
||||
|
|
||||
|
.comment-table td:nth-child(2) { |
||||
|
width: 75%; |
||||
|
/* Adjust as needed for value column width */ |
||||
|
} |
||||
|
</style> |
||||
|
</head> |
||||
|
|
||||
|
<body> |
||||
|
|
||||
|
<!-- Insert the header fragment --> |
||||
|
|
||||
|
<div th:insert="~{fragments/header :: headerFragment}"></div> |
||||
|
|
||||
|
<div class="container mt-4"> |
||||
|
<!-- Loader GIF --> |
||||
|
<div id="loader" style="display: none; text-align: center;"> |
||||
|
<img src="images/Thin broken ring.gif" alt="Loading..." /> |
||||
|
</div> |
||||
|
|
||||
|
|
||||
|
|
||||
|
<div class="mt-1"> |
||||
|
<div class="row align-items-center justify-content-center"> |
||||
|
<h4 class="title resizable-content" style="color: #414f69;">Check Complaint Status</h4> |
||||
|
</div> |
||||
|
</div> |
||||
|
<!-- Card Section --> |
||||
|
<div class="card p-3 resizable-content" style="margin-bottom: 8px;color: #414f69;"> |
||||
|
<div class="card mb-3 resizable-content"> |
||||
|
<div class="card-header text-white" style="background-color: #414f69;">1. Complaining Person's Details |
||||
|
</div> |
||||
|
<div class="card-body"> |
||||
|
<div class="row"> |
||||
|
<div class="col-md-6"> |
||||
|
Complainant ID: |
||||
|
<input type="text" id="complaintid" class="form-control" value="" disabled> |
||||
|
</div> |
||||
|
<div class="col-md-6"> |
||||
|
Complainant Mobile Number: |
||||
|
<input type="text" id="complaint-mobile-number" class="form-control" value="" disabled> |
||||
|
</div> |
||||
|
<div class="col-md-6"> |
||||
|
Complainant Name: |
||||
|
<input type="text" id="complaint-customer-name" class="form-control" value="" disabled> |
||||
|
</div> |
||||
|
|
||||
|
<!--<div class="col-md-6"> |
||||
|
Gender: |
||||
|
<select class="form-control" id="gender" disabled> |
||||
|
<option value="0">Select Gender</option> |
||||
|
<option value="male">Male</option> |
||||
|
<option value="female">Female</option> |
||||
|
<option value="transgender">Transgender</option> |
||||
|
</select> |
||||
|
</div>--> |
||||
|
</div> |
||||
|
</div> |
||||
|
</div> |
||||
|
|
||||
|
<div class="card mb-3 resizable-content"> |
||||
|
<div class="card-header text-white" style="background-color: #414f69;">2. Complaint Location Details |
||||
|
</div> |
||||
|
<div class="card-body"> |
||||
|
<div class="row"> |
||||
|
<div class="col-md-4"> |
||||
|
Complainant Street: |
||||
|
<input type="text" id="street" class="form-control" disabled> |
||||
|
</div> |
||||
|
<div class="col-md-4"> |
||||
|
Complainant Zone: |
||||
|
<input type="text" class="form-control" id="zone" disabled> |
||||
|
</div> |
||||
|
<div class="col-md-4"> |
||||
|
Complainant Ward: |
||||
|
<input type="text" class="form-control" id="ward" disabled> |
||||
|
</div> |
||||
|
<div class="col-md-4"> |
||||
|
Complainant Area: |
||||
|
<input type="text" class="form-control" id="area" disabled> |
||||
|
</div> |
||||
|
<div class="col-md-4"> |
||||
|
Complainant Locality: |
||||
|
<input type="text" class="form-control" id="location" disabled> |
||||
|
</div> |
||||
|
</div> |
||||
|
</div> |
||||
|
</div> |
||||
|
|
||||
|
<div class="card resizable-content"> |
||||
|
<div class="card-header text-white" style="background-color: #414f69;">3. Complaint Type</div> |
||||
|
<div class="card-body"> |
||||
|
<div class="row"> |
||||
|
<div class="col-md-4"> |
||||
|
Complainant Type: |
||||
|
<input type="text" class="form-control" id="complaintType" disabled> |
||||
|
</div> |
||||
|
|
||||
|
<!--<div class="col-md-4"> |
||||
|
Complainant Sub-Type: |
||||
|
<input type="text" class="form-control" disabled> |
||||
|
</div> |
||||
|
<div class="col-md-4"> |
||||
|
Complainant Title: |
||||
|
<input type="text" class="form-control" disabled> |
||||
|
</div>--> |
||||
|
<div class="col-md-12"> |
||||
|
Complainant Description: |
||||
|
<input type="text" class="form-control" id="complaintdesc" disabled> |
||||
|
</div> |
||||
|
</div> |
||||
|
</div> |
||||
|
</div> |
||||
|
</div> |
||||
|
|
||||
|
<div class="card mb-3 resizable-content"> |
||||
|
<div class="card-header text-white" style="background-color: #414f69;">Complaint Action</div> |
||||
|
<div class="card-body"> |
||||
|
<div class="row"> |
||||
|
|
||||
|
|
||||
|
<div class="col-md-4"> |
||||
|
Complaint Closed Date: |
||||
|
|
||||
|
<input type="text" class="form-control" id="commentDate" disabled> |
||||
|
</div> |
||||
|
<div class="col-md-4"> |
||||
|
Official Name: |
||||
|
<input type="text" class="form-control" id="commentuser" disabled> |
||||
|
</div> |
||||
|
|
||||
|
<div class="col-md-4"> |
||||
|
Status: |
||||
|
<input type="text" class="form-control" id="statusshow" |
||||
|
style="background-color: #414f69;color: white;" disabled> |
||||
|
</div> |
||||
|
</div> |
||||
|
|
||||
|
|
||||
|
</div> |
||||
|
</div> |
||||
|
|
||||
|
|
||||
|
<div class="card mb-3 resizable-content"> |
||||
|
<div class="card-header text-white" style="background-color: #414f69;">Complaint Action History</div> |
||||
|
<div class="card-body"> |
||||
|
<div id="comments-container"></div> <!-- Container for comments --> |
||||
|
</div> |
||||
|
</div> |
||||
|
|
||||
|
|
||||
|
|
||||
|
<div class="card mb-3 resizable-content"> |
||||
|
<div class="card-header text-white" style="background-color: #414f69;">Update Complaint</div> |
||||
|
<div class="card-body"> |
||||
|
<div class="row"> |
||||
|
<div class="col-md-6"> |
||||
|
Change Complaint Status: |
||||
|
<select class="form-control" name="complaintStatusID" id="complaintStatus"> |
||||
|
<option value="0">Choose</option> |
||||
|
<option value="8">WITHDRAW</option> |
||||
|
<option value="9">REOPENED</option> |
||||
|
|
||||
|
</select> |
||||
|
</div> |
||||
|
|
||||
|
<div class="col-md-6" id="img" style="display: none;"> |
||||
|
Photo: |
||||
|
<input type="file" class="form-control" id="photo"> |
||||
|
</div> |
||||
|
</div> |
||||
|
<div class="row"> |
||||
|
<div class="col-md-12"> |
||||
|
Details of Complaint: |
||||
|
<textarea class="form-control" id="othercomplaint-details" rows="3" |
||||
|
placeholder="Enter complaint details" maxlength="400" required></textarea> |
||||
|
</div> |
||||
|
</div> |
||||
|
<div class="row align-items-center justify-content-center" style="margin-top: 5px;"> |
||||
|
<button class="btn btn-sm" style="background-color: #414f69;color: white;">Submit</button> |
||||
|
</div> |
||||
|
</div> |
||||
|
</div> |
||||
|
|
||||
|
|
||||
|
|
||||
|
|
||||
|
</div> |
||||
|
|
||||
|
|
||||
|
|
||||
|
<!-- Bootstrap JS --> |
||||
|
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script> |
||||
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.11.0/umd/popper.min.js"></script> |
||||
|
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/js/bootstrap.min.js"></script> |
||||
|
<script src="https://cdn.jsdelivr.net/npm/sweetalert2@11"></script> |
||||
|
|
||||
|
<script> |
||||
|
|
||||
|
</script> |
||||
|
|
||||
|
|
||||
|
<!-- JavaScript to handle button clicks --> |
||||
|
<script> |
||||
|
|
||||
|
// /api/getComplaintDetailsbyId |
||||
|
$(document).ready(function () { |
||||
|
var urlParams = new URLSearchParams(window.location.search); |
||||
|
var complaintNo = urlParams.get('complaintno'); |
||||
|
|
||||
|
if (complaintNo) { |
||||
|
$('#loader').show(); |
||||
|
|
||||
|
$.ajax({ |
||||
|
url: '/pgr/api/getComplaintDetailsbyId', // Replace with your actual API endpoint |
||||
|
type: 'GET', |
||||
|
data: {complaintid: complaintNo}, |
||||
|
success: function (response) { |
||||
|
console.log('API response:', response); |
||||
|
$('#loader').hide(); |
||||
|
|
||||
|
if (Array.isArray(response) && response.length > 0) { |
||||
|
var complaintListHistory = response[0].ComplaintListHistory; |
||||
|
|
||||
|
if (Array.isArray(complaintListHistory) && complaintListHistory.length > 0) { |
||||
|
var complaintDetails = complaintListHistory[0]; |
||||
|
|
||||
|
// Decode HTML entities before populating fields |
||||
|
function decodeHtmlEntities(str) { |
||||
|
var txt = document.createElement('textarea'); |
||||
|
txt.innerHTML = str; |
||||
|
return txt.value; |
||||
|
} |
||||
|
|
||||
|
// Populate other form fields |
||||
|
document.getElementById("complaintid").value = complaintDetails.complaintid || ''; |
||||
|
document.getElementById("complaint-mobile-number").value = complaintDetails.CustomerMobile || ''; |
||||
|
document.getElementById("complaint-customer-name").value = complaintDetails.CustomerName || ''; |
||||
|
document.getElementById("street").value = complaintDetails.Street || ''; |
||||
|
document.getElementById("zone").value = complaintDetails.Zone || ''; |
||||
|
document.getElementById("ward").value = complaintDetails.Division || ''; |
||||
|
document.getElementById("area").value = complaintDetails.Area || ''; |
||||
|
document.getElementById("location").value = complaintDetails.Location || ''; |
||||
|
document.getElementById("complaintType").value = complaintDetails.complainttype || ''; |
||||
|
|
||||
|
// Decode and populate complaint description |
||||
|
document.getElementById("complaintdesc").value = decodeHtmlEntities(complaintDetails.complaintdetails || ''); |
||||
|
|
||||
|
document.getElementById("commentDate").value = complaintDetails.complaintcloseddate || ''; |
||||
|
document.getElementById("commentuser").value = complaintDetails.Officialname || ''; |
||||
|
document.getElementById("statusshow").value = complaintDetails.complaintcurrentstatus || ''; |
||||
|
|
||||
|
// Handle nested Comments array |
||||
|
if (Array.isArray(complaintDetails.Comments) && complaintDetails.Comments.length > 0) { |
||||
|
var commentsContainer = $('#comments-container'); |
||||
|
commentsContainer.empty(); // Clear the container |
||||
|
|
||||
|
var comments = complaintDetails.Comments; |
||||
|
var lastComment = comments[comments.length - 1]; |
||||
|
|
||||
|
// Decode HTML entities for last comment |
||||
|
function decodeHtmlEntities(str) { |
||||
|
var txt = document.createElement('textarea'); |
||||
|
txt.innerHTML = str; |
||||
|
return txt.value; |
||||
|
} |
||||
|
|
||||
|
// Handle last comment |
||||
|
var userImageHtml = ''; |
||||
|
if (Array.isArray(lastComment.userimages) && lastComment.userimages.length > 0) { |
||||
|
var imageUrl = lastComment.userimages[0].Comp_Image; |
||||
|
if (imageUrl && imageUrl !== 'null') { |
||||
|
userImageHtml = ` |
||||
|
<div class="col-md-12"> |
||||
|
<img src="${imageUrl}" alt="User Image" class="img-fluid"> |
||||
|
</div>`; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
var lastCommentHtml = ` |
||||
|
<div class="row mb-3"> |
||||
|
<table class="comment-table"> |
||||
|
<tr> |
||||
|
<td style="color:#3c4959">User:</td> |
||||
|
<td>${lastComment.user || ''}</td> |
||||
|
</tr> |
||||
|
<tr> |
||||
|
<td style="color:#3c4959">Message:</td> |
||||
|
<td>${lastComment.message || ''}</td> |
||||
|
</tr> |
||||
|
<tr> |
||||
|
<td style="color:#3c4959">Comment Date:</td> |
||||
|
<td>${lastComment.comment_date || ''}</td> |
||||
|
</tr> |
||||
|
${userImageHtml} |
||||
|
</table> |
||||
|
</div> |
||||
|
<hr>`; |
||||
|
|
||||
|
commentsContainer.append(lastCommentHtml); |
||||
|
|
||||
|
// Add dropdown button for other comments |
||||
|
if (comments.length > 1) { |
||||
|
var dropdownHtml = ` |
||||
|
<button id="show-all-comments" class="btn mt-3" style="margin-bottom: 10px;background-color: #3c4959; |
||||
|
color: white;">Show All Comments</button> |
||||
|
<div id="all-comments" style="display:none;">`; |
||||
|
|
||||
|
// Add all comments to dropdown |
||||
|
comments.forEach(function (comment, index) { |
||||
|
if (index < comments.length - 1) { // Skip the last comment |
||||
|
var userImageHtml = ''; |
||||
|
if (Array.isArray(comment.userimages) && comment.userimages.length > 0) { |
||||
|
var imageUrl = comment.userimages[0].Comp_Image; |
||||
|
if (imageUrl && imageUrl !== 'null') { |
||||
|
userImageHtml = ` |
||||
|
<div class="col-md-12"> |
||||
|
<img src="${imageUrl}" alt="User Image" class="img-fluid"> |
||||
|
</div>`; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
dropdownHtml += ` |
||||
|
<div class="row mb-3"> |
||||
|
<table class="comment-table"> |
||||
|
<tr> |
||||
|
<td style="color:#3c4959">User:</td> |
||||
|
<td>${comment.user || ''}</td> |
||||
|
</tr> |
||||
|
<tr> |
||||
|
<td style="color:#3c4959">Message:</td> |
||||
|
<td>${comment.message || ''}</td> |
||||
|
</tr> |
||||
|
<tr> |
||||
|
<td style="color:#3c4959">Comment Date:</td> |
||||
|
<td>${comment.comment_date || ''}</td> |
||||
|
</tr> |
||||
|
${userImageHtml} |
||||
|
</table> |
||||
|
</div> |
||||
|
<hr>`; |
||||
|
} |
||||
|
}); |
||||
|
|
||||
|
dropdownHtml += '</div>'; |
||||
|
|
||||
|
commentsContainer.append(dropdownHtml); |
||||
|
|
||||
|
// Toggle display of all comments |
||||
|
$('#show-all-comments').click(function () { |
||||
|
$('#all-comments').toggle(); |
||||
|
$(this).text($(this).text() === 'Show All Comments' ? 'Hide Comments' : 'Show All Comments'); |
||||
|
}); |
||||
|
} |
||||
|
} else { |
||||
|
$('#comments-container').html('<p>No comments found.</p>'); |
||||
|
} |
||||
|
} else { |
||||
|
alert('No complaint details found in ComplaintListHistory.'); |
||||
|
} |
||||
|
} else { |
||||
|
alert('Unexpected response structure.'); |
||||
|
} |
||||
|
}, |
||||
|
error: function (xhr, status, error) { |
||||
|
console.log('Error:', xhr.responseText); |
||||
|
alert('An error occurred while fetching complaint details.'); |
||||
|
$('#loader').hide(); |
||||
|
} |
||||
|
}); |
||||
|
} else { |
||||
|
alert('No complaint number provided.'); |
||||
|
} |
||||
|
}); |
||||
|
|
||||
|
|
||||
|
|
||||
|
|
||||
|
|
||||
|
$(document).ready(function () { |
||||
|
$('#complaintStatus').change(function () { |
||||
|
if ($(this).val() == '9') { // Show the image field if 'REOPENED' is selected |
||||
|
$('#img').show(); |
||||
|
} else { |
||||
|
$('#img').hide(); |
||||
|
} |
||||
|
}); |
||||
|
|
||||
|
$('.btn').click(function (e) { |
||||
|
e.preventDefault(); |
||||
|
|
||||
|
var complaintId = $('#complaintid').val(); |
||||
|
var complaintStatus = $('#complaintStatus').val(); |
||||
|
var message = $('#othercomplaint-details').val(); |
||||
|
|
||||
|
// Validate "Details of Complaint" field |
||||
|
if (message.trim() === "") { |
||||
|
Swal.fire({ |
||||
|
title: 'Validation Error!', |
||||
|
text: 'Please enter the details of the complaint.', |
||||
|
icon: 'warning', |
||||
|
confirmButtonText: 'OK' |
||||
|
}); |
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
if (complaintStatus == '0') { |
||||
|
Swal.fire({ |
||||
|
title: 'Validation Error!', |
||||
|
text: 'Please select a valid complaint status.', |
||||
|
icon: 'warning', |
||||
|
confirmButtonText: 'OK' |
||||
|
}); |
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
var formData = new FormData(); |
||||
|
formData.append("ComplaintId", complaintId); |
||||
|
formData.append("Message", message); |
||||
|
formData.append("Status", complaintStatus); |
||||
|
|
||||
|
var imageFile = $('#photo')[0].files[0]; |
||||
|
if (imageFile) { |
||||
|
formData.append("Comp_Image", imageFile); |
||||
|
} |
||||
|
|
||||
|
$.ajax({ |
||||
|
url: '/publicgrievance/updateComplaint', |
||||
|
type: 'POST', |
||||
|
data: formData, |
||||
|
processData: false, |
||||
|
contentType: false, |
||||
|
success: function (response) { |
||||
|
console.log(imageFile,complaintId,message,complaintStatus); |
||||
|
Swal.fire({ |
||||
|
title: 'Success!', |
||||
|
text: 'Complaint updated successfully.', |
||||
|
icon: 'success', |
||||
|
confirmButtonText: 'OK' |
||||
|
}).then((result) => { |
||||
|
if (result.isConfirmed) { |
||||
|
window.location.href = 'home'; |
||||
|
} |
||||
|
}); |
||||
|
}, |
||||
|
error: function (xhr, status, error) { |
||||
|
console.error('Error updating complaint:', error); |
||||
|
let errorMessage = xhr.responseText ? xhr.responseText : 'An error occurred while updating the complaint.'; |
||||
|
Swal.fire({ |
||||
|
title: 'Error!', |
||||
|
text: errorMessage, |
||||
|
icon: 'error', |
||||
|
confirmButtonText: 'OK' |
||||
|
}); |
||||
|
} |
||||
|
}); |
||||
|
}); |
||||
|
}); |
||||
|
|
||||
|
</script> |
||||
|
<script th:src="@{/js/screenreader.js}"></script> |
||||
|
</body> |
||||
|
|
||||
|
</html> |
||||
@ -0,0 +1,614 @@ |
|||||
|
<!DOCTYPE html> |
||||
|
<html xmlns:th="http://www.thymeleaf.org"> |
||||
|
|
||||
|
<head> |
||||
|
<meta charset="UTF-8"> |
||||
|
<title>CheckList User</title> |
||||
|
<!-- Google Font --> |
||||
|
<link href="https://fonts.googleapis.com/css2?family=Lato:wght@400;700&display=swap" rel="stylesheet"> |
||||
|
<!-- Bootstrap CSS --> |
||||
|
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css" rel="stylesheet"> |
||||
|
|
||||
|
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.7.1/jquery.min.js"></script> |
||||
|
<link rel="stylesheet" href="https://unpkg.com/leaflet/dist/leaflet.css" /> |
||||
|
<script src="https://unpkg.com/leaflet/dist/leaflet.js"></script> |
||||
|
<style> |
||||
|
/*rating style for css*/ |
||||
|
.rating { |
||||
|
direction: rtl; |
||||
|
display: inline-flex; |
||||
|
font-size: 24px; |
||||
|
} |
||||
|
|
||||
|
.rating input { |
||||
|
display: none; |
||||
|
} |
||||
|
|
||||
|
.rating label { |
||||
|
color: #ddd; |
||||
|
cursor: pointer; |
||||
|
margin: 0; |
||||
|
} |
||||
|
|
||||
|
.rating input:checked~label { |
||||
|
color: #414f69; |
||||
|
} |
||||
|
|
||||
|
.rating label:hover, |
||||
|
.rating label:hover~label { |
||||
|
color: #414f69; |
||||
|
} |
||||
|
|
||||
|
/* Style for resizing content */ |
||||
|
.resizable-content { |
||||
|
font-size: medium; |
||||
|
transition: font-size 0.3s ease; |
||||
|
} |
||||
|
|
||||
|
|
||||
|
.comment-table { |
||||
|
width: 100%; |
||||
|
border-collapse: collapse; |
||||
|
} |
||||
|
|
||||
|
.comment-table td { |
||||
|
padding: 0.5rem; |
||||
|
border: 1px solid #ddd; |
||||
|
/* Light border color */ |
||||
|
} |
||||
|
|
||||
|
.comment-table td:first-child { |
||||
|
width: 25%; |
||||
|
/* Adjust as needed for label column width */ |
||||
|
font-weight: bold; |
||||
|
} |
||||
|
|
||||
|
.comment-table td:nth-child(2) { |
||||
|
width: 75%; |
||||
|
/* Adjust as needed for value column width */ |
||||
|
} |
||||
|
</style> |
||||
|
</head> |
||||
|
|
||||
|
<body> |
||||
|
|
||||
|
<!-- Insert the header fragment --> |
||||
|
|
||||
|
<div th:insert="~{fragments/header :: headerFragment}"></div> |
||||
|
|
||||
|
<div class="container mt-4"> |
||||
|
<!-- Loader GIF --> |
||||
|
<div id="loader" style="display: none; text-align: center;"> |
||||
|
<img src="images/Thin broken ring.gif" alt="Loading..." /> |
||||
|
</div> |
||||
|
|
||||
|
|
||||
|
|
||||
|
|
||||
|
|
||||
|
|
||||
|
<div class="mt-1"> |
||||
|
<div class="row align-items-center justify-content-center"> |
||||
|
<h4 class="title resizable-content" style="color: #414f69;">Check Complaint Status</h4> |
||||
|
</div> |
||||
|
</div> |
||||
|
<!-- Card Section --> |
||||
|
<div class="card p-3 resizable-content" style="margin-bottom: 8px;color: #414f69;"> |
||||
|
<div class="card mb-3 resizable-content"> |
||||
|
<div class="card-header text-white" style="background-color: #414f69;">1. Complaining Person's Details |
||||
|
</div> |
||||
|
<div class="card-body"> |
||||
|
<div class="row"> |
||||
|
<div class="col-md-6"> |
||||
|
<label>Complainant ID:</label> |
||||
|
<input type="text" id="complaintid" class="form-control" value="" disabled> |
||||
|
</div> |
||||
|
<div class="col-md-6"> |
||||
|
<label>Complainant Mobile Number:</label> |
||||
|
<input type="text" id="complaint-mobile-number" class="form-control" value="" disabled> |
||||
|
</div> |
||||
|
<div class="col-md-6"> |
||||
|
<label>Complainant Name:</label> |
||||
|
<input type="text" id="complaint-customer-name" class="form-control" value="" disabled> |
||||
|
</div> |
||||
|
|
||||
|
|
||||
|
</div> |
||||
|
</div> |
||||
|
</div> |
||||
|
|
||||
|
<div class="card mb-3 resizable-content"> |
||||
|
<div class="card-header text-white" style="background-color: #414f69;">2. Complaint Location Details |
||||
|
</div> |
||||
|
<div class="card-body"> |
||||
|
<div class="row"> |
||||
|
<div class="col-md-4"> |
||||
|
<label>Complainant Street:</label> |
||||
|
<input type="text" id="street" class="form-control" disabled> |
||||
|
</div> |
||||
|
<div class="col-md-4"> |
||||
|
<label>Complainant Zone:</label> |
||||
|
<input type="text" class="form-control" id="zone" disabled> |
||||
|
</div> |
||||
|
<div class="col-md-4"> |
||||
|
<label>Complainant Ward:</label> |
||||
|
<input type="text" class="form-control" id="ward" disabled> |
||||
|
</div> |
||||
|
<div class="col-md-4"> |
||||
|
<label>Complainant Area:</label> |
||||
|
<input type="text" class="form-control" id="area" disabled> |
||||
|
</div> |
||||
|
<div class="col-md-4"> |
||||
|
<label>Complainant Locality:</label> |
||||
|
<input type="text" class="form-control" id="location" disabled> |
||||
|
</div> |
||||
|
</div> |
||||
|
</div> |
||||
|
</div> |
||||
|
|
||||
|
<div class="card resizable-content"> |
||||
|
<div class="card-header text-white" style="background-color: #414f69;">3. Complaint Type</div> |
||||
|
<div class="card-body"> |
||||
|
<div class="row"> |
||||
|
<div class="col-md-4"> |
||||
|
<label>Complainant Type:</label> |
||||
|
<input type="text" class="form-control" id="complaintType" disabled> |
||||
|
</div> |
||||
|
|
||||
|
<!--<div class="col-md-4"> |
||||
|
Complainant Sub-Type: |
||||
|
<input type="text" class="form-control" disabled> |
||||
|
</div> |
||||
|
<div class="col-md-4"> |
||||
|
Complainant Title: |
||||
|
<input type="text" class="form-control" disabled> |
||||
|
</div>--> |
||||
|
<div class="col-md-12"> |
||||
|
<label>Complainant Description:</label> |
||||
|
<input type="text" class="form-control" id="complaintdesc" disabled> |
||||
|
</div> |
||||
|
</div> |
||||
|
</div> |
||||
|
</div> |
||||
|
</div> |
||||
|
|
||||
|
<div class="card mb-3 resizable-content"> |
||||
|
<div class="card-header text-white" style="background-color: #414f69;">Complaint Action</div> |
||||
|
<div class="card-body"> |
||||
|
<div class="row"> |
||||
|
|
||||
|
|
||||
|
<div class="col-md-4"> |
||||
|
<label>Complaint Closed Date:</label> |
||||
|
|
||||
|
<input type="text" class="form-control" id="commentDate" disabled> |
||||
|
</div> |
||||
|
<div class="col-md-4"> |
||||
|
<label>Official Name:</label> |
||||
|
<input type="text" class="form-control" id="commentuser" disabled> |
||||
|
</div> |
||||
|
|
||||
|
<div class="col-md-4"> |
||||
|
<label>Status:</label> |
||||
|
<input type="text" class="form-control" id="statusshow" |
||||
|
style="background-color: #414f69;color: white;" disabled> |
||||
|
</div> |
||||
|
</div> |
||||
|
|
||||
|
|
||||
|
</div> |
||||
|
</div> |
||||
|
|
||||
|
|
||||
|
<div class="card mb-3 resizable-content"> |
||||
|
<div class="card-header text-white" style="background-color: #414f69;">Complaint Action History</div> |
||||
|
<div class="card-body"> |
||||
|
<div id="comments-container"></div> <!-- Container for comments --> |
||||
|
</div> |
||||
|
</div> |
||||
|
|
||||
|
|
||||
|
|
||||
|
<div class="card mb-3 resizable-content"> |
||||
|
<div class="card-header text-white" style="background-color: #414f69;">Update Complaint</div> |
||||
|
<div class="card-body"> |
||||
|
<div class="row"> |
||||
|
<div class="col-md-6"> |
||||
|
<label>Change Complaint Status:</label> |
||||
|
<select class="form-control" name="complaintStatusID" id="complaintStatus"> |
||||
|
|
||||
|
</select> |
||||
|
</div> |
||||
|
|
||||
|
<div class="col-md-6" id="img" style="display: none;"> |
||||
|
<label>Photo:</label> |
||||
|
<input type="file" class="form-control" id="photo"> |
||||
|
</div> |
||||
|
</div> |
||||
|
<div class="row"> |
||||
|
<div class="col-md-12"> |
||||
|
<label>Details of Complaint:</label> |
||||
|
<textarea class="form-control" id="othercomplaint-details" rows="3" |
||||
|
placeholder="Enter complaint details" maxlength="400" required></textarea> |
||||
|
</div> |
||||
|
</div> |
||||
|
<div class="row align-items-center justify-content-center" style="margin-top: 5px;"> |
||||
|
<button class="btn btn-sm" style="background-color: #414f69;color: white;">Submit</button> |
||||
|
</div> |
||||
|
</div> |
||||
|
</div> |
||||
|
|
||||
|
|
||||
|
|
||||
|
|
||||
|
<!--loader--> |
||||
|
<div id="loaders" style="display: none; text-align: center; margin-bottom: 50px;"> |
||||
|
<img src="images/Thin broken ring.gif" alt="Loading..." /> |
||||
|
</div> |
||||
|
<!--loader--> |
||||
|
|
||||
|
</div> |
||||
|
|
||||
|
|
||||
|
|
||||
|
<!-- Bootstrap JS --> |
||||
|
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script> |
||||
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.11.0/umd/popper.min.js"></script> |
||||
|
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/js/bootstrap.min.js"></script> |
||||
|
<script src="https://cdn.jsdelivr.net/npm/sweetalert2@11"></script> |
||||
|
|
||||
|
<script> |
||||
|
|
||||
|
</script> |
||||
|
|
||||
|
|
||||
|
<!-- JavaScript to handle button clicks --> |
||||
|
<script> |
||||
|
|
||||
|
// /api/getComplaintDetailsbyId |
||||
|
$(document).ready(function () { |
||||
|
var urlParams = new URLSearchParams(window.location.search); |
||||
|
var complaintNo = urlParams.get('complaintno'); |
||||
|
|
||||
|
if (complaintNo) { |
||||
|
$('#loader').show(); |
||||
|
|
||||
|
$.ajax({ |
||||
|
url: '/pgr/api/getComplaintDetailsbyId', // Replace with your actual API endpoint |
||||
|
type: 'GET', |
||||
|
data: {complaintid: complaintNo}, |
||||
|
success: function (response) { |
||||
|
console.log('API response:', response); |
||||
|
$('#loader').hide(); |
||||
|
|
||||
|
if (Array.isArray(response) && response.length > 0) { |
||||
|
var complaintListHistory = response[0].ComplaintListHistory; |
||||
|
|
||||
|
if (Array.isArray(complaintListHistory) && complaintListHistory.length > 0) { |
||||
|
var complaintDetails = complaintListHistory[0]; |
||||
|
|
||||
|
// Decode HTML entities before populating fields |
||||
|
function decodeHtmlEntities(str) { |
||||
|
var txt = document.createElement('textarea'); |
||||
|
txt.innerHTML = str; |
||||
|
return txt.value; |
||||
|
} |
||||
|
|
||||
|
// Populate other form fields |
||||
|
document.getElementById("complaintid").value = complaintDetails.complaintid || ''; |
||||
|
document.getElementById("complaint-mobile-number").value = complaintDetails.CustomerMobile || ''; |
||||
|
document.getElementById("complaint-customer-name").value = complaintDetails.CustomerName || ''; |
||||
|
document.getElementById("street").value = complaintDetails.Street || ''; |
||||
|
document.getElementById("zone").value = complaintDetails.Zone || ''; |
||||
|
document.getElementById("ward").value = complaintDetails.Division || ''; |
||||
|
document.getElementById("area").value = complaintDetails.Area || ''; |
||||
|
document.getElementById("location").value = complaintDetails.Location || ''; |
||||
|
document.getElementById("complaintType").value = complaintDetails.complainttype || ''; |
||||
|
|
||||
|
// Decode and populate complaint description |
||||
|
document.getElementById("complaintdesc").value = decodeHtmlEntities(complaintDetails.complaintdetails || ''); |
||||
|
|
||||
|
document.getElementById("commentDate").value = complaintDetails.complaintcloseddate || ''; |
||||
|
document.getElementById("commentuser").value = complaintDetails.Officialname || ''; |
||||
|
let complaintCurrentStatus = complaintDetails.complaintcurrentstatus || ''; |
||||
|
|
||||
|
// Get the dropdown element |
||||
|
let complaintStatusDropdown = document.getElementById("complaintStatus"); |
||||
|
|
||||
|
// Function to add options to the select element |
||||
|
function addOption(text, value) { |
||||
|
let option = document.createElement("option"); |
||||
|
option.text = text; |
||||
|
option.value = value; |
||||
|
complaintStatusDropdown.add(option); |
||||
|
} |
||||
|
|
||||
|
// Check the current status and add the respective options |
||||
|
if (complaintCurrentStatus === 'REGISTERED') { |
||||
|
addOption('REGISTERED', '2'); |
||||
|
addOption('WITHDRAWN', '8'); |
||||
|
} else if (complaintCurrentStatus === 'WITHDRAWN') { |
||||
|
addOption('WITHDRAWN', '8'); |
||||
|
addOption('REOPENED', '9'); |
||||
|
} |
||||
|
else if (complaintCurrentStatus === 'CLOSE') { |
||||
|
addOption('CLOSE', '10'); |
||||
|
addOption('REOPENED', '9'); |
||||
|
} |
||||
|
else if (complaintCurrentStatus === 'REOPENED') { |
||||
|
addOption('REOPENED', '9'); |
||||
|
addOption('WITHDRAWN', '8'); |
||||
|
} |
||||
|
else if (complaintCurrentStatus === 'FINAL_CLOSURE') { |
||||
|
addOption('FINAL_CLOSURE', '11'); |
||||
|
addOption('REOPENED', '9'); |
||||
|
} |
||||
|
|
||||
|
document.getElementById("statusshow").value = complaintDetails.complaintcurrentstatus || ''; |
||||
|
|
||||
|
// Handle nested Comments array |
||||
|
if (Array.isArray(complaintDetails.Comments) && complaintDetails.Comments.length > 0) { |
||||
|
var commentsContainer = $('#comments-container'); |
||||
|
commentsContainer.empty(); // Clear the container |
||||
|
|
||||
|
var comments = complaintDetails.Comments; |
||||
|
var lastComment = comments[comments.length - 1]; |
||||
|
|
||||
|
// Decode HTML entities for last comment |
||||
|
function decodeHtmlEntities(str) { |
||||
|
var txt = document.createElement('textarea'); |
||||
|
txt.innerHTML = str; |
||||
|
return txt.value; |
||||
|
} |
||||
|
|
||||
|
// Convert image URL to Base64 |
||||
|
function convertImageToBase64(url, callback) { |
||||
|
var xhr = new XMLHttpRequest(); |
||||
|
xhr.onload = function () { |
||||
|
var reader = new FileReader(); |
||||
|
reader.onloadend = function () { |
||||
|
callback(reader.result); |
||||
|
}; |
||||
|
reader.readAsDataURL(xhr.response); |
||||
|
}; |
||||
|
xhr.open('GET', url); |
||||
|
xhr.responseType = 'blob'; |
||||
|
xhr.send(); |
||||
|
} |
||||
|
|
||||
|
// Compress the Base64 image using canvas |
||||
|
function compressImage(base64Str, callback, quality = 0.7, maxWidth = 800) { |
||||
|
var img = new Image(); |
||||
|
img.onload = function () { |
||||
|
var canvas = document.createElement('canvas'); |
||||
|
var ctx = canvas.getContext('2d'); |
||||
|
|
||||
|
var width = img.width; |
||||
|
var height = img.height; |
||||
|
|
||||
|
// Adjust the image size for compression |
||||
|
if (width > maxWidth) { |
||||
|
height *= maxWidth / width; |
||||
|
width = maxWidth; |
||||
|
} |
||||
|
|
||||
|
canvas.width = width; |
||||
|
canvas.height = height; |
||||
|
|
||||
|
// Draw the image onto the canvas |
||||
|
ctx.drawImage(img, 0, 0, width, height); |
||||
|
|
||||
|
// Convert the canvas back to Base64 with the specified quality (compression) |
||||
|
var compressedBase64 = canvas.toDataURL('image/jpeg', quality); |
||||
|
callback(compressedBase64); |
||||
|
}; |
||||
|
img.src = base64Str; |
||||
|
} |
||||
|
|
||||
|
// Handle last comment |
||||
|
var userImageHtml = ''; |
||||
|
if (Array.isArray(lastComment.userimages) && lastComment.userimages.length > 0) { |
||||
|
var imageUrl = lastComment.userimages[0].Comp_Image; |
||||
|
if (imageUrl && imageUrl !== 'null') { |
||||
|
convertImageToBase64(imageUrl, function (base64Image) { |
||||
|
compressImage(base64Image, function (compressedImage) { |
||||
|
userImageHtml = ` |
||||
|
<div class="col-md-12"> |
||||
|
<img src="${compressedImage}" alt="User Image" class="img-fluid"> |
||||
|
</div>`; |
||||
|
commentsContainer.append(lastCommentHtml); |
||||
|
}); |
||||
|
}); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
var lastCommentHtml = ` |
||||
|
<div class="row mb-3"> |
||||
|
<table class="comment-table"> |
||||
|
<tr> |
||||
|
<td style="color:#3c4959">User:</td> |
||||
|
<td>${lastComment.user || ''}</td> |
||||
|
</tr> |
||||
|
<tr> |
||||
|
<td style="color:#3c4959">Message:</td> |
||||
|
<td>${lastComment.message || ''}</td> |
||||
|
</tr> |
||||
|
<tr> |
||||
|
<td style="color:#3c4959">Comment Date:</td> |
||||
|
<td>${lastComment.comment_date || ''}</td> |
||||
|
</tr> |
||||
|
${userImageHtml} |
||||
|
</table> |
||||
|
</div> |
||||
|
<hr>`; |
||||
|
|
||||
|
// Add the comment section with the compressed Base64 image |
||||
|
commentsContainer.append(lastCommentHtml); |
||||
|
|
||||
|
// Add dropdown button for other comments |
||||
|
if (comments.length > 1) { |
||||
|
var dropdownHtml = ` |
||||
|
<button id="show-all-comments" class="btn mt-3" style="margin-bottom: 10px;background-color: #3c4959; color: white;">Show All Comments</button> |
||||
|
<div id="all-comments" style="display:none;">`; |
||||
|
|
||||
|
// Add all comments to dropdown |
||||
|
comments.forEach(function (comment, index) { |
||||
|
if (index < comments.length - 1) { // Skip the last comment |
||||
|
var userImageHtml = ''; |
||||
|
if (Array.isArray(comment.userimages) && comment.userimages.length > 0) { |
||||
|
var imageUrl = comment.userimages[0].Comp_Image; |
||||
|
if (imageUrl && imageUrl !== 'null') { |
||||
|
convertImageToBase64(imageUrl, function (base64Image) { |
||||
|
compressImage(base64Image, function (compressedImage) { |
||||
|
userImageHtml = ` |
||||
|
<div class="col-md-12"> |
||||
|
<img src="${compressedImage}" alt="User Image" class="img-fluid"> |
||||
|
</div>`; |
||||
|
}); |
||||
|
}); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
dropdownHtml += ` |
||||
|
<div class="row mb-3"> |
||||
|
<table class="comment-table"> |
||||
|
<tr> |
||||
|
<td style="color:#3c4959">User:</td> |
||||
|
<td>${comment.user || ''}</td> |
||||
|
</tr> |
||||
|
<tr> |
||||
|
<td style="color:#3c4959">Message:</td> |
||||
|
<td>${comment.message || ''}</td> |
||||
|
</tr> |
||||
|
<tr> |
||||
|
<td style="color:#3c4959">Comment Date:</td> |
||||
|
<td>${comment.comment_date || ''}</td> |
||||
|
</tr> |
||||
|
${userImageHtml} |
||||
|
</table> |
||||
|
</div> |
||||
|
<hr>`; |
||||
|
} |
||||
|
}); |
||||
|
|
||||
|
dropdownHtml += '</div>'; |
||||
|
|
||||
|
commentsContainer.append(dropdownHtml); |
||||
|
|
||||
|
// Toggle display of all comments |
||||
|
$('#show-all-comments').click(function () { |
||||
|
$('#all-comments').toggle(); |
||||
|
$(this).text($(this).text() === 'Show All Comments' ? 'Hide Comments' : 'Show All Comments'); |
||||
|
}); |
||||
|
} |
||||
|
} else { |
||||
|
$('#comments-container').html('<p>No comments found.</p>'); |
||||
|
} |
||||
|
} else { |
||||
|
alert('No complaint details found in ComplaintListHistory.'); |
||||
|
} |
||||
|
} else { |
||||
|
alert('Unexpected response structure.'); |
||||
|
} |
||||
|
}, |
||||
|
error: function (xhr, status, error) { |
||||
|
console.log('Error:', xhr.responseText); |
||||
|
alert('An error occurred while fetching complaint details.'); |
||||
|
$('#loader').hide(); |
||||
|
} |
||||
|
}); |
||||
|
} else { |
||||
|
alert('No complaint number provided.'); |
||||
|
} |
||||
|
}); |
||||
|
|
||||
|
|
||||
|
|
||||
|
|
||||
|
|
||||
|
$(document).ready(function () { |
||||
|
$('#complaintStatus').change(function () { |
||||
|
if ($(this).val() == '9') { // Show the image field if 'REOPENED' is selected |
||||
|
$('#img').show(); |
||||
|
} else { |
||||
|
$('#img').hide(); |
||||
|
} |
||||
|
}); |
||||
|
|
||||
|
$('.btn').click(function (e) { |
||||
|
e.preventDefault(); |
||||
|
|
||||
|
var complaintId = $('#complaintid').val(); |
||||
|
var complaintStatus = $('#complaintStatus').val(); |
||||
|
var message = $('#othercomplaint-details').val(); |
||||
|
|
||||
|
// Validate "Details of Complaint" field |
||||
|
if (message.trim() === "") { |
||||
|
Swal.fire({ |
||||
|
title: 'Validation Error!', |
||||
|
text: 'Please enter the details of the complaint.', |
||||
|
icon: 'warning', |
||||
|
confirmButtonText: 'OK' |
||||
|
}); |
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
if (complaintStatus == '0') { |
||||
|
Swal.fire({ |
||||
|
title: 'Validation Error!', |
||||
|
text: 'Please select a valid complaint status.', |
||||
|
icon: 'warning', |
||||
|
confirmButtonText: 'OK' |
||||
|
}); |
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
var formData = new FormData(); |
||||
|
formData.append("ComplaintId", complaintId); |
||||
|
formData.append("Message", message); |
||||
|
formData.append("Status", complaintStatus); |
||||
|
|
||||
|
var imageFile = $('#photo')[0].files[0]; |
||||
|
if (imageFile) { |
||||
|
formData.append("Comp_Image", imageFile); |
||||
|
} |
||||
|
$('#loaders').show(); |
||||
|
$.ajax({ |
||||
|
url: '/updateComplaint', |
||||
|
type: 'POST', |
||||
|
data: formData, |
||||
|
processData: false, |
||||
|
contentType: false, |
||||
|
success: function (response) { |
||||
|
$('#loaders').hide(); |
||||
|
console.log(imageFile, complaintId, message, complaintStatus); |
||||
|
Swal.fire({ |
||||
|
title: 'Success!', |
||||
|
text: 'Complaint updated successfully.', |
||||
|
icon: 'success', |
||||
|
confirmButtonText: 'OK' |
||||
|
}).then((result) => { |
||||
|
if (result.isConfirmed) { |
||||
|
window.location.href = 'home'; |
||||
|
} |
||||
|
}); |
||||
|
}, |
||||
|
error: function (xhr, status, error) { |
||||
|
console.error('Error updating complaint:', error); |
||||
|
$('#loaders').hide(); |
||||
|
let errorMessage = xhr.responseText ? xhr.responseText : 'An error occurred while updating the complaint.'; |
||||
|
Swal.fire({ |
||||
|
title: 'Error!', |
||||
|
text: errorMessage, |
||||
|
icon: 'error', |
||||
|
confirmButtonText: 'OK' |
||||
|
}); |
||||
|
} |
||||
|
}); |
||||
|
}); |
||||
|
}); |
||||
|
|
||||
|
</script> |
||||
|
</body> |
||||
|
|
||||
|
</html> |
||||
1538
src/main/resources/templates/staff/staffcomplaint.html
File diff suppressed because it is too large
View File
File diff suppressed because it is too large
View File
@ -0,0 +1,543 @@ |
|||||
|
<!DOCTYPE html> |
||||
|
<html xmlns:th="http://www.thymeleaf.org"> |
||||
|
|
||||
|
<head> |
||||
|
<meta charset="UTF-8"> |
||||
|
<title>Main Page</title> |
||||
|
<!--Google Font --> |
||||
|
<link href="https://fonts.googleapis.com/css2?family=Lato:wght@400;700&display=swap" rel="stylesheet"> |
||||
|
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.6.0/css/all.min.css" |
||||
|
integrity="sha512-Kc323vGBEqzTmouAECnVceyQqyqdsSiqLQISBL29aUW4U/M7pSPA/gEUZQqv1cwx4OnYxTxve5UMg5GT6L4JJg==" |
||||
|
crossorigin="anonymous" referrerpolicy="no-referrer" /> |
||||
|
<!--Bootstrap CSS--> |
||||
|
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css" rel="stylesheet"> |
||||
|
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.7.1/jquery.min.js"></script> |
||||
|
<script th:src="@{/js/invertcolor.js}"></script> |
||||
|
<style> |
||||
|
body { |
||||
|
font-family: 'Lato', sans-serif; |
||||
|
background-color: white; |
||||
|
} |
||||
|
|
||||
|
body.inverted { |
||||
|
background-color: black; |
||||
|
color: white; |
||||
|
filter: invert(1); |
||||
|
} |
||||
|
|
||||
|
.card { |
||||
|
border-radius: 15px; |
||||
|
border: none; |
||||
|
padding: 20px; |
||||
|
background-color: #f0f4ff; |
||||
|
text-align: center; |
||||
|
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1); |
||||
|
display: flex; |
||||
|
flex-direction: column; |
||||
|
height: 100%; |
||||
|
/* Make sure cards take up full height of the column */ |
||||
|
} |
||||
|
|
||||
|
.card-body { |
||||
|
flex: 1; |
||||
|
/* Allow card-body to grow and take up available space */ |
||||
|
} |
||||
|
|
||||
|
.card-img { |
||||
|
width: 40px; |
||||
|
margin-bottom: 15px; |
||||
|
} |
||||
|
|
||||
|
.card-title { |
||||
|
font-size: 1.2rem; |
||||
|
font-weight: bold; |
||||
|
} |
||||
|
|
||||
|
.card-text { |
||||
|
color: #666; |
||||
|
margin-bottom: 20px; |
||||
|
} |
||||
|
|
||||
|
.card-footer { |
||||
|
font-weight: bold; |
||||
|
color: #007bff; |
||||
|
display: flex; |
||||
|
align-items: center; |
||||
|
justify-content: center; |
||||
|
} |
||||
|
|
||||
|
.card-footer i { |
||||
|
margin-left: 5px; |
||||
|
} |
||||
|
|
||||
|
.row { |
||||
|
display: flex; |
||||
|
flex-wrap: wrap; |
||||
|
margin-bottom: 30px; |
||||
|
} |
||||
|
|
||||
|
.col-md-4 { |
||||
|
display: flex; |
||||
|
/* Ensure columns use Flexbox to distribute space evenly */ |
||||
|
padding: 0 15px; |
||||
|
/* Adjust padding to fit full width */ |
||||
|
} |
||||
|
|
||||
|
.container { |
||||
|
max-width: 1200px; |
||||
|
} |
||||
|
|
||||
|
.container .row .col-md-4 { |
||||
|
padding: 0 15px; |
||||
|
/* Adjust padding to fit full width */ |
||||
|
display: flex; |
||||
|
flex-direction: column; |
||||
|
} |
||||
|
|
||||
|
.card { |
||||
|
flex-grow: 1; |
||||
|
/* Ensure all cards have the same height */ |
||||
|
} |
||||
|
|
||||
|
.container .row .col-md-12 { |
||||
|
padding: 0 15px; |
||||
|
} |
||||
|
|
||||
|
.card-link { |
||||
|
text-decoration: none; |
||||
|
/* Remove the underline from the link */ |
||||
|
color: inherit; |
||||
|
/* Inherit the text color */ |
||||
|
display: block; |
||||
|
/* Make the link cover the entire card */ |
||||
|
} |
||||
|
|
||||
|
.card-link:hover .card { |
||||
|
box-shadow: 0 6px 12px rgba(0, 0, 0, 0.2); |
||||
|
/* Optional: add hover effect */ |
||||
|
} |
||||
|
|
||||
|
/* Style for reader button */ |
||||
|
|
||||
|
|
||||
|
#reader-btn.active { |
||||
|
background-color: #28a745; |
||||
|
} |
||||
|
|
||||
|
/*header css*/ |
||||
|
.header { |
||||
|
background-color: #3b4858; |
||||
|
padding: 10px 20px; |
||||
|
display: flex; |
||||
|
align-items: center; |
||||
|
justify-content: space-between; |
||||
|
color: white; |
||||
|
} |
||||
|
|
||||
|
.header .logo-left img { |
||||
|
height: 60px; |
||||
|
} |
||||
|
|
||||
|
.header .title { |
||||
|
text-align: center; |
||||
|
flex-grow: 1; |
||||
|
} |
||||
|
|
||||
|
.header .title h2 { |
||||
|
margin: 0; |
||||
|
font-size: 1.5rem; |
||||
|
} |
||||
|
|
||||
|
.header .logos-right img { |
||||
|
height: 60px; |
||||
|
margin-left: 10px; |
||||
|
} |
||||
|
|
||||
|
/*header buttons*/ |
||||
|
.header { |
||||
|
display: flex; |
||||
|
align-items: center; |
||||
|
justify-content: space-between; |
||||
|
/* Space out the items within the header */ |
||||
|
} |
||||
|
|
||||
|
.header-buttons { |
||||
|
padding-left: 5px; |
||||
|
display: flex; |
||||
|
align-items: center; |
||||
|
gap: 10px; |
||||
|
/* Adjust spacing between buttons */ |
||||
|
} |
||||
|
|
||||
|
#reader-btn, |
||||
|
#invertColorBtn { |
||||
|
padding: 5px 10px; |
||||
|
font-size: 14px; |
||||
|
cursor: pointer; |
||||
|
} |
||||
|
|
||||
|
/*for radio button style*/ |
||||
|
.radio-group { |
||||
|
display: flex; |
||||
|
align-items: center; |
||||
|
/* Ensures all items are aligned to the center */ |
||||
|
} |
||||
|
|
||||
|
.radio-item { |
||||
|
display: flex; |
||||
|
align-items: center; |
||||
|
margin-right: 20px; |
||||
|
/* Adds space between each radio item */ |
||||
|
} |
||||
|
|
||||
|
.radio-item input[type="radio"] { |
||||
|
margin-right: 10px; |
||||
|
/* Adds space between the radio button and its label */ |
||||
|
vertical-align: middle; |
||||
|
/* Ensures vertical alignment */ |
||||
|
} |
||||
|
|
||||
|
.radio-item label { |
||||
|
margin: 0; |
||||
|
/* Removes any default margins that might affect alignment */ |
||||
|
} |
||||
|
</style> |
||||
|
</head> |
||||
|
|
||||
|
|
||||
|
<body> |
||||
|
<div th:insert="~{fragments/accessibility :: accessibility}"></div> |
||||
|
|
||||
|
|
||||
|
<!-- <div class="header"> |
||||
|
|
||||
|
<div class="logo-left"> |
||||
|
<img src="images/gcc1.png" alt="Greater Chennai Corporation Logo"> |
||||
|
</div> |
||||
|
<div class="header-buttons"> |
||||
|
<button id="reader-btn" onclick="toggleReader()">Enable Reader</button> |
||||
|
<button id="invertColorBtn" onclick="invertColors()">Invert Colors</button> |
||||
|
</div> |
||||
|
<div class="title"> |
||||
|
<h2>Public Grievance and Redressal System</h2> |
||||
|
</div> |
||||
|
<div class="logos-right"> |
||||
|
<img src="images/tamil.jpg" alt="Tamil Nadu Logo"> |
||||
|
<img src="images/bt-logo.png" style="width: 100px;height: 50px;" alt="bonton Logo"> |
||||
|
</div> |
||||
|
</div>--> |
||||
|
|
||||
|
|
||||
|
|
||||
|
<!-- Insert the header fragment --> |
||||
|
<div th:insert="~{fragments/header :: headerFragment}"></div> |
||||
|
<!--<button id="reader-btn" onclick="toggleReader()">Enable Reader</button>--> |
||||
|
|
||||
|
|
||||
|
<!-- Cards Section --> |
||||
|
<div class="container mt-3"> |
||||
|
<div id="loader" style="display: none; text-align: center;"> |
||||
|
<img src="images/Thin broken ring.gif" alt="Loading..." /> |
||||
|
</div> |
||||
|
<!--<button id="invertColorBtn" onclick="invertColors()">Invert Colors</button>--> |
||||
|
<div class="row"> |
||||
|
<div class="col-md-4"> |
||||
|
<a href="staffcomplaint" class="card-link"> |
||||
|
<div class="card content"> |
||||
|
<div class="card-body"> |
||||
|
<img src="images/register.png" alt="register" class="card-img"> |
||||
|
<div class="card-content"> |
||||
|
<h5 class="card-title">Register Your<br> Complaints</h5> |
||||
|
<p class="card-text">Register Complaints<br> Via Internet</p> |
||||
|
</div> |
||||
|
</div> |
||||
|
<div class="card-footer"> |
||||
|
Get Started <i class="fa fa-arrow-right"></i> |
||||
|
</div> |
||||
|
</div> |
||||
|
</a> |
||||
|
</div> |
||||
|
|
||||
|
<div class="col-md-4"> |
||||
|
<div class="card readable"> |
||||
|
<div class="card-body"> |
||||
|
<img src="images/phone-call.png" alt="Phone" class="card-img"> |
||||
|
<div class="card-content"> |
||||
|
<h5 class="card-title">Register Complaint via Phone</h5> |
||||
|
<p class="card-text">Call 1913 to register your complaint.</p> |
||||
|
</div> |
||||
|
</div> |
||||
|
<div class="card-footer"> |
||||
|
Call Now <i class="fa fa-arrow-right"></i> |
||||
|
</div> |
||||
|
</div> |
||||
|
</div> |
||||
|
|
||||
|
<div class="col-md-4"> |
||||
|
<div class="card readable"> |
||||
|
<div class="card-body"> |
||||
|
<img src="images/contract.png" alt="Paper" class="card-img"> |
||||
|
<div class="card-content"> |
||||
|
<h5 class="card-title">Complaint via Paper Form</h5> |
||||
|
<p class="card-text">Send your Grievance to<br><strong>The Commissioner,<br>Greater Chennai |
||||
|
Corporation,<br>Ripon Building, EVR Salai, Chennai - 600003.</strong></p> |
||||
|
</div> |
||||
|
</div> |
||||
|
</div> |
||||
|
</div> |
||||
|
</div> |
||||
|
|
||||
|
|
||||
|
<!-- Form to Check by Complaint Number --> |
||||
|
<div class="col-md-12"> |
||||
|
<div class="card readable"> |
||||
|
<div class="card-body"> |
||||
|
<img src="images/search.png" alt="Status" class="card-img"> |
||||
|
<div class="card-content"> |
||||
|
<h5 class="card-title">Check Your Complaint Status</h5> |
||||
|
<div class="form-group"> |
||||
|
<input type="radio" id="c_number" name="check_method" value="c_number" checked |
||||
|
onchange="toggleInput()"> |
||||
|
<label class="readable">Check By Complaint Number</label> |
||||
|
|
||||
|
<input type="radio" id="m_number" name="check_method" value="m_number" |
||||
|
onchange="toggleInput()"> |
||||
|
<label class="readable">Check By Mobile Number</label> |
||||
|
</div> |
||||
|
|
||||
|
<!-- Input for Complaint Number --> |
||||
|
<div class="form-group" id="complaint-number-input"> |
||||
|
<input type="text" class="form-control" id="complaint-number" |
||||
|
placeholder="Enter Complaint Number"> |
||||
|
</div> |
||||
|
|
||||
|
<!-- Input for Mobile Number (hidden by default) --> |
||||
|
<div class="form-group" id="complaint-mobile-input" style="display: none;"> |
||||
|
<input type="text" class="form-control" id="complaint-mobile" |
||||
|
placeholder="Enter Mobile Number"> |
||||
|
</div> |
||||
|
</div> |
||||
|
</div> |
||||
|
|
||||
|
<div class="card-footer"> |
||||
|
<!-- Button for Complaint Number --> |
||||
|
<button class="btn btn-danger" id="check-now-btn">Check Now <i |
||||
|
class="fa fa-arrow-right"></i></button> |
||||
|
|
||||
|
<!-- Button for Mobile Number (hidden by default) --> |
||||
|
<button class="btn btn-primary readable" id="check-mobile-btn" style="display: none;">Check Now <i |
||||
|
class="fa fa-arrow-right"></i></button> |
||||
|
|
||||
|
</div> |
||||
|
</div> |
||||
|
</div> |
||||
|
|
||||
|
|
||||
|
<!-- Form to Check by Mobile Number --> |
||||
|
<!--<div class="col-md-6"> |
||||
|
<div class="card readable"> |
||||
|
<div class="card-body"> |
||||
|
<img src="images/search.png" alt="Status" class="card-img"> |
||||
|
<div class="card-content"> |
||||
|
<h5 class="card-title">Check Your Complaint Status</h5> |
||||
|
<div class="form-group"> |
||||
|
<label class="readable">Check By Mobile Number</label> |
||||
|
</div> |
||||
|
<div class="form-group"> |
||||
|
<input type="text" class="form-control" id="complaint-mobile" |
||||
|
placeholder="Enter Mobile Number"> |
||||
|
</div> |
||||
|
</div> |
||||
|
</div> |
||||
|
<div class="card-footer"> |
||||
|
<button class="btn btn-primary readable" id="check-mobile-btn">Check Now <i |
||||
|
class="fa fa-arrow-right"></i></button> |
||||
|
</div> |
||||
|
</div> |
||||
|
</div>--> |
||||
|
|
||||
|
|
||||
|
|
||||
|
|
||||
|
|
||||
|
|
||||
|
|
||||
|
</div> |
||||
|
|
||||
|
|
||||
|
|
||||
|
<div class="modal fade" id="complaintDetailsModal" tabindex="-1" role="dialog" |
||||
|
aria-labelledby="complaintDetailsLabel" aria-hidden="true"> |
||||
|
<div class="modal-dialog modal-lg" role="document"> |
||||
|
<div class="modal-content"> |
||||
|
<div class="modal-header" style="background-color: #3c4959;color: white;"> |
||||
|
<h5 class="modal-title" id="complaintDetailsLabel">Complaint Details</h5> |
||||
|
<button type="button" class="close" data-dismiss="modal" aria-label="Close" style="color: white;"> |
||||
|
<span aria-hidden="true">×</span> |
||||
|
</button> |
||||
|
</div> |
||||
|
<div class="modal-body"> |
||||
|
<table class="table"> |
||||
|
<thead style="background-color: #3c4959;color: white;"> |
||||
|
<tr> |
||||
|
<th>Complaint Number</th> |
||||
|
<th>Complaint Type</th> |
||||
|
<th>View</th> <!-- New column for the eye icon --> |
||||
|
</tr> |
||||
|
</thead> |
||||
|
<tbody> |
||||
|
<!-- Dynamic rows will be appended here by JavaScript --> |
||||
|
</tbody> |
||||
|
</table> |
||||
|
</div> |
||||
|
<div class="modal-footer"> |
||||
|
<button type="button" class="btn btn-secondary" data-dismiss="modal" |
||||
|
style="background-color:#3c4959 ;">Close</button> |
||||
|
</div> |
||||
|
</div> |
||||
|
</div> |
||||
|
</div> |
||||
|
|
||||
|
|
||||
|
|
||||
|
|
||||
|
|
||||
|
|
||||
|
|
||||
|
|
||||
|
<div th:insert="~{fragments/footer :: footerFragment}"></div> |
||||
|
|
||||
|
<!-- Replace Slim jQuery with Full jQuery --> |
||||
|
<script src="https://code.jquery.com/jquery-3.2.1.min.js"></script> |
||||
|
|
||||
|
<!-- Popper.js (for Bootstrap tooltips, popovers, etc.) --> |
||||
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.11.0/umd/popper.min.js"></script> |
||||
|
|
||||
|
<!-- Bootstrap JS --> |
||||
|
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/js/bootstrap.min.js"></script> |
||||
|
|
||||
|
<!-- Font Awesome for Icons --> |
||||
|
<script src="https://kit.fontawesome.com/a076d05399.js"></script> |
||||
|
|
||||
|
<script> |
||||
|
|
||||
|
|
||||
|
$(document).ready(function () { |
||||
|
// Check by complaint number |
||||
|
$('#check-now-btn').click(function () { |
||||
|
var complaintNumber = $('#complaint-number').val(); |
||||
|
if (complaintNumber) { |
||||
|
window.location.href = 'checklistofficer?complaintno=' + encodeURIComponent(complaintNumber); |
||||
|
} else { |
||||
|
alert('Please enter a complaint number.'); |
||||
|
} |
||||
|
}); |
||||
|
|
||||
|
|
||||
|
|
||||
|
}); |
||||
|
|
||||
|
|
||||
|
|
||||
|
|
||||
|
function toggleInput() { |
||||
|
const checkByComplaint = document.getElementById('c_number').checked; |
||||
|
const complaintInput = document.getElementById('complaint-number-input'); |
||||
|
const mobileInput = document.getElementById('complaint-mobile-input'); |
||||
|
const checkNowBtn = document.getElementById('check-now-btn'); |
||||
|
const checkMobileBtn = document.getElementById('check-mobile-btn'); |
||||
|
|
||||
|
if (checkByComplaint) { |
||||
|
complaintInput.style.display = 'block'; |
||||
|
checkNowBtn.style.display = 'block'; |
||||
|
mobileInput.style.display = 'none'; |
||||
|
checkMobileBtn.style.display = 'none'; |
||||
|
} else { |
||||
|
complaintInput.style.display = 'none'; |
||||
|
checkNowBtn.style.display = 'none'; |
||||
|
mobileInput.style.display = 'block'; |
||||
|
checkMobileBtn.style.display = 'block'; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
$(document).ready(function () { |
||||
|
// Trigger modal and load complaint list based on mobile number |
||||
|
$('#check-mobile-btn').on('click', function () { |
||||
|
const mobileNumber = $('#complaint-mobile').val(); // Get the entered mobile number |
||||
|
|
||||
|
if (mobileNumber === "") { |
||||
|
alert("Please enter a mobile number."); |
||||
|
return; |
||||
|
} |
||||
|
$('#loader').show(); |
||||
|
// AJAX request to fetch complaint details by mobile number |
||||
|
$.ajax({ |
||||
|
url: '/pgr/api/getComplaintDetailsByMobile', // Replace with your correct API path |
||||
|
method: 'GET', |
||||
|
data: {mobileNo: mobileNumber}, |
||||
|
success: function (response) { |
||||
|
$('#loader').hide(); |
||||
|
const complaintList = response[0]?.ComplaintListHistory; // Assuming data is inside ComplaintListHistory |
||||
|
|
||||
|
// Clear the table before adding new rows |
||||
|
const tableBody = $('#complaintDetailsModal tbody'); |
||||
|
tableBody.empty(); |
||||
|
|
||||
|
// Check if there are complaints |
||||
|
if (complaintList && complaintList.length > 0) { |
||||
|
// Loop through each complaint and add to the table |
||||
|
complaintList.forEach(function (complaint) { |
||||
|
const complaintId = complaint.complaintid || 'N/A'; // Fallback to N/A if complaintid is null |
||||
|
const complaintType = complaint.complainttype || 'N/A'; |
||||
|
|
||||
|
const newRow = ` |
||||
|
<tr> |
||||
|
<td>${complaintId}</td> |
||||
|
<td>${complaintType}</td> |
||||
|
|
||||
|
<td> |
||||
|
<button class="btn btn-link view-complaint" data-complaintid="${complaintId}"> |
||||
|
<i style="color:#3c4959" class="fa fa-eye"></i> |
||||
|
</button> |
||||
|
</td> |
||||
|
</tr>`; |
||||
|
tableBody.append(newRow); // Append the new row to the table |
||||
|
}); |
||||
|
} else { |
||||
|
// No complaints found for the mobile number |
||||
|
tableBody.append('<tr><td colspan="2">No complaints found for this mobile number.</td></tr>'); |
||||
|
} |
||||
|
|
||||
|
// Display the modal after fetching the data |
||||
|
$('#complaintDetailsModal').modal('show'); |
||||
|
}, |
||||
|
error: function (error) { |
||||
|
console.log('Error fetching complaints:', error); |
||||
|
alert('There was an error fetching the complaint details. Please try again.'); |
||||
|
$('#loader').hide(); |
||||
|
} |
||||
|
}); |
||||
|
}); |
||||
|
|
||||
|
|
||||
|
|
||||
|
|
||||
|
// Event delegation to handle click on dynamically generated eye icons |
||||
|
$(document).on('click', '.view-complaint', function () { |
||||
|
var complaintId = $(this).data('complaintid'); |
||||
|
if (complaintId) { |
||||
|
// Redirect to the complaint details page using complaintId |
||||
|
window.location.href = 'checklistofficer?complaintno=' + encodeURIComponent(complaintId); |
||||
|
} else { |
||||
|
alert('Complaint ID not found.'); |
||||
|
} |
||||
|
}); |
||||
|
|
||||
|
|
||||
|
}); |
||||
|
|
||||
|
</script> |
||||
|
<script th:src="@{/js/screenreader.js}"></script> |
||||
|
</body> |
||||
|
|
||||
|
</html> |
||||
@ -1,13 +0,0 @@ |
|||||
package com.gcc.publicgrievance; |
|
||||
|
|
||||
import org.junit.jupiter.api.Test; |
|
||||
import org.springframework.boot.test.context.SpringBootTest; |
|
||||
|
|
||||
@SpringBootTest |
|
||||
class PublicgrievanceApplicationTests { |
|
||||
|
|
||||
@Test |
|
||||
void contextLoads() { |
|
||||
} |
|
||||
|
|
||||
} |
|
||||
Write
Preview
Loading…
Cancel
Save
Reference in new issue