Implement video watched status display in frontend

This commit is contained in:
Chneemann 2024-09-13 20:53:06 +02:00
parent 95c0bc0e97
commit 90dca91f6d
7 changed files with 48 additions and 21 deletions

View file

@ -4,7 +4,7 @@ from .models import CustomUser
class UserSerializer(serializers.ModelSerializer): class UserSerializer(serializers.ModelSerializer):
class Meta: class Meta:
model = CustomUser model = CustomUser
fields = ["id", "username", "email", "liked_videos"] fields = ["id", "username", "email", "liked_videos", "watched_videos"]
class LikedVideosSerializer(serializers.ModelSerializer): class LikedVideosSerializer(serializers.ModelSerializer):

View file

@ -33,6 +33,7 @@
[movies]="movies" [movies]="movies"
[currentMovie]="currentMovie[0]?.id" [currentMovie]="currentMovie[0]?.id"
[favoriteMovies]="favoriteMovies" [favoriteMovies]="favoriteMovies"
[watchedMovies]="watchedMovies"
(currentMovieId)="currentMovieId($event)" (currentMovieId)="currentMovieId($event)"
></app-categories> ></app-categories>
} @else { } @else {

View file

@ -28,6 +28,7 @@ export class BrowseComponent implements OnInit {
@ViewChild(VideoPlayerComponent) videoPlayer!: VideoPlayerComponent; @ViewChild(VideoPlayerComponent) videoPlayer!: VideoPlayerComponent;
movies: any[] = []; movies: any[] = [];
favoriteMovies: number[] = []; favoriteMovies: number[] = [];
watchedMovies: number[] = [];
currentMovie: any[] = []; currentMovie: any[] = [];
playMovie: string = ''; playMovie: string = '';
isLoading: boolean = true; isLoading: boolean = true;
@ -46,17 +47,18 @@ export class BrowseComponent implements OnInit {
) {} ) {}
async ngOnInit() { async ngOnInit() {
this.loadLikedMovies(); this.loadLikedAndWatchedMovies();
await this.loadAllMovies(); await this.loadAllMovies();
if (this.checkScreenWidth()) { if (this.checkScreenWidth()) {
this.currentMovie.length === 0 ? this.loadRandomMovie() : null; this.currentMovie.length === 0 ? this.loadRandomMovie() : null;
} }
} }
async loadLikedMovies() { async loadLikedAndWatchedMovies() {
try { try {
const likedMovies = await this.userService.getLikedMovies(); const userData = await this.userService.getLikedAndWatchedMovies();
this.favoriteMovies = likedMovies.liked_videos; this.favoriteMovies = userData.liked_videos;
this.watchedMovies = userData.watched_videos;
} catch (error) { } catch (error) {
console.error(error); console.error(error);
} }

View file

@ -46,7 +46,6 @@
</div> </div>
</div> </div>
</div> </div>
<!-- Genre columns --> <!-- Genre columns -->
@for (filmGenre of filmGenres; track filmGenre) { @for (filmGenre of filmGenres; track filmGenre) {
<!-- Movie available in genre --> <!-- Movie available in genre -->
@ -56,13 +55,21 @@
<div class="movies"> <div class="movies">
<!-- Load movies --> <!-- Load movies -->
@for (movie of allMovies(filmGenre.code); track movie) { @for (movie of allMovies(filmGenre.code); track movie) {
<div class="movie" (click)="openCurrentMovie(movie.id)"> <div class="movie" (click)="openCurrentMovie(movie.id)">
<div class="banner">
<img <img
[ngClass]="{ selected: movie.id === currentMovie }" [ngClass]="{ selected: movie.id === currentMovie }"
[src]="getThumbnailUrl(movie.id, movie.file_name)" [src]="getThumbnailUrl(movie.id, movie.file_name)"
alt="" alt=""
/> />
</div> </div>
@if (watchedMovies.includes(movie.id)) {
<div class="watched">
<img src="./../../../../../assets/img/open-eye.svg" alt="" />
</div>
}
</div>
} }
<!-- Buttons for scrolling --> <!-- Buttons for scrolling -->
<div class="scroll-buttons"> <div class="scroll-buttons">

View file

@ -19,9 +19,11 @@ section {
// Movies // Movies
.movie { .movie {
position: relative;
width: 213px; width: 213px;
height: 120px; height: 120px;
padding: 6px; padding: 6px;
.banner {
img { img {
width: 213px; width: 213px;
height: 120px; height: 120px;
@ -34,6 +36,20 @@ section {
} }
} }
} }
.watched {
position: absolute;
top: 15px;
right: 15px;
z-index: 2;
img {
width: 24px;
height: auto;
filter: brightness(0) saturate(100%) invert(100%) sepia(28%) saturate(1%)
hue-rotate(288deg) brightness(101%) contrast(101%)
drop-shadow(0 0 5px rgba(38, 143, 255, 1));
}
}
}
.selected { .selected {
border: 2px solid $blue !important; border: 2px solid $blue !important;

View file

@ -20,6 +20,7 @@ export class CategoriesComponent implements AfterViewInit {
@Input() movies: any[] = []; @Input() movies: any[] = [];
@Input() currentMovie: number = 0; @Input() currentMovie: number = 0;
@Input() favoriteMovies: any[] = []; @Input() favoriteMovies: any[] = [];
@Input() watchedMovies: any[] = [];
@Output() currentMovieId = new EventEmitter<number>(); @Output() currentMovieId = new EventEmitter<number>();
environmentBaseUrl: string = environment.baseUrl; environmentBaseUrl: string = environment.baseUrl;

View file

@ -11,7 +11,7 @@ export class UserService {
constructor(private http: HttpClient) {} constructor(private http: HttpClient) {}
async getLikedMovies(): Promise<any> { async getLikedAndWatchedMovies(): Promise<any> {
const url = environment.baseUrl + `/users/${this.currentUserId}/`; const url = environment.baseUrl + `/users/${this.currentUserId}/`;
const headers = this.getAuthHeaders(); const headers = this.getAuthHeaders();
return lastValueFrom(this.http.get(url, { headers })); return lastValueFrom(this.http.get(url, { headers }));