Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions data/replies.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
1,1,Admin,jkdfnkjadfng,2025-05-16T16:31:09.2848758
9 changes: 1 addition & 8 deletions data/reviews.txt
Original file line number Diff line number Diff line change
@@ -1,8 +1 @@
1,3,Divendra,4,good and delicious,2025-05-14T16:31:40.4368314
3,3,signature,4,greedy,2025-05-14T17:03:58.702685
4,2,Divendra Paramendran,4,WE,2025-05-14T17:17:07.9379123
5,2,User,5,qwerty123,2025-05-14T18:42:05.1667083
6,2,User,3,summa
,2025-05-14T19:07:04.3450932
6,2,Admin,4,qwerty,2025-05-14T19:07:50.1999501
7,2,User1,4,dsvsdfvsdfv,2025-05-15T17:36:36.9874254
1,6,User1,4,askjdffgiadfsjg,2025-05-16T16:30:16.4348461
2 changes: 1 addition & 1 deletion data/users.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
1,Admin,admin@12345,admin@gmail.com,Admin
1,Admin,Admin@12345,admin@gmail.com,Admin
2,User1,User1@12345,User1@gmail.com,User
3,User2,User2@12345,User2@gmail.com,User
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,10 @@
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import javax.imageio.IIOImage;
Expand All @@ -32,8 +34,10 @@
import org.springframework.web.servlet.mvc.support.RedirectAttributes;

import com.backery.backery_management.dao.ReviewDAO;
import com.backery.backery_management.dao.ReplyDAO;
import com.backery.backery_management.model.Product;
import com.backery.backery_management.model.Review;
import com.backery.backery_management.model.Reply;
import com.backery.backery_management.model.User;
import com.backery.backery_management.service.OrderService;
import com.backery.backery_management.service.ProductService;
Expand All @@ -48,6 +52,7 @@ public class ProductController {
@Autowired
private ProductService productService;
private final ReviewDAO reviewDAO = new ReviewDAO();
private final ReplyDAO replyDAO = new ReplyDAO();

@Autowired
private OrderService orderService;
Expand Down Expand Up @@ -443,8 +448,18 @@ public String viewProduct(@PathVariable("id") int id, Model model, RedirectAttri
redirectAttributes.addFlashAttribute("errorMessage", "Product not found.");
return "redirect:/products/customer";
}
List<Review> reviews = reviewDAO.getReviewsByProductId(id);

// Get replies for each review
Map<Integer, List<Reply>> reviewReplies = new HashMap<>();
for (Review review : reviews) {
List<Reply> replies = replyDAO.getRepliesByReviewId(review.getId());
reviewReplies.put(review.getId(), replies);
}

model.addAttribute("product", product);
model.addAttribute("reviews", reviewDAO.getReviewsByProductId(id));
model.addAttribute("reviews", reviews);
model.addAttribute("reviewReplies", reviewReplies);
return "single-product";
}

