Feature/customer list view #4
@@ -0,0 +1,10 @@
|
||||
package com.example.customer;
|
||||
|
||||
import java.time.LocalDate;
|
||||
|
||||
/**
|
||||
* A customer record. This is a plain, immutable value type backed by
|
||||
* {@link CustomerService}'s in-memory dummy data, not a JPA entity.
|
||||
*/
|
||||
public record Customer(String name, String email, String company, String status, LocalDate customerSince) {
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
package com.example.customer;
|
||||
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.time.LocalDate;
|
||||
import java.util.List;
|
||||
|
||||
@Service
|
||||
public class CustomerService {
|
||||
|
||||
// TODO Replace with a real data source (e.g. a JPA-backed CustomerRepository) once
|
||||
// customers are no longer dummy data.
|
||||
private static final List<Customer> DUMMY_CUSTOMERS = List.of(
|
||||
new Customer("Alice Johnson", "alice.johnson@example.com", "Acme Corp", "Active",
|
||||
LocalDate.of(2019, 3, 12)),
|
||||
new Customer("Bob Smith", "bob.smith@example.com", "Globex Inc", "Active", LocalDate.of(2020, 7, 1)),
|
||||
new Customer("Carla Diaz", "carla.diaz@example.com", "Initech", "Inactive", LocalDate.of(2018, 11, 23)),
|
||||
new Customer("David Chen", "david.chen@example.com", "Umbrella Corp", "Prospect",
|
||||
LocalDate.of(2024, 1, 15)),
|
||||
new Customer("Elena Petrova", "elena.petrova@example.com", "Hooli", "Active", LocalDate.of(2021, 5, 30)),
|
||||
new Customer("Frank Müller", "frank.mueller@example.com", "Soylent Corp", "Inactive",
|
||||
LocalDate.of(2017, 9, 4)),
|
||||
new Customer("Grace Kim", "grace.kim@example.com", "Stark Industries", "Active",
|
||||
LocalDate.of(2022, 2, 18)),
|
||||
new Customer("Hassan Ali", "hassan.ali@example.com", "Wayne Enterprises", "Prospect",
|
||||
LocalDate.of(2025, 4, 9)),
|
||||
new Customer("Ingrid Nilsson", "ingrid.nilsson@example.com", "Wonka Industries", "Active",
|
||||
LocalDate.of(2016, 6, 21)),
|
||||
new Customer("Julien Moreau", "julien.moreau@example.com", "Cyberdyne Systems", "Inactive",
|
||||
LocalDate.of(2023, 10, 8)),
|
||||
new Customer("Katrin Bauer", "katrin.bauer@example.com", "Massive Dynamic", "Active",
|
||||
LocalDate.of(2020, 12, 3)),
|
||||
new Customer("Liam O'Connor", "liam.oconnor@example.com", "Aperture Science", "Prospect",
|
||||
LocalDate.of(2026, 1, 27)));
|
||||
|
||||
public List<Customer> list() {
|
||||
return DUMMY_CUSTOMERS;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
@NullMarked
|
||||
package com.example.customer;
|
||||
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
@@ -0,0 +1,42 @@
|
||||
package com.example.customer.ui;
|
||||
|
||||
import com.example.base.ui.ViewTitle;
|
||||
import com.example.customer.Customer;
|
||||
import com.example.customer.CustomerService;
|
||||
import com.vaadin.flow.component.grid.Grid;
|
||||
import com.vaadin.flow.component.orderedlayout.VerticalLayout;
|
||||
import com.vaadin.flow.router.Menu;
|
||||
import com.vaadin.flow.router.PageTitle;
|
||||
import com.vaadin.flow.router.Route;
|
||||
import jakarta.annotation.security.PermitAll;
|
||||
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.time.format.FormatStyle;
|
||||
|
||||
@Route(value = "customers")
|
||||
@PageTitle("Customers")
|
||||
@Menu(order = 1, icon = "vaadin:users", title = "Customers")
|
||||
@PermitAll
|
||||
class CustomerListView extends VerticalLayout {
|
||||
|
||||
final Grid<Customer> customerGrid;
|
||||
|
||||
CustomerListView(CustomerService customerService) {
|
||||
var dateFormatter = DateTimeFormatter.ofLocalizedDate(FormatStyle.MEDIUM).withLocale(getLocale());
|
||||
|
||||
customerGrid = new Grid<>();
|
||||
customerGrid.setItems(customerService.list());
|
||||
customerGrid.addColumn(Customer::name).setHeader("Name").setSortable(true);
|
||||
customerGrid.addColumn(Customer::email).setHeader("Email").setSortable(true);
|
||||
customerGrid.addColumn(Customer::company).setHeader("Company").setSortable(true);
|
||||
customerGrid.addColumn(Customer::status).setHeader("Status").setSortable(true);
|
||||
customerGrid.addColumn(customer -> dateFormatter.format(customer.customerSince()))
|
||||
.setHeader("Customer Since")
|
||||
.setSortable(true);
|
||||
customerGrid.setEmptyStateText("No customers found");
|
||||
customerGrid.setSizeFull();
|
||||
|
||||
setSizeFull();
|
||||
add(new ViewTitle("Customers"), customerGrid);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
@NullMarked
|
||||
package com.example.customer.ui;
|
||||
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
@@ -0,0 +1,31 @@
|
||||
package com.example.customer.ui;
|
||||
|
||||
import com.vaadin.browserless.SpringBrowserlessTest;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.security.test.context.support.WithMockUser;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.MOCK)
|
||||
@WithMockUser(roles = "USER")
|
||||
class CustomerListViewTest extends SpringBrowserlessTest {
|
||||
|
||||
@Test
|
||||
void grid_shows_all_dummy_customers() {
|
||||
var view = navigate(CustomerListView.class);
|
||||
|
||||
assertThat(test(view.customerGrid).size()).isEqualTo(12);
|
||||
}
|
||||
|
||||
@Test
|
||||
void grid_shows_customer_columns() {
|
||||
var view = navigate(CustomerListView.class);
|
||||
|
||||
assertThat(test(view.customerGrid).getCellText(0, 0)).isEqualTo("Alice Johnson");
|
||||
assertThat(test(view.customerGrid).getCellText(0, 1)).isEqualTo("alice.johnson@example.com");
|
||||
assertThat(test(view.customerGrid).getCellText(0, 2)).isEqualTo("Acme Corp");
|
||||
assertThat(test(view.customerGrid).getCellText(0, 3)).isEqualTo("Active");
|
||||
assertThat(test(view.customerGrid).getCellText(0, 4)).isNotEmpty();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user