Skip to content
Merged
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
26 changes: 26 additions & 0 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -56,5 +56,31 @@
<version>2.17.1</version>
</dependency>

<!-- JavaFX -->
<dependency>
<groupId>org.openjfx</groupId>
<artifactId>javafx-controls</artifactId>
<version>21</version>
</dependency>
<dependency>
<groupId>org.openjfx</groupId>
<artifactId>javafx-fxml</artifactId>
<version>21</version>
</dependency>

</dependencies>

<build>
<plugins>
<plugin>
<groupId>org.openjfx</groupId>
<artifactId>javafx-maven-plugin</artifactId>
<version>0.0.8</version>
<configuration>
<mainClass>org.example.ui.MainApp</mainClass>
</configuration>
</plugin>
</plugins>
</build>

</project>
1 change: 1 addition & 0 deletions src/main/java/org/example/App.java
Original file line number Diff line number Diff line change
Expand Up @@ -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");
Expand Down
5 changes: 5 additions & 0 deletions src/main/java/org/example/dto/MovieDetailsDTO.java
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ public class MovieDetailsDTO {
private String title;
private String release_date;
private int runtime;
private String poster_path;
private List<GenreDTO> genres;

public int getId() {
Expand All @@ -28,6 +29,10 @@ public int getRuntime() {
return runtime;
}

public String getPoster_path() {
return poster_path;
}

public List<GenreDTO> getGenres() {
return genres;
}
Expand Down
33 changes: 33 additions & 0 deletions src/main/java/org/example/dto/UiMovieDTO.java
Original file line number Diff line number Diff line change
@@ -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;
}
}

11 changes: 11 additions & 0 deletions src/main/java/org/example/movie/entity/Movie.java
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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;
}




Expand Down
16 changes: 14 additions & 2 deletions src/main/java/org/example/service/MovieImportService.java
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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()
Expand All @@ -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
25 changes: 17 additions & 8 deletions src/main/java/org/example/service/MovieService.java
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -99,5 +106,7 @@ public void importMovieWithTransaction(Runnable action) {
}
}



}

38 changes: 38 additions & 0 deletions src/main/java/org/example/ui/DbMovieDataSource.java
Original file line number Diff line number Diff line change
@@ -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<UiMovieDTO> 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
43 changes: 43 additions & 0 deletions src/main/java/org/example/ui/MainApp.java
Original file line number Diff line number Diff line change
@@ -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
91 changes: 91 additions & 0 deletions src/main/java/org/example/ui/MainController.java
Original file line number Diff line number Diff line change
@@ -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)
16 changes: 16 additions & 0 deletions src/main/java/org/example/ui/MovieDataSource.java
Original file line number Diff line number Diff line change
@@ -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<UiMovieDTO> getMovies();

}

//3️⃣ MovieDataSource.java
//Ansvar: Abstraktion – UI bryr sig inte om var datan kommer ifrån
Loading