Browse Source

new commit

master
SriPaari 1 year ago
parent
commit
0d10e7659e
  1. 19
      .mvn/wrapper/maven-wrapper.properties
  2. 10
      pom.xml
  3. 43
      src/main/java/com/gcc/publicgrievance/Service/ComplaintService.java
  4. 47
      src/main/java/com/gcc/publicgrievance/config/AppConfigur.java
  5. 14
      src/main/java/com/gcc/publicgrievance/configuration/AppConfig.java
  6. 73
      src/main/java/com/gcc/publicgrievance/configuration/DataSourceConfig.java
  7. 24
      src/main/java/com/gcc/publicgrievance/configuration/SecurityConfig.java
  8. 33
      src/main/java/com/gcc/publicgrievance/configuration/UserSessionInterceptor.java
  9. 123
      src/main/java/com/gcc/publicgrievance/controller/APIController.java
  10. 747
      src/main/java/com/gcc/publicgrievance/controller/ComplaintController.java
  11. 18
      src/main/java/com/gcc/publicgrievance/controller/UserController.java
  12. 20
      src/main/resources/application-dev.properties
  13. 24
      src/main/resources/application-prod.properties
  14. 9
      src/main/resources/application.properties
  15. BIN
      src/main/resources/static/images/message.png
  16. BIN
      src/main/resources/static/images/otp.png
  17. BIN
      src/main/resources/static/images/output-onlinepngtools.png
  18. 59
      src/main/resources/static/js/screenreader.js
  19. 78
      src/main/resources/templates/User/home.html
  20. 0
      src/main/resources/templates/User/kin.html
  21. 1852
      src/main/resources/templates/User/registercomplaints.html
  22. 160
      src/main/resources/templates/checklistofficer/checklistofficer.html
  23. 4
      src/main/resources/templates/fragments/accessibility.html
  24. 5
      src/main/resources/templates/fragments/footer.html
  25. 67
      src/main/resources/templates/fragments/header.html
  26. 258
      src/main/resources/templates/officer/checkofficerhome.html
  27. 528
      src/main/resources/templates/officer/checkofficerstatus.html
  28. 614
      src/main/resources/templates/staff/staffcheckstatus.html
  29. 1538
      src/main/resources/templates/staff/staffcomplaint.html
  30. 543
      src/main/resources/templates/staff/staffhome.html
  31. 13
      src/test/java/com/gcc/publicgrievance/PublicgrievanceApplicationTests.java

19
.mvn/wrapper/maven-wrapper.properties

@ -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

10
pom.xml

@ -53,6 +53,16 @@
</dependency>
<dependency>
<groupId>com.example</groupId>
<artifactId>erp</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>in.gov.chennaicorporation</groupId>
<artifactId>gccoffice</artifactId>
<version>0.0.1</version>
</dependency>
</dependencies>
<build>

43
src/main/java/com/gcc/publicgrievance/Service/ComplaintService.java

@ -10,12 +10,20 @@ import java.util.Random;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;
@Service
public class ComplaintService {
private final JdbcTemplate jdbcTemplate;
public ComplaintService(JdbcTemplate jdbcTemplate) {
this.jdbcTemplate = jdbcTemplate;
}
private final String baseUrl = "https://erp.chennaicorporation.gov.in/pgr/external/mobileservice";
public String fetchComplaintCategories() {
@ -45,11 +53,14 @@ public class ComplaintService {
}
}
public List<Map<String, Object>> fetchComplaintDetailsByMobile(String mobileNo) {
public List<Map<String, Object>> fetchComplaintDetailsByMobile(String mobileNo, String fromDate, String toDate, String year) {
RestTemplate restTemplate = new RestTemplate();
String url = baseUrl
+ "?serviceId=getComplaintListWithImg&From_date=01/01/2024&To_date=20/08/2024&jsonResp=Yes&UserType=Public&MobileNo="
+ mobileNo + "&PageIndex=null&Status=null&repYear=2024";
+ "?serviceId=getComplaintListWithImg&From_date=" + fromDate
+ "&To_date=" + toDate
+ "&jsonResp=Yes&UserType=Public&MobileNo=" + mobileNo
+ "&PageIndex=null&Status=null&repYear=" + year;
String response = restTemplate.getForObject(url, String.class);
try {
@ -63,5 +74,31 @@ public class ComplaintService {
}
private final ObjectMapper objectMapper = new ObjectMapper();
public String getComplaintCategories() {
String sql = "SELECT category_id, category_name, label_name " +
"FROM category WHERE is_active = 1 and is_delete = 0";
try {
List<Map<String, Object>> result = jdbcTemplate.queryForList(sql);
return objectMapper.writeValueAsString(result);
} catch (Exception e) {
e.printStackTrace();
return "[]";
}
}
public String getComplaintSubTypes(String categoryId) {
String sql = "SELECT subcategory_id, subcategory_name, category_id " +
"FROM subcategory WHERE is_active = 1 and is_delete = 0 " +
"AND category_id = ?";
try {
List<Map<String, Object>> result = jdbcTemplate.queryForList(sql, categoryId);
return objectMapper.writeValueAsString(result);
} catch (Exception e) {
e.printStackTrace();
return "[]";
}
}
}

47
src/main/java/com/gcc/publicgrievance/config/AppConfigur.java

@ -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;
}
}

14
src/main/java/com/gcc/publicgrievance/configuration/AppConfig.java

@ -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;
package com.gcc.publicgrievance.configuration;
@Configuration
public class AppConfig {
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();
}
}
}

73
src/main/java/com/gcc/publicgrievance/configuration/DataSourceConfig.java

@ -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);
}
}
}

24
src/main/java/com/gcc/publicgrievance/configuration/SecurityConfig.java

@ -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();
}
}

33
src/main/java/com/gcc/publicgrievance/configuration/UserSessionInterceptor.java

@ -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
}
}

123
src/main/java/com/gcc/publicgrievance/controller/APIController.java

@ -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
}
}
}

747
src/main/java/com/gcc/publicgrievance/controller/ComplaintController.java

