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