diff --git a/.gitignore b/.gitignore index de1517dd..94d8f6c0 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,3 @@ ordering-site/* ordering_site/ -counter/ \ No newline at end of file +counter-frontend/ \ No newline at end of file diff --git a/backend/src/main/java/com/rit/canteen/sales/controller/BaseItemController.java b/backend/src/main/java/com/rit/canteen/sales/controller/BaseItemController.java index 19f6498a..90275287 100644 --- a/backend/src/main/java/com/rit/canteen/sales/controller/BaseItemController.java +++ b/backend/src/main/java/com/rit/canteen/sales/controller/BaseItemController.java @@ -7,8 +7,6 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.*; -import java.util.List; - @RestController @RequestMapping("/api/base-items") public class BaseItemController { @@ -18,8 +16,12 @@ public class BaseItemController { @GetMapping public org.springframework.data.domain.Page getAllBaseItems( + @RequestParam(required = false) String search, @RequestParam(defaultValue = "0") int page, @RequestParam(defaultValue = "10") int size) { + if (search != null && !search.isEmpty()) { + return baseItemRepository.findByNameContainingIgnoreCase(search, org.springframework.data.domain.PageRequest.of(page, size)); + } return baseItemRepository.findAll(org.springframework.data.domain.PageRequest.of(page, size)); } diff --git a/backend/src/main/java/com/rit/canteen/sales/controller/OrderController.java b/backend/src/main/java/com/rit/canteen/sales/controller/OrderController.java index 3cc7a299..e69f583a 100644 --- a/backend/src/main/java/com/rit/canteen/sales/controller/OrderController.java +++ b/backend/src/main/java/com/rit/canteen/sales/controller/OrderController.java @@ -40,6 +40,7 @@ public class OrderController { @RequestParam(required = false) @DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME) LocalDateTime endDate, @RequestParam(required = false) String status, @RequestParam(required = false) String paymentType, + @RequestParam(required = false) String orderType, @RequestParam(required = false) String search, @RequestParam(defaultValue = "false") boolean archived, @RequestParam(defaultValue = "0") int page, @@ -66,6 +67,9 @@ public class OrderController { if (paymentType != null && !paymentType.isEmpty()) { predicates.add(cb.equal(root.get("paymentMethod"), paymentType)); } + if (orderType != null && !orderType.isEmpty()) { + predicates.add(cb.equal(root.get("orderType"), orderType)); + } if (search != null && !search.isEmpty()) { String searchLower = "%" + search.toLowerCase() + "%"; Join userJoin = root.join("user", JoinType.LEFT); diff --git a/backend/src/main/java/com/rit/canteen/sales/controller/ProductController.java b/backend/src/main/java/com/rit/canteen/sales/controller/ProductController.java index 89c8aa7a..4596d822 100644 --- a/backend/src/main/java/com/rit/canteen/sales/controller/ProductController.java +++ b/backend/src/main/java/com/rit/canteen/sales/controller/ProductController.java @@ -18,8 +18,12 @@ public class ProductController { @GetMapping public org.springframework.data.domain.Page getAllProducts( + @RequestParam(required = false) String search, @RequestParam(defaultValue = "0") int page, @RequestParam(defaultValue = "10") int size) { + if (search != null && !search.isEmpty()) { + return productRepository.findByNameOrCategoryContainingIgnoreCase(search, org.springframework.data.domain.PageRequest.of(page, size)); + } return productRepository.findAllWithStalls(org.springframework.data.domain.PageRequest.of(page, size)); } diff --git a/backend/src/main/java/com/rit/canteen/sales/controller/UserController.java b/backend/src/main/java/com/rit/canteen/sales/controller/UserController.java index 31f9f4d2..f3142965 100644 --- a/backend/src/main/java/com/rit/canteen/sales/controller/UserController.java +++ b/backend/src/main/java/com/rit/canteen/sales/controller/UserController.java @@ -108,9 +108,10 @@ public class UserController { */ @GetMapping("/users") public ResponseEntity> getAllUsers( + @RequestParam(required = false) String search, @RequestParam(defaultValue = "0") int page, @RequestParam(defaultValue = "10") int size) { - Page users = userService.getAllUsers(PageRequest.of(page, size)); + Page users = userService.getAllUsers(search, PageRequest.of(page, size)); return ResponseEntity.ok(users); } diff --git a/backend/src/main/java/com/rit/canteen/sales/counter/config/CounterDataLoader.java b/backend/src/main/java/com/rit/canteen/sales/counter/config/CounterDataLoader.java new file mode 100644 index 00000000..b1e972e2 --- /dev/null +++ b/backend/src/main/java/com/rit/canteen/sales/counter/config/CounterDataLoader.java @@ -0,0 +1,53 @@ +package com.rit.canteen.sales.counter.config; + +import com.rit.canteen.sales.counter.model.CounterCategory; +import com.rit.canteen.sales.counter.model.CounterProduct; +import com.rit.canteen.sales.counter.repository.CounterCategoryRepository; +import com.rit.canteen.sales.counter.repository.CounterProductRepository; +import org.springframework.boot.CommandLineRunner; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +import java.util.Arrays; +import java.util.List; + +@Configuration +public class CounterDataLoader { + + @Bean + CommandLineRunner initCounterDatabase(CounterCategoryRepository categoryRepository, CounterProductRepository productRepository) { + return args -> { + if (categoryRepository.count() == 0) { + CounterCategory iceCream = categoryRepository.save(new CounterCategory("ICE CREAM")); + CounterCategory biscuit = categoryRepository.save(new CounterCategory("BISCUIT")); + CounterCategory juice = categoryRepository.save(new CounterCategory("READYMADE JUICE")); + CounterCategory chocolate = categoryRepository.save(new CounterCategory("CHOCOLATE")); + CounterCategory snacks = categoryRepository.save(new CounterCategory("SNACKS")); + CounterCategory bakery = categoryRepository.save(new CounterCategory("BAKERY")); + + List products = Arrays.asList( + new CounterProduct("CM BUTTER SCOTCH CONE", 40.0, 47, iceCream), + new CounterProduct("CM CHOCOLATE CONE", 50.0, 24, iceCream), + new CounterProduct("CM COOKIES AND CREAM", 50.0, 58, iceCream), + new CounterProduct("CM SIPUP CHOCOLATE", 10.0, 111, iceCream), + new CounterProduct("CM SIPUP STRAWBERRY", 10.0, 118, iceCream), + new CounterProduct("CM SIPUP PINEAPPLE", 10.0, 120, iceCream), + new CounterProduct("CM VANILLA CUP", 10.0, 31, iceCream), + new CounterProduct("CM PINE APPLE STICK ICE", 10.0, 25, iceCream), + new CounterProduct("CM MINI VANILLA CONE", 20.0, 128, iceCream), + new CounterProduct("CM PISTA STICK ICE", 20.0, 25, iceCream), + new CounterProduct("CM BALL ICE CREAM", 20.0, 18, iceCream), + new CounterProduct("CM CHOCOBAR WITH POUCH", 30.0, 100, iceCream), + new CounterProduct("CM DILSE BUTTER/CHOCO", 30.0, 18, iceCream), + new CounterProduct("CM DILSE REDVEL/VANILLA", 40.0, 20, iceCream), + new CounterProduct("CM SIPUP PISTA", 10.0, 118, iceCream), + new CounterProduct("COCONUT ICE CREAM", 45.0, 30, iceCream), + new CounterProduct("Coke", 25.0, 100, juice) + ); + productRepository.saveAll(products); + + System.out.println("Counter Database seeded with initial categories and products."); + } + }; + } +} diff --git a/backend/src/main/java/com/rit/canteen/sales/counter/config/CounterWebConfig.java b/backend/src/main/java/com/rit/canteen/sales/counter/config/CounterWebConfig.java new file mode 100644 index 00000000..ce54e4cf --- /dev/null +++ b/backend/src/main/java/com/rit/canteen/sales/counter/config/CounterWebConfig.java @@ -0,0 +1,31 @@ +package com.rit.canteen.sales.counter.config; + +import org.springframework.context.annotation.Configuration; +import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; + +import java.nio.file.Path; +import java.nio.file.Paths; + +@Configuration +public class CounterWebConfig implements WebMvcConfigurer { + + @Override + public void addResourceHandlers(ResourceHandlerRegistry registry) { + Path uploadDir = Paths.get("uploads").toAbsolutePath().normalize(); + + // Ensure the directory exists + try { + if (!java.nio.file.Files.exists(uploadDir)) { + java.nio.file.Files.createDirectories(uploadDir); + } + } catch (java.io.IOException e) { + System.err.println("Could not create uploads directory: " + e.getMessage()); + } + + String uploadPath = uploadDir.toUri().toString(); + + registry.addResourceHandler("/uploads/**") + .addResourceLocations(uploadPath); + } +} diff --git a/backend/src/main/java/com/rit/canteen/sales/counter/controller/CounterCategoryController.java b/backend/src/main/java/com/rit/canteen/sales/counter/controller/CounterCategoryController.java new file mode 100644 index 00000000..ebf16bfe --- /dev/null +++ b/backend/src/main/java/com/rit/canteen/sales/counter/controller/CounterCategoryController.java @@ -0,0 +1,23 @@ +package com.rit.canteen.sales.counter.controller; + +import com.rit.canteen.sales.model.BaseItem; +import com.rit.canteen.sales.repository.BaseItemRepository; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +@RestController +@RequestMapping("/api/counter/categories") +public class CounterCategoryController { + + @Autowired + private BaseItemRepository baseItemRepository; + + @GetMapping + public List getAllCategories() { + return baseItemRepository.findAll(); + } + + // Management endpoints are disabled for the counter billing dashboard +} diff --git a/backend/src/main/java/com/rit/canteen/sales/counter/controller/CounterImageUploadController.java b/backend/src/main/java/com/rit/canteen/sales/counter/controller/CounterImageUploadController.java new file mode 100644 index 00000000..773b0056 --- /dev/null +++ b/backend/src/main/java/com/rit/canteen/sales/counter/controller/CounterImageUploadController.java @@ -0,0 +1,53 @@ +package com.rit.canteen.sales.counter.controller; + +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; +import org.springframework.web.multipart.MultipartFile; + +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.nio.file.StandardCopyOption; +import java.util.Map; +import java.util.UUID; + +@RestController +@RequestMapping("/api/counter/upload") +public class CounterImageUploadController { + + private static final String UPLOAD_DIR = "uploads/products"; + + @PostMapping + public ResponseEntity uploadImage(@RequestParam("file") MultipartFile file) { + if (file.isEmpty()) { + return ResponseEntity.badRequest().body(Map.of("error", "No file selected")); + } + + try { + // Create uploads directory if it doesn't exist + Path uploadPath = Paths.get(UPLOAD_DIR).toAbsolutePath().normalize(); + Files.createDirectories(uploadPath); + + // Generate unique filename to prevent collisions + String originalFilename = file.getOriginalFilename(); + String extension = ""; + if (originalFilename != null && originalFilename.contains(".")) { + extension = originalFilename.substring(originalFilename.lastIndexOf(".")); + } + String uniqueFilename = UUID.randomUUID().toString() + extension; + + // Save the file + Path filePath = uploadPath.resolve(uniqueFilename); + Files.copy(file.getInputStream(), filePath, StandardCopyOption.REPLACE_EXISTING); + + // Return the URL path that the frontend can use + String imageUrl = "/uploads/products/" + uniqueFilename; + + return ResponseEntity.ok(Map.of("imageUrl", imageUrl)); + } catch (IOException e) { + return ResponseEntity.internalServerError() + .body(Map.of("error", "Failed to upload image: " + e.getMessage())); + } + } +} diff --git a/backend/src/main/java/com/rit/canteen/sales/counter/controller/CounterInfoController.java b/backend/src/main/java/com/rit/canteen/sales/counter/controller/CounterInfoController.java new file mode 100644 index 00000000..a6698f9d --- /dev/null +++ b/backend/src/main/java/com/rit/canteen/sales/counter/controller/CounterInfoController.java @@ -0,0 +1,47 @@ +package com.rit.canteen.sales.counter.controller; + +import com.rit.canteen.sales.counter.model.CounterInfo; +import com.rit.canteen.sales.counter.service.CounterInfoService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +@RestController +@RequestMapping("/api/counter/counters") +public class CounterInfoController { + + @Autowired + private CounterInfoService counterService; + + @GetMapping + public List getAllCounters() { + return counterService.getAllCounters(); + } + + @GetMapping("/{id}") + public CounterInfo getCounterById(@PathVariable Long id) { + return counterService.getCounterById(id) + .orElseThrow(() -> new RuntimeException("Counter not found")); + } + + @PostMapping + public CounterInfo createCounter(@RequestBody CounterInfo counter) { + return counterService.createCounter(counter); + } + + @PutMapping("/{id}") + public CounterInfo updateCounter(@PathVariable Long id, @RequestBody CounterInfo counter) { + return counterService.updateCounter(id, counter); + } + + @DeleteMapping("/{id}") + public void deleteCounter(@PathVariable Long id) { + counterService.deleteCounter(id); + } + + @PostMapping("/{counterId}/assign-product/{productId}") + public void assignProduct(@PathVariable Long counterId, @PathVariable Long productId) { + counterService.assignProductToCounter(counterId, productId); + } +} diff --git a/backend/src/main/java/com/rit/canteen/sales/counter/controller/CounterOrderController.java b/backend/src/main/java/com/rit/canteen/sales/counter/controller/CounterOrderController.java new file mode 100644 index 00000000..b5963151 --- /dev/null +++ b/backend/src/main/java/com/rit/canteen/sales/counter/controller/CounterOrderController.java @@ -0,0 +1,50 @@ +package com.rit.canteen.sales.counter.controller; + +import com.rit.canteen.sales.model.Order; +import com.rit.canteen.sales.counter.service.CounterOrderService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +@RestController +@RequestMapping("/api/counter/orders") +public class CounterOrderController { + + @Autowired + private CounterOrderService orderService; + + @GetMapping + public List getAllOrders() { + return orderService.getAllOrders(); + } + + @GetMapping("/{id}") + public ResponseEntity getOrderById(@PathVariable Long id) { + return orderService.getOrderById(id) + .map(ResponseEntity::ok) + .orElse(ResponseEntity.notFound().build()); + } + + @PostMapping + public Order createOrder(@RequestBody Order order) { + return orderService.createOrder(order); + } + + @PutMapping("/{id}") + public ResponseEntity updateOrder(@PathVariable Long id, @RequestBody Order orderDetails) { + try { + Order updatedOrder = orderService.updateOrder(id, orderDetails); + return ResponseEntity.ok(updatedOrder); + } catch (RuntimeException e) { + return ResponseEntity.notFound().build(); + } + } + + @DeleteMapping("/{id}") + public ResponseEntity deleteOrder(@PathVariable Long id) { + orderService.deleteOrder(id); + return ResponseEntity.ok().build(); + } +} diff --git a/backend/src/main/java/com/rit/canteen/sales/counter/controller/CounterProductController.java b/backend/src/main/java/com/rit/canteen/sales/counter/controller/CounterProductController.java new file mode 100644 index 00000000..a53d8bfb --- /dev/null +++ b/backend/src/main/java/com/rit/canteen/sales/counter/controller/CounterProductController.java @@ -0,0 +1,28 @@ +package com.rit.canteen.sales.counter.controller; + +import com.rit.canteen.sales.model.Product; +import com.rit.canteen.sales.repository.ProductRepository; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +@RestController +@RequestMapping("/api/counter/products") +public class CounterProductController { + + @Autowired + private ProductRepository productRepository; + + @GetMapping + public List getAllProducts() { + return productRepository.findAll(); + } + + @GetMapping("/category/{categoryName}") + public List getProductsByCategory(@PathVariable String categoryName) { + return productRepository.findByCategory(categoryName); + } + + // Management endpoints are disabled for the counter billing dashboard +} diff --git a/backend/src/main/java/com/rit/canteen/sales/counter/model/CounterCategory.java b/backend/src/main/java/com/rit/canteen/sales/counter/model/CounterCategory.java new file mode 100644 index 00000000..23807f71 --- /dev/null +++ b/backend/src/main/java/com/rit/canteen/sales/counter/model/CounterCategory.java @@ -0,0 +1,51 @@ +package com.rit.canteen.sales.counter.model; + +import jakarta.persistence.*; +import java.util.List; + +@Entity +@Table(name = "counter_categories") +public class CounterCategory { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + @Column(nullable = false, unique = true) + private String name; + + @OneToMany(mappedBy = "category", cascade = CascadeType.ALL) + @com.fasterxml.jackson.annotation.JsonIgnore + private List products; + + public CounterCategory() { + } + + public CounterCategory(String name) { + this.name = name; + } + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public List getProducts() { + return products; + } + + public void setProducts(List products) { + this.products = products; + } +} diff --git a/backend/src/main/java/com/rit/canteen/sales/counter/model/CounterInfo.java b/backend/src/main/java/com/rit/canteen/sales/counter/model/CounterInfo.java new file mode 100644 index 00000000..2a4b166e --- /dev/null +++ b/backend/src/main/java/com/rit/canteen/sales/counter/model/CounterInfo.java @@ -0,0 +1,63 @@ +package com.rit.canteen.sales.counter.model; + +import jakarta.persistence.*; +import java.util.List; + +@Entity +@Table(name = "counter_info") +public class CounterInfo { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + @Column(nullable = false, unique = true) + private String name; + + @Column + private String location; + + @OneToMany(mappedBy = "counter") + @com.fasterxml.jackson.annotation.JsonIgnore + private List products; + + public CounterInfo() { + } + + public CounterInfo(String name, String location) { + this.name = name; + this.location = location; + } + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getLocation() { + return location; + } + + public void setLocation(String location) { + this.location = location; + } + + public List getProducts() { + return products; + } + + public void setProducts(List products) { + this.products = products; + } +} diff --git a/backend/src/main/java/com/rit/canteen/sales/counter/model/CounterOrder.java b/backend/src/main/java/com/rit/canteen/sales/counter/model/CounterOrder.java new file mode 100644 index 00000000..0fdb2348 --- /dev/null +++ b/backend/src/main/java/com/rit/canteen/sales/counter/model/CounterOrder.java @@ -0,0 +1,71 @@ +package com.rit.canteen.sales.counter.model; + +import jakarta.persistence.*; +import java.time.LocalDateTime; +import java.util.List; + +@Entity +@Table(name = "counter_orders") +public class CounterOrder { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + @OneToMany(cascade = CascadeType.ALL, orphanRemoval = true) + @JoinColumn(name = "order_id") + private List items; + + @Column(nullable = false) + private Double totalAmount; + + @Column(nullable = false) + private String status; + + @Column(name = "created_at") + private LocalDateTime createdAt; + + public CounterOrder() { + this.createdAt = LocalDateTime.now(); + } + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public List getItems() { + return items; + } + + public void setItems(List items) { + this.items = items; + } + + public Double getTotalAmount() { + return totalAmount; + } + + public void setTotalAmount(Double totalAmount) { + this.totalAmount = totalAmount; + } + + public String getStatus() { + return status; + } + + public void setStatus(String status) { + this.status = status; + } + + public LocalDateTime getCreatedAt() { + return createdAt; + } + + public void setCreatedAt(LocalDateTime createdAt) { + this.createdAt = createdAt; + } +} diff --git a/backend/src/main/java/com/rit/canteen/sales/counter/model/CounterOrderItem.java b/backend/src/main/java/com/rit/canteen/sales/counter/model/CounterOrderItem.java new file mode 100644 index 00000000..037dc7a8 --- /dev/null +++ b/backend/src/main/java/com/rit/canteen/sales/counter/model/CounterOrderItem.java @@ -0,0 +1,78 @@ +package com.rit.canteen.sales.counter.model; + +import jakarta.persistence.*; + +@Entity +@Table(name = "counter_order_items") +public class CounterOrderItem { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + @Column(name = "product_name", nullable = false) + private String productName; + + @Column(nullable = false) + private Integer quantity; + + @Column(name = "unit_price", nullable = false) + private Double unitPrice; + + @Column(name = "total_price", nullable = false) + private Double totalPrice; + + @Column(name = "product_id") + private Long productId; + + public CounterOrderItem() { + } + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public Long getProductId() { + return productId; + } + + public void setProductId(Long productId) { + this.productId = productId; + } + + public String getProductName() { + return productName; + } + + public void setProductName(String productName) { + this.productName = productName; + } + + public Integer getQuantity() { + return quantity; + } + + public void setQuantity(Integer quantity) { + this.quantity = quantity; + } + + public Double getUnitPrice() { + return unitPrice; + } + + public void setUnitPrice(Double unitPrice) { + this.unitPrice = unitPrice; + } + + public Double getTotalPrice() { + return totalPrice; + } + + public void setTotalPrice(Double totalPrice) { + this.totalPrice = totalPrice; + } +} diff --git a/backend/src/main/java/com/rit/canteen/sales/counter/model/CounterProduct.java b/backend/src/main/java/com/rit/canteen/sales/counter/model/CounterProduct.java new file mode 100644 index 00000000..b8ea278f --- /dev/null +++ b/backend/src/main/java/com/rit/canteen/sales/counter/model/CounterProduct.java @@ -0,0 +1,109 @@ +package com.rit.canteen.sales.counter.model; + +import jakarta.persistence.*; + +@Entity +@Table(name = "counter_products") +public class CounterProduct { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + @Column(nullable = false) + private String name; + + @Column(nullable = false) + private Double price; + + @Column(nullable = false) + private Integer stock; + + @Column(columnDefinition = "TEXT") + private String description; + + @Column + private String imageUrl; + + @ManyToOne + @JoinColumn(name = "category_id") + private CounterCategory category; + + @ManyToOne + @JoinColumn(name = "counter_id") + private CounterInfo counter; + + public CounterProduct() { + } + + public CounterProduct(String name, Double price, Integer stock, CounterCategory category) { + this.name = name; + this.price = price; + this.stock = stock; + this.category = category; + } + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public Double getPrice() { + return price; + } + + public void setPrice(Double price) { + this.price = price; + } + + public Integer getStock() { + return stock; + } + + public void setStock(Integer stock) { + this.stock = stock; + } + + public String getDescription() { + return description; + } + + public void setDescription(String description) { + this.description = description; + } + + public String getImageUrl() { + return imageUrl; + } + + public void setImageUrl(String imageUrl) { + this.imageUrl = imageUrl; + } + + public CounterCategory getCategory() { + return category; + } + + public void setCategory(CounterCategory category) { + this.category = category; + } + + public CounterInfo getCounter() { + return counter; + } + + public void setCounter(CounterInfo counter) { + this.counter = counter; + } +} diff --git a/backend/src/main/java/com/rit/canteen/sales/counter/repository/CounterCategoryRepository.java b/backend/src/main/java/com/rit/canteen/sales/counter/repository/CounterCategoryRepository.java new file mode 100644 index 00000000..923395c1 --- /dev/null +++ b/backend/src/main/java/com/rit/canteen/sales/counter/repository/CounterCategoryRepository.java @@ -0,0 +1,12 @@ +package com.rit.canteen.sales.counter.repository; + +import com.rit.canteen.sales.counter.model.CounterCategory; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; + +import java.util.Optional; + +@Repository +public interface CounterCategoryRepository extends JpaRepository { + Optional findByName(String name); +} diff --git a/backend/src/main/java/com/rit/canteen/sales/counter/repository/CounterInfoRepository.java b/backend/src/main/java/com/rit/canteen/sales/counter/repository/CounterInfoRepository.java new file mode 100644 index 00000000..9097b0ef --- /dev/null +++ b/backend/src/main/java/com/rit/canteen/sales/counter/repository/CounterInfoRepository.java @@ -0,0 +1,12 @@ +package com.rit.canteen.sales.counter.repository; + +import com.rit.canteen.sales.counter.model.CounterInfo; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; + +import java.util.Optional; + +@Repository +public interface CounterInfoRepository extends JpaRepository { + Optional findByName(String name); +} diff --git a/backend/src/main/java/com/rit/canteen/sales/counter/repository/CounterOrderRepository.java b/backend/src/main/java/com/rit/canteen/sales/counter/repository/CounterOrderRepository.java new file mode 100644 index 00000000..1a60f8cc --- /dev/null +++ b/backend/src/main/java/com/rit/canteen/sales/counter/repository/CounterOrderRepository.java @@ -0,0 +1,13 @@ +package com.rit.canteen.sales.counter.repository; + +import com.rit.canteen.sales.counter.model.CounterOrder; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; + +import java.util.List; + +@Repository +public interface CounterOrderRepository extends JpaRepository { + List findByStatus(String status); + List findAllByOrderByCreatedAtDesc(); +} diff --git a/backend/src/main/java/com/rit/canteen/sales/counter/repository/CounterProductRepository.java b/backend/src/main/java/com/rit/canteen/sales/counter/repository/CounterProductRepository.java new file mode 100644 index 00000000..cd6918a6 --- /dev/null +++ b/backend/src/main/java/com/rit/canteen/sales/counter/repository/CounterProductRepository.java @@ -0,0 +1,14 @@ +package com.rit.canteen.sales.counter.repository; + +import com.rit.canteen.sales.counter.model.CounterCategory; +import com.rit.canteen.sales.counter.model.CounterProduct; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; + +import java.util.List; + +@Repository +public interface CounterProductRepository extends JpaRepository { + List findByCategoryName(String categoryName); + List findByCategory(CounterCategory category); +} diff --git a/backend/src/main/java/com/rit/canteen/sales/counter/service/CounterCategoryService.java b/backend/src/main/java/com/rit/canteen/sales/counter/service/CounterCategoryService.java new file mode 100644 index 00000000..3f6d3e70 --- /dev/null +++ b/backend/src/main/java/com/rit/canteen/sales/counter/service/CounterCategoryService.java @@ -0,0 +1,39 @@ +package com.rit.canteen.sales.counter.service; + +import com.rit.canteen.sales.counter.model.CounterCategory; +import com.rit.canteen.sales.counter.repository.CounterCategoryRepository; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.util.List; +import java.util.Optional; + +@Service +public class CounterCategoryService { + + @Autowired + private CounterCategoryRepository categoryRepository; + + public List getAllCategories() { + return categoryRepository.findAll(); + } + + public Optional getCategoryByName(String name) { + return categoryRepository.findByName(name); + } + + public CounterCategory createCategory(CounterCategory category) { + return categoryRepository.save(category); + } + + public CounterCategory updateCategory(Long id, CounterCategory categoryDetails) { + CounterCategory category = categoryRepository.findById(id) + .orElseThrow(() -> new RuntimeException("Category not found")); + category.setName(categoryDetails.getName()); + return categoryRepository.save(category); + } + + public void deleteCategory(Long id) { + categoryRepository.deleteById(id); + } +} diff --git a/backend/src/main/java/com/rit/canteen/sales/counter/service/CounterInfoService.java b/backend/src/main/java/com/rit/canteen/sales/counter/service/CounterInfoService.java new file mode 100644 index 00000000..176a6675 --- /dev/null +++ b/backend/src/main/java/com/rit/canteen/sales/counter/service/CounterInfoService.java @@ -0,0 +1,55 @@ +package com.rit.canteen.sales.counter.service; + +import com.rit.canteen.sales.counter.model.CounterInfo; +import com.rit.canteen.sales.counter.model.CounterProduct; +import com.rit.canteen.sales.counter.repository.CounterInfoRepository; +import com.rit.canteen.sales.counter.repository.CounterProductRepository; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.util.List; +import java.util.Optional; + +@Service +public class CounterInfoService { + + @Autowired + private CounterInfoRepository counterRepository; + + @Autowired + private CounterProductRepository productRepository; + + public List getAllCounters() { + return counterRepository.findAll(); + } + + public Optional getCounterById(Long id) { + return counterRepository.findById(id); + } + + public CounterInfo createCounter(CounterInfo counter) { + return counterRepository.save(counter); + } + + public CounterInfo updateCounter(Long id, CounterInfo counterDetails) { + CounterInfo counter = counterRepository.findById(id) + .orElseThrow(() -> new RuntimeException("Counter not found")); + counter.setName(counterDetails.getName()); + counter.setLocation(counterDetails.getLocation()); + return counterRepository.save(counter); + } + + public void deleteCounter(Long id) { + counterRepository.deleteById(id); + } + + public void assignProductToCounter(Long counterId, Long productId) { + CounterInfo counter = counterRepository.findById(counterId) + .orElseThrow(() -> new RuntimeException("Counter not found")); + CounterProduct product = productRepository.findById(productId) + .orElseThrow(() -> new RuntimeException("Product not found")); + + product.setCounter(counter); + productRepository.save(product); + } +} diff --git a/backend/src/main/java/com/rit/canteen/sales/counter/service/CounterOrderService.java b/backend/src/main/java/com/rit/canteen/sales/counter/service/CounterOrderService.java new file mode 100644 index 00000000..4dc94145 --- /dev/null +++ b/backend/src/main/java/com/rit/canteen/sales/counter/service/CounterOrderService.java @@ -0,0 +1,64 @@ +package com.rit.canteen.sales.counter.service; + +import com.rit.canteen.sales.model.Order; +import com.rit.canteen.sales.model.OrderItem; +import com.rit.canteen.sales.repository.OrderRepository; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.time.LocalDateTime; +import java.util.List; +import java.util.Optional; + +@Service +public class CounterOrderService { + + @Autowired + private OrderRepository orderRepository; + + @Autowired + private CounterProductService productService; + + public List getAllOrders() { + return orderRepository.findAll(); + } + + public Optional getOrderById(Long id) { + return orderRepository.findById(id); + } + + public Order createOrder(Order order) { + order.setCreatedAt(LocalDateTime.now()); + if (order.getStatus() == null) { + order.setStatus("COMPLETED"); + } + + // Ensure bidirectional relationship for items + if (order.getItems() != null) { + for (OrderItem item : order.getItems()) { + item.setOrder(order); + // Update stock if product ID is present + if (item.getProductId() != null) { + productService.updateStock(item.getProductId(), item.getQuantity()); + } + } + } + + return orderRepository.save(order); + } + + public Order updateOrder(Long id, Order orderDetails) { + Order order = orderRepository.findById(id) + .orElseThrow(() -> new RuntimeException("Order not found")); + + order.setItems(orderDetails.getItems()); + order.setTotalAmount(orderDetails.getTotalAmount()); + order.setStatus(orderDetails.getStatus()); + + return orderRepository.save(order); + } + + public void deleteOrder(Long id) { + orderRepository.deleteById(id); + } +} diff --git a/backend/src/main/java/com/rit/canteen/sales/counter/service/CounterProductService.java b/backend/src/main/java/com/rit/canteen/sales/counter/service/CounterProductService.java new file mode 100644 index 00000000..0ef04fbc --- /dev/null +++ b/backend/src/main/java/com/rit/canteen/sales/counter/service/CounterProductService.java @@ -0,0 +1,58 @@ +package com.rit.canteen.sales.counter.service; + +import com.rit.canteen.sales.counter.model.CounterProduct; +import com.rit.canteen.sales.counter.repository.CounterProductRepository; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.util.List; +import java.util.Optional; + +@Service +public class CounterProductService { + + @Autowired + private CounterProductRepository productRepository; + + public List getAllProducts() { + return productRepository.findAll(); + } + + public List getProductsByCategory(String categoryName) { + return productRepository.findByCategoryName(categoryName); + } + + public Optional getProductById(Long id) { + return productRepository.findById(id); + } + + public CounterProduct createProduct(CounterProduct product) { + return productRepository.save(product); + } + + public CounterProduct updateProduct(Long id, CounterProduct productDetails) { + CounterProduct product = productRepository.findById(id) + .orElseThrow(() -> new RuntimeException("Product not found")); + + product.setName(productDetails.getName()); + product.setPrice(productDetails.getPrice()); + product.setStock(productDetails.getStock()); + product.setDescription(productDetails.getDescription()); + product.setImageUrl(productDetails.getImageUrl()); + product.setCategory(productDetails.getCategory()); + product.setCounter(productDetails.getCounter()); + + return productRepository.save(product); + } + + public void deleteProduct(Long id) { + productRepository.deleteById(id); + } + + public CounterProduct updateStock(Long productId, Integer quantity) { + CounterProduct product = productRepository.findById(productId) + .orElseThrow(() -> new RuntimeException("Product not found")); + product.setStock(product.getStock() - quantity); + return productRepository.save(product); + } +} diff --git a/backend/src/main/java/com/rit/canteen/sales/model/BaseItem.java b/backend/src/main/java/com/rit/canteen/sales/model/BaseItem.java index 4dfe2e70..77173367 100644 --- a/backend/src/main/java/com/rit/canteen/sales/model/BaseItem.java +++ b/backend/src/main/java/com/rit/canteen/sales/model/BaseItem.java @@ -1,10 +1,6 @@ package com.rit.canteen.sales.model; -import jakarta.persistence.Entity; -import jakarta.persistence.GeneratedValue; -import jakarta.persistence.GenerationType; -import jakarta.persistence.Id; -import jakarta.persistence.Table; +import jakarta.persistence.*; import jakarta.validation.constraints.NotBlank; @Entity @@ -18,9 +14,11 @@ public class BaseItem { @NotBlank(message = "Item name is required") private String name; + @Column(columnDefinition = "TEXT") private String description; - private boolean active; + @Column(nullable = false) + private boolean active = true; public BaseItem() {} @@ -30,35 +28,15 @@ public class BaseItem { this.active = active; } - public Long getId() { - return id; - } + public Long getId() { return id; } + public void setId(Long id) { this.id = id; } - public void setId(Long id) { - this.id = id; - } + public String getName() { return name; } + public void setName(String name) { this.name = name; } - public String getName() { - return name; - } + public String getDescription() { return description; } + public void setDescription(String description) { this.description = description; } - public void setName(String name) { - this.name = name; - } - - public String getDescription() { - return description; - } - - public void setDescription(String description) { - this.description = description; - } - - public boolean isActive() { - return active; - } - - public void setActive(boolean active) { - this.active = active; - } + public boolean isActive() { return active; } + public void setActive(boolean active) { this.active = active; } } diff --git a/backend/src/main/java/com/rit/canteen/sales/model/DashboardStats.java b/backend/src/main/java/com/rit/canteen/sales/model/DashboardStats.java index ad4ccc32..d3014e9f 100644 --- a/backend/src/main/java/com/rit/canteen/sales/model/DashboardStats.java +++ b/backend/src/main/java/com/rit/canteen/sales/model/DashboardStats.java @@ -4,16 +4,17 @@ public class DashboardStats { private long totalSales; private int activeOrders; private int dailyCustomers; - private double revenueGrowth; + private double growth; - public DashboardStats(long totalSales, int activeOrders, int dailyCustomers, double revenueGrowth) { + public DashboardStats() {} + + public DashboardStats(long totalSales, int activeOrders, int dailyCustomers, double growth) { this.totalSales = totalSales; this.activeOrders = activeOrders; this.dailyCustomers = dailyCustomers; - this.revenueGrowth = revenueGrowth; + this.growth = growth; } - // Getters and Setters public long getTotalSales() { return totalSales; } public void setTotalSales(long totalSales) { this.totalSales = totalSales; } @@ -23,6 +24,6 @@ public class DashboardStats { public int getDailyCustomers() { return dailyCustomers; } public void setDailyCustomers(int dailyCustomers) { this.dailyCustomers = dailyCustomers; } - public double getRevenueGrowth() { return revenueGrowth; } - public void setRevenueGrowth(double revenueGrowth) { this.revenueGrowth = revenueGrowth; } + public double getGrowth() { return growth; } + public void setGrowth(double growth) { this.growth = growth; } } diff --git a/backend/src/main/java/com/rit/canteen/sales/model/GeneralDashboardData.java b/backend/src/main/java/com/rit/canteen/sales/model/GeneralDashboardData.java index 7e81e9cb..336b8f73 100644 --- a/backend/src/main/java/com/rit/canteen/sales/model/GeneralDashboardData.java +++ b/backend/src/main/java/com/rit/canteen/sales/model/GeneralDashboardData.java @@ -9,6 +9,8 @@ public class GeneralDashboardData { private List> hourlySales; private List insights; + public GeneralDashboardData() {} + public GeneralDashboardData(DashboardStats stats, List> storeOverview, List> hourlySales, List insights) { this.stats = stats; this.storeOverview = storeOverview; @@ -16,9 +18,15 @@ public class GeneralDashboardData { this.insights = insights; } - // Getters public DashboardStats getStats() { return stats; } + public void setStats(DashboardStats stats) { this.stats = stats; } + public List> getStoreOverview() { return storeOverview; } + public void setStoreOverview(List> storeOverview) { this.storeOverview = storeOverview; } + public List> getHourlySales() { return hourlySales; } + public void setHourlySales(List> hourlySales) { this.hourlySales = hourlySales; } + public List getInsights() { return insights; } + public void setInsights(List insights) { this.insights = insights; } } diff --git a/backend/src/main/java/com/rit/canteen/sales/model/Order.java b/backend/src/main/java/com/rit/canteen/sales/model/Order.java index 38bf2be1..efb0dc79 100644 --- a/backend/src/main/java/com/rit/canteen/sales/model/Order.java +++ b/backend/src/main/java/com/rit/canteen/sales/model/Order.java @@ -41,6 +41,9 @@ public class Order { @Column(nullable = false) private LocalDateTime createdAt; + @Column(nullable = false) + private String orderType = "STORE_ORDER"; // STORE_ORDER, QR_ORDER, MY_ORDER, etc. + @Column(name = "is_archived", nullable = false) private boolean isArchived = false; @@ -97,6 +100,9 @@ public class Order { public boolean isArchived() { return isArchived; } public void setArchived(boolean archived) { isArchived = archived; } + public String getOrderType() { return orderType; } + public void setOrderType(String orderType) { this.orderType = orderType; } + public List getItems() { return items; } public void setItems(List items) { this.items = items; } } diff --git a/backend/src/main/java/com/rit/canteen/sales/repository/BaseItemRepository.java b/backend/src/main/java/com/rit/canteen/sales/repository/BaseItemRepository.java index c4244749..2444d85a 100644 --- a/backend/src/main/java/com/rit/canteen/sales/repository/BaseItemRepository.java +++ b/backend/src/main/java/com/rit/canteen/sales/repository/BaseItemRepository.java @@ -1,10 +1,13 @@ package com.rit.canteen.sales.repository; import com.rit.canteen.sales.model.BaseItem; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.stereotype.Repository; @Repository public interface BaseItemRepository extends JpaRepository { boolean existsByName(String name); + Page findByNameContainingIgnoreCase(String name, Pageable pageable); } diff --git a/backend/src/main/java/com/rit/canteen/sales/repository/ProductRepository.java b/backend/src/main/java/com/rit/canteen/sales/repository/ProductRepository.java index 8be9ed06..39bbbf56 100644 --- a/backend/src/main/java/com/rit/canteen/sales/repository/ProductRepository.java +++ b/backend/src/main/java/com/rit/canteen/sales/repository/ProductRepository.java @@ -9,6 +9,11 @@ import java.util.List; @Repository public interface ProductRepository extends JpaRepository { + @Query("SELECT DISTINCT p FROM Product p LEFT JOIN FETCH p.stalls " + + "WHERE LOWER(p.name) LIKE LOWER(CONCAT('%', :search, '%')) " + + "OR LOWER(p.category) LIKE LOWER(CONCAT('%', :search, '%'))") + org.springframework.data.domain.Page findByNameOrCategoryContainingIgnoreCase(String search, org.springframework.data.domain.Pageable pageable); + @Query(value = "SELECT DISTINCT p FROM Product p LEFT JOIN FETCH p.stalls", countQuery = "SELECT count(p) FROM Product p") org.springframework.data.domain.Page findAllWithStalls(org.springframework.data.domain.Pageable pageable); diff --git a/backend/src/main/java/com/rit/canteen/sales/repository/UserRepository.java b/backend/src/main/java/com/rit/canteen/sales/repository/UserRepository.java index 4cecb491..a889760d 100644 --- a/backend/src/main/java/com/rit/canteen/sales/repository/UserRepository.java +++ b/backend/src/main/java/com/rit/canteen/sales/repository/UserRepository.java @@ -2,6 +2,7 @@ package com.rit.canteen.sales.repository; import com.rit.canteen.sales.model.User; import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; import org.springframework.stereotype.Repository; import java.util.Optional; @@ -10,4 +11,8 @@ import java.util.Optional; public interface UserRepository extends JpaRepository { Optional findByMobileNumber(String mobileNumber); boolean existsByMobileNumber(String mobileNumber); + + @Query("SELECT u FROM User u WHERE LOWER(u.name) LIKE LOWER(CONCAT('%', :search, '%')) " + + "OR u.mobileNumber LIKE CONCAT('%', :search, '%')") + org.springframework.data.domain.Page findByNameOrMobileContainingIgnoreCase(String search, org.springframework.data.domain.Pageable pageable); } diff --git a/backend/src/main/java/com/rit/canteen/sales/service/DashboardService.java b/backend/src/main/java/com/rit/canteen/sales/service/DashboardService.java index 2a1b3354..6cc62986 100644 --- a/backend/src/main/java/com/rit/canteen/sales/service/DashboardService.java +++ b/backend/src/main/java/com/rit/canteen/sales/service/DashboardService.java @@ -50,7 +50,7 @@ public class DashboardService { hourMap.put("value", 0); for (Object[] row : hourlyData) { - int h = (int) row[0]; + int h = ((Number) row[0]).intValue(); if (h >= i && h < i + 2) { BigDecimal val = (BigDecimal) row[1]; hourMap.put("value", ((Number) hourMap.get("value")).doubleValue() + val.doubleValue()); diff --git a/backend/src/main/java/com/rit/canteen/sales/service/UserService.java b/backend/src/main/java/com/rit/canteen/sales/service/UserService.java index 54a77206..dc4938ff 100644 --- a/backend/src/main/java/com/rit/canteen/sales/service/UserService.java +++ b/backend/src/main/java/com/rit/canteen/sales/service/UserService.java @@ -158,16 +158,22 @@ public class UserService { } /** - * Get all registered users for administration dashboard (Paginated). + * Get all registered users for administration dashboard (Paginated with Search). */ - public Page getAllUsers(Pageable pageable) { - return userRepository.findAll(pageable) - .map(user -> new LoginResponse.UserDto( - user.getId(), - user.getMobileNumber(), - user.getName(), - user.isLoggedIn() - )); + public Page getAllUsers(String search, Pageable pageable) { + Page users; + if (search != null && !search.isEmpty()) { + users = userRepository.findByNameOrMobileContainingIgnoreCase(search, pageable); + } else { + users = userRepository.findAll(pageable); + } + + return users.map(user -> new LoginResponse.UserDto( + user.getId(), + user.getMobileNumber(), + user.getName(), + user.isLoggedIn() + )); } /** diff --git a/frontend/src/pages/BaseMenu.tsx b/frontend/src/pages/BaseMenu.tsx index b7ca69fd..d425dba8 100644 --- a/frontend/src/pages/BaseMenu.tsx +++ b/frontend/src/pages/BaseMenu.tsx @@ -30,6 +30,7 @@ const BaseMenu = () => { const [currentPage, setCurrentPage] = useState(0); const [pageSize, setPageSize] = useState(10); const [totalElements, setTotalElements] = useState(0); + const [debouncedSearchTerm, setDebouncedSearchTerm] = useState(''); // Associated Products State const [selectedBaseItem, setSelectedBaseItem] = useState(null); @@ -39,9 +40,24 @@ const BaseMenu = () => { const menuRef = useRef(null); + // Debounce search term + useEffect(() => { + const timer = setTimeout(() => { + setDebouncedSearchTerm(searchTerm); + }, 500); + return () => clearTimeout(timer); + }, [searchTerm]); + + // Reset to first page when search changes + useEffect(() => { + setCurrentPage(0); + }, [debouncedSearchTerm]); + useEffect(() => { fetchItems(); - + }, [currentPage, pageSize, debouncedSearchTerm]); + + useEffect(() => { const handleClickOutside = (event: MouseEvent) => { if (menuRef.current && !menuRef.current.contains(event.target as Node)) { setOpenMenuId(null); @@ -49,13 +65,20 @@ const BaseMenu = () => { }; document.addEventListener('mousedown', handleClickOutside); return () => document.removeEventListener('mousedown', handleClickOutside); - }, [currentPage, pageSize]); + }, []); const fetchItems = async () => { setLoading(true); try { const host = window.location.hostname; - const response = await fetch(`http://${host}:8080/api/base-items?page=${currentPage}&size=${pageSize}`); + const params = new URLSearchParams(); + params.append('page', currentPage.toString()); + params.append('size', pageSize.toString()); + if (debouncedSearchTerm) { + params.append('search', debouncedSearchTerm); + } + + const response = await fetch(`http://${host}:8080/api/base-items?${params.toString()}`); const data = await response.json(); if (data && data.content) { setItems(data.content); @@ -200,17 +223,15 @@ const BaseMenu = () => { - ) : items.filter(item => item.name.toLowerCase().includes(searchTerm.toLowerCase())).length === 0 ? ( + ) : items.length === 0 ? (

No items found

-

Click "Add New Item" to create your first item.

+

Try adjusting your search or add a new item.

) : ( - items - .filter(item => item.name.toLowerCase().includes(searchTerm.toLowerCase())) - .map((item) => ( + items.map((item) => ( #{item.id} diff --git a/frontend/src/pages/Customers.tsx b/frontend/src/pages/Customers.tsx index 8fbfc04b..6385c6ec 100644 --- a/frontend/src/pages/Customers.tsx +++ b/frontend/src/pages/Customers.tsx @@ -19,6 +19,7 @@ const Customers: React.FC = () => { const [currentPage, setCurrentPage] = useState(0); const [pageSize, setPageSize] = useState(10); const [totalElements, setTotalElements] = useState(0); + const [debouncedSearchTerm, setDebouncedSearchTerm] = useState(''); // Edit Modal State const [showEditModal, setShowEditModal] = useState(false); @@ -34,15 +35,33 @@ const Customers: React.FC = () => { // Action Menu State const [openMenuId, setOpenMenuId] = useState(null); + useEffect(() => { + const timer = setTimeout(() => { + setDebouncedSearchTerm(searchTerm); + }, 500); + return () => clearTimeout(timer); + }, [searchTerm]); + + useEffect(() => { + setCurrentPage(0); + }, [debouncedSearchTerm]); + useEffect(() => { fetchUsers(); - }, [currentPage, pageSize]); + }, [currentPage, pageSize, debouncedSearchTerm]); const fetchUsers = async () => { try { setIsLoading(true); const host = window.location.hostname; - const response = await fetch(`http://${host}:8080/api/auth/users?page=${currentPage}&size=${pageSize}`); + const params = new URLSearchParams(); + params.append('page', currentPage.toString()); + params.append('size', pageSize.toString()); + if (debouncedSearchTerm) { + params.append('search', debouncedSearchTerm); + } + + const response = await fetch(`http://${host}:8080/api/auth/users?${params.toString()}`); if (response.ok) { const data = await response.json(); if (data && data.content) { @@ -146,11 +165,6 @@ const Customers: React.FC = () => { return name.split(' ').map(n => n[0]).join('').toUpperCase().slice(0, 2); }; - const filteredUsers = users.filter(user => - user.name?.toLowerCase().includes(searchTerm.toLowerCase()) || - user.mobileNumber?.includes(searchTerm) - ); - return ( <> {/* Toast Notification - Moved outside animation trapping */} @@ -232,8 +246,8 @@ const Customers: React.FC = () => { - {filteredUsers.length > 0 ? ( - filteredUsers.map((user) => ( + {users.length > 0 ? ( + users.map((user) => (
@@ -300,7 +314,7 @@ const Customers: React.FC = () => {
) : (
- {filteredUsers.map(user => ( + {users.map(user => (