design movie hero banner & category

This commit is contained in:
Chneemann 2024-08-03 13:17:44 +02:00
parent 7bda7ca5d2
commit 3ab7614e7e
11 changed files with 263 additions and 3 deletions

3
frontend/.gitignore vendored
View file

@ -40,3 +40,6 @@ testem.log
# System files # System files
.DS_Store .DS_Store
Thumbs.db Thumbs.db
# Movies
src/assets/movies/*

View file

@ -1,3 +1,8 @@
<section> <section>
<app-header [browse]="true"></app-header> <app-header [browse]="true"></app-header>
<app-hero-banner [currentMovie]="currentMovie"></app-hero-banner>
<app-categories
[movies]="movies"
(currentMovieId)="currentMovieId($event)"
></app-categories>
</section> </section>

View file

@ -1,11 +1,43 @@
import { Component } from '@angular/core'; import { Component, OnInit } from '@angular/core';
import { HeaderComponent } from '../../../shared/components/header/header.component'; import { HeaderComponent } from '../../../shared/components/header/header.component';
import { HeroBannerComponent } from './hero-banner/hero-banner.component';
import { CategoriesComponent } from './categories/categories.component';
@Component({ @Component({
selector: 'app-browse', selector: 'app-browse',
standalone: true, standalone: true,
imports: [HeaderComponent], imports: [HeaderComponent, HeroBannerComponent, CategoriesComponent],
templateUrl: './browse.component.html', templateUrl: './browse.component.html',
styleUrl: './browse.component.scss', styleUrl: './browse.component.scss',
}) })
export class BrowseComponent {} export class BrowseComponent implements OnInit {
movies = [
{
id: 1,
title: 'Our Galaxy',
description:
'Experience the fascinating journey through the infinite expanse of our galaxy. "Our Galaxy" offers a detailed insight into the breathtaking structures, stars and planets of our cosmic home. Through stunning visual effects and comprehensive explanations, this documentary guides viewers through the mysteries of the universe and reveals the beauty and complexity of outer space. Perfect for astronomy lovers and the curious who want to learn more about the wonders of the universe',
category: 'documentation',
imgPath: 'galaxy.png',
videoPath: 'galaxy.mp4',
},
];
currentMovie: any[] = [];
ngOnInit(): void {
this.currentMovie.length === 0 ? this.loadRandomMovie() : null;
}
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]);
}
}
}

View file

@ -0,0 +1,28 @@
<section class="hide-scrollbar">
<div class="category">
<p>New Releases</p>
@for (movie of movies; track movie) {
<div class="movie" (click)="openCurrentMovie(movie.id)">
<img
src="./../../../../../assets/movies/banner/{{ movie.imgPath }}"
alt=""
/>
</div>
}
</div>
<div class="category">
<p>Continue Watching</p>
</div>
<div class="category">
<p>Action & Adventure</p>
</div>
<div class="category">
<p>Science Fiction & Fantasy</p>
</div>
<div class="category">
<p>Drama & Romance</p>
</div>
<div class="category">
<p>All Other Categories</p>
</div>
</section>

View file

@ -0,0 +1,44 @@
@import "./../../../../../assets/style/colors.scss";
section {
height: 60%;
padding: 0 48px;
}
.category {
height: 165px;
p {
font-size: 22px;
font-weight: 700;
}
}
.movie {
width: 213px;
height: 120px;
padding: 6px 6px 6px 0;
img {
width: 213px;
height: 120px;
transition: scale 300ms ease-in-out;
border: 2px solid rgba($black, 0);
cursor: pointer;
&:hover {
scale: 1.02;
border: 2px solid $blue;
}
}
}
// Hide scrollbar
.hide-scrollbar {
overflow: scroll;
height: 60%;
-ms-overflow-style: none;
scrollbar-width: none;
}
.hide-scrollbar::-webkit-scrollbar {
width: 0px;
}

View file

@ -0,0 +1,23 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { CategoriesComponent } from './categories.component';
describe('CategoriesComponent', () => {
let component: CategoriesComponent;
let fixture: ComponentFixture<CategoriesComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
imports: [CategoriesComponent]
})
.compileComponents();
fixture = TestBed.createComponent(CategoriesComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View file

@ -0,0 +1,21 @@
import { Component, EventEmitter, Input, Output } from '@angular/core';
@Component({
selector: 'app-categories',
standalone: true,
imports: [],
templateUrl: './categories.component.html',
styleUrl: './categories.component.scss',
})
export class CategoriesComponent {
@Input() movies: any[] = [];
@Output() currentMovieId = new EventEmitter<number>();
openCurrentMovie(movieId: number) {
this.currentMovieId.emit(movieId);
}
get documentaryMovies() {
return this.movies.filter((movie) => movie.category === 'documentary');
}
}

View file

@ -0,0 +1,14 @@
<section
class="movie-banner"
[style.backgroundImage]="'url(' + getImagePath() + ')'"
>
@if (currentMovie.length > 0) {
<div class="content">
<div class="title">{{ currentMovie[0].title }}</div>
<div class="description">
{{ currentMovie[0].description }}
</div>
<app-btn-large [value]="'Play'"></app-btn-large>
</div>
}
</section>

View file

@ -0,0 +1,49 @@
@import "./../../../../../assets/style/colors.scss";
section {
height: 40%;
position: relative;
overflow: hidden;
img {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
object-fit: cover;
}
}
.content {
position: absolute;
width: 40%;
height: 40%;
top: 140px;
left: 96px;
gap: 32px;
opacity: 0px;
}
.title {
font-size: 5vw;
font-weight: 700;
}
.description {
font-size: 1.2vw;
font-weight: 400;
overflow: scroll;
height: 40%;
margin-bottom: 24px;
-ms-overflow-style: none;
scrollbar-width: none;
&::-webkit-scrollbar {
width: 0px;
}
}
.movie-banner {
background-size: cover;
background-position: center;
background-repeat: no-repeat;
}

View file

@ -0,0 +1,23 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { HeroBannerComponent } from './hero-banner.component';
describe('HeroBannerComponent', () => {
let component: HeroBannerComponent;
let fixture: ComponentFixture<HeroBannerComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
imports: [HeroBannerComponent]
})
.compileComponents();
fixture = TestBed.createComponent(HeroBannerComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View file

@ -0,0 +1,18 @@
import { CommonModule } from '@angular/common';
import { Component, Input } from '@angular/core';
import { BtnLargeComponent } from '../../../../shared/components/btn-large/btn-large.component';
@Component({
selector: 'app-hero-banner',
standalone: true,
imports: [CommonModule, BtnLargeComponent],
templateUrl: './hero-banner.component.html',
styleUrl: './hero-banner.component.scss',
})
export class HeroBannerComponent {
@Input() currentMovie: any[] = [];
getImagePath(): string {
return `./../../../../../assets/movies/banner/${this.currentMovie[0]?.imgPath}`;
}
}