@ -1,8 +1,13 @@
package com.gcc.publicgrievance.controller;
import java.util.List;
import java.util.Map;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.*;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.CrossOrigin;
@ -13,6 +18,8 @@ import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.util.UriComponentsBuilder;
import org.springframework.web.util.UriUtils;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.util.LinkedMultiValueMap;
@ -26,21 +33,30 @@ import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import org.springframework.http.*;
import java.util.Base64;
import java.util.HashMap;
import com.gcc.publicgrievance.Service.ComplaintService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.multipart.MultipartFile;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.management.modelmbean.RequiredModelMBean;
import java.util.Base64;
import java.util.stream.Collectors;
@CrossOrigin
//@CrossOrigin
@RestController
@RequestMapping("/pgr/api")
public class ComplaintController {
private final RestTemplate restTemplate;
@ -52,28 +68,55 @@ public class ComplaintController {
@Autowired
private ComplaintService complaintService;
@GetMapping("/api/getComplaintCategories")
@GetMapping("/getComplaintCategories")
public @ResponseBody String getComplaintCategories() {
return complaintService.fetchComplaintCategories();
}
@GetMapping("/api/getComplaintSubTypes")
@GetMapping("/getComplaintSubTypes")
public @ResponseBody String getComplaintSubTypes(@RequestParam String groupId) {
return complaintService.fetchComplaintSubTypes(groupId);
}
@GetMapping("/api/getComplaintDetailsbyId")
@GetMapping("/ComplaintCategories")
public @ResponseBody String ComplaintCategories() {
return complaintService.getComplaintCategories();
}
@GetMapping("/ComplaintSubTypes")
public @ResponseBody String ComplaintSubTypes(@RequestParam String categoryId) {
return complaintService.getComplaintSubTypes(categoryId);
}
@GetMapping("/getComplaintDetailsbyId")
public List<Map<String, Object>> getComplaintDetailsById(@RequestParam String complaintid) {
return complaintService.fetchComplaintDetailsById(complaintid);
}
@GetMapping("/api/getComplaintDetailsByMobile")
public List<Map<String, Object>> getComplaintDetailsByMobile(@RequestParam String mobileNo) {
return complaintService.fetchComplaintDetailsByMobile(mobileNo);
@GetMapping("/getComplaintDetailsByMobile")
public List<Map<String, Object>> getComplaintDetailsByMobile(@RequestParam String mobileNo,
@RequestParam String fromDate,
@RequestParam String toDate,
@RequestParam String year) {
List<Map<String, Object>> result = complaintService.fetchComplaintDetailsByMobile(mobileNo, fromDate, toDate, year);
// If the result is empty, return a response with "No data found" message
if (result == null || result.isEmpty()) {
// Create a response map to indicate no data found
Map<String, Object> noDataResponse = new HashMap<>();
noDataResponse.put("message", "No data found");
noDataResponse.put("status", "404");
// Return the no data response in a list
return Collections.singletonList(noDataResponse);
}
@PostMapping("/register")
public ResponseEntity<String> registerComplaint(
return result;
}
@PostMapping("/register")
public ResponseEntity<?> registerComplaint(
@RequestParam(value = "ComplainantName", required = false) String complainantName,
@RequestParam(value = "ComplainantAddr", required = false) String complainantAddr,
@RequestParam(value = "MobileNo", required = false) String mobileNo,
@ -82,7 +125,7 @@ public class ComplaintController {
@RequestParam(value = "ComplaintTitle", required = false) String complaintTitle,
@RequestParam(value = "ComplaintDetails", required = false) String complaintDetails,
@RequestParam(value = "StreetId", required = false) String streetId,
@RequestParam(value = "Comp_Image", required = false) String compImage,
@RequestParam(value = "Comp_Image", required = false) MultipartFile compImage,
@RequestParam(value = "latitude", required = false) String latitude,
@RequestParam(value = "longtitude", required = false) String longtitude,
@RequestParam(value = "Landmark", required = false) String landmark,
@ -91,38 +134,41 @@ public class ComplaintController {
String externalUrl = "https://erp.chennaicorporation.gov.in/pgr/external/mobileservice";
try {
// Create the URL object
URL url = new URL(externalUrl);
// Create the HttpURLConnection object
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setRequestMethod("POST");
conn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
conn.setDoOutput(true);
// Create the parameters string, handling null values
String params = "serviceId=RegComplaint" + "&ComplainantName="
+ URLEncoder.encode(complainantName != null ? complainantName : "", "UTF-8") + "&ComplainantAddr="
+ URLEncoder.encode(complainantAddr != null ? complainantAddr : "", "UTF-8") + "&MobileNo="
+ URLEncoder.encode(mobileNo != null ? mobileNo : "", "UTF-8") + "&Email="
+ URLEncoder.encode(email != null ? email : "", "UTF-8") + "&ComplaintType="
+ URLEncoder.encode(complaintType != null ? complaintType : "", "UTF-8") + "&ComplaintTitle="
+ URLEncoder.encode(complaintTitle != null ? complaintTitle : "", "UTF-8") + "&ComplaintDetails="
+ URLEncoder.encode(complaintDetails != null ? complaintDetails : "", "UTF-8") + "&StreetId="
+ URLEncoder.encode(streetId != null ? streetId : "", "UTF-8") + "&Comp_Image="
+ URLEncoder.encode(compImage != null ? compImage : "", "UTF-8") + "&latitude="
+ URLEncoder.encode(latitude != null ? latitude : "", "UTF-8") + "&longtitude="
+ URLEncoder.encode(longtitude != null ? longtitude : "", "UTF-8") + "&Landmark="
+ URLEncoder.encode(landmark != null ? landmark : "", "UTF-8") + "&gender="
+ URLEncoder.encode(gender != null ? gender : "", "UTF-8");
// Write parameters to request body
// 1) Convert MultipartFile to Base64 string
String compImageBase64 = "";
if (compImage != null && !compImage.isEmpty()) {
byte[] bytes = compImage.getBytes();
compImageBase64 = Base64.getEncoder().encodeToString(bytes);
}
System.out.println("compImage.."+compImage);
String params = "serviceId=RegComplaint" +
"&ComplainantName=" + URLEncoder.encode(complainantName != null ? complainantName : "", "UTF-8") +
"&ComplainantAddr=" + URLEncoder.encode(complainantAddr != null ? complainantAddr : "", "UTF-8") +
"&MobileNo=" + URLEncoder.encode(mobileNo != null ? mobileNo : "", "UTF-8") +
"&Email=" + URLEncoder.encode(email != null ? email : "", "UTF-8") +
"&ComplaintType=" + URLEncoder.encode(complaintType != null ? complaintType : "", "UTF-8") +
"&ComplaintTitle=" + URLEncoder.encode(complaintTitle != null ? complaintTitle : "", "UTF-8") +
"&ComplaintDetails=" + URLEncoder.encode(complaintDetails != null ? complaintDetails : "", "UTF-8") +
"&StreetId=" + URLEncoder.encode(streetId != null ? streetId : "", "UTF-8") +
"&Comp_Image=" + URLEncoder.encode(compImageBase64 , "UTF-8")+
"&latitude=" + URLEncoder.encode(latitude != null ? latitude : "", "UTF-8") +
"&longtitude=" + URLEncoder.encode(longtitude != null ? longtitude : "", "UTF-8") +
"&Landmark=" + URLEncoder.encode(landmark != null ? landmark : "", "UTF-8") +
"&gender=" + URLEncoder.encode(gender != null ? gender : "", "UTF-8") +
"&compmode=2";
try (OutputStream os = conn.getOutputStream()) {
byte[] input = params.getBytes("UTF-8");
os.write(input, 0, input.length);
}
// Read the response
int responseCode = conn.getResponseCode();
BufferedReader reader;
if (responseCode == HttpURLConnection.HTTP_OK) {
@ -138,150 +184,51 @@ public class ComplaintController {
}
reader.close();
// Return the response from the external API
return ResponseEntity.status(responseCode).body(response.toString());
// ✅ Parse and return only the complaint number
ObjectMapper mapper = new ObjectMapper();
Map<String, String> responseMap = mapper.readValue(response.toString(), Map.class);
String complaintNo = responseMap.getOrDefault("Complaint Number", "N/A");
System.out.println("complaintNo===="+complaintNo);
return ResponseEntity.ok()
.contentType(MediaType.APPLICATION_JSON)
.body(Map.of("complaintNumber", complaintNo));
} catch (IOException e) {
e.printStackTrace();
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
.body("An error occurred while processing the request.");
.body(Map.of("error", "An error occurred while processing the request."));
}
}
// @PostMapping("/updateComplaint")
// public ResponseEntity<String> updateComplaint(@RequestParam("ComplaintId") String complaintId,
// @RequestParam(value = "Message", required = false) String message,
// @RequestParam(value = "UserType", required = false) String userType,
// @RequestParam(value = "Status", required = false) String status,
// @RequestParam(value = "Comp_Image", required = false) String compImage) {
//
// // Print for debugging
// System.out.println("ComplaintId: " + complaintId);
// System.out.println("Message: " + message);
// System.out.println("Status: " + status);
//
// // External API URL
// String externalUrl = "https://erp.chennaicorporation.gov.in/pgr/external/mobileservice";
//
// // Create the request body as MultiValueMap for form-encoded data
// MultiValueMap<String, String> requestBody = new LinkedMultiValueMap<>();
// requestBody.add("serviceId", "UpdateComplaint");
// requestBody.add("ComplaintId", complaintId != null ? complaintId : "");
// requestBody.add("Message", message != null ? message : "");
// requestBody.add("UserType", userType != null ? userType : "");
// requestBody.add("Status", status != null ? status : "");
// requestBody.add("Comp_Image", compImage != null ? compImage : "");
// requestBody.add("Token", "718333469976265947044293");
//// MultiValueMap<String, String> requestBody = new LinkedMultiValueMap<>();
//// requestBody.add("serviceId", "UpdateComplaint");
//// requestBody.add("ComplaintId", "2024-516FGB");
//// requestBody.add("Message","test");
//// requestBody.add("UserType", "Public");
//// requestBody.add("Status","8");
//// requestBody.add("Comp_Image","null");
//// requestBody.add("Token", "718333469976265947044293");
// System.out.println(requestBody);
//
// // Set headers to indicate form data
// HttpHeaders headers = new HttpHeaders();
// headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
//
// // Build the request entity with headers and body
// HttpEntity<MultiValueMap<String, String>> entity = new HttpEntity<>(requestBody, headers);
//
// try {
// // Make the POST request using RestTemplate
// ResponseEntity<String> response = restTemplate.exchange(externalUrl, // External API endpoint
// HttpMethod.GET, // HTTP Method
// entity, // The request entity containing body and headers
// String.class // Expected response type
// );
// System.out.println(response.getBody());
//
// // Return the response from the external API
// return new ResponseEntity<>(response.getBody(), response.getStatusCode());
//
// } catch (Exception e) {
// e.printStackTrace();
// return ResponseEntity.status(500).body("An error occurred while processing the request.");
// }
// }
}
/*
* @PostMapping("/updateComplaint") public ResponseEntity<String>
* updateComplaint(@RequestParam("ComplaintId") String complaintId,
*
* @RequestParam(value = "Message", required = false) String message,
*
* @RequestParam(value = "Status") String status,
*
* @RequestParam(value = "Comp_Image", required = false) String compImage) {
* String userType = "Public";
* System.out.println("message:-"+message+"\n UserType:-"+userType+"\n Status:-"
* +status); String externalUrl =
* "https://erp.chennaicorporation.gov.in/pgr/external/mobileservice";
*
* try { // Create the URL object URL url = new URL(externalUrl);
*
* // Create the HttpURLConnection object HttpURLConnection conn =
* (HttpURLConnection) url.openConnection(); conn.setRequestMethod("POST");
* conn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
* conn.setDoOutput(true);
*
* // Create the parameters string, handling null values String params =
* "serviceId=UpdateComplaint" + "&ComplaintId=" + URLEncoder.encode(complaintId
* != null ? complaintId : "", "UTF-8") + "&Message=" +
* URLEncoder.encode(message != null ? message : "", "UTF-8") + "&UserType=" +
* URLEncoder.encode(userType , "UTF-8") + "&Status=" + URLEncoder.encode(status
* != null ? status : "", "UTF-8") + "&Comp_Image=" +
* URLEncoder.encode(compImage != null ? compImage : "", "UTF-8") +
* "&Token=718333469976265947044293"; System.out.println(params); // Write
* parameters to request body try (OutputStream os = conn.getOutputStream()) {
* byte[] input = params.getBytes("UTF-8"); os.write(input, 0, input.length); }
*
* // Read the response int responseCode = conn.getResponseCode();
* BufferedReader reader; if (responseCode == HttpURLConnection.HTTP_OK) {
* reader = new BufferedReader(new InputStreamReader(conn.getInputStream())); }
* else { reader = new BufferedReader(new
* InputStreamReader(conn.getErrorStream())); }
*
* StringBuilder response = new StringBuilder(); String line; while ((line =
* reader.readLine()) != null) { response.append(line); } reader.close();
* System.out.println(response.toString()); // Return the response from the
* external API return
* ResponseEntity.status(responseCode).body(response.toString());
*
* } catch (IOException e) { e.printStackTrace(); return
* ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
* .body("An error occurred while processing the request."); } }
*/
@PostMapping("/updateComplaint")
public ResponseEntity<String> updateComplaint(
@RequestParam("ComplaintId") String complaintId,
public ResponseEntity<String> updateComplaint(@RequestParam("ComplaintId") String complaintId,
@RequestParam(value = "Message", required = false) String message,
@RequestParam(value = "Status") String status,
@RequestPart(value = "Comp_Image", required = false) MultipartFile compImage) {
String userType = "Public";
System.out.println("message:-" + message + "\n UserType:-" + userType + "\n Status:-" + status);
String externalUrl = "https://erp.chennaicorporation.gov.in/pgr/external/mobileservice";
System.out.println("message:-" + message + "\n UserType:-" + userType + "\n Status:-" + status);
System.out.println(compImage == null);
String externalUrl = "https://erp.chennaicorporation.gov.in/pgr/newmobileservice";
try {
// Convert and compress the image to base64 if provided
String base64Image = null;
if (compImage != null && !compImage.isEmpty()) {
base64Image = compressAndEncodeToBase64(compImage);
System.out.println("imageee" + base64Image);
}
// Construct the POST body with parameters
String params = "serviceId=UpdateComplaint" +
"&ComplaintId=" + URLEncoder.encode(complaintId != null ? complaintId : "", "UTF-8") +
"&Message=" + URLEncoder.encode(message != null ? message : "", "UTF-8") +
"&UserType=" + URLEncoder.encode(userType, "UTF-8") +
"&Status=" + URLEncoder.encode(status != null ? status : "", "UTF-8") +
"&Token=718333469976265947044293";
String params = "serviceId=UpdateComplaint" + "&ComplaintId="
+ URLEncoder.encode(complaintId != null ? complaintId : "", "UTF-8") + "&Message="
+ URLEncoder.encode(message != null ? message : "", "UTF-8") + "&UserType="
+ URLEncoder.encode(userType, "UTF-8") + "&Status="
+ URLEncoder.encode(status != null ? status : "", "UTF-8") + "&Comp_Image="
+ URLEncoder.encode(compImage != null ? base64Image : "", "UTF-8")
+ "&Token=718333469976265947044293";
// Open connection and send POST request
URL url = new URL(externalUrl);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
@ -320,7 +267,6 @@ public class ComplaintController {
}
}
private String compressAndEncodeToBase64(MultipartFile file) throws IOException {
// Convert MultipartFile to BufferedImage
BufferedImage originalImage = ImageIO.read(file.getInputStream());
@ -343,5 +289,486 @@ public class ComplaintController {
// Convert the compressed image to base64
return Base64.getEncoder().encodeToString(compressedBytes);
}
@GetMapping("/getdetails")
public ResponseEntity<?> getComplaintMatch(
@RequestParam("mobileNo") String mobileNo,
@RequestParam("complaintId") String complaintId,
@RequestParam("streetName") String streetName
) {
try {
// 1. Map complaintId to complaint title
Map<String, String> complaintIdToTitle = new HashMap<>();
complaintIdToTitle.put("97", "Removal of Garbage");
complaintIdToTitle.put("98", "Overflowing of Garbage Bin");
complaintIdToTitle.put("99", "Removal of Debris");
complaintIdToTitle.put("100", "Absenteeism of Sweepers");
complaintIdToTitle.put("101", "Absenteeism of Door to door garbage Collector");
complaintIdToTitle.put("102", "Improper Sweeping");
complaintIdToTitle.put("103", "Provison of Garbage Bin");
complaintIdToTitle.put("104", "Broken Bin");
complaintIdToTitle.put("105", "Shifting of Garbage Bin");
complaintIdToTitle.put("106", "Cleaning of Water Table");
complaintIdToTitle.put("107", "Nuisance by Garbage Tractor/Truck");
complaintIdToTitle.put("108", "Burning of Garbage");
complaintIdToTitle.put("109", "Garbage Lorry without Net");
complaintIdToTitle.put("110", "Spilling of Garbage from Lorry");
complaintIdToTitle.put("111", "Burning of Garbage at Dumping Ground");
complaintIdToTitle.put("112", "Pot hole fill up / Repairs to the damaged surface");
complaintIdToTitle.put("113", "Relaying of Road");
complaintIdToTitle.put("114", "Formation of New Road");
complaintIdToTitle.put("115", "Repairs to existing Footpath");
complaintIdToTitle.put("116", "Request to provide Footpath");
complaintIdToTitle.put("117", "Removal of Shops in the Footpath");
complaintIdToTitle.put("118", "Mosquito Menace");
complaintIdToTitle.put("119", "Street Dogs");
complaintIdToTitle.put("120", "Stray Cattle");
complaintIdToTitle.put("121", "Stray Pigs");
complaintIdToTitle.put("122", "Death of Stray Animals");
complaintIdToTitle.put("123", "Public Health / Dengue / Malaria / Gastro Enteritis");
complaintIdToTitle.put("124", "Transfer Station Smell");
complaintIdToTitle.put("125", "Flies Menace from Dumping Ground");
complaintIdToTitle.put("126", "Open Defecation");
complaintIdToTitle.put("127", "Illegal Draining of Sewage to SWD / Open Site");
complaintIdToTitle.put("128", "Complaints regarding unhygenic Restaurants");
complaintIdToTitle.put("129", "Complaints regarding quality of food in hotels");
complaintIdToTitle.put("130", "Road Side Eateries");
complaintIdToTitle.put("131", "Slaughter House related complaints");
complaintIdToTitle.put("132", "Unauthorized Sale of Meat and Meat products");
complaintIdToTitle.put("133", "Illegal Slaughtering");
complaintIdToTitle.put("134", "Unhygenic and Improper Transport of Meat and Livestock");
complaintIdToTitle.put("135", "Biomedical waste / Health hazard waste removal");
complaintIdToTitle.put("136", "Complaints regarding Corporation Hospitals");
complaintIdToTitle.put("137", "Complaints regarding CDH");
complaintIdToTitle.put("138", "Stagnation of Water");
complaintIdToTitle.put("139", "Obstruction of Water Flow");
complaintIdToTitle.put("140", "Desilting of Drain");
complaintIdToTitle.put("141", "Desilting of Canal");
complaintIdToTitle.put("142", "Repairs to Storm Water Drain");
complaintIdToTitle.put("143", "Covering Manholes of Storm Water Drain");
complaintIdToTitle.put("144", "New Drain Construction");
complaintIdToTitle.put("145", "Disposal of Removed Silt on the Road");
complaintIdToTitle.put("146", "Non burning of Street lights");
complaintIdToTitle.put("147", "Electric shock due to street light");
complaintIdToTitle.put("148", "Damage to the Electric pole");
complaintIdToTitle.put("149", "New Street lights");
complaintIdToTitle.put("150", "Shifting of Street light pole");
complaintIdToTitle.put("151", "Overhead cable wires running in a haphazard manner");
complaintIdToTitle.put("152", "Removal of Fallen Trees");
complaintIdToTitle.put("153", "Complaints regarding Park");
complaintIdToTitle.put("154", "Complaints regarding Playground");
complaintIdToTitle.put("155", "Complaints regarding Centre Median");
complaintIdToTitle.put("156", "Complaints regarding Traffic Island");
complaintIdToTitle.put("157", "Unauthorized Tree Cutting");
complaintIdToTitle.put("158", "Obstruction of Trees");
complaintIdToTitle.put("159", "Complaints regarding Public Toilets");
complaintIdToTitle.put("160", "Complaints regarding Free Usage of Public Toilets");
complaintIdToTitle.put("161", "Complaints regarding Cleanliness of Toilets in Theatre");
complaintIdToTitle.put("162", "Complaints regarding Cleanliness of Toilets in Shopping Complex");
complaintIdToTitle.put("163", "Building Plan Sanction");
complaintIdToTitle.put("164", "Violation of DCR/Building By laws");
complaintIdToTitle.put("165", "Unauthorized / Illegal Construction");
complaintIdToTitle.put("166", "Complaints related to Property Tax");
complaintIdToTitle.put("167", "Complaints related to Professional Tax");
complaintIdToTitle.put("168", "Complaints related to Trade Licence");
complaintIdToTitle.put("174", "Name Error (Spelling Related)");
complaintIdToTitle.put("175", "Change of Address in Electoral Roll");
complaintIdToTitle.put("176", "Issue of Voter ID");
complaintIdToTitle.put("177", "Inclusion, Deletion, Correction in Voter List");
complaintIdToTitle.put("178", "Complaints regarding Voter List");
complaintIdToTitle.put("179", "Name not found in the Electoral Roll");
complaintIdToTitle.put("180", "Issue of Birth and Death Certificate");
complaintIdToTitle.put("181", "Encroachment on the Public Property");
complaintIdToTitle.put("182", " Complaints related to Schools");
complaintIdToTitle.put("183", "Sanction of Financial Assistance under Moovalaur Thirumana Thittam");
complaintIdToTitle.put("184", "Complaints related to issue of all types of Registration Certificate");
complaintIdToTitle.put("185", "Slow Progress of Work");
complaintIdToTitle.put("186", "Poor Quality of Work");
complaintIdToTitle.put("187", "Unauthorized Advertisement Boards");
complaintIdToTitle.put("188", "Complaints regarding Bridges / Flyovers / Subways");
complaintIdToTitle.put("189", "Complaints related Shopping Complex");
complaintIdToTitle.put("190", "Complaints regarding Community Hall");
complaintIdToTitle.put("191", "Complaints regarding Burial Ground");
complaintIdToTitle.put("192", "Complaints regarding any other CoC building");
complaintIdToTitle.put("193", "Parking Issue");
complaintIdToTitle.put("195", "Complaints Regarding Plastics");
complaintIdToTitle.put("196", "No electricity in public toilet");
complaintIdToTitle.put("197", "No water supply in public toilet");
complaintIdToTitle.put("198", "Public toilet blockage");
complaintIdToTitle.put("199", "Public toilet cleaning");
complaintIdToTitle.put("200", "Burning of street light in daytime");
complaintIdToTitle.put("201", "Illegal Parking on foot path");
complaintIdToTitle.put("202", "Complaints regarding non availability of Doctors");
complaintIdToTitle.put("203", "Complaints regarding non availability of medicines");
complaintIdToTitle.put("204", "Complaints regarding laboratory issues");
complaintIdToTitle.put("205", "Issues regarding amma baby care kits (After Delivery)");
complaintIdToTitle.put("206", "Issues regarding Amma nutrition kit for pregnant woman");
complaintIdToTitle.put("207", "Issues regarding Muthulakshmi Reddy Maternity Benefit Scheme (MRMBS)");
complaintIdToTitle.put("208", "Issues regarding janani suraksha yojana scheme (JSY)");
complaintIdToTitle.put("209", "Travel pass related complaints");
complaintIdToTitle.put("210", "Food related complaints");
complaintIdToTitle.put("212", "Covid Health Related Queries");
complaintIdToTitle.put("213", "Hospital and Covid care centre(CCC) Related Queries");
complaintIdToTitle.put("214", "Medical Emergencies");
complaintIdToTitle.put("215", "Essentials and Medicines");
complaintIdToTitle.put("216", "PSYCHO-SOCIO support");
complaintIdToTitle.put("218", "Quarantine and isolation Related Queries");
complaintIdToTitle.put("219", "General Health Queries");
complaintIdToTitle.put("220", "Disinfection request");
complaintIdToTitle.put("221", "Non Covid Health Related Queries");
complaintIdToTitle.put("222", "Milling/Scraping of Road before Relaying of Road");
complaintIdToTitle.put("226", "Food Requirement");
complaintIdToTitle.put("227", "Relief Center Requirement");
complaintIdToTitle.put("228", "Covid19 Ambulance Service");
complaintIdToTitle.put("229", "Air Quality");
complaintIdToTitle.put("230", "Online Payment Issue");
complaintIdToTitle.put("231", "General Revision Objection");
complaintIdToTitle.put("232", "Water Mixed with Sewarage");
complaintIdToTitle.put("233", "Sewerage Overflow");
complaintIdToTitle.put("234", "Drinking water supply");
complaintIdToTitle.put("235", "Electricity Shock");
complaintIdToTitle.put("236", "Electricity Unavailability");
complaintIdToTitle.put("237", "Insufficient Barricading");
complaintIdToTitle.put("238", "Fallen poles/towers/hoardings/other infra");
complaintIdToTitle.put("239", "Fallen EB cables");
complaintIdToTitle.put("240", "Project information not provided (Thiruvotriyur High Road)");
complaintIdToTitle.put("241", "Project information not provided (Arunachaleshwar Road)");
complaintIdToTitle.put("242", "Project information not provided (MC Road)");
complaintIdToTitle.put("243", "Project information not provided (Washermenpet Metro)");
complaintIdToTitle.put("244", "Project information not provided (Khadar Nawas Khan Road)");
complaintIdToTitle.put("245", "Project information not provided (Race Course road + Guindy MMI)");
complaintIdToTitle.put("246", "Advance information on consultation not provided (Thiruvotriyur High Road)");
complaintIdToTitle.put("247", "Advance information on consultation not provided (Arunachaleshwar Road)");
complaintIdToTitle.put("248", "Advance information on consultation not provided (MC Road)");
complaintIdToTitle.put("249", "Advance information on consultation not provided (Washermenpet Metro)");
complaintIdToTitle.put("250", "Advance information on consultation not provided (Khadar Nawas Khan Road)");
complaintIdToTitle.put("251", "Advance information on consultation not provided (Race Course road + Guindy MMI)");
complaintIdToTitle.put("252", "Location and area of consultation not provided (Thiruvotriyur High Road)");
complaintIdToTitle.put("253", "Location and area of consultation not provided (Arunachaleshwar Road)");
complaintIdToTitle.put("254", "Location and area of consultation not provided (MC Road)");
complaintIdToTitle.put("255", "Location and area of consultation not provided (Washermenpet Metro)");
complaintIdToTitle.put("256", "Location and area of consultation not provided (Khadar Nawas Khan Road)");
complaintIdToTitle.put("257", "Location and area of consultation not provided (Race Course road + Guindy MMI)");
complaintIdToTitle.put("258", "Information on detailed work plan not provided (Thiruvotriyur High Road)");
complaintIdToTitle.put("259", "Information on detailed work plan not provided (Arunachaleshwar Road)");
complaintIdToTitle.put("260", "Information on detailed work plan not provided (MC Road)");
complaintIdToTitle.put("261", "Information on detailed work plan not provided (Washermenpet Metro)");
complaintIdToTitle.put("262", "Information on detailed work plan not provided (Khadar Nawas Khan Road)");
complaintIdToTitle.put("263", "Information on detailed work plan not provided (Race Course road + Guindy MMI)");
complaintIdToTitle.put("264", "Others (Thiruvotriyur High Road)");
complaintIdToTitle.put("265", "Others (Arunachaleshwar Road)");
complaintIdToTitle.put("266", "Others (MC Road)");
complaintIdToTitle.put("267", "Others (Washermenpet Metro)");
complaintIdToTitle.put("268", "Others (Khadar Nawas Khan Road)");
complaintIdToTitle.put("269", "Others (Race Course road + Guindy MMI)");
complaintIdToTitle.put("270", "No information in advance provided on the date and time of civil works (Thiruvotriyur High Road)");
complaintIdToTitle.put("271", "No information in advance provided on the date and time of civil works (Arunachaleshwar Road)");
complaintIdToTitle.put("272", "No information in advance provided on the date and time of civil works (MC Road)");
complaintIdToTitle.put("273", "No information in advance provided on the date and time of civil works (Washermenpet Metro)");
complaintIdToTitle.put("274", "No information in advance provided on the date and time of civil works (Khadar Nawas Khan Road)");
complaintIdToTitle.put("275", "No information in advance provided on the date and time of civil works (Race Course road + Guindy MMI)");
complaintIdToTitle.put("276", "No information provided on the nature and schedule of civil work (Thiruvotriyur High Road)");
complaintIdToTitle.put("277", "No information provided on the nature and schedule of civil work (Arunachaleshwar Road)");
complaintIdToTitle.put("278", "No information provided on the nature and schedule of civil work (MC Road)");
complaintIdToTitle.put("279", "No information provided on the nature and schedule of civil work (Washermenpet Metro)");
complaintIdToTitle.put("280", "No information provided on the nature and schedule of civil work (Khadar Nawas Khan Road)");
complaintIdToTitle.put("281", "No information provided on the nature and schedule of civil work (Race Course road + Guindy MMI)");
complaintIdToTitle.put("282", "No consultation carried out with the people affected by the civil works (Thiruvotriyur High Road)");
complaintIdToTitle.put("283", "No consultation carried out with the people affected by the civil works (Arunachaleshwar Road)");
complaintIdToTitle.put("284", "No consultation carried out with the people affected by the civil works (MC Road)");
complaintIdToTitle.put("285", "No consultation carried out with the people affected by the civil works (Washermenpet Metro)");
complaintIdToTitle.put("286", "No consultation carried out with the people affected by the civil works (Khadar Nawas Khan Road)");
complaintIdToTitle.put("287", "No consultation carried out with the people affected by the civil works (Race Course road + Guindy MMI)");
complaintIdToTitle.put("288", "No arrangement made for temporary displacement (Thiruvotriyur High Road)");
complaintIdToTitle.put("289", "No arrangement made for temporary displacement (Arunachaleshwar Road)");
complaintIdToTitle.put("290", "No arrangement made for temporary displacement (MC Road)");
complaintIdToTitle.put("291", "No arrangement made for temporary displacement (Washermenpet Metro)");
complaintIdToTitle.put("292", "No arrangement made for temporary displacement (Khadar Nawas Khan Road)");
complaintIdToTitle.put("293", "No arrangement made for temporary displacement (Race Course road + Guindy MMI)");
complaintIdToTitle.put("294", "No display board on the project installed at work site (Thiruvotriyur High Road)");
complaintIdToTitle.put("295", "No display board on the project installed at work site (Arunachaleshwar Road)");
complaintIdToTitle.put("296", "No display board on the project installed at work site (MC Road)");
complaintIdToTitle.put("297", "No display board on the project installed at work site (Washermenpet Metro)");
complaintIdToTitle.put("298", "No display board on the project installed at work site (Khadar Nawas Khan Road)");
complaintIdToTitle.put("299", "No display board on the project installed at work site (Race Course road + Guindy MMI)");
complaintIdToTitle.put("300", "Temporary access to structures not provided and or not adequate (Thiruvotriyur High Road)");
complaintIdToTitle.put("301", "Temporary access to structures not provided and or not adequate (Arunachaleshwar Road)");
complaintIdToTitle.put("302", "Temporary access to structures not provided and or not adequate (MC Road)");
complaintIdToTitle.put("303", "Temporary access to structures not provided and or not adequate (Washermenpet Metro)");
complaintIdToTitle.put("304", "Temporary access to structures not provided and or not adequate (Khadar Nawas Khan Road)");
complaintIdToTitle.put("305", "Temporary access to structures not provided and or not adequate (Race Course road + Guindy MMI)");
complaintIdToTitle.put("306", "No safety measures taken at worksite (Thiruvotriyur High Road)");
complaintIdToTitle.put("307", "No safety measures taken at worksite (Arunachaleshwar Road)");
complaintIdToTitle.put("308", "No safety measures taken at worksite (MC Road)");
complaintIdToTitle.put("309", "No safety measures taken at worksite (Washermenpet Metro)");
complaintIdToTitle.put("310", "No safety measures taken at worksite (Khadar Nawas Khan Road)");
complaintIdToTitle.put("311", "No safety measures taken at worksite (Race Course road + Guindy MMI)");
complaintIdToTitle.put("312", "Water supply disrupted and alternate arrangement not provided (Thiruvotriyur High Road)");
complaintIdToTitle.put("313", "Water supply disrupted and alternate arrangement not provided (Arunachaleshwar Road)");
complaintIdToTitle.put("314", "Water supply disrupted and alternate arrangement not provided (MC Road)");
complaintIdToTitle.put("315", "Water supply disrupted and alternate arrangement not provided (Washermenpet Metro)");
complaintIdToTitle.put("316", "Water supply disrupted and alternate arrangement not provided (Khadar Nawas Khan Road)");
complaintIdToTitle.put("317", "Water supply disrupted and alternate arrangement not provided (Race Course road + Guindy MMI)");
complaintIdToTitle.put("318", "Electricity supply disrupted and alternate arrangement not provided (Thiruvotriyur High Road)");
complaintIdToTitle.put("319", "Electricity supply disrupted and alternate arrangement not provided (Arunachaleshwar Road)");
complaintIdToTitle.put("320", "Electricity supply disrupted and alternate arrangement not provided (MC Road)");
complaintIdToTitle.put("321", "Electricity supply disrupted and alternate arrangement not provided (Washermenpet Metro)");
complaintIdToTitle.put("322", "Electricity supply disrupted and alternate arrangement not provided (Khadar Nawas Khan Road)");
complaintIdToTitle.put("323", "Electricity supply disrupted and alternate arrangement not provided (Race Course road + Guindy MMI)");
complaintIdToTitle.put("324", "Disposal of debris not appropriately managed (Thiruvotriyur High Road)");
complaintIdToTitle.put("325", "Disposal of debris not appropriately managed (Arunachaleshwar Road)");
complaintIdToTitle.put("326", "Disposal of debris not appropriately managed (MC Road)");
complaintIdToTitle.put("327", "Disposal of debris not appropriately managed (Washermenpet Metro)");
complaintIdToTitle.put("328", "Disposal of debris not appropriately managed (Khadar Nawas Khan Road)");
complaintIdToTitle.put("329", "Disposal of debris not appropriately managed (Race Course road + Guindy MMI)");
complaintIdToTitle.put("330", " Temporary arrangement for parking not provided (Thiruvotriyur High Road)");
complaintIdToTitle.put("331", " Temporary arrangement for parking not provided (Arunachaleshwar Road)");
complaintIdToTitle.put("332", " Temporary arrangement for parking not provided (MC Road)");
complaintIdToTitle.put("333", " Temporary arrangement for parking not provided (Washermenpet Metro)");
complaintIdToTitle.put("334", " Temporary arrangement for parking not provided (Khadar Nawas Khan Road)");
complaintIdToTitle.put("335", " Temporary arrangement for parking not provided (Race Course road + Guindy MMI)");
complaintIdToTitle.put("336", "GRM and helpline numbers not displayed at worksite (Thiruvotriyur High Road)");
complaintIdToTitle.put("337", "GRM and helpline numbers not displayed at worksite (Arunachaleshwar Road)");
complaintIdToTitle.put("338", "GRM and helpline numbers not displayed at worksite (MC Road)");
complaintIdToTitle.put("339", "GRM and helpline numbers not displayed at worksite (Washermenpet Metro)");
complaintIdToTitle.put("340", "GRM and helpline numbers not displayed at worksite (Khadar Nawas Khan Road)");
complaintIdToTitle.put("341", "GRM and helpline numbers not displayed at worksite (Race Course road + Guindy MMI)");
complaintIdToTitle.put("342", "Drinking water/ other basic needs for Labour not available at worksite (Thiruvotriyur High Road)");
complaintIdToTitle.put("343", "Drinking water/ other basic needs for Labour not available at worksite (Arunachaleshwar Road)");
complaintIdToTitle.put("344", "Drinking water/ other basic needs for Labour not available at worksite (MC Road)");
complaintIdToTitle.put("345", "Drinking water/ other basic needs for Labour not available at worksite (Washermenpet Metro)");
complaintIdToTitle.put("346", "Drinking water/ other basic needs for Labour not available at worksite (Khadar Nawas Khan Road)");
complaintIdToTitle.put("347", "Drinking water/ other basic needs for Labour not available at worksite (Race Course road + Guindy MMI)");
complaintIdToTitle.put("348", "Noise levels are very high (Thiruvotriyur High Road)");
complaintIdToTitle.put("349", "Noise levels are very high (Arunachaleshwar Road)");
complaintIdToTitle.put("350", "Noise levels are very high (MC Road)");
complaintIdToTitle.put("351", "Noise levels are very high (Washermenpet Metro)");
complaintIdToTitle.put("352", "Noise levels are very high (Khadar Nawas Khan Road)");
complaintIdToTitle.put("353", "Noise levels are very high (Race Course road + Guindy MMI)");
complaintIdToTitle.put("354", " Sprinkling of water at worksite not carried out (Thiruvotriyur High Road)");
complaintIdToTitle.put("355", " Sprinkling of water at worksite not carried out (Arunachaleshwar Road)");
complaintIdToTitle.put("356", " Sprinkling of water at worksite not carried out (MC Road)");
complaintIdToTitle.put("357", " Sprinkling of water at worksite not carried out (Washermenpet Metro)");
complaintIdToTitle.put("358", " Sprinkling of water at worksite not carried out (Khadar Nawas Khan Road)");
complaintIdToTitle.put("359", " Sprinkling of water at worksite not carried out (Race Course road + Guindy MMI)");
complaintIdToTitle.put("360", "The worksite is not barricaded; (Thiruvotriyur High Road)");
complaintIdToTitle.put("361", "The worksite is not barricaded; (Arunachaleshwar Road)");
complaintIdToTitle.put("362", "The worksite is not barricaded; (MC Road)");
complaintIdToTitle.put("363", "The worksite is not barricaded; (Washermenpet Metro)");
complaintIdToTitle.put("364", "The worksite is not barricaded; (Khadar Nawas Khan Road)");
complaintIdToTitle.put("365", "The worksite is not barricaded; (Race Course road + Guindy MMI)");
complaintIdToTitle.put("366", " No information on number of labour working at the site (Thiruvotriyur High Road)");
complaintIdToTitle.put("367", " No information on number of labour working at the site (Arunachaleshwar Road)");
complaintIdToTitle.put("368", " No information on number of labour working at the site (MC Road)");
complaintIdToTitle.put("369", " No information on number of labour working at the site (Washermenpet Metro)");
complaintIdToTitle.put("370", " No information on number of labour working at the site (Khadar Nawas Khan Road)");
complaintIdToTitle.put("371", " No information on number of labour working at the site (Race Course road + Guindy MMI)");
complaintIdToTitle.put("372", "Labourer not using the safety equipment (Thiruvotriyur High Road)");
complaintIdToTitle.put("373", "Labourer not using the safety equipment (Arunachaleshwar Road)");
complaintIdToTitle.put("374", "Labourer not using the safety equipment (MC Road)");
complaintIdToTitle.put("375", "Labourer not using the safety equipment (Washermenpet Metro)");
complaintIdToTitle.put("376", "Labourer not using the safety equipment (Khadar Nawas Khan Road)");
complaintIdToTitle.put("377", "Labourer not using the safety equipment (Race Course road + Guindy MMI)");
complaintIdToTitle.put("378", "Sewerage pipe is damaged (Thiruvotriyur High Road)");
complaintIdToTitle.put("379", "Sewerage pipe is damaged (Arunachaleshwar Road)");
complaintIdToTitle.put("380", "Sewerage pipe is damaged (MC Road)");
complaintIdToTitle.put("381", "Sewerage pipe is damaged (Washermenpet Metro)");
complaintIdToTitle.put("382", "Sewerage pipe is damaged (Khadar Nawas Khan Road)");
complaintIdToTitle.put("383", "Sewerage pipe is damaged (Race Course road + Guindy MMI)");
complaintIdToTitle.put("384", "Others (Thiruvotriyur High Road)");
complaintIdToTitle.put("385", "Others (Arunachaleshwar Road)");
complaintIdToTitle.put("386", "Others (MC Road)");
complaintIdToTitle.put("387", "Others (Washermenpet Metro)");
complaintIdToTitle.put("388", "Others (Khadar Nawas Khan Road)");
complaintIdToTitle.put("389", "Others (Race Course road + Guindy MMI)");
complaintIdToTitle.put("390", "Insufficient Barricading (Thiruvotriyur High Road)");
complaintIdToTitle.put("391", "Insufficient Barricading (Arunachaleshwar Road)");
complaintIdToTitle.put("392", "Insufficient Barricading (MC Road)");
complaintIdToTitle.put("393", "Insufficient Barricading (Washermenpet Metro)");
complaintIdToTitle.put("394", "Insufficient Barricading (Khadar Nawas Khan Road)");
complaintIdToTitle.put("395", "Insufficient Barricading (Race Course road + Guindy MMI)");
complaintIdToTitle.put("396", "Non Removal of Debris (Thiruvotriyur High Road)");
complaintIdToTitle.put("397", "Non Removal of Debris (Arunachaleshwar Road)");
complaintIdToTitle.put("398", "Non Removal of Debris (MC Road)");
complaintIdToTitle.put("399", "Non Removal of Debris (Washermenpet Metro)");
complaintIdToTitle.put("400", "Non Removal of Debris (Khadar Nawas Khan Road)");
complaintIdToTitle.put("401", "Non Removal of Debris (Race Course road + Guindy MMI)");
complaintIdToTitle.put("402", "Potholes fill up (Thiruvotriyur High Road)");
complaintIdToTitle.put("403", "Potholes fill up (Arunachaleshwar Road)");
complaintIdToTitle.put("404", "Potholes fill up (MC Road)");
complaintIdToTitle.put("405", "Potholes fill up (Washermenpet Metro)");
complaintIdToTitle.put("406", "Potholes fill up (Khadar Nawas Khan Road)");
complaintIdToTitle.put("407", "Potholes fill up (Race Course road + Guindy MMI)");
complaintIdToTitle.put("408", "Damage to utilities (TNEB, CMWSSB, BSNL) (Thiruvotriyur High Road)");
complaintIdToTitle.put("409", "Damage to utilities (TNEB, CMWSSB, BSNL) (Arunachaleshwar Road)");
complaintIdToTitle.put("410", "Damage to utilities (TNEB, CMWSSB, BSNL) (MC Road)");
complaintIdToTitle.put("411", "Damage to utilities (TNEB, CMWSSB, BSNL) (Washermenpet Metro)");
complaintIdToTitle.put("412", "Damage to utilities (TNEB, CMWSSB, BSNL) (Khadar Nawas Khan Road)");
complaintIdToTitle.put("413", "Damage to utilities (TNEB, CMWSSB, BSNL) (Race Course road + Guindy MMI)");
complaintIdToTitle.put("414", "Encroaching Public Space (Thiruvotriyur High Road)");
complaintIdToTitle.put("415", "Encroaching Public Space (Arunachaleshwar Road)");
complaintIdToTitle.put("416", "Encroaching Public Space (MC Road)");
complaintIdToTitle.put("417", "Encroaching Public Space (Washermenpet Metro)");
complaintIdToTitle.put("418", "Encroaching Public Space (Khadar Nawas Khan Road)");
complaintIdToTitle.put("419", "Encroaching Public Space (Race Course road + Guindy MMI)");
complaintIdToTitle.put("420", "Need Pathway ramp (Thiruvotriyur High Road)");
complaintIdToTitle.put("421", "Need Pathway ramp (Arunachaleshwar Road)");
complaintIdToTitle.put("422", "Need Pathway ramp (MC Road)");
complaintIdToTitle.put("423", "Need Pathway ramp (Washermenpet Metro)");
complaintIdToTitle.put("424", "Need Pathway ramp (Khadar Nawas Khan Road)");
complaintIdToTitle.put("425", "Need Pathway ramp (Race Course road + Guindy MMI)");
complaintIdToTitle.put("426", "Cleanliness in Parks");
complaintIdToTitle.put("427", "Greenary in Parks");
complaintIdToTitle.put("428", "Play Equipment");
complaintIdToTitle.put("429", "Opening and closing hours");
complaintIdToTitle.put("430", "Toilets in parks");
complaintIdToTitle.put("431", "Non functional lights/ no lights in parks");
complaintIdToTitle.put("432", "Safety in parks/playgrounds");
complaintIdToTitle.put("433", "Women related safety issues in parks");
complaintIdToTitle.put("434", "Availability or cleanliness of dustbins in public toilets");
complaintIdToTitle.put("435", "Cleanliness/ water supply in toilets");
complaintIdToTitle.put("436", "Broken sinks, toilets or urinals and doors");
complaintIdToTitle.put("437", "Request for new toilet");
complaintIdToTitle.put("438", "Illegal activities in toilet");
complaintIdToTitle.put("439", "Toilets not in use/ closed");
complaintIdToTitle.put("440", "Inadequate lighting in and around the toilet");
complaintIdToTitle.put("441", "Safety in public toilets");
complaintIdToTitle.put("442", "Cleanliness in footpath");
complaintIdToTitle.put("443", "Electrical wires/obstruction on footpath");
complaintIdToTitle.put("444", "Unsafe dark spots/ corners");
complaintIdToTitle.put("445", "Public defecation/urination");
complaintIdToTitle.put("446", "Women related safety issues ");
complaintIdToTitle.put("447", "Inadequate light in a particular location or spot/ dark spots");
String expectedType;
if (complaintIdToTitle.containsKey(complaintId)) {
expectedType = complaintIdToTitle.get(complaintId).trim().toLowerCase();
} else {
// Fallback: Use sub-type text directly if not found in map (i.e. for "Others")
expectedType = complaintId.trim().toLowerCase();
}
// 2. Date range: last 7 days
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd/MM/yyyy");
LocalDate today = LocalDate.now();
String endDate = today.format(formatter);
String startDate = today.minusDays(7).format(formatter);
int repYear = today.getYear();
// 3. Construct external URL
String externalUrl = String.format(
"https://erp.chennaicorporation.gov.in/pgr/newmobileservice?serviceId=getComplaintListWithImg" +
"&From_date=%s&To_date=%s&jsonResp=Yes&UserType=Public&Token=&PageIndex=null&Status=null&repYear=%d&MobileNo=%s",
startDate, endDate, repYear, mobileNo
);
System.out.println("External API URL: " + externalUrl);
// 4. Fetch and parse response
RestTemplate restTemplate = new RestTemplate();
String json = restTemplate.getForObject(externalUrl, String.class);
ObjectMapper mapper = new ObjectMapper();
JsonNode rootArray = mapper.readTree(json);
boolean found = false;
if (rootArray.isArray() && rootArray.size() > 0) {
JsonNode complaintList = rootArray.get(0).path("ComplaintListHistory");
if (complaintList.isArray()) {
for (JsonNode item : complaintList) {
String type = item.path("complainttype").asText("").trim().toLowerCase();
String street = item.path("Street").asText("").trim().toLowerCase();
System.out.println("Complaint type in data: " + type);
System.out.println("Expected complaint type: " + expectedType);
System.out.println("Street in data: " + street);
System.out.println("Given street name: " + streetName.trim().toLowerCase());
if (type.equals(expectedType) &&
street.equals(streetName.trim().toLowerCase())) {
found = true;
break;
}
}
}
}
// 5. Return response
Map<String, Object> response = new HashMap<>();
response.put("duplicate", found);
return ResponseEntity.ok(response);
} catch (Exception e) {
e.printStackTrace();
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
.body(Collections.singletonMap("error", "Failed to process the request"));
}
}
/*
* private static final Logger log =
* LoggerFactory.getLogger(ComplaintController.class);
*
*
* @GetMapping("/getStreets") public ResponseEntity<?> getStreets(
*
* @RequestParam double lat,
*
* @RequestParam double lon ) throws Exception { // 1) raw ESRI geometry JSON
* String geomJson = String.format("{\"x\":%f,\"y\":%f}", lon, lat);
*
* // 2) build & encode the full query URL in one go String url =
* UriComponentsBuilder .fromHttpUrl("https://gisgcc.chennaicorporation.gov.in"
* + "/server/rest/services/GCCDepts/EDPMobile2025/FeatureServer/0/query")
* .queryParam("where", "") .queryParam("geometry", geomJson) // <<< raw JSON
* here .queryParam("geometryType", "esriGeometryPoint") .queryParam("inSR",
* "4326") .queryParam("spatialRel", "esriSpatialRelIntersects")
* .queryParam("distance", "25") .queryParam("units", "esriSRUnit_Meter")
* .queryParam("outFields",
* "region,new_zone,new_ward,road_id,road_name,gis_id,type")
* .queryParam("returnGeometry", "false") .queryParam("f", "geojson") .build()
* .encode() // <<< encode once .toUriString();
*
* log.info("Calling ESRI: {}", url);
*
* // 3) fetch the raw JSON String rawJson = restTemplate.getForObject(url,
* String.class); log.info("ESRI raw response: {}", rawJson);
*
* // 4) detect ESRI-level errors JsonNode root = new
* ObjectMapper().readTree(rawJson); if (root.has("error")) { String msg =
* root.path("error").path("message").asText(); return ResponseEntity
* .status(HttpStatus.BAD_GATEWAY) .body(Map.of("message",
* "ESRI service error: " + msg)); }
*
* // 5) now safe to bind only the “features” array FeatureCollection fc = new
* ObjectMapper() .readerFor(FeatureCollection.class) .readValue(root);
*
* List<Feature> feats = Optional.ofNullable(fc.getFeatures())
* .orElse(List.of());
*
* if (feats.isEmpty()) { return ResponseEntity.noContent().build(); }
*
* // 6) extract unique road names List<String> streets = feats.stream() .map(f
* -> f.getProperties().getRoadName()) .filter(Objects::nonNull) .distinct()
* .toList();
*
* return ResponseEntity.ok(Map.of("streets", streets)); }
*
* @JsonIgnoreProperties(ignoreUnknown = true) public static class
* FeatureCollection { private List<Feature> features; public List<Feature>
* getFeatures() { return features; } public void setFeatures(List<Feature>
* features) { this.features = features; } }
*
* @JsonIgnoreProperties(ignoreUnknown = true) public static class Feature {
* private Properties properties; public Properties getProperties() { return
* properties; } public void setProperties(Properties properties) {
* this.properties = properties; } }
*
* @JsonIgnoreProperties(ignoreUnknown = true) public static class Properties {
*
* @JsonProperty("road_name") private String roadName; public String
* getRoadName() { return roadName; } public void setRoadName(String roadName) {
* this.roadName = roadName; } }
*/
}

18
src/main/java/com/gcc/publicgrievance/controller/UserController.java

@ -3,11 +3,13 @@ package com.gcc.publicgrievance.controller;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller
@RequestMapping("/pgr")
public class UserController {
@GetMapping({"/", "/home"})
@GetMapping({"/","", "/home"})
public String home(Model model) {
return "User/home";
}
@ -23,9 +25,17 @@ public class UserController {
public String checklistofficer(Model model) {
return "checklistofficer/checklistofficer";
}
@GetMapping("/checklistuser")
public String checklistuser(Model model) {
return "checklistuser/checklistuser";
@GetMapping("/checkofficerhome")
public String checkofficerhome(Model model) {
return "officer/checkofficerhome";
}
@GetMapping("/staffcomplaint")
public String staffcomplaint(Model model) {
return "staff/staffcomplaint";
}
@GetMapping("/staffhome")
public String staffhome(Model model) {
return "staff/staffhome";
}
}

20
src/main/resources/application-dev.properties

@ -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

24
src/main/resources/application-prod.properties

@ -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

9
src/main/resources/application.properties

@ -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

BIN
src/main/resources/static/images/message.png

After

Width: 512  |  Height: 512  |  Size: 16 KiB

BIN
src/main/resources/static/images/otp.png

After

Width: 1102  |  Height: 1020  |  Size: 234 KiB

BIN
src/main/resources/static/images/output-onlinepngtools.png

After

Width: 512  |  Height: 512  |  Size: 4.6 KiB

59
src/main/resources/static/js/screenreader.js

@ -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 stopReading() {
if (speechSynthesisUtterance) {
window.speechSynthesis.cancel();
isReading = false;
// 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 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
// 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 {
readScreenContent();
button.innerText = "Stop Reading"; // Update button text when reading
speakText(element.textContent.trim()); // Speak the element's text when hovered
}
});
}
});
}
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}`;
});
});

78
src/main/resources/templates/User/home.html

@ -230,22 +230,26 @@
<!-- Insert the header fragment -->
<div th:insert="fragments/header :: headerFragment"></div>
<div th:insert="~{fragments/header :: headerFragment}"></div>
<!--<button id="reader-btn" onclick="toggleReader()">Enable Reader</button>-->
<br>
<a href="https://chennaicorporation.gov.in/gcc/" class="btn btn-secondary" target="_blank" style="font-size: 17px;">
Back </i>
</a>
<!-- 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..." />
<img src="/pgr/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="registercomplaints" class="card-link">
<div class="card readable">
<a href="/pgr/registercomplaints" class="card-link">
<div class="card content">
<div class="card-body">
<img src="images/register.png" alt="register" class="card-img">
<img src="/pgr/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>
@ -261,7 +265,7 @@
<div class="col-md-4">
<div class="card readable">
<div class="card-body">
<img src="images/phone-call.png" alt="Phone" class="card-img">
<img src="/pgr/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>
@ -276,7 +280,7 @@
<div class="col-md-4">
<div class="card readable">
<div class="card-body">
<img src="images/contract.png" alt="Paper" class="card-img">
<img src="/pgr/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
@ -292,7 +296,7 @@
<div class="col-md-12">
<div class="card readable">
<div class="card-body">
<img src="images/search.png" alt="Status" class="card-img">
<img src="/pgr/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">
@ -313,7 +317,7 @@
<!-- 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"
<input type="text" class="form-control" id="complaint-mobile" minlength="10" maxlength="10"
placeholder="Enter Mobile Number">
</div>
</div>
@ -332,6 +336,12 @@
</div>
</div>
<br>
<br>
<br>
<br>
<br>
<br>
<!-- Form to Check by Mobile Number -->
<!--<div class="col-md-6">
@ -405,8 +415,7 @@
<!-- <div th:insert="fragments/footer :: footerFragment"></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>
@ -428,7 +437,7 @@
$('#check-now-btn').click(function () {
var complaintNumber = $('#complaint-number').val();
if (complaintNumber) {
window.location.href = 'checklistofficer?complaintno=' + encodeURIComponent(complaintNumber);
window.location.href = '/pgr/checklistofficer?complaintno=' + encodeURIComponent(complaintNumber);
} else {
alert('Please enter a complaint number.');
}
@ -461,7 +470,39 @@
}
}
// ✅ Mobile number validation as user types
$('#complaint-mobile').on('input', function () {
let value = this.value;
// Allow only digits
value = value.replace(/[^0-9]/g, '');
// Prevent starting with 0
if (value.startsWith('0')) {
value = '';
//showSnackbar("Mobile number cannot start with 0.");
}
// Limit to 10 digits
if (value.length > 10) {
value = value.slice(0, 10);
}
this.value = value;
// Check for all repeating digits
if (/^(\d)\1{9}$/.test(value)) {
$(this).addClass('is-invalid');
showSnackbar("Mobile number cannot be all repeating digits.");
} else {
$(this).removeClass('is-invalid');
}
});
$(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
@ -470,10 +511,16 @@
alert("Please enter a mobile number.");
return;
}
if (mobileNumber.length !== 10 || !/^\d{10}$/.test(mobileNumber) || mobileNumber.startsWith('0') || /^(\d)\1{9}$/.test(mobileNumber)) {
alert("Enter a valid 10-digit mobile number.");
return;
}
$('#loader').show();
// AJAX request to fetch complaint details by mobile number
$.ajax({
url: '/api/getComplaintDetailsByMobile', // Replace with your correct API path
url: '/pgr/api/getComplaintDetailsByMobile',
method: 'GET',
data: {mobileNo: mobileNumber},
success: function (response) {
@ -528,7 +575,7 @@
var complaintId = $(this).data('complaintid');
if (complaintId) {
// Redirect to the complaint details page using complaintId
window.location.href = 'checklistofficer?complaintno=' + encodeURIComponent(complaintId);
window.location.href = '/pgr/checklistofficer?complaintno=' + encodeURIComponent(complaintId);
} else {
alert('Complaint ID not found.');
}
@ -538,6 +585,7 @@
});
</script>
<script th:src="@{/js/screenreader.js}"></script>
</body>
</html>

0
src/main/resources/templates/User/kin.html

1852
src/main/resources/templates/User/registercomplaints.html
File diff suppressed because it is too large
View File

160
src/main/resources/templates/checklistofficer/checklistofficer.html

@ -84,6 +84,9 @@
<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>
@ -97,27 +100,19 @@
<div class="card-body">
<div class="row">
<div class="col-md-6">
Complainant ID:
<label>Complainant ID:</label>
<input type="text" id="complaintid" class="form-control" value="" disabled>
</div>
<div class="col-md-6">
Complainant Mobile Number:
<label>Complainant Mobile Number:</label>
<input type="text" id="complaint-mobile-number" class="form-control" value="" disabled>
</div>
<div class="col-md-6">
Complainant Name:
<label>Complainant Name:</label>
<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>
@ -128,23 +123,23 @@
<div class="card-body">
<div class="row">
<div class="col-md-4">
Complainant Street:
<label>Complainant Street:</label>
<input type="text" id="street" class="form-control" disabled>
</div>
<div class="col-md-4">
Complainant Zone:
<label>Complainant Zone:</label>
<input type="text" class="form-control" id="zone" disabled>
</div>
<div class="col-md-4">
Complainant Ward:
<label>Complainant Ward:</label>
<input type="text" class="form-control" id="ward" disabled>
</div>
<div class="col-md-4">
Complainant Area:
<label>Complainant Area:</label>
<input type="text" class="form-control" id="area" disabled>
</div>
<div class="col-md-4">
Complainant Locality:
<label>Complainant Locality:</label>
<input type="text" class="form-control" id="location" disabled>
</div>
</div>
@ -156,7 +151,7 @@
<div class="card-body">
<div class="row">
<div class="col-md-4">
Complainant Type:
<label>Complainant Type:</label>
<input type="text" class="form-control" id="complaintType" disabled>
</div>
@ -169,7 +164,7 @@
<input type="text" class="form-control" disabled>
</div>-->
<div class="col-md-12">
Complainant Description:
<label>Complainant Description:</label>
<input type="text" class="form-control" id="complaintdesc" disabled>
</div>
</div>
@ -184,17 +179,17 @@
<div class="col-md-4">
Complaint Closed Date:
<label>Complaint Closed Date:</label>
<input type="text" class="form-control" id="commentDate" disabled>
</div>
<div class="col-md-4">
Official Name:
<label>Official Name:</label>
<input type="text" class="form-control" id="commentuser" disabled>
</div>
<div class="col-md-4">
Status:
<label>Status:</label>
<input type="text" class="form-control" id="statusshow"
style="background-color: #414f69;color: white;" disabled>
</div>
@ -219,23 +214,20 @@
<div class="card-body">
<div class="row">
<div class="col-md-6">
Change Complaint Status:
<label>Change Complaint Status:</label>
<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:
<label>Photo:</label>
<input type="file" class="form-control" id="photo">
</div>
</div>
<div class="row">
<div class="col-md-12">
Details of Complaint:
<label>Details of Complaint:</label>
<textarea class="form-control" id="othercomplaint-details" rows="3"
placeholder="Enter complaint details" maxlength="400" required></textarea>
</div>
@ -249,6 +241,12 @@
<!--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>
@ -276,7 +274,7 @@
$('#loader').show();
$.ajax({
url: '/api/getComplaintDetailsbyId', // Replace with your actual API endpoint
url: '/pgr/api/getComplaintDetailsbyId', // Replace with your actual API endpoint
type: 'GET',
data: {complaintid: complaintNo},
success: function (response) {
@ -312,6 +310,40 @@
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
@ -329,15 +361,64 @@
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="${imageUrl}" alt="User Image" class="img-fluid">
<img src="${compressedImage}" alt="User Image" class="img-fluid">
</div>`;
commentsContainer.append(lastCommentHtml);
});
});
}
}
@ -361,13 +442,13 @@
</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>
<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
@ -377,10 +458,14 @@
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="${imageUrl}" alt="User Image" class="img-fluid">
<img src="${compressedImage}" alt="User Image" class="img-fluid">
</div>`;
});
});
}
}
@ -487,14 +572,16 @@
if (imageFile) {
formData.append("Comp_Image", imageFile);
}
$('#loaders').show();
$.ajax({
url: '/updateComplaint',
url: '/pgr/api/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.',
@ -508,6 +595,7 @@
},
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!',
@ -518,7 +606,7 @@
}
});
});
});
});
</script>
</body>

4
src/main/resources/templates/fragments/accessibility.html

@ -3,6 +3,8 @@
<head>
<meta charset="UTF-8">
<title>Title</title>
<base th:href="${baseURL}" />
</head>
<body>
<div th:fragment="accessibility">
@ -149,7 +151,7 @@
</div>
</div>
<button id="uw-widget-custom-trigger" class="uw-widget-custom-trigger" aria-label="Accessibility Widget"
data-uw-trigger="true" aria-haspopup="dialog"><img
data-uw-trigger="true" aria-haspopup="dialog" style="margin-bottom: 50px;"><img
src="data:image/svg+xml,%0A%3Csvg width='32' height='32' viewBox='0 0 32 32' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cg clip-path='url(%23clip0_1_1506)'%3E%3Cpath d='M16 7C15.3078 7 14.6311 6.79473 14.0555 6.41015C13.4799 6.02556 13.0313 5.47894 12.7664 4.83939C12.5015 4.19985 12.4322 3.49612 12.5673 2.81719C12.7023 2.13825 13.0356 1.51461 13.5251 1.02513C14.0146 0.535644 14.6383 0.202301 15.3172 0.0672531C15.9961 -0.0677952 16.6999 0.00151652 17.3394 0.266423C17.9789 0.53133 18.5256 0.979934 18.9101 1.55551C19.2947 2.13108 19.5 2.80777 19.5 3.5C19.499 4.42796 19.1299 5.31762 18.4738 5.97378C17.8176 6.62994 16.928 6.99901 16 7Z' fill='white'/%3E%3Cpath d='M27 7.05L26.9719 7.0575L26.9456 7.06563C26.8831 7.08313 26.8206 7.10188 26.7581 7.12125C25.595 7.4625 19.95 9.05375 15.9731 9.05375C12.2775 9.05375 7.14313 7.67875 5.50063 7.21188C5.33716 7.14867 5.17022 7.09483 5.00063 7.05063C3.81313 6.73813 3.00063 7.94438 3.00063 9.04688C3.00063 10.1388 3.98188 10.6588 4.9725 11.0319V11.0494L10.9238 12.9081C11.5319 13.1413 11.6944 13.3794 11.7738 13.5856C12.0319 14.2475 11.8256 15.5581 11.7525 16.0156L11.39 18.8281L9.37813 29.84C9.37188 29.87 9.36625 29.9006 9.36125 29.9319L9.34688 30.0112C9.20188 31.0206 9.94313 32 11.3469 32C12.5719 32 13.1125 31.1544 13.3469 30.0037C13.5813 28.8531 15.0969 20.1556 15.9719 20.1556C16.8469 20.1556 18.6494 30.0037 18.6494 30.0037C18.8838 31.1544 19.4244 32 20.6494 32C22.0569 32 22.7981 31.0162 22.6494 30.0037C22.6363 29.9175 22.6206 29.8325 22.6019 29.75L20.5625 18.8294L20.2006 16.0169C19.9387 14.3788 20.1494 13.8375 20.2206 13.7106C20.2225 13.7076 20.2242 13.7045 20.2256 13.7013C20.2931 13.5763 20.6006 13.2963 21.3181 13.0269L26.8981 11.0763C26.9324 11.0671 26.9662 11.0563 26.9994 11.0438C27.9994 10.6688 28.9994 10.15 28.9994 9.04813C28.9994 7.94625 28.1875 6.73813 27 7.05Z' fill='white'/%3E%3C/g%3E%3Cdefs%3E%3CclipPath id='clip0_1_1506'%3E%3Crect width='32' height='32' fill='white'/%3E%3C/clipPath%3E%3C/defs%3E%3C/svg%3E%0A"><span>Accessibility Options</span>
</button><!-- accessibility panel end-->

5
src/main/resources/templates/fragments/footer.html

@ -42,10 +42,11 @@
<body>
<div class="footer">
<div class="footer-content">
<img src="images/ripon.jpg" style="height: 51px; width: 155px;margin-top: 10px;" alt="Left Image" class="footer-image left-image">
<img src="/pgr/images/ripon.jpg" style="height: 51px; width: 155px;margin-top: 10px;" alt="Left Image" class="footer-image left-image">
<p>Public Grievance System provided to Greater Chennai Corporation by Bonton Software Private Limited.</p>
<img src="images/ripon.jpg" style="height: 51px; width: 155px;margin-top: 10px;" alt="Right Image" class="footer-image right-image">
<img src="/pgr/images/ripon.jpg" style="height: 51px; width: 155px;margin-top: 10px;" alt="Right Image" class="footer-image right-image">
</div>
</div>

67
src/main/resources/templates/fragments/header.html

@ -3,6 +3,7 @@
<head>
<title>Header Fragment</title>
<base th:href="${baseURL}" />
</head>
@ -36,10 +37,25 @@
height: 60px;
margin-left: 10px;
}
</style>
#toggleSpeech {
background-color: white;
color: black;
margin: 3px;
}
#toggleSpeech img {
height: 30px;
/* Set height for the image */
margin-right: 8px;
/* Add some space between the image and text */
}
</style>
<div class="header">
<div class="logo-left">
<img src="images/gcc1.png" alt="Greater Chennai Corporation Logo">
<img src="/pgr/images/gcc1.png" alt="Greater Chennai Corporation Logo">
<!--<button id="toggleSpeech" class="btn btn-secondary">
<img src="/staffcomplaint/images/message.png" alt="Accessibility Icon">Turn On Speech</button>-->
</div>
<div class="title">
@ -47,52 +63,11 @@
</div>
<!--<button id="screenReaderButton">Read Screen</button>-->
<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>
<img src="/pgr/images/tamil.jpg" alt="Tamil Nadu Logo">
<!--<img src="images/bt-logo.png" style="width: 100px;height: 50px;" alt="bonton Logo">-->
</div>
</div>
<script>
// screenReader.js
let isReading = false;
let speechSynthesisUtterance;
function readScreenContent() {
const content = document.body.innerText;
speechSynthesisUtterance = new SpeechSynthesisUtterance(content);
window.speechSynthesis.speak(speechSynthesisUtterance);
isReading = true;
}
function stopReading() {
if (speechSynthesisUtterance) {
window.speechSynthesis.cancel();
isReading = false;
}
}
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 () {
toggleScreenReader('screenReaderButton');
});
</script>
</div>
<script th:src="@{/js/screenreader.js}"></script>
</body>
</html>

258
src/main/resources/templates/officer/checkofficerhome.html

@ -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>

528
src/main/resources/templates/officer/checkofficerstatus.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>

614
src/main/resources/templates/staff/staffcheckstatus.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

543
src/main/resources/templates/staff/staffhome.html

@ -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">&times;</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>

13
src/test/java/com/gcc/publicgrievance/PublicgrievanceApplicationTests.java

@ -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() {
}
}
Loading…
Cancel
Save