refactor: reorganize component structure and update imports
This commit is contained in:
parent
9c14319236
commit
d77aee2b9f
35 changed files with 698 additions and 689 deletions
|
|
@ -1,17 +1,17 @@
|
|||
import { Routes } from '@angular/router';
|
||||
import { HomeComponent } from './components/home/home.component';
|
||||
import { ImprintComponent } from './shared/components/legal-information/imprint/imprint.component';
|
||||
import { PrivacyPolicyComponent } from './shared/components/legal-information/privacy-policy/privacy-policy.component';
|
||||
import { BrowseComponent } from './components/home/browse/browse.component';
|
||||
import { HomeComponent } from './components/home/home.component';
|
||||
import { AuthComponent } from './components/auth/auth.component';
|
||||
import { AuthGuard } from './auth.guard';
|
||||
|
||||
export const routes: Routes = [
|
||||
{ path: '', component: HomeComponent },
|
||||
{ path: 'login', component: HomeComponent },
|
||||
{ path: 'register', component: HomeComponent },
|
||||
{ path: 'forgot-password', component: HomeComponent },
|
||||
{ path: 'verify-email', component: HomeComponent },
|
||||
{ path: '', component: AuthComponent },
|
||||
{ path: 'login', component: AuthComponent },
|
||||
{ path: 'register', component: AuthComponent },
|
||||
{ path: 'forgot-password', component: AuthComponent },
|
||||
{ path: 'verify-email', component: AuthComponent },
|
||||
{ path: 'imprint', component: ImprintComponent },
|
||||
{ path: 'privacy-policy', component: PrivacyPolicyComponent },
|
||||
{ path: 'browse', component: BrowseComponent, canActivate: [AuthGuard] },
|
||||
{ path: 'browse', component: HomeComponent, canActivate: [AuthGuard] },
|
||||
];
|
||||
|
|
|
|||
|
|
@ -1,48 +1,22 @@
|
|||
<section>
|
||||
<div class="headline">
|
||||
<p>Movies, TV shows, and more</p>
|
||||
<p>Watch whenever you want wherever you want</p>
|
||||
<p>Enter your email to create or restart your subscription.</p>
|
||||
</div>
|
||||
<form
|
||||
#taskForm="ngForm"
|
||||
(ngSubmit)="onSubmit(taskForm, mail)"
|
||||
onsubmit="return false"
|
||||
>
|
||||
<input
|
||||
type="mail"
|
||||
id="mail"
|
||||
name="mail"
|
||||
#mail="ngModel"
|
||||
placeholder="Email Address"
|
||||
class="custom-input"
|
||||
autocomplete="email"
|
||||
[(ngModel)]="authData.mail"
|
||||
[class.error-border]="
|
||||
(!mail.valid && mail.touched) ||
|
||||
(mail.touched &&
|
||||
!isUserEmailValid(authData.mail.toLowerCase()) &&
|
||||
authData.mail.length > 0)
|
||||
"
|
||||
required
|
||||
/>
|
||||
<div class="error-msg">
|
||||
@if (!mail.valid && mail.touched) {
|
||||
<p>Please enter your email</p>
|
||||
} @else { @if (mail.touched && authData.mail.length > 0 &&
|
||||
!isUserEmailValid(authData.mail.toLowerCase())) {
|
||||
<p>This is not a valid email format</p>
|
||||
<section class="bg-home">
|
||||
<app-header />
|
||||
|
||||
<!-- Non auth Routing -->
|
||||
@switch (currentRoute) { @case ('') {
|
||||
<app-landing-page />
|
||||
} @case ('login') {
|
||||
<app-login />
|
||||
} @case ('register') {
|
||||
<app-register />
|
||||
} @case ('forgot-password') {
|
||||
<app-forgot-password />
|
||||
} @case ('verify-email') {
|
||||
<app-verify-email />
|
||||
} }
|
||||
</div>
|
||||
<app-btn-large
|
||||
[value]="'Sign Up'"
|
||||
[imgPath]="'play'"
|
||||
[imgPath]="'arrow_right'"
|
||||
[imgReverse]="true"
|
||||
[disabled]="
|
||||
(!isUserEmailValid(authData.mail) && authData.mail.length > 0) ||
|
||||
authData.send
|
||||
"
|
||||
></app-btn-large>
|
||||
</form>
|
||||
|
||||
<app-footer />
|
||||
|
||||
@if (errorService.displayError) {
|
||||
<app-error-toast />
|
||||
}
|
||||
</section>
|
||||
|
|
|
|||
|
|
@ -1,88 +1,4 @@
|
|||
@use "./../../../assets/style/colors.scss" as *;
|
||||
@use "./../../../assets/style/form.scss" as *;
|
||||
@use "./../../../assets/style/auth-layout.scss" as *;
|
||||
|
||||
section {
|
||||
background-image: linear-gradient(rgba(0, 0, 0, 0.4), rgba(0, 0, 0, 0.4)),
|
||||
url(./../../../assets/img/backgrounds/home.png);
|
||||
}
|
||||
|
||||
.headline {
|
||||
p:nth-child(1) {
|
||||
font-size: 48px;
|
||||
font-weight: 700;
|
||||
padding: 12px;
|
||||
}
|
||||
p:nth-child(2) {
|
||||
font-size: 24px;
|
||||
font-weight: 500;
|
||||
padding: 12px;
|
||||
}
|
||||
p:nth-child(3) {
|
||||
font-size: 18px;
|
||||
font-weight: 400;
|
||||
padding: 12px;
|
||||
}
|
||||
}
|
||||
|
||||
form {
|
||||
flex-direction: row;
|
||||
position: relative;
|
||||
width: 500px;
|
||||
padding: 24px;
|
||||
input {
|
||||
width: 65%;
|
||||
padding: 12px 18px;
|
||||
margin: 8px 0;
|
||||
color: $white;
|
||||
border: 2px solid $white;
|
||||
border-radius: 24px;
|
||||
font-size: 18px;
|
||||
&::placeholder {
|
||||
color: rgba($white, 0.6);
|
||||
}
|
||||
}
|
||||
.error-border {
|
||||
border: 2px solid $red;
|
||||
}
|
||||
}
|
||||
|
||||
.error-msg {
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
padding: 6px;
|
||||
width: 57%;
|
||||
}
|
||||
|
||||
/*------------- RESPONSIVE -------------*/
|
||||
|
||||
@media screen and (max-width: 550px) {
|
||||
form {
|
||||
flex-direction: column;
|
||||
width: 90%;
|
||||
input {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
.error-msg {
|
||||
position: relative;
|
||||
padding: 0;
|
||||
height: 12px;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
}
|
||||
|
||||
@media screen and (max-width: 500px) {
|
||||
.headline {
|
||||
p:nth-child(1) {
|
||||
font-size: 36px;
|
||||
}
|
||||
p:nth-child(2) {
|
||||
font-size: 20px;
|
||||
}
|
||||
p:nth-child(3) {
|
||||
font-size: 16px;
|
||||
}
|
||||
}
|
||||
width: 100dvw;
|
||||
height: 100dvh;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,56 +1,44 @@
|
|||
import { Component } from '@angular/core';
|
||||
import { FormsModule, NgForm } from '@angular/forms';
|
||||
import { BtnLargeComponent } from '../../shared/components/buttons/btn-large/btn-large.component';
|
||||
import { Router } from '@angular/router';
|
||||
import { Component, OnInit } from '@angular/core';
|
||||
import { HeaderComponent } from '../../shared/components/header/header.component';
|
||||
import { FooterComponent } from '../../shared/components/footer/footer.component';
|
||||
import { ActivatedRoute } from '@angular/router';
|
||||
import { RegisterComponent } from '../auth/register/register.component';
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { LoginComponent } from '../auth/login/login.component';
|
||||
import { ForgotPasswordComponent } from '../auth/forgot-password/forgot-password.component';
|
||||
import { VerifyEmailComponent } from '../auth/verify-email/verify-email.component';
|
||||
import { ErrorToastComponent } from '../../shared/components/error-toast/error-toast.component';
|
||||
import { ErrorService } from '../../services/error.service';
|
||||
import { AuthService } from '../../services/auth.service';
|
||||
import { LandingPageComponent } from './landing-page/landing-page.component';
|
||||
|
||||
@Component({
|
||||
selector: 'app-auth',
|
||||
standalone: true,
|
||||
imports: [CommonModule, BtnLargeComponent, FormsModule],
|
||||
imports: [
|
||||
CommonModule,
|
||||
HeaderComponent,
|
||||
FooterComponent,
|
||||
LandingPageComponent,
|
||||
RegisterComponent,
|
||||
LoginComponent,
|
||||
ForgotPasswordComponent,
|
||||
VerifyEmailComponent,
|
||||
ErrorToastComponent,
|
||||
],
|
||||
templateUrl: './auth.component.html',
|
||||
styleUrl: './auth.component.scss',
|
||||
})
|
||||
export class AuthComponent {
|
||||
authData = {
|
||||
mail: '',
|
||||
send: false,
|
||||
};
|
||||
export class AuthComponent implements OnInit {
|
||||
currentRoute: any;
|
||||
|
||||
constructor(
|
||||
private router: Router,
|
||||
public errorService: ErrorService,
|
||||
private authService: AuthService
|
||||
private route: ActivatedRoute,
|
||||
public errorService: ErrorService
|
||||
) {}
|
||||
|
||||
isUserEmailValid(emailValue: string) {
|
||||
const emailRegex = /^[\w.%+-]+@[\w.-]+\.[a-zA-Z]{2,}$/;
|
||||
return emailRegex.test(emailValue);
|
||||
}
|
||||
|
||||
async onSubmit(ngForm: NgForm, mailInput: any) {
|
||||
if (ngForm.submitted && ngForm.form.valid) {
|
||||
await this.checkDuplicatesEmail();
|
||||
} else {
|
||||
mailInput.control.markAsTouched();
|
||||
}
|
||||
}
|
||||
|
||||
async checkDuplicatesEmail() {
|
||||
const body = {
|
||||
email: this.authData.mail,
|
||||
};
|
||||
try {
|
||||
this.authData.send = true;
|
||||
await this.authService.checkAuthUserMail(body);
|
||||
const queryParams = { mail: this.authData.mail };
|
||||
this.router.navigate(['/register'], { queryParams });
|
||||
this.errorService.clearError();
|
||||
} catch (error) {
|
||||
this.authData.send = false;
|
||||
this.errorService.handleError(error);
|
||||
}
|
||||
ngOnInit(): void {
|
||||
this.route.url.subscribe((url) => {
|
||||
this.currentRoute = url[0]?.path || '';
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,48 @@
|
|||
<section>
|
||||
<div class="headline">
|
||||
<p>Movies, TV shows, and more</p>
|
||||
<p>Watch whenever you want wherever you want</p>
|
||||
<p>Enter your email to create or restart your subscription.</p>
|
||||
</div>
|
||||
<form
|
||||
#taskForm="ngForm"
|
||||
(ngSubmit)="onSubmit(taskForm, mail)"
|
||||
onsubmit="return false"
|
||||
>
|
||||
<input
|
||||
type="mail"
|
||||
id="mail"
|
||||
name="mail"
|
||||
#mail="ngModel"
|
||||
placeholder="Email Address"
|
||||
class="custom-input"
|
||||
autocomplete="email"
|
||||
[(ngModel)]="authData.mail"
|
||||
[class.error-border]="
|
||||
(!mail.valid && mail.touched) ||
|
||||
(mail.touched &&
|
||||
!isUserEmailValid(authData.mail.toLowerCase()) &&
|
||||
authData.mail.length > 0)
|
||||
"
|
||||
required
|
||||
/>
|
||||
<div class="error-msg">
|
||||
@if (!mail.valid && mail.touched) {
|
||||
<p>Please enter your email</p>
|
||||
} @else { @if (mail.touched && authData.mail.length > 0 &&
|
||||
!isUserEmailValid(authData.mail.toLowerCase())) {
|
||||
<p>This is not a valid email format</p>
|
||||
}}
|
||||
</div>
|
||||
<app-btn-large
|
||||
[value]="'Sign Up'"
|
||||
[imgPath]="'play'"
|
||||
[imgPath]="'arrow_right'"
|
||||
[imgReverse]="true"
|
||||
[disabled]="
|
||||
(!isUserEmailValid(authData.mail) && authData.mail.length > 0) ||
|
||||
authData.send
|
||||
"
|
||||
></app-btn-large>
|
||||
</form>
|
||||
</section>
|
||||
|
|
@ -0,0 +1,88 @@
|
|||
@use "./../../../../assets/style/colors.scss" as *;
|
||||
@use "./../../../../assets/style/form.scss" as *;
|
||||
@use "./../../../../assets/style/auth-layout.scss" as *;
|
||||
|
||||
section {
|
||||
background-image: linear-gradient(rgba(0, 0, 0, 0.4), rgba(0, 0, 0, 0.4)),
|
||||
url(./../../../../assets/img/backgrounds/home.png);
|
||||
}
|
||||
|
||||
.headline {
|
||||
p:nth-child(1) {
|
||||
font-size: 48px;
|
||||
font-weight: 700;
|
||||
padding: 12px;
|
||||
}
|
||||
p:nth-child(2) {
|
||||
font-size: 24px;
|
||||
font-weight: 500;
|
||||
padding: 12px;
|
||||
}
|
||||
p:nth-child(3) {
|
||||
font-size: 18px;
|
||||
font-weight: 400;
|
||||
padding: 12px;
|
||||
}
|
||||
}
|
||||
|
||||
form {
|
||||
flex-direction: row;
|
||||
position: relative;
|
||||
width: 500px;
|
||||
padding: 24px;
|
||||
input {
|
||||
width: 65%;
|
||||
padding: 12px 18px;
|
||||
margin: 8px 0;
|
||||
color: $white;
|
||||
border: 2px solid $white;
|
||||
border-radius: 24px;
|
||||
font-size: 18px;
|
||||
&::placeholder {
|
||||
color: rgba($white, 0.6);
|
||||
}
|
||||
}
|
||||
.error-border {
|
||||
border: 2px solid $red;
|
||||
}
|
||||
}
|
||||
|
||||
.error-msg {
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
padding: 6px;
|
||||
width: 57%;
|
||||
}
|
||||
|
||||
/*------------- RESPONSIVE -------------*/
|
||||
|
||||
@media screen and (max-width: 550px) {
|
||||
form {
|
||||
flex-direction: column;
|
||||
width: 90%;
|
||||
input {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
.error-msg {
|
||||
position: relative;
|
||||
padding: 0;
|
||||
height: 12px;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
}
|
||||
|
||||
@media screen and (max-width: 500px) {
|
||||
.headline {
|
||||
p:nth-child(1) {
|
||||
font-size: 36px;
|
||||
}
|
||||
p:nth-child(2) {
|
||||
font-size: 20px;
|
||||
}
|
||||
p:nth-child(3) {
|
||||
font-size: 16px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,18 +1,18 @@
|
|||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { BrowseComponent } from './browse.component';
|
||||
import { LandingPageComponent } from './landing-page.component';
|
||||
|
||||
describe('BrowseComponent', () => {
|
||||
let component: BrowseComponent;
|
||||
let fixture: ComponentFixture<BrowseComponent>;
|
||||
describe('LandingPageComponent', () => {
|
||||
let component: LandingPageComponent;
|
||||
let fixture: ComponentFixture<LandingPageComponent>;
|
||||
|
||||
beforeEach(async () => {
|
||||
await TestBed.configureTestingModule({
|
||||
imports: [BrowseComponent]
|
||||
imports: [LandingPageComponent]
|
||||
})
|
||||
.compileComponents();
|
||||
|
||||
fixture = TestBed.createComponent(BrowseComponent);
|
||||
fixture = TestBed.createComponent(LandingPageComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
|
@ -0,0 +1,56 @@
|
|||
import { Component } from '@angular/core';
|
||||
import { FormsModule, NgForm } from '@angular/forms';
|
||||
import { BtnLargeComponent } from '../../../shared/components/buttons/btn-large/btn-large.component';
|
||||
import { Router } from '@angular/router';
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { ErrorService } from '../../../services/error.service';
|
||||
import { AuthService } from '../../../services/auth.service';
|
||||
|
||||
@Component({
|
||||
selector: 'app-landing-page',
|
||||
standalone: true,
|
||||
imports: [CommonModule, BtnLargeComponent, FormsModule],
|
||||
templateUrl: './landing-page.component.html',
|
||||
styleUrl: './landing-page.component.scss',
|
||||
})
|
||||
export class LandingPageComponent {
|
||||
authData = {
|
||||
mail: '',
|
||||
send: false,
|
||||
};
|
||||
|
||||
constructor(
|
||||
private router: Router,
|
||||
public errorService: ErrorService,
|
||||
private authService: AuthService
|
||||
) {}
|
||||
|
||||
isUserEmailValid(emailValue: string) {
|
||||
const emailRegex = /^[\w.%+-]+@[\w.-]+\.[a-zA-Z]{2,}$/;
|
||||
return emailRegex.test(emailValue);
|
||||
}
|
||||
|
||||
async onSubmit(ngForm: NgForm, mailInput: any) {
|
||||
if (ngForm.submitted && ngForm.form.valid) {
|
||||
await this.checkDuplicatesEmail();
|
||||
} else {
|
||||
mailInput.control.markAsTouched();
|
||||
}
|
||||
}
|
||||
|
||||
async checkDuplicatesEmail() {
|
||||
const body = {
|
||||
email: this.authData.mail,
|
||||
};
|
||||
try {
|
||||
this.authData.send = true;
|
||||
await this.authService.checkAuthUserMail(body);
|
||||
const queryParams = { mail: this.authData.mail };
|
||||
this.router.navigate(['/register'], { queryParams });
|
||||
this.errorService.clearError();
|
||||
} catch (error) {
|
||||
this.authData.send = false;
|
||||
this.errorService.handleError(error);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,118 +0,0 @@
|
|||
<section>
|
||||
<div *ngIf="isLoading"></div>
|
||||
@if (!isLoading && movies.length > 0) {
|
||||
<!-- If at least one film has been uploaded -->
|
||||
@if (playMovie === "") {
|
||||
<app-header
|
||||
(moviesChange)="onMoviesChange($event)"
|
||||
[showFullLogo]="false"
|
||||
></app-header>
|
||||
<!-- Hero Banner -->
|
||||
<app-hero-banner
|
||||
*ngIf="
|
||||
currentMovie.length === 1 ||
|
||||
(this.isWideScreen() && currentMovie.length > 1)
|
||||
"
|
||||
[isWideScreen]="isWideScreen()"
|
||||
[currentMovie]="currentMovie"
|
||||
[favoriteMovies]="favoriteMovies"
|
||||
[watchedMovies]="watchedMovies"
|
||||
(playMovie)="playVideo($event)"
|
||||
(movieIsUploadedChange)="onMovieIsUploadedChange($event)"
|
||||
(moviesChange)="onMoviesChange($event)"
|
||||
(refreshChange)="onRefreshPage($event)"
|
||||
(favoriteMovieChange)="onFavoriteMovieChange($event)"
|
||||
></app-hero-banner>
|
||||
<!-- Spacer -->
|
||||
<div *ngIf="!this.isWideScreen()" class="spacer"></div>
|
||||
<!-- Movie Categories -->
|
||||
<app-categories
|
||||
*ngIf="
|
||||
this.isWideScreen() || (!this.isWideScreen() && currentMovie.length === 0)
|
||||
"
|
||||
[movies]="movies"
|
||||
[currentMovie]="currentMovie[0]?.id"
|
||||
[favoriteMovies]="favoriteMovies"
|
||||
[watchedMovies]="watchedMovies"
|
||||
(currentMovieId)="currentMovieId($event)"
|
||||
></app-categories>
|
||||
} @else {
|
||||
<div class="video-overlay">
|
||||
<div class="video-header">
|
||||
<div class="back-button" (click)="closeVideo()">
|
||||
<img src="./../../../../assets/img/back.svg" alt="Back" />
|
||||
</div>
|
||||
<div class="center">
|
||||
<div class="resolution-controls">
|
||||
<button
|
||||
[ngClass]="{
|
||||
'resolution-btn': true,
|
||||
active: currentResolution === '360p',
|
||||
'not-available': !movieIsUploaded['360']
|
||||
}"
|
||||
[disabled]="!movieIsUploaded['360'] || currentResolution === '360p'"
|
||||
(click)="changeResolution('360p')"
|
||||
>
|
||||
360p
|
||||
</button>
|
||||
<button
|
||||
[ngClass]="{
|
||||
'resolution-btn': true,
|
||||
active: currentResolution === '720p',
|
||||
'not-available': !movieIsUploaded['720']
|
||||
}"
|
||||
[disabled]="!movieIsUploaded['720'] || currentResolution === '720p'"
|
||||
(click)="changeResolution('720p')"
|
||||
>
|
||||
720p
|
||||
</button>
|
||||
<button
|
||||
[ngClass]="{
|
||||
'resolution-btn': true,
|
||||
active: currentResolution === '1080p',
|
||||
'not-available': !movieIsUploaded['1080']
|
||||
}"
|
||||
[disabled]="
|
||||
!movieIsUploaded['1080'] || currentResolution === '1080p'
|
||||
"
|
||||
(click)="changeResolution('1080p')"
|
||||
>
|
||||
1080p
|
||||
</button>
|
||||
</div>
|
||||
<p
|
||||
*ngIf="
|
||||
!movieIsUploaded['360'] ||
|
||||
!movieIsUploaded['720'] ||
|
||||
!movieIsUploaded['1080']
|
||||
"
|
||||
>
|
||||
(If a button cannot be selected, the video will be converted, which
|
||||
may take a few seconds.)
|
||||
</p>
|
||||
</div>
|
||||
<div class="logo">
|
||||
<img src="./../../../../assets/img/logo_ci.svg" alt="Logo" />
|
||||
</div>
|
||||
</div>
|
||||
<app-video-player [playMovie]="playMovie"></app-video-player>
|
||||
</div>
|
||||
} } @if (!isLoading && movies.length === 0) {
|
||||
<!-- If the database is empty -->
|
||||
<app-header [showFullLogo]="false"></app-header>
|
||||
<div class="error">
|
||||
<h2>Unfortunately there are no films available in the database.</h2>
|
||||
</div>
|
||||
}
|
||||
<div class="add-button">
|
||||
<app-btn-small
|
||||
[imgPath]="'add'"
|
||||
(click)="toggleUploadMovieOverview(true)"
|
||||
></app-btn-small>
|
||||
</div>
|
||||
</section>
|
||||
@if (uploadMovieOverview) {
|
||||
<app-upload-movie
|
||||
(toggleUploadMovieOverview)="toggleUploadMovieOverview($event)"
|
||||
></app-upload-movie>
|
||||
}
|
||||
|
|
@ -1,183 +0,0 @@
|
|||
@use "./../../../../assets/style/colors.scss" as *;
|
||||
|
||||
section {
|
||||
height: 100dvh;
|
||||
width: 100dvw;
|
||||
background-color: $black;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.video-overlay {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: $black;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
z-index: 1000;
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
video {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
&:hover .video-header {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
.video-header {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: 24px 48px;
|
||||
background: rgba($black, 0.5);
|
||||
z-index: 1001;
|
||||
opacity: 0;
|
||||
transition: opacity 300ms ease-in-out;
|
||||
}
|
||||
|
||||
.center {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
p {
|
||||
font-size: 14px;
|
||||
font-weight: 400;
|
||||
color: $light-blue;
|
||||
text-shadow: 1px 1px 2px $black;
|
||||
}
|
||||
}
|
||||
|
||||
.spacer {
|
||||
margin-top: 120px;
|
||||
}
|
||||
|
||||
.add-button {
|
||||
position: absolute;
|
||||
bottom: 24px;
|
||||
right: 24px;
|
||||
}
|
||||
|
||||
.back-button {
|
||||
cursor: pointer;
|
||||
background: none;
|
||||
border: none;
|
||||
padding: 0;
|
||||
img {
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
filter: brightness(0) saturate(100%) invert(100%) sepia(6%) saturate(312%)
|
||||
hue-rotate(234deg) brightness(113%) contrast(100%);
|
||||
transition: filter 300ms ease-in-out;
|
||||
&:hover {
|
||||
filter: brightness(0) saturate(100%) invert(13%) sepia(90%)
|
||||
saturate(7329%) hue-rotate(344deg) brightness(105%) contrast(117%);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.logo img {
|
||||
width: 32px;
|
||||
height: auto;
|
||||
}
|
||||
|
||||
.error {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
position: fixed;
|
||||
top: 120px;
|
||||
left: 0;
|
||||
right: 0;
|
||||
padding: 24px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
// Resolution Buttons
|
||||
|
||||
.resolution-controls {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
gap: 12px;
|
||||
margin: 18px 0;
|
||||
}
|
||||
|
||||
.resolution-btn {
|
||||
background-color: $light-blue;
|
||||
color: $white;
|
||||
border: none;
|
||||
border-radius: 4px;
|
||||
padding: 6px 12px;
|
||||
font-size: 16px;
|
||||
cursor: pointer;
|
||||
transition: background-color 0.3s ease, transform 0.2s ease;
|
||||
}
|
||||
|
||||
.resolution-btn.active {
|
||||
background-color: $blue;
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
.resolution-btn:disabled {
|
||||
cursor: auto;
|
||||
}
|
||||
|
||||
.resolution-btn:not(.active):hover {
|
||||
background-color: $blue;
|
||||
transform: scale(1.05);
|
||||
}
|
||||
|
||||
.resolution-btn:focus {
|
||||
outline: none;
|
||||
box-shadow: 0 0 0 3px rgba(38, 143, 255, 0.5);
|
||||
}
|
||||
|
||||
.not-available {
|
||||
opacity: 0.5;
|
||||
background-color: $gray;
|
||||
}
|
||||
|
||||
.not-available:not(.active):hover {
|
||||
background-color: $gray;
|
||||
transform: scale(1);
|
||||
}
|
||||
|
||||
/*------------- RESPONSIVE -------------*/
|
||||
|
||||
@media screen and (max-width: 600px) {
|
||||
.video-header {
|
||||
padding: 12px 24px;
|
||||
}
|
||||
}
|
||||
|
||||
@media screen and (max-width: 550px) {
|
||||
form {
|
||||
flex-direction: column;
|
||||
width: 90%;
|
||||
input {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
.error-msg {
|
||||
position: relative;
|
||||
padding: 0;
|
||||
height: 12px;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
}
|
||||
|
||||
@media screen and (max-width: 500px) {
|
||||
.resolution-btn {
|
||||
border-radius: 2px;
|
||||
padding: 3px 6px;
|
||||
font-size: 14px;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,142 +0,0 @@
|
|||
import { Component, OnInit, ViewChild } from '@angular/core';
|
||||
import { HeaderComponent } from '../../../shared/components/header/header.component';
|
||||
import { HeroBannerComponent } from './hero-banner/hero-banner.component';
|
||||
import { CategoriesComponent } from './categories/categories.component';
|
||||
import { MovieService } from '../../../services/movie.service';
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { VideoPlayerComponent } from './video-player/video-player.component';
|
||||
import { BtnSmallComponent } from '../../../shared/components/buttons/btn-small/btn-small.component';
|
||||
import { UploadMovieComponent } from './upload-movie/upload-movie.component';
|
||||
import { UserService } from '../../../services/user.service';
|
||||
|
||||
@Component({
|
||||
selector: 'app-browse',
|
||||
standalone: true,
|
||||
imports: [
|
||||
CommonModule,
|
||||
HeaderComponent,
|
||||
HeroBannerComponent,
|
||||
CategoriesComponent,
|
||||
VideoPlayerComponent,
|
||||
BtnSmallComponent,
|
||||
UploadMovieComponent,
|
||||
],
|
||||
templateUrl: './browse.component.html',
|
||||
styleUrl: './browse.component.scss',
|
||||
})
|
||||
export class BrowseComponent implements OnInit {
|
||||
@ViewChild(VideoPlayerComponent) videoPlayer!: VideoPlayerComponent;
|
||||
movies: any[] = [];
|
||||
favoriteMovies: number[] = [];
|
||||
watchedMovies: number[] = [];
|
||||
currentMovie: any[] = [];
|
||||
playMovie: string = '';
|
||||
isLoading: boolean = true;
|
||||
uploadMovieOverview: boolean = false;
|
||||
currentResolution: '360p' | '720p' | '1080p' = '720p';
|
||||
movieIsUploaded: { [resolution: string]: boolean } = {
|
||||
'360': false,
|
||||
'720': false,
|
||||
'1080': false,
|
||||
};
|
||||
|
||||
constructor(
|
||||
private movieService: MovieService,
|
||||
public userService: UserService
|
||||
) {}
|
||||
|
||||
async ngOnInit() {
|
||||
this.loadLikedAndWatchedMovies();
|
||||
await this.loadAllMovies();
|
||||
if (this.isWideScreen()) {
|
||||
this.currentMovie.length === 0 ? this.loadRandomMovie() : null;
|
||||
}
|
||||
}
|
||||
|
||||
async loadLikedAndWatchedMovies() {
|
||||
try {
|
||||
const userData = await this.userService.getLikedAndWatchedMovies();
|
||||
this.favoriteMovies = userData.liked_videos;
|
||||
this.watchedMovies = userData.watched_videos;
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
}
|
||||
}
|
||||
|
||||
updateLikeMovies() {
|
||||
const body = {
|
||||
liked_videos: this.favoriteMovies,
|
||||
};
|
||||
this.userService.updateLikedMovies(body);
|
||||
}
|
||||
|
||||
onRefreshPage(updatedMovies: any[]) {
|
||||
this.currentMovie = [];
|
||||
setTimeout(() => {
|
||||
this.currentMovie = updatedMovies;
|
||||
}, 1);
|
||||
}
|
||||
|
||||
onMoviesChange(updatedMovies: any[]) {
|
||||
if (this.isWideScreen()) {
|
||||
this.loadRandomMovie();
|
||||
} else {
|
||||
this.currentMovie = updatedMovies;
|
||||
}
|
||||
}
|
||||
|
||||
isWideScreen() {
|
||||
return window.innerWidth > 600;
|
||||
}
|
||||
|
||||
onMovieIsUploadedChange(newStatus: { [resolution: string]: boolean }) {
|
||||
this.movieIsUploaded = newStatus;
|
||||
}
|
||||
|
||||
onFavoriteMovieChange(favoriteMovies: any) {
|
||||
this.favoriteMovies = favoriteMovies;
|
||||
this.updateLikeMovies();
|
||||
}
|
||||
|
||||
changeResolution(resolution: '360p' | '720p' | '1080p') {
|
||||
if (this.videoPlayer && this.movieIsUploaded[resolution.replace('p', '')]) {
|
||||
this.videoPlayer.switchResolution(resolution);
|
||||
this.currentResolution = resolution;
|
||||
}
|
||||
}
|
||||
|
||||
async loadAllMovies() {
|
||||
this.isLoading = true;
|
||||
try {
|
||||
this.movies = await this.movieService.getAllMovies();
|
||||
} finally {
|
||||
this.isLoading = false;
|
||||
}
|
||||
}
|
||||
|
||||
closeVideo(): void {
|
||||
this.playMovie = '';
|
||||
}
|
||||
|
||||
playVideo(videoPath: string) {
|
||||
this.currentResolution = '720p';
|
||||
this.playMovie = videoPath;
|
||||
}
|
||||
|
||||
loadRandomMovie(): void {
|
||||
const randomIndex = Math.floor(Math.random() * this.movies.length);
|
||||
this.currentMovie = [this.movies[randomIndex]];
|
||||
}
|
||||
|
||||
currentMovieId(movieId: number) {
|
||||
let index = this.movies.findIndex((movie) => movie.id === movieId);
|
||||
if (index !== -1) {
|
||||
this.currentMovie = [];
|
||||
this.currentMovie.push(this.movies[index]);
|
||||
}
|
||||
}
|
||||
|
||||
toggleUploadMovieOverview(value: any) {
|
||||
this.uploadMovieOverview = value;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
@use "./../../../../../assets/style/colors.scss" as *;
|
||||
@use "./../../../../assets/style/colors.scss" as *;
|
||||
|
||||
section {
|
||||
margin-top: 12px;
|
||||
|
|
@ -7,7 +7,7 @@ import {
|
|||
Input,
|
||||
Output,
|
||||
} from '@angular/core';
|
||||
import { environment } from '../../../../../environments/environment';
|
||||
import { environment } from '../../../../environments/environment';
|
||||
import { MoviesListComponent } from './movie-list/movie-list.component';
|
||||
|
||||
@Component({
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
@use "./../../../../../../assets/style/colors.scss" as *;
|
||||
@use "./../../../../../assets/style/colors.scss" as *;
|
||||
|
||||
.movies {
|
||||
display: flex;
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
import { Component, Input, Output, EventEmitter } from '@angular/core';
|
||||
import { environment } from '../../../../../../environments/environment';
|
||||
import { environment } from '../../../../../environments/environment';
|
||||
import { CommonModule } from '@angular/common';
|
||||
|
||||
@Component({
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
@use "./../../../../../assets/style/colors.scss" as *;
|
||||
@use "./../../../../assets/style/colors.scss" as *;
|
||||
|
||||
section {
|
||||
height: 400px;
|
||||
|
|
@ -9,11 +9,11 @@ import {
|
|||
SimpleChanges,
|
||||
ViewChild,
|
||||
} from '@angular/core';
|
||||
import { BtnLargeComponent } from '../../../../shared/components/buttons/btn-large/btn-large.component';
|
||||
import { MovieService } from '../../../../services/movie.service';
|
||||
import { environment } from '../../../../../environments/environment';
|
||||
import { BtnSmallComponent } from '../../../../shared/components/buttons/btn-small/btn-small.component';
|
||||
import { UserService } from '../../../../services/user.service';
|
||||
import { BtnLargeComponent } from '../../../shared/components/buttons/btn-large/btn-large.component';
|
||||
import { MovieService } from '../../../services/movie.service';
|
||||
import { environment } from '../../../../environments/environment';
|
||||
import { BtnSmallComponent } from '../../../shared/components/buttons/btn-small/btn-small.component';
|
||||
import { UserService } from '../../../services/user.service';
|
||||
|
||||
@Component({
|
||||
selector: 'app-hero-banner',
|
||||
|
|
@ -1,12 +1,118 @@
|
|||
<section class="bg-home">
|
||||
<app-header></app-header>
|
||||
<app-auth *ngIf="currentRoute === ''"></app-auth>
|
||||
<app-login *ngIf="currentRoute === 'login'"></app-login>
|
||||
<app-register *ngIf="currentRoute === 'register'"></app-register>
|
||||
<app-forgot-password
|
||||
*ngIf="currentRoute === 'forgot-password'"
|
||||
></app-forgot-password>
|
||||
<app-verify-email *ngIf="currentRoute === 'verify-email'"></app-verify-email>
|
||||
<app-footer></app-footer>
|
||||
<app-error-toast *ngIf="errorService.displayError"></app-error-toast>
|
||||
<section>
|
||||
<div *ngIf="isLoading"></div>
|
||||
@if (!isLoading && movies.length > 0) {
|
||||
<!-- If at least one film has been uploaded -->
|
||||
@if (playMovie === "") {
|
||||
<app-header
|
||||
(moviesChange)="onMoviesChange($event)"
|
||||
[showFullLogo]="false"
|
||||
></app-header>
|
||||
<!-- Hero Banner -->
|
||||
<app-hero-banner
|
||||
*ngIf="
|
||||
currentMovie.length === 1 ||
|
||||
(this.isWideScreen() && currentMovie.length > 1)
|
||||
"
|
||||
[isWideScreen]="isWideScreen()"
|
||||
[currentMovie]="currentMovie"
|
||||
[favoriteMovies]="favoriteMovies"
|
||||
[watchedMovies]="watchedMovies"
|
||||
(playMovie)="playVideo($event)"
|
||||
(movieIsUploadedChange)="onMovieIsUploadedChange($event)"
|
||||
(moviesChange)="onMoviesChange($event)"
|
||||
(refreshChange)="onRefreshPage($event)"
|
||||
(favoriteMovieChange)="onFavoriteMovieChange($event)"
|
||||
></app-hero-banner>
|
||||
<!-- Spacer -->
|
||||
<div *ngIf="!this.isWideScreen()" class="spacer"></div>
|
||||
<!-- Movie Categories -->
|
||||
<app-categories
|
||||
*ngIf="
|
||||
this.isWideScreen() || (!this.isWideScreen() && currentMovie.length === 0)
|
||||
"
|
||||
[movies]="movies"
|
||||
[currentMovie]="currentMovie[0]?.id"
|
||||
[favoriteMovies]="favoriteMovies"
|
||||
[watchedMovies]="watchedMovies"
|
||||
(currentMovieId)="currentMovieId($event)"
|
||||
></app-categories>
|
||||
} @else {
|
||||
<div class="video-overlay">
|
||||
<div class="video-header">
|
||||
<div class="back-button" (click)="closeVideo()">
|
||||
<img src="./../../../../assets/img/back.svg" alt="Back" />
|
||||
</div>
|
||||
<div class="center">
|
||||
<div class="resolution-controls">
|
||||
<button
|
||||
[ngClass]="{
|
||||
'resolution-btn': true,
|
||||
active: currentResolution === '360p',
|
||||
'not-available': !movieIsUploaded['360']
|
||||
}"
|
||||
[disabled]="!movieIsUploaded['360'] || currentResolution === '360p'"
|
||||
(click)="changeResolution('360p')"
|
||||
>
|
||||
360p
|
||||
</button>
|
||||
<button
|
||||
[ngClass]="{
|
||||
'resolution-btn': true,
|
||||
active: currentResolution === '720p',
|
||||
'not-available': !movieIsUploaded['720']
|
||||
}"
|
||||
[disabled]="!movieIsUploaded['720'] || currentResolution === '720p'"
|
||||
(click)="changeResolution('720p')"
|
||||
>
|
||||
720p
|
||||
</button>
|
||||
<button
|
||||
[ngClass]="{
|
||||
'resolution-btn': true,
|
||||
active: currentResolution === '1080p',
|
||||
'not-available': !movieIsUploaded['1080']
|
||||
}"
|
||||
[disabled]="
|
||||
!movieIsUploaded['1080'] || currentResolution === '1080p'
|
||||
"
|
||||
(click)="changeResolution('1080p')"
|
||||
>
|
||||
1080p
|
||||
</button>
|
||||
</div>
|
||||
<p
|
||||
*ngIf="
|
||||
!movieIsUploaded['360'] ||
|
||||
!movieIsUploaded['720'] ||
|
||||
!movieIsUploaded['1080']
|
||||
"
|
||||
>
|
||||
(If a button cannot be selected, the video will be converted, which
|
||||
may take a few seconds.)
|
||||
</p>
|
||||
</div>
|
||||
<div class="logo">
|
||||
<img src="./../../../../assets/img/logo_ci.svg" alt="Logo" />
|
||||
</div>
|
||||
</div>
|
||||
<app-video-player [playMovie]="playMovie"></app-video-player>
|
||||
</div>
|
||||
} } @if (!isLoading && movies.length === 0) {
|
||||
<!-- If the database is empty -->
|
||||
<app-header [showFullLogo]="false"></app-header>
|
||||
<div class="error">
|
||||
<h2>Unfortunately there are no films available in the database.</h2>
|
||||
</div>
|
||||
}
|
||||
<div class="add-button">
|
||||
<app-btn-small
|
||||
[imgPath]="'add'"
|
||||
(click)="toggleUploadMovieOverview(true)"
|
||||
></app-btn-small>
|
||||
</div>
|
||||
</section>
|
||||
@if (uploadMovieOverview) {
|
||||
<app-upload-movie
|
||||
(toggleUploadMovieOverview)="toggleUploadMovieOverview($event)"
|
||||
></app-upload-movie>
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,183 @@
|
|||
@use "./../../../assets/style/colors.scss" as *;
|
||||
|
||||
section {
|
||||
width: 100dvw;
|
||||
height: 100dvh;
|
||||
width: 100dvw;
|
||||
background-color: $black;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.video-overlay {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: $black;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
z-index: 1000;
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
video {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
&:hover .video-header {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
.video-header {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: 24px 48px;
|
||||
background: rgba($black, 0.5);
|
||||
z-index: 1001;
|
||||
opacity: 0;
|
||||
transition: opacity 300ms ease-in-out;
|
||||
}
|
||||
|
||||
.center {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
p {
|
||||
font-size: 14px;
|
||||
font-weight: 400;
|
||||
color: $light-blue;
|
||||
text-shadow: 1px 1px 2px $black;
|
||||
}
|
||||
}
|
||||
|
||||
.spacer {
|
||||
margin-top: 120px;
|
||||
}
|
||||
|
||||
.add-button {
|
||||
position: absolute;
|
||||
bottom: 24px;
|
||||
right: 24px;
|
||||
}
|
||||
|
||||
.back-button {
|
||||
cursor: pointer;
|
||||
background: none;
|
||||
border: none;
|
||||
padding: 0;
|
||||
img {
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
filter: brightness(0) saturate(100%) invert(100%) sepia(6%) saturate(312%)
|
||||
hue-rotate(234deg) brightness(113%) contrast(100%);
|
||||
transition: filter 300ms ease-in-out;
|
||||
&:hover {
|
||||
filter: brightness(0) saturate(100%) invert(13%) sepia(90%)
|
||||
saturate(7329%) hue-rotate(344deg) brightness(105%) contrast(117%);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.logo img {
|
||||
width: 32px;
|
||||
height: auto;
|
||||
}
|
||||
|
||||
.error {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
position: fixed;
|
||||
top: 120px;
|
||||
left: 0;
|
||||
right: 0;
|
||||
padding: 24px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
// Resolution Buttons
|
||||
|
||||
.resolution-controls {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
gap: 12px;
|
||||
margin: 18px 0;
|
||||
}
|
||||
|
||||
.resolution-btn {
|
||||
background-color: $light-blue;
|
||||
color: $white;
|
||||
border: none;
|
||||
border-radius: 4px;
|
||||
padding: 6px 12px;
|
||||
font-size: 16px;
|
||||
cursor: pointer;
|
||||
transition: background-color 0.3s ease, transform 0.2s ease;
|
||||
}
|
||||
|
||||
.resolution-btn.active {
|
||||
background-color: $blue;
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
.resolution-btn:disabled {
|
||||
cursor: auto;
|
||||
}
|
||||
|
||||
.resolution-btn:not(.active):hover {
|
||||
background-color: $blue;
|
||||
transform: scale(1.05);
|
||||
}
|
||||
|
||||
.resolution-btn:focus {
|
||||
outline: none;
|
||||
box-shadow: 0 0 0 3px rgba(38, 143, 255, 0.5);
|
||||
}
|
||||
|
||||
.not-available {
|
||||
opacity: 0.5;
|
||||
background-color: $gray;
|
||||
}
|
||||
|
||||
.not-available:not(.active):hover {
|
||||
background-color: $gray;
|
||||
transform: scale(1);
|
||||
}
|
||||
|
||||
/*------------- RESPONSIVE -------------*/
|
||||
|
||||
@media screen and (max-width: 600px) {
|
||||
.video-header {
|
||||
padding: 12px 24px;
|
||||
}
|
||||
}
|
||||
|
||||
@media screen and (max-width: 550px) {
|
||||
form {
|
||||
flex-direction: column;
|
||||
width: 90%;
|
||||
input {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
.error-msg {
|
||||
position: relative;
|
||||
padding: 0;
|
||||
height: 12px;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
}
|
||||
|
||||
@media screen and (max-width: 500px) {
|
||||
.resolution-btn {
|
||||
border-radius: 2px;
|
||||
padding: 3px 6px;
|
||||
font-size: 14px;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,9 +8,8 @@ describe('HomeComponent', () => {
|
|||
|
||||
beforeEach(async () => {
|
||||
await TestBed.configureTestingModule({
|
||||
imports: [HomeComponent]
|
||||
})
|
||||
.compileComponents();
|
||||
imports: [HomeComponent],
|
||||
}).compileComponents();
|
||||
|
||||
fixture = TestBed.createComponent(HomeComponent);
|
||||
component = fixture.componentInstance;
|
||||
|
|
|
|||
|
|
@ -1,15 +1,13 @@
|
|||
import { Component, OnInit } from '@angular/core';
|
||||
import { Component, OnInit, ViewChild } from '@angular/core';
|
||||
import { HeaderComponent } from '../../shared/components/header/header.component';
|
||||
import { FooterComponent } from '../../shared/components/footer/footer.component';
|
||||
import { AuthComponent } from '../auth/auth.component';
|
||||
import { ActivatedRoute } from '@angular/router';
|
||||
import { RegisterComponent } from '../auth/register/register.component';
|
||||
import { HeroBannerComponent } from './hero-banner/hero-banner.component';
|
||||
import { CategoriesComponent } from './categories/categories.component';
|
||||
import { MovieService } from '../../services/movie.service';
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { LoginComponent } from '../auth/login/login.component';
|
||||
import { ForgotPasswordComponent } from '../auth/forgot-password/forgot-password.component';
|
||||
import { VerifyEmailComponent } from '../auth/verify-email/verify-email.component';
|
||||
import { ErrorToastComponent } from '../../shared/components/error-toast/error-toast.component';
|
||||
import { ErrorService } from '../../services/error.service';
|
||||
import { VideoPlayerComponent } from './video-player/video-player.component';
|
||||
import { BtnSmallComponent } from '../../shared/components/buttons/btn-small/btn-small.component';
|
||||
import { UploadMovieComponent } from './upload-movie/upload-movie.component';
|
||||
import { UserService } from '../../services/user.service';
|
||||
|
||||
@Component({
|
||||
selector: 'app-home',
|
||||
|
|
@ -17,28 +15,128 @@ import { ErrorService } from '../../services/error.service';
|
|||
imports: [
|
||||
CommonModule,
|
||||
HeaderComponent,
|
||||
FooterComponent,
|
||||
AuthComponent,
|
||||
RegisterComponent,
|
||||
LoginComponent,
|
||||
ForgotPasswordComponent,
|
||||
VerifyEmailComponent,
|
||||
ErrorToastComponent,
|
||||
HeroBannerComponent,
|
||||
CategoriesComponent,
|
||||
VideoPlayerComponent,
|
||||
BtnSmallComponent,
|
||||
UploadMovieComponent,
|
||||
],
|
||||
templateUrl: './home.component.html',
|
||||
styleUrl: './home.component.scss',
|
||||
})
|
||||
export class HomeComponent implements OnInit {
|
||||
currentRoute: any;
|
||||
@ViewChild(VideoPlayerComponent) videoPlayer!: VideoPlayerComponent;
|
||||
movies: any[] = [];
|
||||
favoriteMovies: number[] = [];
|
||||
watchedMovies: number[] = [];
|
||||
currentMovie: any[] = [];
|
||||
playMovie: string = '';
|
||||
isLoading: boolean = true;
|
||||
uploadMovieOverview: boolean = false;
|
||||
currentResolution: '360p' | '720p' | '1080p' = '720p';
|
||||
movieIsUploaded: { [resolution: string]: boolean } = {
|
||||
'360': false,
|
||||
'720': false,
|
||||
'1080': false,
|
||||
};
|
||||
|
||||
constructor(
|
||||
private route: ActivatedRoute,
|
||||
public errorService: ErrorService
|
||||
private movieService: MovieService,
|
||||
public userService: UserService
|
||||
) {}
|
||||
|
||||
ngOnInit(): void {
|
||||
this.route.url.subscribe((url) => {
|
||||
this.currentRoute = url[0]?.path || '';
|
||||
});
|
||||
async ngOnInit() {
|
||||
this.loadLikedAndWatchedMovies();
|
||||
await this.loadAllMovies();
|
||||
if (this.isWideScreen()) {
|
||||
this.currentMovie.length === 0 ? this.loadRandomMovie() : null;
|
||||
}
|
||||
}
|
||||
|
||||
async loadLikedAndWatchedMovies() {
|
||||
try {
|
||||
const userData = await this.userService.getLikedAndWatchedMovies();
|
||||
this.favoriteMovies = userData.liked_videos;
|
||||
this.watchedMovies = userData.watched_videos;
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
}
|
||||
}
|
||||
|
||||
updateLikeMovies() {
|
||||
const body = {
|
||||
liked_videos: this.favoriteMovies,
|
||||
};
|
||||
this.userService.updateLikedMovies(body);
|
||||
}
|
||||
|
||||
onRefreshPage(updatedMovies: any[]) {
|
||||
this.currentMovie = [];
|
||||
setTimeout(() => {
|
||||
this.currentMovie = updatedMovies;
|
||||
}, 1);
|
||||
}
|
||||
|
||||
onMoviesChange(updatedMovies: any[]) {
|
||||
if (this.isWideScreen()) {
|
||||
this.loadRandomMovie();
|
||||
} else {
|
||||
this.currentMovie = updatedMovies;
|
||||
}
|
||||
}
|
||||
|
||||
isWideScreen() {
|
||||
return window.innerWidth > 600;
|
||||
}
|
||||
|
||||
onMovieIsUploadedChange(newStatus: { [resolution: string]: boolean }) {
|
||||
this.movieIsUploaded = newStatus;
|
||||
}
|
||||
|
||||
onFavoriteMovieChange(favoriteMovies: any) {
|
||||
this.favoriteMovies = favoriteMovies;
|
||||
this.updateLikeMovies();
|
||||
}
|
||||
|
||||
changeResolution(resolution: '360p' | '720p' | '1080p') {
|
||||
if (this.videoPlayer && this.movieIsUploaded[resolution.replace('p', '')]) {
|
||||
this.videoPlayer.switchResolution(resolution);
|
||||
this.currentResolution = resolution;
|
||||
}
|
||||
}
|
||||
|
||||
async loadAllMovies() {
|
||||
this.isLoading = true;
|
||||
try {
|
||||
this.movies = await this.movieService.getAllMovies();
|
||||
} finally {
|
||||
this.isLoading = false;
|
||||
}
|
||||
}
|
||||
|
||||
closeVideo(): void {
|
||||
this.playMovie = '';
|
||||
}
|
||||
|
||||
playVideo(videoPath: string) {
|
||||
this.currentResolution = '720p';
|
||||
this.playMovie = videoPath;
|
||||
}
|
||||
|
||||
loadRandomMovie(): void {
|
||||
const randomIndex = Math.floor(Math.random() * this.movies.length);
|
||||
this.currentMovie = [this.movies[randomIndex]];
|
||||
}
|
||||
|
||||
currentMovieId(movieId: number) {
|
||||
let index = this.movies.findIndex((movie) => movie.id === movieId);
|
||||
if (index !== -1) {
|
||||
this.currentMovie = [];
|
||||
this.currentMovie.push(this.movies[index]);
|
||||
}
|
||||
}
|
||||
|
||||
toggleUploadMovieOverview(value: any) {
|
||||
this.uploadMovieOverview = value;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
@use "./../../../../../assets/style/colors.scss" as *;
|
||||
@use "./../../../../../assets/style/form.scss" as *;
|
||||
@use "./../../../../../assets/style/auth-layout.scss" as *;
|
||||
@use "./../../../../assets/style/colors.scss" as *;
|
||||
@use "./../../../../assets/style/form.scss" as *;
|
||||
@use "./../../../../assets/style/auth-layout.scss" as *;
|
||||
|
||||
.center {
|
||||
display: flex;
|
||||
|
|
@ -1,10 +1,10 @@
|
|||
import { CommonModule } from '@angular/common';
|
||||
import { Component, EventEmitter, Output } from '@angular/core';
|
||||
import { FormsModule, NgForm } from '@angular/forms';
|
||||
import { ErrorService } from '../../../../services/error.service';
|
||||
import { BtnLargeComponent } from '../../../../shared/components/buttons/btn-large/btn-large.component';
|
||||
import { MovieService } from '../../../../services/movie.service';
|
||||
import { LoadingDialogComponent } from '../../../../shared/components/loading-dialog/loading-dialog.component';
|
||||
import { ErrorService } from '../../../services/error.service';
|
||||
import { BtnLargeComponent } from '../../../shared/components/buttons/btn-large/btn-large.component';
|
||||
import { MovieService } from '../../../services/movie.service';
|
||||
import { LoadingDialogComponent } from '../../../shared/components/loading-dialog/loading-dialog.component';
|
||||
|
||||
@Component({
|
||||
selector: 'app-upload-movie',
|
||||
Loading…
Reference in a new issue