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
53 changes: 53 additions & 0 deletions src/main/java/videoshop/catalog/CatalogController.java
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,16 @@
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;

// ------------------------------------------------------------
// imports for price sorting
// ------------------------------------------------------------
import org.springframework.web.bind.annotation.RequestParam;
import java.math.BigDecimal;
import java.util.Comparator;
import java.util.List;
import java.util.stream.StreamSupport;
// ------------------------------------------------------------

@Controller
class CatalogController {

Expand Down Expand Up @@ -97,6 +107,49 @@ public String comment(@PathVariable Disc disc, @Valid CommentAndRating form, Err

return "redirect:/disc/" + disc.getId();
}
// -----------------------------------------------------
// tiny helpers to sort by price
// --------------------------------------------------------

/** Return price as BigDecimal so we can compare easily. */
private static BigDecimal getFilmPrice(Disc film) {
return film.getPrice().getNumber().numberValueExact(BigDecimal.class);
}

/** Sort any list of films by price, ascending or descending. */
private static List<Disc> sortFilmsByPrice(Iterable<Disc> films, boolean ascending) {
var stream = StreamSupport.stream(films.spliterator(), false);
var comparator = Comparator.comparing(CatalogController::getFilmPrice);
return stream.sorted(ascending ? comparator : comparator.reversed()).toList();
}

// ------------------------------------------------------------
// ONE unified route – sorts ALL films by price (no type distinction = all films)
// ------------------------------------------------------------
@GetMapping("/catalog/sort")
String sortWholeCatalogByPrice(
@RequestParam(name = "dir", defaultValue = "asc") String direction,
Model model) {

// 1) Get ALL films (DVDs, Blurays, alles zusammen)
var allFilms = catalog.findAll();

// 2) Determine direction (default: ascending)
var ascending = !("desc".equalsIgnoreCase(direction));

// 3) Sort
var sorted = sortFilmsByPrice(allFilms, ascending);

// 4) Hand over to the same template
model.addAttribute("catalog", sorted);
// i18n key = a translation key used to show text in different languages, just in case for language options
model.addAttribute("title", "All films (sorted by price)");
model.addAttribute("sort", "price");
model.addAttribute("dir", ascending ? "asc" : "desc");

return "catalog";
}
// ----------------------------------------------

/**
* Describes the payload to be expected to add a comment.
Expand Down
85 changes: 58 additions & 27 deletions src/main/resources/templates/catalog.html
Original file line number Diff line number Diff line change
@@ -1,33 +1,64 @@
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org"
<html lang="en"
xmlns:th="http://www.thymeleaf.org"
xmlns:sec="http://www.thymeleaf.org/extras/spring-security"
xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
layout:decorate="~{layout.html(title=#{${title}})}">
<head>
</head>
<body>
<header>
<h1 th:text="#{${title}}">Katalog</h1>
</header>
<nav th:insert="~{navigation :: navigation}"></nav>
<section layout:fragment="content">
<div class="ui link cards" th:remove="all-but-first">
<div class="ui card" th:each="disc : ${catalog}">
<div class="content">
<a class="header" th:href="@{/disc/{id}(id=${disc.id})}" th:text="${disc.name}">Last Action Hero</a>
</div>
<div class="image">
<a th:href="@{/disc/{id}(id=${disc.id})}">
<img class="thumbnail" th:src="@{/resources/img/cover/{image}.jpg(image=${disc.image})}"
src="../static/resources/img/cover/lac.jpg"/>
</a>
</div>
<div class="content">
<div class="description" th:text="${{disc.price}}">9.99 €</div>
</div>
<div class="extra content" th:text="${disc.genre}"> Action</div>
layout:decorate="~{layout.html(title=${title})}">
<head></head>
<body>
<header>
<h1 th:text="${title}">Catalog</h1>
</header>

<nav th:insert="~{navigation :: navigation}"></nav>

<section layout:fragment="content">


<div class="ui segment" style="margin-bottom: 1.5rem;">
<strong>Sort by price:</strong>
<div class="ui buttons" style="margin-left:.75rem;">
<a class="ui button"
th:href="@{'/catalog/sort?dir=asc'}"
th:classappend="${dir == 'asc' or dir == null ? ' primary' : ''}">
💰 Low → High
</a>
<div class="or" data-text="or"></div>
<a class="ui button"
th:href="@{'/catalog/sort?dir=desc'}"
th:classappend="${dir == 'desc' ? ' primary' : ''}">
💰 High → Low
</a>
</div>
</div>


<div class="ui link cards" th:remove="all-but-first">
<div class="ui card" th:each="disc : ${catalog}">
<div class="content">
<a class="header"
th:href="@{/disc/{id}(id=${disc.id})}"
th:text="${disc.name}">
Movie Title
</a>
</div>

<div class="image">
<a th:href="@{/disc/{id}(id=${disc.id})}">
<img class="thumbnail"
th:src="@{/resources/img/cover/{image}.jpg(image=${disc.image})}"
src="../static/resources/img/cover/lac.jpg" />
</a>
</div>

<div class="content">
<div class="description" th:text="${{disc.price}}">9.99 €</div>
</div>

<div class="extra content" th:text="${disc.genre}">Action</div>
</div>
</section>
</body>
</div>

</section>
</body>
</html>