Expand Down Expand Up @@ -490,11 +505,17 @@ public String placeOrder(
@PostMapping("/{id}/review")
public String addReview(
@PathVariable("id") int productId,
@RequestParam("customerName") String customerName,
@RequestParam("rating") int rating,
@RequestParam("comment") String comment,
HttpSession session,
RedirectAttributes redirectAttributes) {

String customerName = (String) session.getAttribute("customerName");
if (customerName == null) {
redirectAttributes.addFlashAttribute("errorMessage", "Please login to add a review.");
return "redirect:/products/view/" + productId;
}

if (rating < 1 || rating > 5) {
redirectAttributes.addFlashAttribute("errorMessage", "Invalid rating value.");
return "redirect:/products/view/" + productId;
Expand Down Expand Up @@ -550,38 +571,126 @@ public String editReview(
@PostMapping("/review/delete")
public String deleteReview(
@RequestParam int reviewId,
@RequestParam int productId,
HttpSession session,
RedirectAttributes redirectAttributes) {
String customerName = (String) session.getAttribute("customerName");
if (customerName == null) {
redirectAttributes.addFlashAttribute("errorMessage", "Please login to delete reviews");
return "redirect:/products/customer";
return "redirect:/products/view/" + productId;
}

ReviewDAO reviewDAO = new ReviewDAO();
Review existingReview = reviewDAO.getReviewById(reviewId);

if (existingReview == null) {
redirectAttributes.addFlashAttribute("errorMessage", "Review not found");
return "redirect:/products/customer";
return "redirect:/products/view/" + productId;
}

if (!existingReview.getCustomerName().equals(customerName)) {
redirectAttributes.addFlashAttribute("errorMessage", "You can only delete your own reviews");
return "redirect:/products/customer";
return "redirect:/products/view/" + productId;
}

// First delete all replies associated with this review
boolean repliesDeleted = replyDAO.deleteRepliesByReviewId(reviewId);

// Then delete the review
if (reviewDAO.deleteReview(reviewId)) {
redirectAttributes.addFlashAttribute("successMessage", "Review deleted successfully!");
if (!repliesDeleted) {
redirectAttributes.addFlashAttribute("warningMessage", "Review deleted but there was an issue deleting some replies.");
} else {
redirectAttributes.addFlashAttribute("successMessage", "Review and all replies deleted successfully!");
}
} else {
redirectAttributes.addFlashAttribute("errorMessage", "Failed to delete review");
}
return "redirect:/products/customer";
return "redirect:/products/view/" + productId;
}

@GetMapping("/review/delete-test")
@ResponseBody
public String testDelete() {
return "Delete mapping works!";
}

@GetMapping("/reviews")
public String showAllReviews(
@RequestParam(required = false) String search,
@RequestParam(required = false) String rating,
Model model,
HttpSession session,
RedirectAttributes redirectAttributes) {

// Check if user is admin
String role = (String) session.getAttribute("role");
if (!"Admin".equals(role)) {
redirectAttributes.addFlashAttribute("errorMessage", "Access denied. Admin only.");
return "redirect:/";
}

// Get all reviews
ReviewDAO reviewDAO = new ReviewDAO();
List<Review> reviews = reviewDAO.getAllReviews();

// Filter by rating if specified
if (rating != null && !rating.isEmpty()) {
int ratingValue = Integer.parseInt(rating);
reviews = reviews.stream()
.filter(r -> r.getRating() == ratingValue)
.collect(Collectors.toList());
}

// Filter by search term if specified
if (search != null && !search.trim().isEmpty()) {
String searchLower = search.toLowerCase();
reviews = reviews.stream()
.filter(r -> {
Product product = productService.getProductById(r.getProductId());
return (product != null && product.getName().toLowerCase().contains(searchLower)) ||
r.getCustomerName().toLowerCase().contains(searchLower) ||
r.getComment().toLowerCase().contains(searchLower);
})
.collect(Collectors.toList());
}

// Create a map of product names for display
Map<Integer, String> productNames = new HashMap<>();
for (Review review : reviews) {
Product product = productService.getProductById(review.getProductId());
if (product != null) {
productNames.put(review.getProductId(), product.getName());
}
}

model.addAttribute("reviews", reviews);
model.addAttribute("productNames", productNames);
return "all-reviews";
}

@PostMapping("/review/reply")
public String addReply(
@RequestParam int reviewId,
@RequestParam int productId,
@RequestParam String comment,
HttpSession session,
RedirectAttributes redirectAttributes) {

// Check if user is admin
String role = (String) session.getAttribute("role");
String adminName = (String) session.getAttribute("username");
if (!"Admin".equals(role)) {
redirectAttributes.addFlashAttribute("errorMessage", "Only admins can reply to reviews.");
return "redirect:/products/view/" + productId;
}

Reply reply = new Reply(0, reviewId, adminName, comment, null);
if (replyDAO.addReply(reply)) {
redirectAttributes.addFlashAttribute("successMessage", "Reply added successfully!");
} else {
redirectAttributes.addFlashAttribute("errorMessage", "Failed to add reply.");
}
return "redirect:/products/view/" + productId;
}
}
136 changes: 136 additions & 0 deletions src/main/java/com/backery/backery_management/dao/ReplyDAO.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
package com.backery.backery_management.dao;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.List;

import com.backery.backery_management.model.Reply;

public class ReplyDAO {
private final String filePath = "data/replies.txt";
private final DateTimeFormatter formatter = DateTimeFormatter.ISO_LOCAL_DATE_TIME;

public List<Reply> getRepliesByReviewId(int reviewId) {
List<Reply> replies = new ArrayList<>();
File file = new File(filePath);
try {
if (!file.exists()) {
file.getParentFile().mkdirs();
file.createNewFile();
return replies;
}
try (BufferedReader reader = new BufferedReader(new FileReader(filePath))) {
String line;
while ((line = reader.readLine()) != null) {
if (line.trim().isEmpty()) {
continue;
}
String[] parts = line.split(",");
if (parts.length >= 5) {
int id = Integer.parseInt(parts[0].trim());
int revId = Integer.parseInt(parts[1].trim());
if (revId == reviewId) {
String adminName = parts[2].trim();
String comment = parts[3].trim();
LocalDateTime createdAt = LocalDateTime.parse(parts[4].trim(), formatter);
replies.add(new Reply(id, revId, adminName, comment, createdAt));
}
}
}
}
} catch (IOException e) {
e.printStackTrace();
}
return replies;
}

public boolean addReply(Reply reply) {
try {
File file = new File(filePath);
if (!file.exists()) {
file.getParentFile().mkdirs();
file.createNewFile();
}

List<Reply> replies = getAllReplies();
int newId = replies.isEmpty() ? 1 : replies.get(replies.size() - 1).getId() + 1;
reply.setId(newId);
reply.setCreatedAt(LocalDateTime.now());

try (BufferedWriter writer = new BufferedWriter(new FileWriter(filePath, true))) {
writer.write(String.format("%d,%d,%s,%s,%s%n",
reply.getId(),
reply.getReviewId(),
reply.getAdminName(),
reply.getComment(),
reply.getCreatedAt().format(formatter)));
}
return true;
} catch (IOException e) {
e.printStackTrace();
return false;
}
}

private List<Reply> getAllReplies() {
List<Reply> replies = new ArrayList<>();
File file = new File(filePath);
try {
if (!file.exists()) {
return replies;
}
try (BufferedReader reader = new BufferedReader(new FileReader(filePath))) {
String line;
while ((line = reader.readLine()) != null) {
if (line.trim().isEmpty()) {
continue;
}
String[] parts = line.split(",");
if (parts.length >= 5) {
int id = Integer.parseInt(parts[0].trim());
int reviewId = Integer.parseInt(parts[1].trim());
String adminName = parts[2].trim();
String comment = parts[3].trim();
LocalDateTime createdAt = LocalDateTime.parse(parts[4].trim(), formatter);
replies.add(new Reply(id, reviewId, adminName, comment, createdAt));
}
}
}
} catch (IOException e) {
e.printStackTrace();
}
return replies;
}

public boolean deleteRepliesByReviewId(int reviewId) {
try {
List<Reply> allReplies = getAllReplies();
List<Reply> remainingReplies = allReplies.stream()
.filter(reply -> reply.getReviewId() != reviewId)
.toList();

// Write remaining replies back to file
try (BufferedWriter writer = new BufferedWriter(new FileWriter(filePath))) {
for (Reply reply : remainingReplies) {
writer.write(String.format("%d,%d,%s,%s,%s%n",
reply.getId(),
reply.getReviewId(),
reply.getAdminName(),
reply.getComment(),
reply.getCreatedAt().format(formatter)));
}
}
return true;
} catch (IOException e) {
e.printStackTrace();
return false;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,7 @@ public Review getReviewById(int reviewId) {
.orElse(null);
}

private List<Review> getAllReviews() {
public List<Review> getAllReviews() {
List<Review> reviews = new ArrayList<>();
File file = new File(filePath);
try {
Expand Down
Loading