add like function for movies
This commit is contained in:
parent
5e5d0f9517
commit
de49073d9e
7 changed files with 99 additions and 4 deletions
|
|
@ -4,4 +4,4 @@ from .models import CustomUser
|
||||||
class UserSerializer(serializers.ModelSerializer):
|
class UserSerializer(serializers.ModelSerializer):
|
||||||
class Meta:
|
class Meta:
|
||||||
model = CustomUser
|
model = CustomUser
|
||||||
fields = ["id", "username", "email"]
|
fields = ["id", "username", "email", "liked_videos"]
|
||||||
|
|
@ -58,6 +58,14 @@
|
||||||
)
|
)
|
||||||
"
|
"
|
||||||
></app-btn-large>
|
></app-btn-large>
|
||||||
|
<div class="btn-small">
|
||||||
|
<img
|
||||||
|
[class.red]="currentUserLikedCurrentMovie"
|
||||||
|
src="./../../../../assets/img/favorite.svg"
|
||||||
|
alt=""
|
||||||
|
(click)="toggleLikeMovie(currentMovie[0].id)"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -81,9 +81,37 @@ section {
|
||||||
bottom: -70px;
|
bottom: -70px;
|
||||||
left: 0;
|
left: 0;
|
||||||
display: flex;
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
justify-content: left;
|
justify-content: left;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
gap: 12px;
|
gap: 12px;
|
||||||
|
.btn-small {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
width: 48px;
|
||||||
|
height: 48px;
|
||||||
|
background-color: blue;
|
||||||
|
border-radius: 50%;
|
||||||
|
cursor: pointer;
|
||||||
|
&:hover {
|
||||||
|
background-color: $white;
|
||||||
|
transition: 300ms ease-in-out;
|
||||||
|
img {
|
||||||
|
filter: brightness(0) saturate(100%) invert(18%) sepia(98%)
|
||||||
|
saturate(7267%) hue-rotate(342deg) brightness(94%) contrast(119%);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
img {
|
||||||
|
width: 28px;
|
||||||
|
height: 28px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.red {
|
||||||
|
filter: brightness(0) saturate(100%) invert(18%) sepia(98%) saturate(7267%)
|
||||||
|
hue-rotate(342deg) brightness(94%) contrast(119%);
|
||||||
}
|
}
|
||||||
|
|
||||||
.movie-banner {
|
.movie-banner {
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,7 @@ import { BtnLargeComponent } from '../../../../shared/components/buttons/btn-lar
|
||||||
import { MovieService } from '../../../../services/movie.service';
|
import { MovieService } from '../../../../services/movie.service';
|
||||||
import { environment } from '../../../../environments/environment';
|
import { environment } from '../../../../environments/environment';
|
||||||
import { BtnSmallComponent } from '../../../../shared/components/buttons/btn-small/btn-small.component';
|
import { BtnSmallComponent } from '../../../../shared/components/buttons/btn-small/btn-small.component';
|
||||||
|
import { UserService } from '../../../../services/user.service';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-hero-banner',
|
selector: 'app-hero-banner',
|
||||||
|
|
@ -28,17 +29,36 @@ export class HeroBannerComponent {
|
||||||
}>();
|
}>();
|
||||||
@Output() moviesChange = new EventEmitter<any[]>();
|
@Output() moviesChange = new EventEmitter<any[]>();
|
||||||
|
|
||||||
|
currentUserLikedCurrentMovie: boolean = false;
|
||||||
environmentBaseUrl: string = environment.baseUrl;
|
environmentBaseUrl: string = environment.baseUrl;
|
||||||
movieIsUploaded: { [resolution: string]: boolean } = {
|
movieIsUploaded: { [resolution: string]: boolean } = {
|
||||||
'480': false,
|
'480': false,
|
||||||
'720': false,
|
'720': false,
|
||||||
'1080': false,
|
'1080': false,
|
||||||
};
|
};
|
||||||
constructor(private el: ElementRef, private movieService: MovieService) {}
|
constructor(
|
||||||
|
private el: ElementRef,
|
||||||
|
private movieService: MovieService,
|
||||||
|
public userService: UserService
|
||||||
|
) {}
|
||||||
|
|
||||||
|
async loadLikedMovies() {
|
||||||
|
try {
|
||||||
|
const likedMovies = await this.userService.getLikedMovies();
|
||||||
|
this.currentUserLikedCurrentMovie = likedMovies.liked_videos.includes(
|
||||||
|
this.currentMovie[0].id
|
||||||
|
);
|
||||||
|
} catch (error) {
|
||||||
|
console.error(error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
toggleLikeMovie(movieId: number) {}
|
||||||
|
|
||||||
ngOnChanges(changes: SimpleChanges) {
|
ngOnChanges(changes: SimpleChanges) {
|
||||||
if (changes['currentMovie'] && this.currentMovie.length > 0) {
|
if (changes['currentMovie'] && this.currentMovie.length > 0) {
|
||||||
const movieId = this.currentMovie[0]?.id;
|
const movieId = this.currentMovie[0]?.id;
|
||||||
|
this.loadLikedMovies();
|
||||||
if (movieId) {
|
if (movieId) {
|
||||||
this.movieService
|
this.movieService
|
||||||
.isMovieResolutionUploaded(movieId)
|
.isMovieResolutionUploaded(movieId)
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@ import { HttpClient, HttpHeaders } from '@angular/common/http';
|
||||||
import { Injectable } from '@angular/core';
|
import { Injectable } from '@angular/core';
|
||||||
import { catchError, lastValueFrom, map, Observable, of } from 'rxjs';
|
import { catchError, lastValueFrom, map, Observable, of } from 'rxjs';
|
||||||
import { environment } from '../environments/environment';
|
import { environment } from '../environments/environment';
|
||||||
|
import { UserService } from './user.service';
|
||||||
|
|
||||||
@Injectable({
|
@Injectable({
|
||||||
providedIn: 'root',
|
providedIn: 'root',
|
||||||
|
|
@ -11,7 +12,7 @@ export class AuthService {
|
||||||
passwordFieldType: string = 'password';
|
passwordFieldType: string = 'password';
|
||||||
passwordIcon: string = './../../../assets/img/close-eye.svg';
|
passwordIcon: string = './../../../assets/img/close-eye.svg';
|
||||||
|
|
||||||
constructor(private http: HttpClient) {}
|
constructor(private http: HttpClient, private userService: UserService) {}
|
||||||
|
|
||||||
togglePasswordVisibility() {
|
togglePasswordVisibility() {
|
||||||
this.passwordFieldType =
|
this.passwordFieldType =
|
||||||
|
|
@ -66,11 +67,18 @@ export class AuthService {
|
||||||
checkAuthUser(): Observable<boolean> {
|
checkAuthUser(): Observable<boolean> {
|
||||||
const headers = this.getAuthHeaders();
|
const headers = this.getAuthHeaders();
|
||||||
return this.http.get<any>(`${environment.baseUrl}/auth/`, { headers }).pipe(
|
return this.http.get<any>(`${environment.baseUrl}/auth/`, { headers }).pipe(
|
||||||
map((response) => true),
|
map((response) => {
|
||||||
|
this.saveUserId(response);
|
||||||
|
return true;
|
||||||
|
}),
|
||||||
catchError(() => of(false))
|
catchError(() => of(false))
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
saveUserId(userId: string): void {
|
||||||
|
this.userService.currentUserId = userId;
|
||||||
|
}
|
||||||
|
|
||||||
async checkAuthUserMail(body: any) {
|
async checkAuthUserMail(body: any) {
|
||||||
await lastValueFrom(this.http.post(`${environment.baseUrl}/auth/`, body));
|
await lastValueFrom(this.http.post(`${environment.baseUrl}/auth/`, body));
|
||||||
}
|
}
|
||||||
|
|
|
||||||
30
frontend/src/app/services/user.service.ts
Normal file
30
frontend/src/app/services/user.service.ts
Normal file
|
|
@ -0,0 +1,30 @@
|
||||||
|
import { HttpClient, HttpHeaders } from '@angular/common/http';
|
||||||
|
import { Injectable } from '@angular/core';
|
||||||
|
import { environment } from '../environments/environment';
|
||||||
|
import { lastValueFrom } from 'rxjs';
|
||||||
|
|
||||||
|
@Injectable({
|
||||||
|
providedIn: 'root',
|
||||||
|
})
|
||||||
|
export class UserService {
|
||||||
|
currentUserId: string | null = null;
|
||||||
|
|
||||||
|
constructor(private http: HttpClient) {}
|
||||||
|
|
||||||
|
async getLikedMovies(): Promise<any> {
|
||||||
|
const url = environment.baseUrl + `/users/${this.currentUserId}/`;
|
||||||
|
const headers = this.getAuthHeaders();
|
||||||
|
|
||||||
|
return lastValueFrom(this.http.get(url, { headers }));
|
||||||
|
}
|
||||||
|
|
||||||
|
private getAuthHeaders(): HttpHeaders {
|
||||||
|
let authToken = localStorage.getItem('authToken');
|
||||||
|
if (!authToken) {
|
||||||
|
authToken = sessionStorage.getItem('authToken');
|
||||||
|
}
|
||||||
|
return new HttpHeaders({
|
||||||
|
Authorization: `Token ${authToken}`,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
1
frontend/src/assets/img/favorite.svg
Normal file
1
frontend/src/assets/img/favorite.svg
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 -960 960 960" width="24px" fill="#fff"><path d="m480-120-58-52q-101-91-167-157T150-447.5Q111-500 95.5-544T80-634q0-94 63-157t157-63q52 0 99 22t81 62q34-40 81-62t99-22q94 0 157 63t63 157q0 46-15.5 90T810-447.5Q771-395 705-329T538-172l-58 52Zm0-108q96-86 158-147.5t98-107q36-45.5 50-81t14-70.5q0-60-40-100t-100-40q-47 0-87 26.5T518-680h-76q-15-41-55-67.5T300-774q-60 0-100 40t-40 100q0 35 14 70.5t50 81q36 45.5 98 107T480-228Zm0-273Z"/></svg>
|
||||||
|
After Width: | Height: | Size: 505 B |
Loading…
Reference in a new issue