From 75cd6aa8d06628d768370fd40af9ffd95dab714d Mon Sep 17 00:00:00 2001 From: Tatjana Date: Mon, 29 Dec 2025 18:53:22 +0100 Subject: [PATCH] Updates UI, app.java, javafx:run --- pom.xml | 26 ++++++ src/main/java/org/example/App.java | 1 + .../java/org/example/dto/MovieDetailsDTO.java | 5 + src/main/java/org/example/dto/UiMovieDTO.java | 33 +++++++ .../java/org/example/movie/entity/Movie.java | 11 +++ .../example/service/MovieImportService.java | 16 +++- .../org/example/service/MovieService.java | 25 +++-- .../org/example/ui/DbMovieDataSource.java | 38 ++++++++ src/main/java/org/example/ui/MainApp.java | 43 +++++++++ .../java/org/example/ui/MainController.java | 91 +++++++++++++++++++ .../java/org/example/ui/MovieDataSource.java | 16 ++++ src/main/resources/MainView.fxml | 47 ++++++++++ src/main/resources/images/no-poster.jpg | 0 13 files changed, 342 insertions(+), 10 deletions(-) create mode 100644 src/main/java/org/example/dto/UiMovieDTO.java create mode 100644 src/main/java/org/example/ui/DbMovieDataSource.java create mode 100644 src/main/java/org/example/ui/MainApp.java create mode 100644 src/main/java/org/example/ui/MainController.java create mode 100644 src/main/java/org/example/ui/MovieDataSource.java create mode 100644 src/main/resources/MainView.fxml create mode 100644 src/main/resources/images/no-poster.jpg diff --git a/pom.xml b/pom.xml index 26564b7..8d47e71 100644 --- a/pom.xml +++ b/pom.xml @@ -56,5 +56,31 @@ 2.17.1 + + + org.openjfx + javafx-controls + 21 + + + org.openjfx + javafx-fxml + 21 + + + + + + + org.openjfx + javafx-maven-plugin + 0.0.8 + + org.example.ui.MainApp + + + + + diff --git a/src/main/java/org/example/App.java b/src/main/java/org/example/App.java index d2fa71f..3a95508 100644 --- a/src/main/java/org/example/App.java +++ b/src/main/java/org/example/App.java @@ -28,6 +28,7 @@ public static void main(String[] args) { MovieImportService importService = new MovieImportService(new TmdbClient(), movieService); + // Inception //importService.importMovie(27205); //System.out.println("✅ TMDB-import klar"); diff --git a/src/main/java/org/example/dto/MovieDetailsDTO.java b/src/main/java/org/example/dto/MovieDetailsDTO.java index 77c44a6..df9ab00 100644 --- a/src/main/java/org/example/dto/MovieDetailsDTO.java +++ b/src/main/java/org/example/dto/MovieDetailsDTO.java @@ -10,6 +10,7 @@ public class MovieDetailsDTO { private String title; private String release_date; private int runtime; + private String poster_path; private List genres; public int getId() { @@ -28,6 +29,10 @@ public int getRuntime() { return runtime; } + public String getPoster_path() { + return poster_path; + } + public List getGenres() { return genres; } diff --git a/src/main/java/org/example/dto/UiMovieDTO.java b/src/main/java/org/example/dto/UiMovieDTO.java new file mode 100644 index 0000000..e01978e --- /dev/null +++ b/src/main/java/org/example/dto/UiMovieDTO.java @@ -0,0 +1,33 @@ +package org.example.dto; + +public class UiMovieDTO { + + private final Long id; + private final String title; + private final int releaseYear; + private final String posterPath; + + public UiMovieDTO(Long id, String title, int releaseYear, String posterPath) { + this.id = id; + this.title = title; + this.releaseYear = releaseYear; + this.posterPath = posterPath; + } + + public Long getId() { + return id; + } + + public String getTitle() { + return title; + } + + public int getReleaseYear() { + return releaseYear; + } + + public String getPosterPath() { + return posterPath; + } +} + diff --git a/src/main/java/org/example/movie/entity/Movie.java b/src/main/java/org/example/movie/entity/Movie.java index 7659c56..191ce69 100644 --- a/src/main/java/org/example/movie/entity/Movie.java +++ b/src/main/java/org/example/movie/entity/Movie.java @@ -18,6 +18,9 @@ public class Movie { private int releaseDate; + @Column(length = 500) + private String posterPath; + // Den säger att En film kan ha många roller-rader(skådisar, regissör osv) //Mini-sammanfattning //@OneToMany = en film har många roller @@ -75,6 +78,14 @@ public void setReleaseDate(int releaseDate) { this.releaseDate = releaseDate; } + public String getPosterPath() { + return posterPath; + } + + public void setPosterPath(String posterPath) { + this.posterPath = posterPath; + } + diff --git a/src/main/java/org/example/service/MovieImportService.java b/src/main/java/org/example/service/MovieImportService.java index 8242f9e..1d8f100 100644 --- a/src/main/java/org/example/service/MovieImportService.java +++ b/src/main/java/org/example/service/MovieImportService.java @@ -27,7 +27,8 @@ public void importMovie(int tmdbMovieId) { // 2️⃣ Skapa film var movie = movieService.createMovie( movieDto.getTitle(), - extractYear(movieDto.getRelease_date()) + extractYear(movieDto.getRelease_date()), + movieDto.getPoster_path() ); // 3️⃣ Skådespelare – MAX 10 @@ -65,7 +66,6 @@ private int extractYear(String releaseDate) { //import 20 top rated movies lägg till int limit 20 public void importTopRatedMovies(int limit) { - var response = tmdbClient.getTopRatedMovies(); response.getResults().stream() @@ -90,3 +90,15 @@ public void importTopRatedMovies(int limit) { //testkörning App.java //main() Alltid i App.java +//Och endast här ska du: +// +//prata med TmdbClient +// +//sätta limits +// +//mappa DTO → Entity +// +//kalla MovieService +// +//👉 UI ska aldrig anropa TMDB direkt +//👉 Repository ska aldrig veta om TMDB diff --git a/src/main/java/org/example/service/MovieService.java b/src/main/java/org/example/service/MovieService.java index adf0ca4..22fd096 100644 --- a/src/main/java/org/example/service/MovieService.java +++ b/src/main/java/org/example/service/MovieService.java @@ -25,15 +25,22 @@ public MovieService(MovieRepository movieRepo, } // 1) Skapa film - public Movie createMovie(String title, int releaseDate) { - - return movieRepo.findByTitleAndReleaseDate(title, releaseDate) - .orElseGet(() -> { - Movie movie = new Movie(title, releaseDate); - movieRepo.save(movie); - return movie; - }); + public Movie createMovie(String title, int year, String posterPath) { + Movie movie = new Movie(title, year); + movie.setPosterPath(posterPath); + movieRepo.save(movie); + return movie; } + //detta ändras till för att ha posters +// public Movie createMovie(String title, int releaseDate) { +// +// return movieRepo.findByTitleAndReleaseDate(title, releaseDate) +// .orElseGet(() -> { +// Movie movie = new Movie(title, releaseDate); +// movieRepo.save(movie); +// return movie; +// }); +// } // 2) Skapa person @@ -99,5 +106,7 @@ public void importMovieWithTransaction(Runnable action) { } } + + } diff --git a/src/main/java/org/example/ui/DbMovieDataSource.java b/src/main/java/org/example/ui/DbMovieDataSource.java new file mode 100644 index 0000000..518c410 --- /dev/null +++ b/src/main/java/org/example/ui/DbMovieDataSource.java @@ -0,0 +1,38 @@ +package org.example.ui; + +import org.example.dto.UiMovieDTO; +import org.example.repository.MovieRepository; + +import java.util.List; + + +public class DbMovieDataSource implements MovieDataSource { + + private final MovieRepository movieRepository; + + public DbMovieDataSource(MovieRepository movieRepository) { + this.movieRepository = movieRepository; + } + + @Override + public List getMovies() { + return movieRepository.findAll().stream() + .map(movie -> new UiMovieDTO( + movie.getId(), + movie.getTitle(), + movie.getReleaseDate(), + movie.getPosterPath() // ⭐ NU KOMMER DEN FRÅN DB + )) + .toList(); + } + + +} + + + + +//4️⃣ DbMovieDataSource.java +//Ansvar: Översätta JPA → DTO → UI +//👉 Detta är nyckeln +//👉 Här möts JPA och UI – men isolerat diff --git a/src/main/java/org/example/ui/MainApp.java b/src/main/java/org/example/ui/MainApp.java new file mode 100644 index 0000000..0f455db --- /dev/null +++ b/src/main/java/org/example/ui/MainApp.java @@ -0,0 +1,43 @@ +package org.example.ui; + +import javafx.application.Application; +import javafx.fxml.FXMLLoader; +import javafx.scene.Scene; +import javafx.stage.Stage; +import org.example.repository.MovieRepository; + +public class MainApp extends Application { + + @Override + public void start(Stage stage) throws Exception { + + MovieDataSource dataSource = + new DbMovieDataSource(new MovieRepository()); + + FXMLLoader loader = new FXMLLoader( + getClass().getResource("/MainView.fxml") + ); + + loader.setControllerFactory(type -> { + if (type == MainController.class) { + return new MainController(dataSource); + } + try { + return type.getDeclaredConstructor().newInstance(); + } catch (Exception e) { + throw new RuntimeException(e); + } + }); + + stage.setScene(new Scene(loader.load(), 1000, 700)); + stage.setTitle("🎬 Movie Database"); + stage.show(); + } + + public static void main(String[] args) { + launch(args); + } + +} +//1️⃣ MainApp.java +//Ansvar: Starta JavaFX och koppla ihop UI + datasource diff --git a/src/main/java/org/example/ui/MainController.java b/src/main/java/org/example/ui/MainController.java new file mode 100644 index 0000000..784ecf1 --- /dev/null +++ b/src/main/java/org/example/ui/MainController.java @@ -0,0 +1,91 @@ +package org.example.ui; + +import javafx.fxml.FXML; +import javafx.scene.control.Label; +import javafx.scene.image.Image; +import javafx.scene.image.ImageView; +import javafx.scene.layout.FlowPane; +import javafx.scene.layout.VBox; +import org.example.dto.UiMovieDTO; + +import java.io.InputStream; +import java.util.Objects; + +public class MainController { + + private final MovieDataSource dataSource; + + public MainController(MovieDataSource dataSource) { + this.dataSource = dataSource; + } + + @FXML + private FlowPane movieContainer; + + @FXML + public void initialize() { + dataSource.getMovies().forEach(movie -> + movieContainer.getChildren().add(createMovieCard(movie)) + ); + } + + // ========================= + // UI-KONSTANTER + // ========================= + + private static final String IMAGE_BASE_URL = "https://image.tmdb.org/t/p/w500"; + private static final double CARD_WIDTH = 160; + private static final double POSTER_HEIGHT = 220; + + // ========================= + // UI-BYGGARE + // ========================= + + private VBox createMovieCard(UiMovieDTO movie) { + + VBox card = new VBox(6); + card.setPrefWidth(CARD_WIDTH); + card.setStyle(""" + -fx-background-color: #1e1e1e; + -fx-padding: 6; + -fx-border-radius: 6; + -fx-background-radius: 6; + -fx-effect: dropshadow(gaussian, rgba(0,0,0,0.2), 8, 0, 0, 2); + """); + + // 🎞 Poster + ImageView poster = new ImageView(); + poster.setFitWidth(CARD_WIDTH - 12); + poster.setFitHeight(POSTER_HEIGHT); + poster.setPreserveRatio(false); + + String posterPath = movie.getPosterPath(); + InputStream placeholder = getClass().getResourceAsStream("/images/no-poster.jpg"); + + if (posterPath != null && !posterPath.isBlank()) { + poster.setImage(new Image(IMAGE_BASE_URL + posterPath, true)); + } else if (placeholder != null) { + poster.setImage(new Image(placeholder)); + } else { + // sista skyddet – ingen bild alls (UI kraschar inte) + poster.setImage(null); + } + + + // 🎬 Titel + Label title = new Label(movie.getTitle()); + title.setWrapText(true); + title.setStyle(""" + -fx-text-fill: white; + -fx-font-size: 12px; + -fx-font-weight: bold; + """); + + card.getChildren().addAll(poster, title); + return card; + } +} + +//2️⃣ MainController.java + +//Ansvar: UI-logik (visa filmer) diff --git a/src/main/java/org/example/ui/MovieDataSource.java b/src/main/java/org/example/ui/MovieDataSource.java new file mode 100644 index 0000000..dd0d694 --- /dev/null +++ b/src/main/java/org/example/ui/MovieDataSource.java @@ -0,0 +1,16 @@ +package org.example.ui; + +import org.example.dto.MovieDTO; +import org.example.dto.UiMovieDTO; + +import java.util.List; + + +public interface MovieDataSource { + + List getMovies(); + +} + +//3️⃣ MovieDataSource.java +//Ansvar: Abstraktion – UI bryr sig inte om var datan kommer ifrån diff --git a/src/main/resources/MainView.fxml b/src/main/resources/MainView.fxml new file mode 100644 index 0000000..86099a2 --- /dev/null +++ b/src/main/resources/MainView.fxml @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/main/resources/images/no-poster.jpg b/src/main/resources/images/no-poster.jpg new file mode 100644 index 0000000..e69de29