├── src ├── assets │ ├── .gitkeep │ ├── barra.png │ ├── img │ │ ├── 1.png │ │ ├── 2.png │ │ ├── 3.png │ │ ├── 4.png │ │ ├── 5.png │ │ ├── movie-poster-people-1698949-wallhere.com.jpg │ │ ├── 1000_F_477056624_XAKvgSV5jgHHDEOyoyBAuOuPBJYySzHR (2).jpg │ │ ├── 1000_F_477056624_XAKvgSV5jgHHDEOyoyBAuOuPBJYySzHR (3).jpg │ │ ├── 1000_F_477056624_XAKvgSV5jgHHDEOyoyBAuOuPBJYySzHR (4).jpg │ │ ├── 1000_F_477056624_XAKvgSV5jgHHDEOyoyBAuOuPBJYySzHR (5).jpg │ │ ├── 1000_F_477056624_XAKvgSV5jgHHDEOyoyBAuOuPBJYySzHR (6).jpg │ │ ├── 1000_F_477056624_XAKvgSV5jgHHDEOyoyBAuOuPBJYySzHR (7).jpg │ │ ├── 1000_F_477056624_XAKvgSV5jgHHDEOyoyBAuOuPBJYySzHR (8).jpg │ │ └── 1000_F_477056624_XAKvgSV5jgHHDEOyoyBAuOuPBJYySzHR (9).jpg │ ├── olho.png │ ├── sair.png │ ├── salvo.png │ ├── estrela.png │ ├── google.png │ ├── olho (1).png │ ├── pipoca.png │ ├── pra-cima.png │ ├── salvar.png │ ├── coracaoCheio.png │ ├── coracaoVazio.png │ ├── estrela-azul.png │ ├── estrela-cinza.png │ ├── menu-aberto.png │ ├── salvar-cheio.png │ ├── seta-direita.png │ ├── seta-esquerda.png │ ├── tocar-video.png │ ├── salvar-amarelo.png │ ├── estrela-azul-cheia.png │ ├── estrela-grande-amarela.png │ ├── lixeira-de-reciclagem.png │ └── estrela-azul-arredondada.png ├── app │ ├── app.component.css │ ├── app.component.html │ ├── Interfaces │ │ ├── token.ts │ │ ├── session.ts │ │ ├── Results.ts │ │ ├── user.ts │ │ ├── usuario.ts │ │ ├── genre.ts │ │ ├── provider.ts │ │ ├── FilmeLista.ts │ │ └── Filme.ts │ ├── Pipes │ │ ├── number.pipe.ts │ │ └── resenha.pipe.ts │ ├── Services │ │ ├── notificacao.service.ts │ │ ├── salvos.service.ts │ │ ├── favoritos.service.ts │ │ ├── api-filmes.service.ts │ │ └── auth.service.ts │ ├── app.component.ts │ ├── Components │ │ ├── carrossel │ │ │ ├── carrossel.component.html │ │ │ ├── carrossel.component.ts │ │ │ └── carrossel.component.css │ │ ├── dialogs │ │ │ └── dialog-voto │ │ │ │ ├── dialog-voto.component.html │ │ │ │ ├── dialog-voto.component.css │ │ │ │ └── dialog-voto.component.ts │ │ └── header │ │ │ ├── header.component.html │ │ │ ├── header.component.ts │ │ │ └── header.component.css │ ├── Guards │ │ ├── testar-numero.guard.ts │ │ └── auth.guard.ts │ ├── Pages │ │ ├── login │ │ │ ├── login.component.html │ │ │ ├── login.component.css │ │ │ └── login.component.ts │ │ ├── cadastro │ │ │ ├── cadastro.component.ts │ │ │ ├── cadastro.component.html │ │ │ └── cadastro.component.css │ │ ├── filme │ │ │ ├── filme.component.ts │ │ │ ├── filme.component.html │ │ │ └── filme.component.css │ │ ├── lista-favoritos │ │ │ ├── lista-favoritos.component.ts │ │ │ ├── lista-favoritos.component.html │ │ │ └── lista-favoritos.component.css │ │ ├── lista-assistir-depois │ │ │ ├── lista-assistir-depois.component.ts │ │ │ ├── lista-assistir-depois.component.html │ │ │ └── lista-assistir-depois.component.css │ │ └── lista-filmes │ │ │ ├── lista-filmes.component.css │ │ │ ├── lista-filmes.component.ts │ │ │ └── lista-filmes.component.html │ ├── app-routing.module.ts │ ├── app.module.ts │ └── material │ │ └── material.module.ts ├── favicon.ico ├── variaveis.css ├── main.ts ├── environments │ ├── environment.prod.ts │ └── environment.ts ├── test.ts ├── index.html ├── styles.scss ├── styles.css └── polyfills.ts ├── .firebaserc ├── .vscode ├── extensions.json ├── launch.json └── tasks.json ├── firebase.json ├── .editorconfig ├── tsconfig.app.json ├── tsconfig.spec.json ├── .browserslistrc ├── .gitignore ├── tsconfig.json ├── package.json ├── karma.conf.js ├── README.md ├── angular.json └── .firebase └── hosting.ZGlzdFx0bWRiLWZpbG1lcw.cache /src/assets/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/app/app.component.css: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/app/app.component.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /src/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Daniflav94/App-filmes/HEAD/src/favicon.ico -------------------------------------------------------------------------------- /.firebaserc: -------------------------------------------------------------------------------- 1 | { 2 | "projects": { 3 | "default": "api-filmes-1c278" 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /src/app/Interfaces/token.ts: -------------------------------------------------------------------------------- 1 | export interface Token { 2 | request_token: string; 3 | } 4 | -------------------------------------------------------------------------------- /src/assets/barra.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Daniflav94/App-filmes/HEAD/src/assets/barra.png -------------------------------------------------------------------------------- /src/assets/img/1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Daniflav94/App-filmes/HEAD/src/assets/img/1.png -------------------------------------------------------------------------------- /src/assets/img/2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Daniflav94/App-filmes/HEAD/src/assets/img/2.png -------------------------------------------------------------------------------- /src/assets/img/3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Daniflav94/App-filmes/HEAD/src/assets/img/3.png -------------------------------------------------------------------------------- /src/assets/img/4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Daniflav94/App-filmes/HEAD/src/assets/img/4.png -------------------------------------------------------------------------------- /src/assets/img/5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Daniflav94/App-filmes/HEAD/src/assets/img/5.png -------------------------------------------------------------------------------- /src/assets/olho.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Daniflav94/App-filmes/HEAD/src/assets/olho.png -------------------------------------------------------------------------------- /src/assets/sair.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Daniflav94/App-filmes/HEAD/src/assets/sair.png -------------------------------------------------------------------------------- /src/assets/salvo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Daniflav94/App-filmes/HEAD/src/assets/salvo.png -------------------------------------------------------------------------------- /src/assets/estrela.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Daniflav94/App-filmes/HEAD/src/assets/estrela.png -------------------------------------------------------------------------------- /src/assets/google.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Daniflav94/App-filmes/HEAD/src/assets/google.png -------------------------------------------------------------------------------- /src/assets/olho (1).png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Daniflav94/App-filmes/HEAD/src/assets/olho (1).png -------------------------------------------------------------------------------- /src/assets/pipoca.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Daniflav94/App-filmes/HEAD/src/assets/pipoca.png -------------------------------------------------------------------------------- /src/assets/pra-cima.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Daniflav94/App-filmes/HEAD/src/assets/pra-cima.png -------------------------------------------------------------------------------- /src/assets/salvar.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Daniflav94/App-filmes/HEAD/src/assets/salvar.png -------------------------------------------------------------------------------- /src/assets/coracaoCheio.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Daniflav94/App-filmes/HEAD/src/assets/coracaoCheio.png -------------------------------------------------------------------------------- /src/assets/coracaoVazio.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Daniflav94/App-filmes/HEAD/src/assets/coracaoVazio.png -------------------------------------------------------------------------------- /src/assets/estrela-azul.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Daniflav94/App-filmes/HEAD/src/assets/estrela-azul.png -------------------------------------------------------------------------------- /src/assets/estrela-cinza.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Daniflav94/App-filmes/HEAD/src/assets/estrela-cinza.png -------------------------------------------------------------------------------- /src/assets/menu-aberto.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Daniflav94/App-filmes/HEAD/src/assets/menu-aberto.png -------------------------------------------------------------------------------- /src/assets/salvar-cheio.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Daniflav94/App-filmes/HEAD/src/assets/salvar-cheio.png -------------------------------------------------------------------------------- /src/assets/seta-direita.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Daniflav94/App-filmes/HEAD/src/assets/seta-direita.png -------------------------------------------------------------------------------- /src/assets/seta-esquerda.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Daniflav94/App-filmes/HEAD/src/assets/seta-esquerda.png -------------------------------------------------------------------------------- /src/assets/tocar-video.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Daniflav94/App-filmes/HEAD/src/assets/tocar-video.png -------------------------------------------------------------------------------- /src/assets/salvar-amarelo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Daniflav94/App-filmes/HEAD/src/assets/salvar-amarelo.png -------------------------------------------------------------------------------- /src/app/Interfaces/session.ts: -------------------------------------------------------------------------------- 1 | export interface Session { 2 | success: boolean; 3 | session_id: string; 4 | } 5 | -------------------------------------------------------------------------------- /src/assets/estrela-azul-cheia.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Daniflav94/App-filmes/HEAD/src/assets/estrela-azul-cheia.png -------------------------------------------------------------------------------- /src/assets/estrela-grande-amarela.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Daniflav94/App-filmes/HEAD/src/assets/estrela-grande-amarela.png -------------------------------------------------------------------------------- /src/assets/lixeira-de-reciclagem.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Daniflav94/App-filmes/HEAD/src/assets/lixeira-de-reciclagem.png -------------------------------------------------------------------------------- /src/assets/estrela-azul-arredondada.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Daniflav94/App-filmes/HEAD/src/assets/estrela-azul-arredondada.png -------------------------------------------------------------------------------- /src/app/Interfaces/Results.ts: -------------------------------------------------------------------------------- 1 | import { FilmeLista } from "./FilmeLista"; 2 | 3 | export interface Results{ 4 | results: FilmeLista[] 5 | } -------------------------------------------------------------------------------- /.vscode/extensions.json: -------------------------------------------------------------------------------- 1 | { 2 | // For more information, visit: https://go.microsoft.com/fwlink/?linkid=827846 3 | "recommendations": ["angular.ng-template"] 4 | } 5 | -------------------------------------------------------------------------------- /src/assets/img/movie-poster-people-1698949-wallhere.com.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Daniflav94/App-filmes/HEAD/src/assets/img/movie-poster-people-1698949-wallhere.com.jpg -------------------------------------------------------------------------------- /src/app/Interfaces/user.ts: -------------------------------------------------------------------------------- 1 | export interface User { 2 | uid: string; 3 | email: string; 4 | senha: string; 5 | displayName: string | null; 6 | photoURL?: string; 7 | } 8 | -------------------------------------------------------------------------------- /src/assets/img/1000_F_477056624_XAKvgSV5jgHHDEOyoyBAuOuPBJYySzHR (2).jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Daniflav94/App-filmes/HEAD/src/assets/img/1000_F_477056624_XAKvgSV5jgHHDEOyoyBAuOuPBJYySzHR (2).jpg -------------------------------------------------------------------------------- /src/assets/img/1000_F_477056624_XAKvgSV5jgHHDEOyoyBAuOuPBJYySzHR (3).jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Daniflav94/App-filmes/HEAD/src/assets/img/1000_F_477056624_XAKvgSV5jgHHDEOyoyBAuOuPBJYySzHR (3).jpg -------------------------------------------------------------------------------- /src/assets/img/1000_F_477056624_XAKvgSV5jgHHDEOyoyBAuOuPBJYySzHR (4).jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Daniflav94/App-filmes/HEAD/src/assets/img/1000_F_477056624_XAKvgSV5jgHHDEOyoyBAuOuPBJYySzHR (4).jpg -------------------------------------------------------------------------------- /src/assets/img/1000_F_477056624_XAKvgSV5jgHHDEOyoyBAuOuPBJYySzHR (5).jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Daniflav94/App-filmes/HEAD/src/assets/img/1000_F_477056624_XAKvgSV5jgHHDEOyoyBAuOuPBJYySzHR (5).jpg -------------------------------------------------------------------------------- /src/assets/img/1000_F_477056624_XAKvgSV5jgHHDEOyoyBAuOuPBJYySzHR (6).jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Daniflav94/App-filmes/HEAD/src/assets/img/1000_F_477056624_XAKvgSV5jgHHDEOyoyBAuOuPBJYySzHR (6).jpg -------------------------------------------------------------------------------- /src/assets/img/1000_F_477056624_XAKvgSV5jgHHDEOyoyBAuOuPBJYySzHR (7).jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Daniflav94/App-filmes/HEAD/src/assets/img/1000_F_477056624_XAKvgSV5jgHHDEOyoyBAuOuPBJYySzHR (7).jpg -------------------------------------------------------------------------------- /src/assets/img/1000_F_477056624_XAKvgSV5jgHHDEOyoyBAuOuPBJYySzHR (8).jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Daniflav94/App-filmes/HEAD/src/assets/img/1000_F_477056624_XAKvgSV5jgHHDEOyoyBAuOuPBJYySzHR (8).jpg -------------------------------------------------------------------------------- /src/assets/img/1000_F_477056624_XAKvgSV5jgHHDEOyoyBAuOuPBJYySzHR (9).jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Daniflav94/App-filmes/HEAD/src/assets/img/1000_F_477056624_XAKvgSV5jgHHDEOyoyBAuOuPBJYySzHR (9).jpg -------------------------------------------------------------------------------- /src/app/Interfaces/usuario.ts: -------------------------------------------------------------------------------- 1 | export interface Usuario { 2 | uid: string | undefined; 3 | email: string | null; 4 | displayName: string | null; 5 | photoURL: string | undefined | null; 6 | } 7 | -------------------------------------------------------------------------------- /src/app/Interfaces/genre.ts: -------------------------------------------------------------------------------- 1 | export interface Genre { 2 | genres: [ 3 | { 4 | id: number; 5 | name: string; 6 | ativo?: boolean; 7 | } 8 | ] 9 | } 10 | -------------------------------------------------------------------------------- /src/variaveis.css: -------------------------------------------------------------------------------- 1 | :root{ 2 | --yellow: rgb(239, 214, 90); 3 | --gray1: rgb(55, 53, 53); 4 | --gray2: rgb(37, 37, 37); 5 | --blue: #76afff; 6 | --black: rgb(12, 12, 12); 7 | --blue2: #1d3248; 8 | --blue3: #112435; 9 | --font: #9cb3c9; 10 | 11 | } -------------------------------------------------------------------------------- /src/app/Pipes/number.pipe.ts: -------------------------------------------------------------------------------- 1 | import { Pipe, PipeTransform } from '@angular/core'; 2 | 3 | @Pipe({ 4 | name: 'number' 5 | }) 6 | export class NumberPipe implements PipeTransform { 7 | 8 | transform(value: number, ...args: number[]): string { 9 | return value.toFixed(1); 10 | } 11 | 12 | } 13 | -------------------------------------------------------------------------------- /src/app/Pipes/resenha.pipe.ts: -------------------------------------------------------------------------------- 1 | import { Pipe, PipeTransform } from '@angular/core'; 2 | 3 | @Pipe({ 4 | name: 'resenha' 5 | }) 6 | export class ResenhaPipe implements PipeTransform { 7 | 8 | transform(value: string, ...args: string[]): string { 9 | return value.slice(0, 360) + '...' 10 | } 11 | 12 | } 13 | -------------------------------------------------------------------------------- /firebase.json: -------------------------------------------------------------------------------- 1 | { 2 | "hosting": { 3 | "public": "dist\\tmdb-filmes", 4 | "ignore": [ 5 | "firebase.json", 6 | "**/.*", 7 | "**/node_modules/**" 8 | ], 9 | "rewrites": [ 10 | { 11 | "source": "**", 12 | "destination": "/index.html" 13 | } 14 | ] 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | # Editor configuration, see https://editorconfig.org 2 | root = true 3 | 4 | [*] 5 | charset = utf-8 6 | indent_style = space 7 | indent_size = 2 8 | insert_final_newline = true 9 | trim_trailing_whitespace = true 10 | 11 | [*.ts] 12 | quote_type = single 13 | 14 | [*.md] 15 | max_line_length = off 16 | trim_trailing_whitespace = false 17 | -------------------------------------------------------------------------------- /tsconfig.app.json: -------------------------------------------------------------------------------- 1 | /* To learn more about this file see: https://angular.io/config/tsconfig. */ 2 | { 3 | "extends": "./tsconfig.json", 4 | "compilerOptions": { 5 | "outDir": "./out-tsc/app", 6 | "types": [] 7 | }, 8 | "files": [ 9 | "src/main.ts", 10 | "src/polyfills.ts" 11 | ], 12 | "include": [ 13 | "src/**/*.d.ts" 14 | ] 15 | } 16 | -------------------------------------------------------------------------------- /src/app/Interfaces/provider.ts: -------------------------------------------------------------------------------- 1 | export interface Provider { 2 | id: number; 3 | results: { 4 | BR: { 5 | flatrate: [{ 6 | logo_path: string; 7 | provider_name: string; 8 | }], 9 | rent: [{ 10 | logo_path: string; 11 | provider_name: string; 12 | }] 13 | } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /tsconfig.spec.json: -------------------------------------------------------------------------------- 1 | /* To learn more about this file see: https://angular.io/config/tsconfig. */ 2 | { 3 | "extends": "./tsconfig.json", 4 | "compilerOptions": { 5 | "outDir": "./out-tsc/spec", 6 | "types": [ 7 | "jasmine" 8 | ] 9 | }, 10 | "files": [ 11 | "src/test.ts", 12 | "src/polyfills.ts" 13 | ], 14 | "include": [ 15 | "src/**/*.spec.ts", 16 | "src/**/*.d.ts" 17 | ] 18 | } 19 | -------------------------------------------------------------------------------- /src/main.ts: -------------------------------------------------------------------------------- 1 | import { enableProdMode } from '@angular/core'; 2 | import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'; 3 | 4 | import { AppModule } from './app/app.module'; 5 | import { environment } from './environments/environment'; 6 | 7 | if (environment.production) { 8 | enableProdMode(); 9 | } 10 | 11 | platformBrowserDynamic().bootstrapModule(AppModule) 12 | .catch(err => console.error(err)); 13 | -------------------------------------------------------------------------------- /src/environments/environment.prod.ts: -------------------------------------------------------------------------------- 1 | export const environment = { 2 | production: true, 3 | firebaseConfig: { 4 | apiKey: "AIzaSyBeNRmzC1bdzPST5j0_0ZEF7IrfhWfzTvU", 5 | authDomain: "api-filmes-1c278.firebaseapp.com", 6 | projectId: "api-filmes-1c278", 7 | storageBucket: "api-filmes-1c278.appspot.com", 8 | messagingSenderId: "811972400673", 9 | appId: "1:811972400673:web:d760fea105a78bbf3fb560" 10 | } 11 | }; 12 | -------------------------------------------------------------------------------- /src/app/Interfaces/FilmeLista.ts: -------------------------------------------------------------------------------- 1 | export interface FilmeLista { 2 | original_title: string; 3 | title: string; 4 | poster_path: string; 5 | backdrop_path: string; 6 | release_date: string; 7 | vote_average: number; 8 | overview: string; 9 | id: number; 10 | idBanco?: any; 11 | voto?: number; 12 | isFavorite?: boolean; 13 | isSave?: boolean; 14 | assistido?: boolean; 15 | genre_ids?: Number[] 16 | } -------------------------------------------------------------------------------- /src/test.ts: -------------------------------------------------------------------------------- 1 | // This file is required by karma.conf.js and loads recursively all the .spec and framework files 2 | 3 | import 'zone.js/testing'; 4 | import { getTestBed } from '@angular/core/testing'; 5 | import { 6 | BrowserDynamicTestingModule, 7 | platformBrowserDynamicTesting 8 | } from '@angular/platform-browser-dynamic/testing'; 9 | 10 | // First, initialize the Angular testing environment. 11 | getTestBed().initTestEnvironment( 12 | BrowserDynamicTestingModule, 13 | platformBrowserDynamicTesting(), 14 | ); 15 | -------------------------------------------------------------------------------- /src/app/Services/notificacao.service.ts: -------------------------------------------------------------------------------- 1 | import { Injectable } from '@angular/core'; 2 | import { MatSnackBar } from '@angular/material/snack-bar'; 3 | 4 | @Injectable({ 5 | providedIn: 'root' 6 | }) 7 | export class NotificationService { 8 | 9 | constructor(private snackbar:MatSnackBar) { } 10 | 11 | showmessage(message:string){ 12 | this.snackbar.open(message,'fechar',{ 13 | duration:3000, 14 | horizontalPosition:'center', 15 | verticalPosition:"top", 16 | panelClass: ['warning'] 17 | }) 18 | } 19 | } -------------------------------------------------------------------------------- /.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 3 | "version": "0.2.0", 4 | "configurations": [ 5 | { 6 | "name": "ng serve", 7 | "type": "pwa-chrome", 8 | "request": "launch", 9 | "preLaunchTask": "npm: start", 10 | "url": "http://localhost:4200/" 11 | }, 12 | { 13 | "name": "ng test", 14 | "type": "chrome", 15 | "request": "launch", 16 | "preLaunchTask": "npm: test", 17 | "url": "http://localhost:9876/debug.html" 18 | } 19 | ] 20 | } 21 | -------------------------------------------------------------------------------- /src/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | TmdbFilmes 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /src/app/app.component.ts: -------------------------------------------------------------------------------- 1 | import { Component } from '@angular/core'; 2 | import { FilmeLista } from './Interfaces/FilmeLista'; 3 | import { Results } from './Interfaces/Results'; 4 | import { ApiFilmesService } from './Services/api-filmes.service'; 5 | import { FavoritosService } from './Services/favoritos.service'; 6 | import { NotificationService } from './Services/notificacao.service'; 7 | 8 | @Component({ 9 | selector: 'app-root', 10 | templateUrl: './app.component.html', 11 | styleUrls: ['./app.component.css'] 12 | }) 13 | export class AppComponent { 14 | title = 'tmdb-filmes'; 15 | 16 | constructor( 17 | 18 | ) { } 19 | 20 | 21 | } 22 | -------------------------------------------------------------------------------- /.browserslistrc: -------------------------------------------------------------------------------- 1 | # This file is used by the build system to adjust CSS and JS output to support the specified browsers below. 2 | # For additional information regarding the format and rule options, please see: 3 | # https://github.com/browserslist/browserslist#queries 4 | 5 | # For the full list of supported browsers by the Angular framework, please see: 6 | # https://angular.io/guide/browser-support 7 | 8 | # You can see what browsers were selected by your queries by running: 9 | # npx browserslist 10 | 11 | last 1 Chrome version 12 | last 1 Firefox version 13 | last 2 Edge major versions 14 | last 2 Safari major versions 15 | last 2 iOS major versions 16 | Firefox ESR 17 | -------------------------------------------------------------------------------- /src/app/Interfaces/Filme.ts: -------------------------------------------------------------------------------- 1 | export interface Filme { 2 | backdrop_path: string; 3 | genres: [ 4 | { 5 | name: string 6 | } 7 | ]; 8 | id: number; 9 | overview: string; 10 | poster_path: string; 11 | release_date: string; 12 | runtime: number; 13 | title: string; 14 | vote_count: number; 15 | cast?: [ 16 | { 17 | name: string, 18 | profile_path: string, 19 | character: string, 20 | known_for_department: string 21 | } 22 | ]; 23 | crew?: [ 24 | { 25 | name: string, 26 | known_for_department: string, 27 | job: string 28 | } 29 | ] 30 | } -------------------------------------------------------------------------------- /src/styles.scss: -------------------------------------------------------------------------------- 1 | @import './variaveis.css'; 2 | @import url('https://fonts.googleapis.com/css2?family=Lilita+One&family=Open+Sans:wght@300;500;600;700;800&display=swap'); 3 | 4 | * { 5 | margin: 0; 6 | } 7 | 8 | html, 9 | body { 10 | margin: 0; 11 | font-family: Roboto, "Helvetica Neue", sans-serif; 12 | background-color: var(--black); 13 | width: 100vw; 14 | height: (100vh - 70px); 15 | display: flex; 16 | } 17 | 18 | .mat-dialog-container { 19 | background-color: rgb(36, 35, 35); 20 | } 21 | 22 | .mat-simple-snackbar-action { 23 | color: var(--yellow) !important; 24 | } 25 | 26 | .mat-select-value{ 27 | color: aliceblue; 28 | } 29 | 30 | .mat-menu-panel{ 31 | background-color: var(--gray2); 32 | } -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # See http://help.github.com/ignore-files/ for more about ignoring files. 2 | 3 | # Compiled output 4 | /dist 5 | /tmp 6 | /out-tsc 7 | /bazel-out 8 | 9 | # Node 10 | /node_modules 11 | npm-debug.log 12 | yarn-error.log 13 | 14 | # IDEs and editors 15 | .idea/ 16 | .project 17 | .classpath 18 | .c9/ 19 | *.launch 20 | .settings/ 21 | *.sublime-workspace 22 | 23 | # Visual Studio Code 24 | .vscode/* 25 | !.vscode/settings.json 26 | !.vscode/tasks.json 27 | !.vscode/launch.json 28 | !.vscode/extensions.json 29 | .history/* 30 | 31 | # Miscellaneous 32 | /.angular/cache 33 | .sass-cache/ 34 | /connect.lock 35 | /coverage 36 | /libpeerconnection.log 37 | testem.log 38 | /typings 39 | 40 | # System files 41 | .DS_Store 42 | Thumbs.db 43 | -------------------------------------------------------------------------------- /src/app/Components/carrossel/carrossel.component.html: -------------------------------------------------------------------------------- 1 | 2 |
5 |
6 |
{{listaFilmes[indexImagemAtiva].title}}
7 |
{{listaFilmes[indexImagemAtiva].overview | resenha}}
8 |
9 | 10 |
11 |
12 |
13 | 15 |
16 | 17 | -------------------------------------------------------------------------------- /src/app/Guards/testar-numero.guard.ts: -------------------------------------------------------------------------------- 1 | import { Injectable } from '@angular/core'; 2 | import { ActivatedRouteSnapshot, CanActivate, RouterStateSnapshot, UrlTree } from '@angular/router'; 3 | import { Observable } from 'rxjs'; 4 | 5 | @Injectable({ 6 | providedIn: 'root' 7 | }) 8 | export class TestarNumeroGuard implements CanActivate { 9 | canActivate( 10 | route: ActivatedRouteSnapshot, 11 | state: RouterStateSnapshot): Observable | Promise | boolean | UrlTree { 12 | //saber se o id informado é um num ou nao, se for pode seguir 13 | 14 | 15 | const id = route.paramMap.get('id') //recuperar o parametro que guarda o valor do id 16 | 17 | if(isNaN(Number(id))){ 18 | return false 19 | }else { 20 | return true 21 | } 22 | } 23 | 24 | } -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | /* To learn more about this file see: https://angular.io/config/tsconfig. */ 2 | { 3 | "compileOnSave": false, 4 | "compilerOptions": { 5 | "baseUrl": "./", 6 | "outDir": "./dist/out-tsc", 7 | "forceConsistentCasingInFileNames": true, 8 | "strict": true, 9 | "noImplicitOverride": true, 10 | "noPropertyAccessFromIndexSignature": true, 11 | "noImplicitReturns": true, 12 | "noFallthroughCasesInSwitch": true, 13 | "sourceMap": true, 14 | "declaration": false, 15 | "downlevelIteration": true, 16 | "experimentalDecorators": true, 17 | "moduleResolution": "node", 18 | "importHelpers": true, 19 | "target": "ES2022", 20 | "module": "es2020", 21 | "lib": [ 22 | "es2020", 23 | "dom" 24 | ], 25 | "useDefineForClassFields": false 26 | }, 27 | "angularCompilerOptions": { 28 | "enableI18nLegacyMessageIdFormat": false, 29 | "strictInjectionParameters": true, 30 | "strictInputAccessModifiers": true, 31 | "strictTemplates": true 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/environments/environment.ts: -------------------------------------------------------------------------------- 1 | // This file can be replaced during build by using the `fileReplacements` array. 2 | // `ng build` replaces `environment.ts` with `environment.prod.ts`. 3 | // The list of file replacements can be found in `angular.json`. 4 | 5 | export const environment = { 6 | production: false, 7 | firebaseConfig: { 8 | apiKey: "AIzaSyBeNRmzC1bdzPST5j0_0ZEF7IrfhWfzTvU", 9 | authDomain: "api-filmes-1c278.firebaseapp.com", 10 | projectId: "api-filmes-1c278", 11 | storageBucket: "api-filmes-1c278.appspot.com", 12 | messagingSenderId: "811972400673", 13 | appId: "1:811972400673:web:d760fea105a78bbf3fb560" 14 | } 15 | }; 16 | 17 | /* 18 | * For easier debugging in development mode, you can import the following file 19 | * to ignore zone related error stack frames such as `zone.run`, `zoneDelegate.invokeTask`. 20 | * 21 | * This import should be commented out in production mode because it will have a negative impact 22 | * on performance if an error is thrown. 23 | */ 24 | // import 'zone.js/plugins/zone-error'; // Included with Angular CLI. 25 | -------------------------------------------------------------------------------- /.vscode/tasks.json: -------------------------------------------------------------------------------- 1 | { 2 | // For more information, visit: https://go.microsoft.com/fwlink/?LinkId=733558 3 | "version": "2.0.0", 4 | "tasks": [ 5 | { 6 | "type": "npm", 7 | "script": "start", 8 | "isBackground": true, 9 | "problemMatcher": { 10 | "owner": "typescript", 11 | "pattern": "$tsc", 12 | "background": { 13 | "activeOnStart": true, 14 | "beginsPattern": { 15 | "regexp": "(.*?)" 16 | }, 17 | "endsPattern": { 18 | "regexp": "bundle generation complete" 19 | } 20 | } 21 | } 22 | }, 23 | { 24 | "type": "npm", 25 | "script": "test", 26 | "isBackground": true, 27 | "problemMatcher": { 28 | "owner": "typescript", 29 | "pattern": "$tsc", 30 | "background": { 31 | "activeOnStart": true, 32 | "beginsPattern": { 33 | "regexp": "(.*?)" 34 | }, 35 | "endsPattern": { 36 | "regexp": "bundle generation complete" 37 | } 38 | } 39 | } 40 | } 41 | ] 42 | } 43 | -------------------------------------------------------------------------------- /src/app/Guards/auth.guard.ts: -------------------------------------------------------------------------------- 1 | import { Injectable } from '@angular/core'; 2 | import { AngularFireAuth } from '@angular/fire/compat/auth'; 3 | import { ActivatedRouteSnapshot, CanActivate, Router, RouterStateSnapshot, UrlTree } from '@angular/router'; 4 | import { map, Observable } from 'rxjs'; 5 | import { NotificationService } from '../Services/notificacao.service'; 6 | 7 | @Injectable({ 8 | providedIn: 'root' 9 | }) 10 | export class AuthGuard implements CanActivate { 11 | 12 | constructor( 13 | private autenticacao: AngularFireAuth, 14 | private notificacao: NotificationService, 15 | private router: Router 16 | ){} 17 | 18 | canActivate( 19 | route: ActivatedRouteSnapshot, 20 | state: RouterStateSnapshot): Observable | Promise | boolean | UrlTree { 21 | return this.autenticacao.authState.pipe( 22 | map(user => { 23 | if(user){ 24 | return true 25 | }else{ 26 | this.notificacao.showmessage("Não foi possível acessar essa página, login necessário!") 27 | this.router.navigate(["/login"]) 28 | return false 29 | } 30 | }) 31 | ); 32 | } 33 | 34 | } 35 | -------------------------------------------------------------------------------- /src/app/Pages/login/login.component.html: -------------------------------------------------------------------------------- 1 |
2 | 27 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "tmdb-filmes", 3 | "version": "0.0.0", 4 | "scripts": { 5 | "ng": "ng", 6 | "start": "ng serve", 7 | "build": "ng build", 8 | "watch": "ng build --watch --configuration development", 9 | "test": "ng test" 10 | }, 11 | "private": true, 12 | "dependencies": { 13 | "@angular/animations": "^15.1.4", 14 | "@angular/cdk": "^14.2.7", 15 | "@angular/common": "^15.1.4", 16 | "@angular/compiler": "^15.1.4", 17 | "@angular/core": "^15.1.4", 18 | "@angular/fire": "^7.5.0", 19 | "@angular/forms": "^15.1.4", 20 | "@angular/material": "^14.2.7", 21 | "@angular/platform-browser": "^15.1.4", 22 | "@angular/platform-browser-dynamic": "^15.1.4", 23 | "@angular/router": "^15.1.4", 24 | "firebase": "^9.14.0", 25 | "igniteui-angular": "^14.2.12", 26 | "ng-lazyload-image": "^9.1.3", 27 | "normalize.css": "^8.0.1", 28 | "rxjs": "~7.5.0", 29 | "save": "^2.9.0", 30 | "swiper": "^9.0.4", 31 | "tslib": "^2.3.0", 32 | "zone.js": "~0.11.4" 33 | }, 34 | "devDependencies": { 35 | "@angular-devkit/build-angular": "^15.1.5", 36 | "@angular/cli": "~15.1.5", 37 | "@angular/compiler-cli": "^15.1.4", 38 | "@types/jasmine": "~4.0.0", 39 | "jasmine-core": "~4.3.0", 40 | "karma": "~6.4.0", 41 | "karma-chrome-launcher": "~3.1.0", 42 | "karma-coverage": "~2.2.0", 43 | "karma-jasmine": "~5.1.0", 44 | "karma-jasmine-html-reporter": "~2.0.0", 45 | "typescript": "~4.9.5" 46 | } 47 | } -------------------------------------------------------------------------------- /src/styles.css: -------------------------------------------------------------------------------- 1 | @import './variaveis.css'; 2 | @import url('https://fonts.googleapis.com/css2?family=Lilita+One&family=Open+Sans:wght@300;500;600;700;800&display=swap'); 3 | 4 | * { 5 | margin: 0; 6 | } 7 | 8 | html, 9 | body { 10 | margin: 0; 11 | font-family: Roboto, "Helvetica Neue", sans-serif; 12 | background: rgb(23, 41, 60); 13 | background: radial-gradient(circle, rgb(24, 43, 61) 19%, rrgb(29, 51, 73)53%, rgb(29, 50, 71) 83%); 14 | width: 100vw; 15 | height: (100vh - 70px); 16 | display: flex; 17 | } 18 | 19 | .mat-mdc-dialog-container { 20 | --mdc-dialog-container-color: rgb(23, 41, 60); 21 | background: radial-gradient(circle, rgb(24, 43, 61) 19%, rgb(29, 51, 73)53%, rgb(29, 50, 71) 83%); 22 | } 23 | 24 | 25 | .mat-mdc-snack-bar-container { 26 | --mat-mdc-snack-bar-button-color: yellow; 27 | --mdc-snackbar-container-color: var(--blue2); 28 | --mdc-snackbar-supporting-text-color: whitesmoke; 29 | } 30 | 31 | .mdc-tab__text-label{ 32 | color: whitesmoke!important; 33 | } 34 | 35 | .mdc-list-item__primary-text{ 36 | color: aliceblue!important; 37 | 38 | } 39 | 40 | .mat-mdc-menu-content, .mat-mdc-menu-content .mat-mdc-menu-item .mdc-list-item__primary-text{ 41 | font-size: 12px; 42 | } 43 | 44 | 45 | .warning{ 46 | background-color: var(--blue3); 47 | } 48 | 49 | .mat-select-value{ 50 | color: aliceblue; 51 | } 52 | 53 | .mat-mdc-menu-panel{ 54 | background-color: var(--blue2); 55 | } 56 | 57 | .mat-tooltip{ 58 | background-color: var(--blue3); 59 | } 60 | 61 | .mdc-icon-button{ 62 | fill: aliceblue!important; 63 | } 64 | 65 | 66 | -------------------------------------------------------------------------------- /karma.conf.js: -------------------------------------------------------------------------------- 1 | // Karma configuration file, see link for more information 2 | // https://karma-runner.github.io/1.0/config/configuration-file.html 3 | 4 | module.exports = function (config) { 5 | config.set({ 6 | basePath: '', 7 | frameworks: ['jasmine', '@angular-devkit/build-angular'], 8 | plugins: [ 9 | require('karma-jasmine'), 10 | require('karma-chrome-launcher'), 11 | require('karma-jasmine-html-reporter'), 12 | require('karma-coverage'), 13 | require('@angular-devkit/build-angular/plugins/karma') 14 | ], 15 | client: { 16 | jasmine: { 17 | // you can add configuration options for Jasmine here 18 | // the possible options are listed at https://jasmine.github.io/api/edge/Configuration.html 19 | // for example, you can disable the random execution with `random: false` 20 | // or set a specific seed with `seed: 4321` 21 | }, 22 | clearContext: false // leave Jasmine Spec Runner output visible in browser 23 | }, 24 | jasmineHtmlReporter: { 25 | suppressAll: true // removes the duplicated traces 26 | }, 27 | coverageReporter: { 28 | dir: require('path').join(__dirname, './coverage/tmdb-filmes'), 29 | subdir: '.', 30 | reporters: [ 31 | { type: 'html' }, 32 | { type: 'text-summary' } 33 | ] 34 | }, 35 | reporters: ['progress', 'kjhtml'], 36 | port: 9876, 37 | colors: true, 38 | logLevel: config.LOG_INFO, 39 | autoWatch: true, 40 | browsers: ['Chrome'], 41 | singleRun: false, 42 | restartOnFileChange: true 43 | }); 44 | }; 45 | -------------------------------------------------------------------------------- /src/app/Components/dialogs/dialog-voto/dialog-voto.component.html: -------------------------------------------------------------------------------- 1 |
2 | 3 |
4 | 5 |

{{nota}}

6 |
7 |
SUA AVALIAÇÃO
8 |

{{filme.title}}

9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 |
21 | 22 |
23 | -------------------------------------------------------------------------------- /src/app/Pages/cadastro/cadastro.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, OnInit } from '@angular/core'; 2 | import { FormBuilder, FormGroup, Validators } from '@angular/forms'; 3 | import { Router } from '@angular/router'; 4 | import { User } from 'src/app/Interfaces/user'; 5 | import { AuthService } from 'src/app/Services/auth.service'; 6 | import { NotificationService } from 'src/app/Services/notificacao.service'; 7 | 8 | @Component({ 9 | selector: 'app-cadastro', 10 | templateUrl: './cadastro.component.html', 11 | styleUrls: ['./cadastro.component.css'] 12 | }) 13 | export class CadastroComponent implements OnInit { 14 | 15 | public formLogin: FormGroup; 16 | 17 | constructor( 18 | fb: FormBuilder, 19 | private authService: AuthService, 20 | private router: Router, 21 | private notification: NotificationService 22 | ) { 23 | this.formLogin = fb.group({ 24 | displayName: ["", [Validators.required]], 25 | email: ["", [Validators.required, Validators.email]], 26 | senha: ["", [Validators.required, Validators.minLength(5)]] 27 | }) 28 | } 29 | 30 | verSenha: boolean = false 31 | tipoInput: string = 'password' 32 | 33 | ngOnInit(): void { 34 | } 35 | 36 | cadastrar():void{ 37 | if(this.formLogin.valid){ 38 | const user: User = this.formLogin.value 39 | user.photoURL = '/assets/img/1000_F_477056624_XAKvgSV5jgHHDEOyoyBAuOuPBJYySzHR (2).jpg' 40 | this.authService.criarUsuarioEmaileSenha(user).subscribe(resposta => { 41 | this.notification.showmessage("Cadastro realizado!") 42 | this.router.navigate(["/login"]) 43 | }) 44 | } 45 | } 46 | 47 | mudarTipoInput(): void{ 48 | if(this.tipoInput == 'password'){ 49 | this.tipoInput = 'text' 50 | this.verSenha = true 51 | }else{ 52 | this.tipoInput = 'password' 53 | this.verSenha = false 54 | } 55 | } 56 | 57 | } 58 | -------------------------------------------------------------------------------- /src/app/app-routing.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { RouterModule, Routes } from '@angular/router'; 3 | import { HeaderComponent } from './Components/header/header.component'; 4 | import { AuthGuard } from './Guards/auth.guard'; 5 | import { TestarNumeroGuard } from './Guards/testar-numero.guard'; 6 | import { CadastroComponent } from './Pages/cadastro/cadastro.component'; 7 | import { FilmeComponent } from './Pages/filme/filme.component'; 8 | import { ListaAssistirDepoisComponent } from './Pages/lista-assistir-depois/lista-assistir-depois.component'; 9 | import { ListaFavoritosComponent } from './Pages/lista-favoritos/lista-favoritos.component'; 10 | import { ListaFilmesComponent } from './Pages/lista-filmes/lista-filmes.component'; 11 | import { LoginComponent } from './Pages/login/login.component'; 12 | 13 | 14 | 15 | const rotas: Routes = [ 16 | { 17 | path: '', 18 | redirectTo: 'filmes', //redireciona o usuário para outra no momento que ele entrar nessa rota 19 | pathMatch: 'full' 20 | }, 21 | { 22 | path: 'filmes', 23 | component: ListaFilmesComponent, 24 | canActivate: [AuthGuard] 25 | }, 26 | { 27 | path: 'filmes/:idFilme', 28 | component: FilmeComponent, 29 | canActivate: [TestarNumeroGuard, AuthGuard] 30 | }, 31 | { 32 | path: 'favoritos', 33 | component: ListaFavoritosComponent, 34 | canActivate: [AuthGuard] 35 | }, 36 | { 37 | path: 'salvos', 38 | component: ListaAssistirDepoisComponent, 39 | canActivate: [AuthGuard] 40 | }, 41 | { 42 | path: 'login', 43 | component: LoginComponent 44 | }, 45 | { 46 | path: 'cadastro', 47 | component: CadastroComponent, 48 | }, 49 | { 50 | path: 'header', 51 | component: HeaderComponent, 52 | } 53 | 54 | ]; 55 | 56 | @NgModule({ 57 | imports: [RouterModule.forRoot(rotas)], 58 | exports: [RouterModule] 59 | }) 60 | export class AppRoutingModule { } 61 | 62 | -------------------------------------------------------------------------------- /src/app/Pages/filme/filme.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, OnInit } from '@angular/core'; 2 | import { MatSnackBar } from '@angular/material/snack-bar'; 3 | import { ActivatedRoute, Router } from '@angular/router'; 4 | import { Filme } from 'src/app/Interfaces/Filme'; 5 | import { Provider } from 'src/app/Interfaces/provider'; 6 | import { ApiFilmesService } from 'src/app/Services/api-filmes.service'; 7 | 8 | @Component({ 9 | selector: 'app-filme', 10 | templateUrl: './filme.component.html', 11 | styleUrls: ['./filme.component.css'] 12 | }) 13 | export class FilmeComponent implements OnInit { 14 | 15 | constructor( 16 | private rota: ActivatedRoute, 17 | private filmesService: ApiFilmesService, 18 | private snackbar: MatSnackBar 19 | ) { } 20 | 21 | filme!: Filme 22 | creditos!: Filme 23 | diretor!: string 24 | ondeAssistir: Provider = { 25 | id: 0, 26 | results: { 27 | BR: { 28 | flatrate: [{ 29 | logo_path: '', 30 | provider_name: '' 31 | }], 32 | rent: [{ 33 | logo_path: '', 34 | provider_name: '' 35 | }] 36 | } 37 | } 38 | } 39 | 40 | 41 | ngOnInit(): void { 42 | const idFilme = this.rota.snapshot.paramMap.get('idFilme') as string 43 | this.filmesService.getFilmeById(parseInt(idFilme)).subscribe( 44 | (filme) => { 45 | this.filme = filme 46 | 47 | }, 48 | (erro) => { 49 | this.snackbar.open("Erro ao encontrar filme", 'ok') 50 | } 51 | ) 52 | 53 | this.filmesService.getCreditsFilme(parseInt(idFilme)).subscribe( 54 | (credits) => { 55 | this.creditos = credits 56 | credits.crew?.forEach(element => { 57 | if(element.job == "Director"){ 58 | this.diretor = element.name 59 | } 60 | }); 61 | } 62 | ) 63 | 64 | this.filmesService.getProviders(parseInt(idFilme)).subscribe( 65 | (provedores) => { 66 | this.ondeAssistir = provedores 67 | } 68 | ) 69 | } 70 | 71 | 72 | } 73 | 74 | -------------------------------------------------------------------------------- /src/app/Pages/cadastro/cadastro.component.html: -------------------------------------------------------------------------------- 1 |
2 | 37 | 38 | -------------------------------------------------------------------------------- /src/app/Components/carrossel/carrossel.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, OnInit, OnDestroy } from '@angular/core'; 2 | import { Subscription, timer } from 'rxjs'; 3 | import { FilmeLista } from 'src/app/Interfaces/FilmeLista'; 4 | import { Results } from 'src/app/Interfaces/Results'; 5 | import { ApiFilmesService } from 'src/app/Services/api-filmes.service'; 6 | 7 | @Component({ 8 | selector: 'app-carrossel', 9 | templateUrl: './carrossel.component.html', 10 | styleUrls: ['./carrossel.component.css'] 11 | }) 12 | export class CarrosselComponent implements OnInit, OnDestroy { 13 | 14 | constructor( 15 | private filmesService: ApiFilmesService 16 | ) { } 17 | 18 | listaFilmes: FilmeLista[] = [] 19 | imagens: string[] = [] 20 | // Guarda a referência do temporizador. 21 | // Assim conseguimos interromper o temporizador 22 | // a qualquer momento 23 | timerSubs!: Subscription; 24 | private _indexImagemAtiva: number = 0; 25 | 26 | get indexImagemAtiva() { 27 | return this._indexImagemAtiva; 28 | } 29 | 30 | set indexImagemAtiva(value: number) { 31 | this._indexImagemAtiva = 32 | value < this.imagens.length ? value : 0; 33 | } 34 | 35 | ngOnInit(): void { 36 | this.listarFilmes() 37 | this.iniciarTimer(); 38 | 39 | } 40 | 41 | ngOnDestroy(): void { 42 | this.pararTimer(); 43 | } 44 | 45 | listarFilmes(): void { 46 | this.filmesService.listarFilmesNosCinemas().subscribe(lista => { 47 | lista.results.map((filme: FilmeLista) => { 48 | if(filme.overview != ''){ 49 | this.listaFilmes.push(filme) 50 | this.imagens.push('https://image.tmdb.org/t/p/original/' + filme.backdrop_path) 51 | } 52 | }) 53 | 54 | }) 55 | } 56 | 57 | iniciarTimer(): void { 58 | this.timerSubs = timer(6000).subscribe(() => { 59 | this.ativarImagem( 60 | this.indexImagemAtiva + 1 61 | ); 62 | }); 63 | } 64 | 65 | pararTimer(): void { 66 | this.timerSubs?.unsubscribe(); 67 | } 68 | 69 | ativarImagem(index: number): void { 70 | this.indexImagemAtiva = index; 71 | this.iniciarTimer(); 72 | } 73 | 74 | 75 | } 76 | -------------------------------------------------------------------------------- /src/app/Components/carrossel/carrossel.component.css: -------------------------------------------------------------------------------- 1 | .item { 2 | background-size: cover; 3 | background-repeat: no-repeat; 4 | background-position: 25% 35%; 5 | width: 100%; 6 | height: 500px; 7 | transition: all 0.5s ease-in-out; 8 | filter: sepia(6%) brightness(100%) saturate(100%) contrast(90%); 9 | -webkit-filter: sepia(6%) brightness(100%) saturate(100%) contrast(90%); 10 | -moz-filter: sepia(6%) brightness(100%) saturate(100%) contrast(90%); 11 | } 12 | 13 | 14 | .botoes-controle { 15 | display: flex; 16 | gap: 10px; 17 | justify-content: center; 18 | margin-top: 8px; 19 | z-index: 2; 20 | } 21 | 22 | .botoes-controle button { 23 | background: #ccc; 24 | border: none; 25 | border-radius: 50%; 26 | cursor: pointer; 27 | height: 15px; 28 | width: 15px; 29 | } 30 | 31 | .botoes-controle button.ativo { 32 | background: #ff0000; 33 | cursor: default; 34 | } 35 | 36 | a { 37 | text-decoration: none; 38 | color: #d9d8d8; 39 | } 40 | 41 | .texto { 42 | height: 135px; 43 | width: 100%; 44 | position: relative; 45 | top: 73%; 46 | padding: 20px 0 0 50px; 47 | background-color: rgba(0, 0, 0, 0.472); 48 | box-sizing: border-box; 49 | 50 | } 51 | 52 | 53 | .titulo { 54 | font-size: 28px; 55 | font-weight: bold; 56 | text-align: start; 57 | margin-bottom: 10px; 58 | z-index: 2; 59 | } 60 | 61 | .resenha { 62 | width: 95%; 63 | height: 80px; 64 | overflow: hidden !important; 65 | text-overflow: ellipsis; 66 | box-sizing: border-box; 67 | max-height: 8.5ch; 68 | z-index: 2; 69 | font-size: 15.5px; 70 | } 71 | 72 | @media only screen and (max-device-width: 900px) { 73 | .item { 74 | height: 200px; 75 | } 76 | 77 | .botoes-controle button { 78 | height: 12px; 79 | width: 12px; 80 | } 81 | 82 | .botoes-controle{ 83 | visibility: hidden; 84 | } 85 | 86 | .texto { 87 | height: 60px; 88 | top: 70%; 89 | padding: 17px 10px; 90 | } 91 | 92 | .titulo { 93 | font-size: 17px; 94 | margin-left: 20px; 95 | } 96 | 97 | .resenha { 98 | display: none; 99 | } 100 | } 101 | -------------------------------------------------------------------------------- /src/app/Components/dialogs/dialog-voto/dialog-voto.component.css: -------------------------------------------------------------------------------- 1 | .dialog-container { 2 | display: flex; 3 | flex-direction: column; 4 | align-items: center; 5 | justify-content: center; 6 | line-height: 22px; 7 | position: absolute; 8 | left: 0; 9 | top: 20px; 10 | width: auto; 11 | height: auto; 12 | text-align: center; 13 | } 14 | 15 | 16 | .avaliacao { 17 | position: relative; 18 | top: -55px; 19 | height: 70px; 20 | } 21 | 22 | h5 { 23 | color: var(--yellow); 24 | font-size: 14px; 25 | font-weight: 500; 26 | margin-bottom: 20px; 27 | } 28 | 29 | h3 { 30 | color: aliceblue; 31 | font-size: 20px; 32 | } 33 | 34 | span{ 35 | position: relative; 36 | width: 50px; 37 | height: 50px; 38 | text-align: center; 39 | top: -65px; 40 | left: 0; 41 | } 42 | 43 | h2 { 44 | color: aliceblue; 45 | } 46 | 47 | .estrela { 48 | width: 27px; 49 | margin-right: 5px; 50 | cursor: pointer; 51 | margin-top: 20px; 52 | } 53 | 54 | button { 55 | width: 320px; 56 | color: rgb(197, 197, 197); 57 | font-size: 13px; 58 | font-weight: bold; 59 | background-color: #25415e; 60 | padding: 10px 0; 61 | border: none; 62 | border-radius: 5px; 63 | cursor: pointer; 64 | margin-top: 20px; 65 | } 66 | 67 | .btn-close{ 68 | width: 500px; 69 | height: 40px; 70 | color: var(--yellow); 71 | background-color: transparent; 72 | font-size: 18px; 73 | text-align: end; 74 | margin: 0; 75 | position: static; 76 | } 77 | 78 | .btn-ativo { 79 | background-color: var(--yellow); 80 | color: var(--gray1); 81 | } 82 | 83 | .btn-ativo:hover { 84 | background-color: rgb(252, 209, 35); 85 | color: var(--gray1); 86 | } 87 | 88 | @media only screen and (max-device-width: 900px) { 89 | .dialog-container{ 90 | width: 300px; 91 | padding: 15px; 92 | } 93 | 94 | .btn-close{ 95 | width: 310px; 96 | } 97 | 98 | .estrela{ 99 | width: 20px; 100 | margin-top: 5px; 101 | } 102 | 103 | button{ 104 | width: 90%; 105 | } 106 | 107 | .icone-estrela-grande{ 108 | width: 95px; 109 | } 110 | 111 | 112 | h3{ 113 | font-size: 18px; 114 | } 115 | 116 | h5{ 117 | font-size: 14px; 118 | margin-bottom: 5px; 119 | } 120 | } 121 | -------------------------------------------------------------------------------- /src/app/Services/salvos.service.ts: -------------------------------------------------------------------------------- 1 | import { Injectable } from '@angular/core'; 2 | import { AngularFirestore } from '@angular/fire/compat/firestore'; 3 | import { FilmeLista } from '../Interfaces/FilmeLista'; 4 | import { NotificationService } from './notificacao.service'; 5 | import { from, Observable, EMPTY } from 'rxjs'; 6 | import { catchError, map } from 'rxjs/operators' 7 | 8 | @Injectable({ 9 | providedIn: 'root' 10 | }) 11 | export class SalvosService { 12 | 13 | constructor( 14 | private firestore: AngularFirestore, 15 | private notificacao: NotificationService 16 | ) { } 17 | 18 | public adicionarFilme(filme: FilmeLista): Observable{ 19 | const promise = this.firestore.collection("assistirDepois").add({ 20 | uidUser:localStorage.getItem('uidUser'), 21 | ...filme 22 | }) 23 | return from(promise).pipe( 24 | catchError(error => { 25 | this.notificacao.showmessage("Erro ao salvar") 26 | console.error(error) 27 | return EMPTY 28 | }) 29 | ) 30 | } 31 | 32 | public listarFilmesSalvos(): Observable{ 33 | const uidUser = localStorage.getItem('uidUser') 34 | const promise = this.firestore.collection("assistirDepois",ref => ref.where('uidUser', '==', uidUser)).get() 35 | return from(promise).pipe( 36 | map(resposta => { 37 | return resposta.docs.map(doc => { 38 | const filme: FilmeLista = doc.data() as FilmeLista 39 | filme.idBanco = doc.id 40 | return filme 41 | 42 | }) 43 | }), 44 | catchError(error => { 45 | this.notificacao.showmessage("Erro ao listar") 46 | console.error(error) 47 | return EMPTY 48 | }) 49 | ) 50 | } 51 | 52 | public editarFilmeSalvo(filme: FilmeLista): Observable{ 53 | const promise = this.firestore.collection("assistirDepois").doc(filme.idBanco).update(filme) 54 | return from(promise).pipe( 55 | catchError(error => { 56 | 57 | console.error(error) 58 | return EMPTY 59 | }) 60 | ) 61 | } 62 | 63 | public deletarFilmeSalvo(id: string){ 64 | const promise = this.firestore.collection("assistirDepois").doc(id).delete() 65 | return from(promise).pipe( 66 | catchError(error => { 67 | this.notificacao.showmessage("Erro ao excluir") 68 | console.error(error) 69 | return EMPTY 70 | }) 71 | ) 72 | } 73 | 74 | } 75 | -------------------------------------------------------------------------------- /src/app/app.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { BrowserModule } from '@angular/platform-browser'; 3 | 4 | import { AppRoutingModule } from './app-routing.module'; 5 | import { AppComponent } from './app.component'; 6 | import { BrowserAnimationsModule } from '@angular/platform-browser/animations'; 7 | import { HttpClientModule } from '@angular/common/http'; 8 | import { FormsModule, ReactiveFormsModule } from '@angular/forms'; 9 | import { ListaFilmesComponent } from './Pages/lista-filmes/lista-filmes.component'; 10 | import { FilmeComponent } from './Pages/filme/filme.component'; 11 | import { ListaFavoritosComponent } from './Pages/lista-favoritos/lista-favoritos.component'; 12 | import { MaterialModule } from './material/material.module'; 13 | import { environment } from 'src/environments/environment' 14 | import { AngularFireModule } from '@angular/fire/compat'; 15 | import { AngularFireAuthModule } from '@angular/fire/compat/auth' 16 | import { AngularFirestoreModule } from '@angular/fire/compat/firestore'; 17 | import { LoginComponent } from './Pages/login/login.component'; 18 | import { HeaderComponent } from './Components/header/header.component'; 19 | import { CadastroComponent } from './Pages/cadastro/cadastro.component'; 20 | import { ListaAssistirDepoisComponent } from './Pages/lista-assistir-depois/lista-assistir-depois.component'; 21 | import { CarrosselComponent } from './Components/carrossel/carrossel.component'; 22 | import { ResenhaPipe } from './Pipes/resenha.pipe'; 23 | import { LazyLoadImageModule } from 'ng-lazyload-image'; 24 | import { NumberPipe } from './Pipes/number.pipe'; 25 | 26 | @NgModule({ 27 | declarations: [ 28 | AppComponent, 29 | ListaFilmesComponent, 30 | FilmeComponent, 31 | ListaFavoritosComponent, 32 | LoginComponent, 33 | HeaderComponent, 34 | CadastroComponent, 35 | ListaAssistirDepoisComponent, 36 | CarrosselComponent, 37 | ResenhaPipe, 38 | NumberPipe 39 | 40 | ], 41 | imports: [ 42 | BrowserModule, 43 | AppRoutingModule, 44 | BrowserAnimationsModule, 45 | HttpClientModule, 46 | FormsModule, 47 | MaterialModule, 48 | AngularFireModule.initializeApp(environment.firebaseConfig), 49 | AngularFirestoreModule, 50 | AngularFireAuthModule, 51 | ReactiveFormsModule, 52 | LazyLoadImageModule, 53 | ], 54 | providers: [], 55 | bootstrap: [AppComponent], 56 | 57 | }) 58 | export class AppModule { } 59 | 60 | -------------------------------------------------------------------------------- /src/app/Services/favoritos.service.ts: -------------------------------------------------------------------------------- 1 | import { Injectable } from '@angular/core'; 2 | import { from, Observable, EMPTY } from 'rxjs'; 3 | import { FilmeLista } from '../Interfaces/FilmeLista'; 4 | import { Results } from '../Interfaces/Results'; 5 | import { AngularFirestore } from '@angular/fire/compat/firestore' 6 | import { NotificationService } from './notificacao.service'; 7 | import { catchError, map } from 'rxjs/operators' 8 | 9 | @Injectable({ 10 | providedIn: 'root' 11 | }) 12 | export class FavoritosService { 13 | 14 | constructor( 15 | private firestore: AngularFirestore, 16 | private notificacao: NotificationService 17 | ) { } 18 | 19 | 20 | public adicionarFavorito(filme: FilmeLista): Observable{ 21 | const promise = this.firestore.collection("filmesFavoritos").add({ 22 | uidUser:localStorage.getItem('uidUser'), 23 | ...filme 24 | }) 25 | return from(promise).pipe( 26 | catchError(error => { 27 | this.notificacao.showmessage("Erro ao favoritar") 28 | console.error(error) 29 | return EMPTY 30 | }) 31 | ) 32 | } 33 | 34 | public listarFavoritos(): Observable{ 35 | const uidUser = localStorage.getItem('uidUser') 36 | const promise = this.firestore.collection("filmesFavoritos",ref => ref.where('uidUser', '==', uidUser)).get() 37 | return from(promise).pipe( 38 | map(resposta => { 39 | return resposta.docs.map(doc => { 40 | const filme: FilmeLista = doc.data() as FilmeLista 41 | filme.idBanco = doc.id 42 | return filme 43 | 44 | }) 45 | }), 46 | catchError(error => { 47 | this.notificacao.showmessage("Erro ao listar") 48 | console.error(error) 49 | return EMPTY 50 | }) 51 | ) 52 | } 53 | 54 | public editarFilmeFavorito(filme: FilmeLista): Observable{ 55 | const promise = this.firestore.collection("filmesFavoritos").doc(filme.idBanco).update(filme) 56 | return from(promise).pipe( 57 | catchError(error => { 58 | console.error(error) 59 | return EMPTY 60 | }) 61 | ) 62 | } 63 | 64 | public deletarFilmeFavorito(id: string){ 65 | const promise = this.firestore.collection("filmesFavoritos").doc(id).delete() 66 | return from(promise).pipe( 67 | catchError(error => { 68 | this.notificacao.showmessage("Erro ao excluir") 69 | console.error(error) 70 | return EMPTY 71 | }) 72 | ) 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /src/polyfills.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * This file includes polyfills needed by Angular and is loaded before the app. 3 | * You can add your own extra polyfills to this file. 4 | * 5 | * This file is divided into 2 sections: 6 | * 1. Browser polyfills. These are applied before loading ZoneJS and are sorted by browsers. 7 | * 2. Application imports. Files imported after ZoneJS that should be loaded before your main 8 | * file. 9 | * 10 | * The current setup is for so-called "evergreen" browsers; the last versions of browsers that 11 | * automatically update themselves. This includes recent versions of Safari, Chrome (including 12 | * Opera), Edge on the desktop, and iOS and Chrome on mobile. 13 | * 14 | * Learn more in https://angular.io/guide/browser-support 15 | */ 16 | 17 | /*************************************************************************************************** 18 | * BROWSER POLYFILLS 19 | */ 20 | 21 | /** 22 | * By default, zone.js will patch all possible macroTask and DomEvents 23 | * user can disable parts of macroTask/DomEvents patch by setting following flags 24 | * because those flags need to be set before `zone.js` being loaded, and webpack 25 | * will put import in the top of bundle, so user need to create a separate file 26 | * in this directory (for example: zone-flags.ts), and put the following flags 27 | * into that file, and then add the following code before importing zone.js. 28 | * import './zone-flags'; 29 | * 30 | * The flags allowed in zone-flags.ts are listed here. 31 | * 32 | * The following flags will work for all browsers. 33 | * 34 | * (window as any).__Zone_disable_requestAnimationFrame = true; // disable patch requestAnimationFrame 35 | * (window as any).__Zone_disable_on_property = true; // disable patch onProperty such as onclick 36 | * (window as any).__zone_symbol__UNPATCHED_EVENTS = ['scroll', 'mousemove']; // disable patch specified eventNames 37 | * 38 | * in IE/Edge developer tools, the addEventListener will also be wrapped by zone.js 39 | * with the following flag, it will bypass `zone.js` patch for IE/Edge 40 | * 41 | * (window as any).__Zone_enable_cross_context_check = true; 42 | * 43 | */ 44 | 45 | /*************************************************************************************************** 46 | * Zone JS is required by default for Angular itself. 47 | */ 48 | import 'zone.js'; // Included with Angular CLI. 49 | 50 | 51 | /*************************************************************************************************** 52 | * APPLICATION IMPORTS 53 | */ 54 | -------------------------------------------------------------------------------- /src/app/Pages/lista-favoritos/lista-favoritos.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, HostListener, Input, OnInit } from '@angular/core'; 2 | import { MatDialog } from '@angular/material/dialog'; 3 | import { PageEvent } from '@angular/material/paginator'; 4 | import { DialogVotoComponent } from 'src/app/Components/dialogs/dialog-voto/dialog-voto.component'; 5 | import { Filme } from 'src/app/Interfaces/Filme'; 6 | import { FilmeLista } from 'src/app/Interfaces/FilmeLista'; 7 | import { FavoritosService } from 'src/app/Services/favoritos.service'; 8 | import { NotificationService } from 'src/app/Services/notificacao.service'; 9 | import { SalvosService } from 'src/app/Services/salvos.service'; 10 | 11 | 12 | @Component({ 13 | selector: 'app-lista-favoritos', 14 | templateUrl: './lista-favoritos.component.html', 15 | styleUrls: ['./lista-favoritos.component.css'] 16 | }) 17 | export class ListaFavoritosComponent implements OnInit { 18 | 19 | constructor( 20 | private favoritosService: FavoritosService, 21 | private notificacao: NotificationService, 22 | public dialog: MatDialog, 23 | private salvosService: SalvosService 24 | ) { } 25 | 26 | listaFavoritos: FilmeLista[] = [] 27 | listaTop5: FilmeLista[] = [] 28 | 29 | 30 | ngOnInit(): void { 31 | this.listarFavoritos() 32 | } 33 | 34 | private listarFavoritos(): void{ 35 | this.favoritosService.listarFavoritos().subscribe( 36 | (filmes) => { 37 | this.listaFavoritos = filmes 38 | } 39 | ) 40 | } 41 | 42 | public deletarFilmeFavorito(id: string, filme: FilmeLista): void{ 43 | this.favoritosService.deletarFilmeFavorito(id).subscribe( 44 | (resposta) => { 45 | this.notificacao.showmessage("Filme excluído da sua lista de favoritos!") 46 | this.listarFavoritos() 47 | this.salvosService.listarFilmesSalvos().subscribe(lista => { 48 | lista.map((film: FilmeLista) => { 49 | if(film.id == filme.id){ 50 | film.isFavorite = false 51 | this.salvosService.editarFilmeSalvo(film).subscribe() 52 | } 53 | }) 54 | }) 55 | } 56 | ) 57 | } 58 | 59 | public openDialog(filme: FilmeLista) { 60 | 61 | 62 | this.dialog.open(DialogVotoComponent, { 63 | width: "520px", 64 | height: "320px", 65 | data: filme 66 | }) 67 | } 68 | 69 | public voltarAoTopo(): void{ 70 | window.scroll(0, 0) 71 | } 72 | 73 | @HostListener('window:scroll') onWindowScroll(): void{ 74 | const botao = document.querySelector(".btn-voltar") 75 | if(window.scrollY > 7.5){ 76 | botao?.classList.add("visible") 77 | 78 | }else { 79 | botao?.classList.remove("visible") 80 | } 81 | } 82 | } 83 | 84 | 85 | 86 | -------------------------------------------------------------------------------- /src/app/Services/api-filmes.service.ts: -------------------------------------------------------------------------------- 1 | import { HttpClient, HttpHeaders } from '@angular/common/http'; 2 | import { Injectable } from '@angular/core'; 3 | import { catchError, EMPTY, Observable } from 'rxjs'; 4 | import { Filme } from '../Interfaces/Filme'; 5 | import { FilmeLista } from '../Interfaces/FilmeLista'; 6 | import { Genre } from '../Interfaces/genre'; 7 | import { Provider } from '../Interfaces/provider'; 8 | import { Results } from '../Interfaces/Results'; 9 | import { Session } from '../Interfaces/session'; 10 | import { Token } from '../Interfaces/token'; 11 | 12 | @Injectable({ 13 | providedIn: 'root' 14 | }) 15 | export class ApiFilmesService { 16 | 17 | private readonly filtroURL: string = 'https://api.themoviedb.org/3/search/movie?api_key=d0d17cbea03e1e751061b001e857b4fb&language=pt-BR&query=' 18 | private readonly baseURL = 'https://api.themoviedb.org/3/movie/' 19 | private readonly apiKey = 'api_key=818306944e112ccf75d496086ac6c42e&language=pt-BR' 20 | 21 | constructor( 22 | private http: HttpClient 23 | ) { } 24 | 25 | 26 | 27 | listarFilmesPopulares(page: number) { 28 | return this.http.get(this.baseURL + 'popular?' + this.apiKey + '&page=' + page) 29 | } 30 | 31 | listarMelhoresAvaliados(page: number) { 32 | return this.http.get(this.baseURL + 'top_rated?' + this.apiKey + '&page=' + page) 33 | } 34 | 35 | listarFilmesNosCinemas() { 36 | return this.http.get(this.baseURL + 'now_playing?' + this.apiKey + '&page=1®ion=BR') 37 | } 38 | 39 | filtrarFilmes(nomeFilme: string) { 40 | return this.http.get(this.filtroURL + nomeFilme) 41 | } 42 | 43 | getFilmeById(idFilme: number) { 44 | return this.http.get(this.baseURL + idFilme + '?' + this.apiKey) 45 | } 46 | 47 | getCreditsFilme(idFilme: number) { 48 | return this.http.get(this.baseURL + idFilme + '/credits?' + this.apiKey) 49 | } 50 | 51 | getProviders(idFilme: number) { 52 | return this.http.get(this.baseURL + idFilme + '/watch/providers?' + this.apiKey) 53 | } 54 | 55 | getGenres() { 56 | return this.http.get('https://api.themoviedb.org/3/genre/movie/list?' + this.apiKey) 57 | } 58 | 59 | discoverMovies(page: number) { 60 | return this.http.get('https://api.themoviedb.org/3/discover/movie?' + this.apiKey + '&include_adult=false&sort_by=vote_count.desc&page=' + page) 61 | } 62 | 63 | autenticarUsuarioPorToken() { 64 | return this.http.get('https://api.themoviedb.org/3/authentication/token/new?' + this.apiKey) 65 | } 66 | 67 | createSession(token: Token) { 68 | return this.http.post('https://api.themoviedb.org/3/authentication/session/new?' + this.apiKey, token) 69 | } 70 | 71 | 72 | } 73 | 74 | -------------------------------------------------------------------------------- /src/app/Pages/cadastro/cadastro.component.css: -------------------------------------------------------------------------------- 1 | .background{ 2 | background-color: rgba(0, 0, 0, 0.462); 3 | background-repeat:no-repeat; 4 | position: fixed; 5 | left: 0; 6 | right: 0; 7 | z-index: 1; 8 | display: block; 9 | height: 100%; 10 | width: 100%; 11 | } 12 | 13 | .login-container{ 14 | background-image: url(../../../assets/img/movie-poster-people-1698949-wallhere.com.jpg); 15 | width: 100vw; 16 | height: 100vh; 17 | display: flex; 18 | align-items: center; 19 | justify-content: center; 20 | padding: 30px; 21 | 22 | } 23 | 24 | .login-form{ 25 | display: flex; 26 | flex-direction: column; 27 | align-items: center; 28 | justify-content: center; 29 | width: 370px; 30 | height: 480px; 31 | background: rgb(23, 41, 60); 32 | background: radial-gradient(circle, rgb(24, 43, 61) 19%, rrgb(29, 51, 73)53%, rgb(29, 50, 71) 83%); 33 | margin-top: 230px; 34 | margin-bottom: 230px; 35 | z-index: 9999; 36 | border-radius: 8px; 37 | box-sizing: border-box; 38 | } 39 | 40 | h1{ 41 | color: rgb(233, 179, 41); 42 | margin-bottom: 10px; 43 | } 44 | 45 | form{ 46 | width: 70%; 47 | height: auto; 48 | padding: 18px; 49 | display: flex; 50 | flex-direction: column; 51 | } 52 | 53 | input{ 54 | border-radius: 5px; 55 | border: 1px solid rgb(164, 159, 145); 56 | background-color: transparent; 57 | height: 30px; 58 | color: rgb(218, 224, 230); 59 | padding: 5px; 60 | margin-top: 17px; 61 | 62 | } 63 | 64 | .senha input{ 65 | width: 96%; 66 | } 67 | 68 | .senha{ 69 | position: relative; 70 | } 71 | 72 | .validacao{ 73 | color: rgb(248, 57, 57); 74 | font-size: 12px; 75 | margin-top: 5px; 76 | } 77 | 78 | .olho{ 79 | width: 18px; 80 | position: absolute; 81 | top: 30px; 82 | left: 230px; 83 | margin: 0; 84 | cursor: pointer; 85 | } 86 | 87 | .btn{ 88 | background-color: rgb(233, 179, 41); 89 | border: none; 90 | height: 42px; 91 | padding: 5px; 92 | border-radius: 5px; 93 | margin-bottom: 5px; 94 | margin-top: 17px; 95 | text-transform: uppercase; 96 | font-weight: bold; 97 | cursor: pointer; 98 | } 99 | 100 | .cadastre-se{ 101 | display: flex; 102 | justify-content: space-between; 103 | width: 70%; 104 | font-size: 14px; 105 | } 106 | 107 | .cadastre-se a { 108 | text-decoration: none; 109 | color: rgb(233, 179, 41); 110 | cursor: pointer; 111 | } 112 | 113 | .cadastre-se span { 114 | color: rgb(224, 223, 223); 115 | } 116 | 117 | @media only screen and (max-device-width: 900px) { 118 | .login-form{ 119 | width: 90%; 120 | 121 | } 122 | 123 | .olho{ 124 | left: 210px; 125 | } 126 | } 127 | -------------------------------------------------------------------------------- /src/app/Pages/login/login.component.css: -------------------------------------------------------------------------------- 1 | .background{ 2 | background-color: rgba(0, 0, 0, 0.462); 3 | background-repeat:no-repeat; 4 | position: fixed; 5 | left: 0; 6 | right: 0; 7 | z-index: 1; 8 | display: block; 9 | height: 100%; 10 | width: 100%; 11 | } 12 | 13 | .login-container{ 14 | background-image: url(../../../assets/img/movie-poster-people-1698949-wallhere.com.jpg); 15 | width: 100vw; 16 | height: 100vh; 17 | display: flex; 18 | align-items: center; 19 | justify-content: center; 20 | 21 | } 22 | 23 | .login-form{ 24 | display: flex; 25 | flex-direction: column; 26 | align-items: center; 27 | justify-content: center; 28 | width: 370px; 29 | height: 470px; 30 | background: rgb(23, 41, 60); 31 | background: radial-gradient(circle, rgb(24, 43, 61) 19%, rrgb(29, 51, 73)53%, rgb(29, 50, 71) 83%); 32 | margin-top: 230px; 33 | margin-bottom: 230px; 34 | z-index: 9999; 35 | border-radius: 8px; 36 | box-sizing: border-box; 37 | } 38 | 39 | h1{ 40 | color: rgb(233, 179, 41); 41 | margin-bottom: 10px; 42 | } 43 | 44 | form{ 45 | width: 70%; 46 | height: auto; 47 | padding: 20px; 48 | display: flex; 49 | flex-direction: column; 50 | } 51 | 52 | input{ 53 | border-radius: 5px; 54 | border: 1px solid rgb(164, 159, 145); 55 | background-color: transparent; 56 | height: 30px; 57 | color: rgb(218, 224, 230); 58 | padding: 5px; 59 | margin-bottom: 20px; 60 | } 61 | 62 | .btn{ 63 | background-color: rgb(233, 179, 41); 64 | border: none; 65 | height: 42px; 66 | padding: 5px; 67 | border-radius: 5px; 68 | margin-bottom: 20px; 69 | text-transform: uppercase; 70 | font-weight: bold; 71 | cursor: pointer; 72 | } 73 | 74 | .btn-google{ 75 | display: flex; 76 | padding: 5px; 77 | height: 42px; 78 | border-radius: 5px; 79 | justify-content: center; 80 | align-items: center; 81 | font-weight: bold; 82 | cursor: pointer; 83 | } 84 | 85 | .btn-google img{ 86 | margin-right: 15px; 87 | } 88 | 89 | .cadastre-se{ 90 | display: flex; 91 | justify-content: space-between; 92 | width: 70%; 93 | font-size: 14px; 94 | } 95 | 96 | .cadastre-se a { 97 | text-decoration: none; 98 | color: rgb(233, 179, 41); 99 | cursor: pointer; 100 | } 101 | 102 | .cadastre-se span { 103 | color: rgb(224, 223, 223); 104 | } 105 | 106 | .olho{ 107 | width: 18px; 108 | position: absolute; 109 | top: 12px; 110 | left: 230px; 111 | margin: 0; 112 | cursor: pointer; 113 | } 114 | 115 | .senha input{ 116 | width: 96%; 117 | } 118 | .senha{ 119 | position: relative; 120 | } 121 | 122 | @media only screen and (max-device-width: 900px) { 123 | .login-form{ 124 | width: 90%; 125 | 126 | } 127 | 128 | .btn-google{ 129 | display: none; 130 | } 131 | 132 | .olho{ 133 | left: 210px; 134 | } 135 | } 136 | -------------------------------------------------------------------------------- /src/app/Pages/filme/filme.component.html: -------------------------------------------------------------------------------- 1 | 2 | 3 |
4 | 5 |
6 | 7 |
8 |

{{filme.title}} ({{filme.release_date | date: 'yyyy'}})

9 |
10 |
11 |

{{genero.name}}

12 |
13 |

14 |

Lançamento: {{filme.release_date | date: 'dd/MM/yyyy'}}

15 |

16 |

Diretor: {{diretor}}

17 | 18 |
19 | 20 |

Sinopse

21 |

{{filme.overview}}

22 | 23 |
24 |
25 |
26 | 27 |

Elenco principal

28 |
29 | 30 |
31 |
32 | 34 |
35 |

{{credito.name}}

36 |

{{credito.character}}

37 |
38 |
39 |
40 | 41 |
42 | 43 |

Onde assistir

44 | 45 |
46 |
47 |
Ainda não consta em nenhum catálogo!
48 |
49 |
50 | {{provedor.provider_name}} 52 |
53 |
54 | {{provedor.provider_name}} 56 |
57 |
58 |
59 |
60 |
61 |
-------------------------------------------------------------------------------- /src/app/Pages/lista-favoritos/lista-favoritos.component.html: -------------------------------------------------------------------------------- 1 | 2 | 3 |
4 |
5 |

Nenhum filme por aqui...

6 |
7 |
8 |
9 | 10 |

Lista de favoritos

11 |
12 |
13 |
14 | 16 |
17 |
18 |
19 |

{{ filme.title }}

20 | ( {{filme.release_date | date: "yyyy"}} ) 21 |
22 | 26 |
27 |
28 |
29 | 30 |

{{filme.vote_average | number}}

31 | 39 | 40 |
41 |
42 |

{{filme.overview}}

43 | 44 |
45 |
46 | 47 |
48 | 49 |
50 |
51 | 52 |
53 | 54 | 55 |
56 | 57 |
58 |
59 | -------------------------------------------------------------------------------- /src/app/Pages/login/login.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, OnInit } from '@angular/core'; 2 | import { FormBuilder, FormGroup, Validators } from '@angular/forms'; 3 | import { Router } from '@angular/router'; 4 | import { User } from 'src/app/Interfaces/user'; 5 | import { AuthService } from 'src/app/Services/auth.service'; 6 | import { NotificationService } from 'src/app/Services/notificacao.service'; 7 | 8 | @Component({ 9 | selector: 'app-login', 10 | templateUrl: './login.component.html', 11 | styleUrls: ['./login.component.css'] 12 | }) 13 | export class LoginComponent implements OnInit { 14 | 15 | public formLogin: FormGroup; 16 | 17 | constructor( 18 | fb: FormBuilder, 19 | private authService: AuthService, 20 | private router: Router, 21 | private notification: NotificationService 22 | ) { 23 | this.formLogin = fb.group({ 24 | email: ["", [Validators.required, Validators.email]], 25 | senha: ["", [Validators.required]] 26 | }) 27 | } 28 | verSenha: boolean = false 29 | tipoInput: string = 'password' 30 | 31 | ngOnInit(): void { 32 | 33 | } 34 | 35 | public entrar(): void{ 36 | if(this.formLogin.valid){ 37 | const credenciais: User = this.formLogin.value 38 | this.authService.autenticarPorEmaileSenha(credenciais).subscribe(resposta => { 39 | this.router.navigate(["/filmes"]) 40 | let usuario = resposta.user 41 | console.log(usuario) 42 | localStorage.setItem("uidUser", usuario.uid) 43 | 44 | this.authService.listarUsuarios().subscribe(resposta => { 45 | this.authService.getCurrentUser().subscribe(resp => { 46 | resposta.map((user: User) => { 47 | if(resp?.email == user.email){ 48 | localStorage.setItem("user-name", user.displayName as string) 49 | localStorage.setItem("user-photo", user.photoURL as string) 50 | } 51 | }) 52 | }) 53 | }) 54 | }) 55 | } 56 | else{ 57 | this.notification.showmessage("Verifique os dados digitados e tente novamente!") 58 | } 59 | } 60 | 61 | public entrarComGoogle(): void{ 62 | let usuario: any 63 | this.authService.autenticarPeloGoogle().subscribe(resposta => { 64 | this.router.navigate(["/filmes"]) 65 | const usuario = resposta.user 66 | localStorage.setItem("uidUser", usuario.uid) 67 | this.authService.listarUsuarios().subscribe(resposta => { 68 | this.authService.getCurrentUser().subscribe(resp => { 69 | resposta.map((user: User) => { 70 | if(resp?.email == user.email){ 71 | localStorage.setItem("user-photo", user.photoURL as string) 72 | localStorage.setItem("user-name", user.displayName as string) 73 | usuario.displayName = user.displayName 74 | usuario.photoURL = user.photoURL 75 | usuario.uid = user.uid 76 | } 77 | }) 78 | }) 79 | }) 80 | }) 81 | } 82 | 83 | mudarTipoInput(): void{ 84 | if(this.tipoInput == 'password'){ 85 | this.tipoInput = 'text' 86 | this.verSenha = true 87 | }else{ 88 | this.tipoInput = 'password' 89 | this.verSenha = false 90 | } 91 | } 92 | 93 | } 94 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # TMDB Filmes 2 | 3 | Aplicação web que consome a API do The Movie DB. 4 | 5 | Link deploy: https://api-filmes-1c278.web.app/login 6 | 7 | ### Objetivo 8 | Criar uma aplicação de filmes personalizável, onde o usuário pode se cadastrar e fazer login, salvar filmes, avaliar, favoritar e fazer pesquisas. 9 | 10 | ### Descrição 11 | Para acessar a aplicação, o usuário deve se cadastrar e fazer login ou fazer a autenticação pelo Google, devido ao guard de autenticação não será possível acessar sem se autenticar. Quando é feita a autenticação se for o primeiro login do usuário ele será salvo no banco de dados. 12 | 13 | Foram feitas diversas requisições para a API do The Movie DB para obter as listas de filmes e suas informações completas. 14 | 15 | Todas as páginas possuem uma navBar que exibe o nome do usuário logado e um avatar padrão que pode ser alterado. Também possui um input para pesquisar filmes pelo nome e as listas salvas pelo usuário de favoritos e salvos para assistir depois . A página inicial renderiza listas de lançamentos, filmes com melhores avaliações e filmes mais populares. Possui uma aba de Gêneros que faz uma filtragem nos filmes pelo gênero que foi selecionado. Caso o usuário queira visualizar mais informações de um filme, é possível clicar no poster e será redirecionado para uma página com informações completas do filme desejado. Todos os cards dos filmes possuem botão de favoritar e salvar, as listas podem ser visualizadas clicando nos botões correspondentes na navbar. Caso o usuário queira, pode remover um filme salvo clicando no ícone de lixeira e também pode fazer sua própria avaliação do filme clicando na estrela azul. Na lista de assistir depois, há um botão de assistido que salva esse filme em outra lista, caso o usuário queira ver seu histórico de filmes assistidos. 16 | A aplicação está responsiva e pode ser acessada via mobile ou tablets. 17 | 18 | ### Tecnologias 19 | - Angular (front-end); 20 | - Firebase (back-end). 21 | 22 | ### Imagens 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | ### **Versão mobile 35 | 36 | 37 | 38 | 39 | 40 | 41 | -------------------------------------------------------------------------------- /src/app/material/material.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core' 2 | 3 | //material 4 | import { MatAutocompleteModule } from '@angular/material/autocomplete' 5 | import { MatBadgeModule } from '@angular/material/badge' 6 | import { MatButtonModule } from '@angular/material/button' 7 | import { MatButtonToggleModule } from '@angular/material/button-toggle' 8 | import { MatCardModule } from '@angular/material/card' 9 | import { MatCheckboxModule } from '@angular/material/checkbox' 10 | import { MatChipsModule } from '@angular/material/chips' 11 | import { MatCommonModule } from '@angular/material/core' 12 | import { MatDatepickerModule } from '@angular/material/datepicker' 13 | import { MatDialogModule } from '@angular/material/dialog' 14 | import { MatDividerModule } from '@angular/material/divider' 15 | import { MatExpansionModule } from '@angular/material/expansion' 16 | import { MatFormFieldModule } from '@angular/material/form-field' 17 | import { MatGridListModule } from '@angular/material/grid-list' 18 | import { MatIconModule } from '@angular/material/icon' 19 | import { MatInputModule } from '@angular/material/input' 20 | import { MatListModule } from '@angular/material/list' 21 | import { MatMenuModule } from '@angular/material/menu' 22 | import { MatPaginatorModule } from '@angular/material/paginator' 23 | import { MatProgressBarModule } from '@angular/material/progress-bar' 24 | import { MatProgressSpinnerModule } from '@angular/material/progress-spinner' 25 | import { MatRadioModule } from '@angular/material/radio' 26 | import { MatRippleModule } from '@angular/material/core' 27 | import { MatSelectModule } from '@angular/material/select' 28 | import { MatSidenavModule } from '@angular/material/sidenav' 29 | import { MatSlideToggleModule } from '@angular/material/slide-toggle' 30 | import { MatSliderModule } from '@angular/material/slider' 31 | import { MatSnackBarModule } from '@angular/material/snack-bar' 32 | import { MatSortModule } from '@angular/material/sort' 33 | import { MatStepperModule } from '@angular/material/stepper' 34 | import { MatTableModule } from '@angular/material/table' 35 | import { MatTabsModule } from '@angular/material/tabs' 36 | import { MatToolbarModule } from '@angular/material/toolbar' 37 | import { MatTreeModule } from '@angular/material/tree' 38 | import { MatTooltipModule } from '@angular/material/tooltip' 39 | import {DragDropModule} from '@angular/cdk/drag-drop' 40 | 41 | @NgModule({ 42 | exports: [ 43 | MatAutocompleteModule, 44 | MatBadgeModule, 45 | MatButtonModule, 46 | MatButtonToggleModule, 47 | MatCardModule, 48 | MatCheckboxModule, 49 | MatChipsModule, 50 | MatCommonModule, 51 | MatDatepickerModule, 52 | MatDialogModule, 53 | MatDividerModule, 54 | MatExpansionModule, 55 | MatFormFieldModule, 56 | MatGridListModule, 57 | MatIconModule, 58 | MatInputModule, 59 | MatListModule, 60 | MatMenuModule, 61 | MatPaginatorModule, 62 | MatProgressBarModule, 63 | MatProgressSpinnerModule, 64 | MatRadioModule, 65 | MatRippleModule, 66 | MatSelectModule, 67 | MatSidenavModule, 68 | MatSlideToggleModule, 69 | MatSliderModule, 70 | MatSnackBarModule, 71 | MatSortModule, 72 | MatStepperModule, 73 | MatTableModule, 74 | MatTabsModule, 75 | MatToolbarModule, 76 | MatTreeModule, 77 | MatTooltipModule, 78 | DragDropModule 79 | ] 80 | }) 81 | export class MaterialModule { 82 | 83 | } 84 | 85 | -------------------------------------------------------------------------------- /src/app/Pages/lista-favoritos/lista-favoritos.component.css: -------------------------------------------------------------------------------- 1 | .container { 2 | display: flex; 3 | width: 100%; 4 | margin-top: 110px; 5 | justify-content: center; 6 | } 7 | 8 | h1 { 9 | color: whitesmoke; 10 | margin-top: 80px; 11 | text-align: center; 12 | width: 100%; 13 | } 14 | 15 | 16 | .subtitulo-lista { 17 | display: flex; 18 | align-items: center; 19 | margin-top: 30px; 20 | color: whitesmoke; 21 | margin-bottom: 30px; 22 | } 23 | 24 | .lista-filmes { 25 | display: flex; 26 | flex-direction: column; 27 | width: auto; 28 | flex-wrap: wrap; 29 | box-sizing: border-box; 30 | } 31 | 32 | .card-filme { 33 | display: flex; 34 | background-color: var(--blue2); 35 | border: none; 36 | width: 850px; 37 | height: 160px; 38 | border-radius: 5px; 39 | box-sizing: border-box; 40 | margin-bottom: 20px; 41 | color: var(--font); 42 | } 43 | 44 | .poster { 45 | width: 110px; 46 | height: 100%; 47 | border-radius: 5px 0 0 5px; 48 | margin-right: 30px; 49 | } 50 | 51 | .conteudo-card { 52 | height: 100%; 53 | } 54 | 55 | 56 | .header { 57 | display: flex; 58 | align-items: center; 59 | justify-content: space-between; 60 | width: 100%; 61 | height: 40px; 62 | margin: 0; 63 | } 64 | 65 | .header span { 66 | font-size: 15px; 67 | } 68 | 69 | .titulo-filme { 70 | display: flex; 71 | } 72 | 73 | .titulo-filme p { 74 | font-size: 15px; 75 | color: whitesmoke; 76 | font-weight: bold; 77 | margin-right: 10px; 78 | } 79 | 80 | .avaliacao { 81 | display: flex; 82 | width: 9%; 83 | height: 20px; 84 | align-items: center; 85 | color: white; 86 | font-size: 14px; 87 | margin-bottom: 10px; 88 | } 89 | 90 | .informacoes p { 91 | font-size: 13px; 92 | padding: 0 20px 20px 0; 93 | width: 97%; 94 | height: 80px; 95 | overflow: hidden !important; 96 | text-overflow: ellipsis; 97 | box-sizing: border-box; 98 | } 99 | 100 | 101 | .icone-estrela { 102 | margin-right: 10px; 103 | } 104 | 105 | .icone-estrela-azul { 106 | cursor: pointer; 107 | display: flex; 108 | justify-content: center; 109 | background-color: transparent; 110 | border: none; 111 | border-radius: 4px; 112 | padding: 5px; 113 | width: auto; 114 | margin-left: 20px; 115 | } 116 | 117 | .icone-estrela-azul p { 118 | color: rgb(215, 215, 215); 119 | font-size: 14px; 120 | margin: 0 0 0 5px; 121 | } 122 | 123 | .icone-estrela-azul:hover { 124 | opacity: 0.8; 125 | } 126 | 127 | 128 | .btn-voltar{ 129 | visibility: hidden; 130 | } 131 | 132 | .visible{ 133 | visibility: visible; 134 | position: fixed; 135 | bottom: 10px; 136 | right: 0; 137 | background-color: transparent; 138 | border: none; 139 | cursor: pointer; 140 | } 141 | 142 | @media only screen and (max-device-width: 900px) { 143 | .lista-filmes { 144 | width: 100%; 145 | } 146 | 147 | .subtitulo-lista { 148 | margin-top: 5px; 149 | color: whitesmoke; 150 | margin-bottom: 30px; 151 | font-size: 14px; 152 | } 153 | 154 | .card-filme { 155 | width: 395px; 156 | height: 200px; 157 | box-sizing: border-box; 158 | margin: 0 5px 10px 10px; 159 | border-radius: 0; 160 | } 161 | 162 | .poster { 163 | width: 130px; 164 | height: 100%; 165 | border-radius: 0; 166 | margin-right: 25px; 167 | } 168 | 169 | .conteudo-card { 170 | height: 100%; 171 | align-self: center; 172 | } 173 | 174 | 175 | .header { 176 | display: flex; 177 | align-items: center; 178 | justify-content: space-between; 179 | width: 100%; 180 | height: 30px; 181 | margin: 10px 0; 182 | } 183 | 184 | .header span { 185 | display: none; 186 | } 187 | 188 | 189 | .titulo-filme p { 190 | margin-right: 5px; 191 | } 192 | 193 | .informacoes p { 194 | font-size: 12.5px; 195 | height: 100px; 196 | } 197 | 198 | 199 | } 200 | -------------------------------------------------------------------------------- /angular.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "./node_modules/@angular/cli/lib/config/schema.json", 3 | "version": 1, 4 | "newProjectRoot": "projects", 5 | "projects": { 6 | "tmdb-filmes": { 7 | "projectType": "application", 8 | "schematics": { 9 | "@schematics/angular:class": { 10 | "skipTests": true 11 | }, 12 | "@schematics/angular:component": { 13 | "skipTests": true 14 | }, 15 | "@schematics/angular:directive": { 16 | "skipTests": true 17 | }, 18 | "@schematics/angular:guard": { 19 | "skipTests": true 20 | }, 21 | "@schematics/angular:interceptor": { 22 | "skipTests": true 23 | }, 24 | "@schematics/angular:pipe": { 25 | "skipTests": true 26 | }, 27 | "@schematics/angular:resolver": { 28 | "skipTests": true 29 | }, 30 | "@schematics/angular:service": { 31 | "skipTests": true 32 | } 33 | }, 34 | "root": "", 35 | "sourceRoot": "src", 36 | "prefix": "app", 37 | "architect": { 38 | "build": { 39 | "builder": "@angular-devkit/build-angular:browser", 40 | "options": { 41 | "outputPath": "dist/tmdb-filmes", 42 | "index": "src/index.html", 43 | "main": "src/main.ts", 44 | "polyfills": "src/polyfills.ts", 45 | "tsConfig": "tsconfig.app.json", 46 | "assets": [ 47 | "src/favicon.ico", 48 | "src/assets" 49 | ], 50 | "styles": [ 51 | "./node_modules/@angular/material/prebuilt-themes/indigo-pink.css", 52 | "src/styles.css" 53 | ], 54 | "scripts": [] 55 | }, 56 | "configurations": { 57 | "production": { 58 | "budgets": [ 59 | { 60 | "type": "initial", 61 | "maximumWarning": "2mb", 62 | "maximumError": "3mb" 63 | }, 64 | { 65 | "type": "anyComponentStyle", 66 | "maximumWarning": "2mb", 67 | "maximumError": "4mb" 68 | } 69 | ], 70 | "fileReplacements": [ 71 | { 72 | "replace": "src/environments/environment.ts", 73 | "with": "src/environments/environment.prod.ts" 74 | } 75 | ], 76 | "outputHashing": "all" 77 | }, 78 | "development": { 79 | "buildOptimizer": false, 80 | "optimization": false, 81 | "vendorChunk": true, 82 | "extractLicenses": false, 83 | "sourceMap": true, 84 | "namedChunks": true 85 | } 86 | }, 87 | "defaultConfiguration": "production" 88 | }, 89 | "serve": { 90 | "builder": "@angular-devkit/build-angular:dev-server", 91 | "configurations": { 92 | "production": { 93 | "browserTarget": "tmdb-filmes:build:production" 94 | }, 95 | "development": { 96 | "browserTarget": "tmdb-filmes:build:development" 97 | } 98 | }, 99 | "defaultConfiguration": "development" 100 | }, 101 | "extract-i18n": { 102 | "builder": "@angular-devkit/build-angular:extract-i18n", 103 | "options": { 104 | "browserTarget": "tmdb-filmes:build" 105 | } 106 | }, 107 | "test": { 108 | "builder": "@angular-devkit/build-angular:karma", 109 | "options": { 110 | "main": "src/test.ts", 111 | "polyfills": "src/polyfills.ts", 112 | "tsConfig": "tsconfig.spec.json", 113 | "karmaConfig": "karma.conf.js", 114 | "assets": [ 115 | "src/favicon.ico", 116 | "src/assets" 117 | ], 118 | "styles": [ 119 | "./node_modules/@angular/material/prebuilt-themes/indigo-pink.css", 120 | "src/styles.css" 121 | ], 122 | "scripts": [] 123 | } 124 | } 125 | } 126 | } 127 | }, 128 | "cli": { 129 | "analytics": false 130 | } 131 | } 132 | -------------------------------------------------------------------------------- /src/app/Pages/lista-assistir-depois/lista-assistir-depois.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, HostListener, OnInit } from '@angular/core'; 2 | import { MatDialog } from '@angular/material/dialog'; 3 | import { PageEvent } from '@angular/material/paginator'; 4 | import { DialogVotoComponent } from 'src/app/Components/dialogs/dialog-voto/dialog-voto.component'; 5 | import { Filme } from 'src/app/Interfaces/Filme'; 6 | import { FilmeLista } from 'src/app/Interfaces/FilmeLista'; 7 | import { Results } from 'src/app/Interfaces/Results'; 8 | import { FavoritosService } from 'src/app/Services/favoritos.service'; 9 | import { NotificationService } from 'src/app/Services/notificacao.service'; 10 | import { SalvosService } from 'src/app/Services/salvos.service'; 11 | 12 | @Component({ 13 | selector: 'app-lista-assistir-depois', 14 | templateUrl: './lista-assistir-depois.component.html', 15 | styleUrls: ['./lista-assistir-depois.component.css'] 16 | }) 17 | export class ListaAssistirDepoisComponent implements OnInit { 18 | 19 | constructor( 20 | private notificacao: NotificationService, 21 | public dialog: MatDialog, 22 | private salvosService: SalvosService, 23 | private favoritosService: FavoritosService 24 | ) { } 25 | 26 | ngOnInit(): void { 27 | this.listarFilmes() 28 | this.listarFavoritos() 29 | } 30 | 31 | listaAssistirDepois: FilmeLista[] = [] 32 | listaAssistidos: FilmeLista[] = [] 33 | verAssistidos: boolean = false 34 | listaFavoritos: FilmeLista[] = [] 35 | 36 | 37 | public listarFilmes(): void { 38 | this.salvosService.listarFilmesSalvos().subscribe(lista => { 39 | this.verificarFavoritos(lista) 40 | lista.forEach((filme: FilmeLista) => { 41 | if(filme.assistido == true){ 42 | this.listaAssistidos.push(filme) 43 | }else{ 44 | this.listaAssistirDepois.push(filme) 45 | } 46 | }); 47 | }) 48 | } 49 | 50 | public marcarComoAssistido(filme: FilmeLista): void { 51 | const index = this.listaAssistirDepois.indexOf(filme) 52 | this.listaAssistirDepois.splice(index, 1) 53 | filme.assistido = true 54 | this.salvosService.editarFilmeSalvo(filme).subscribe() 55 | this.listaAssistidos.push(filme) 56 | } 57 | 58 | public deletarFilme(id: string, filme: FilmeLista): void{ 59 | this.salvosService.deletarFilmeSalvo(id).subscribe( 60 | (resposta) => { 61 | this.notificacao.showmessage("Filme excluído da sua lista de favoritos!") 62 | const index = this.listaAssistirDepois.indexOf(filme) 63 | this.listaAssistirDepois.splice(index, 1) 64 | 65 | } 66 | ) 67 | } 68 | 69 | public visualizarAssistidos(): void{ 70 | this.verAssistidos = !this.verAssistidos 71 | } 72 | 73 | public openDialog(filme: FilmeLista) { 74 | this.dialog.open(DialogVotoComponent, { 75 | width: "520px", 76 | height: "320px", 77 | data: filme 78 | }) 79 | } 80 | 81 | public favoritar(filmeFavorito: FilmeLista): void { 82 | filmeFavorito.isFavorite = true 83 | 84 | this.favoritosService.adicionarFavorito(filmeFavorito).subscribe( 85 | (resposta) => { 86 | this.notificacao.showmessage("Filme inserido na lista de favoritos!") 87 | } 88 | ) 89 | this.salvosService.editarFilmeSalvo(filmeFavorito).subscribe() 90 | } 91 | 92 | public listarFavoritos(): void { 93 | this.favoritosService.listarFavoritos().subscribe( 94 | (lista) => { 95 | this.listaFavoritos = lista 96 | }) 97 | } 98 | 99 | public verificarFavoritos(listaFilmes: Results): void { 100 | this.favoritosService.listarFavoritos().subscribe( 101 | (lista) => { 102 | for(let filme of lista){ 103 | for(let listaFilme of listaFilmes.results){ 104 | if(filme.id === listaFilme.id){ 105 | listaFilme.isFavorite = true 106 | } 107 | } 108 | 109 | } 110 | }) 111 | } 112 | 113 | 114 | public voltarAoTopo(): void{ 115 | window.scroll(0, 0) 116 | } 117 | 118 | @HostListener('window:scroll') onWindowScroll(): void{ 119 | const botao = document.querySelector(".btn-voltar") 120 | if(window.scrollY > 7.5){ 121 | botao?.classList.add("visible") 122 | 123 | }else { 124 | botao?.classList.remove("visible") 125 | } 126 | } 127 | 128 | } 129 | -------------------------------------------------------------------------------- /.firebase/hosting.ZGlzdFx0bWRiLWZpbG1lcw.cache: -------------------------------------------------------------------------------- 1 | favicon.ico,1674836454830,2c19690e9587bae12f419b34d2edeecc76808099540a9c9f4ea6194116cfc8f7 2 | assets/barra.png,1674836454791,c59944a919c26b04aaf49d741678ceac00ef74e64ce376c38288ba12f41d5df5 3 | assets/coracaoCheio.png,1674836454791,ab01e9bdc3486919dd725ac7684772ab35129658f854117e4deb87912fb95333 4 | assets/coracaoVazio.png,1674836454824,5698a3950f061173d94f600326189a595fa820992ebdc3aaad0e4f29104451a7 5 | assets/estrela-azul-arredondada.png,1675016546804,a188939094236a73360a139f242cd7385f2f31510809216fd2cdeacc581d0348 6 | assets/estrela-azul-cheia.png,1675012664578,8614a9634b038a3d63802739cfb96fac2f0d93079ddceb0d20611794d274643d 7 | assets/estrela-azul.png,1675012610682,112d78602207c73bf9dafa3e6864951ba5146fc51b7c1e5690884ae0aa5eb5c5 8 | assets/estrela-cinza.png,1675014780687,f98cd1765179ecfe9f088e648a8ec8c8ca1c1e4bb508157fe336e628138c841f 9 | assets/estrela-grande-amarela.png,1675452910753,536a1e4debc7374200dfb6e18f14a95c3a7264ebd6debb9771fc32ab54e1bea4 10 | assets/estrela.png,1674836454825,c88ee7de18acc3cd5344490b38129796a86f7821821cc18a9fc2ee12d8f1818f 11 | assets/google.png,1675184729184,6550bb39895a85f41a322f4c0c2455f31e87d979740f10b8223cc0cc47074614 12 | assets/lixeira-de-reciclagem.png,1675128828255,0d71b3b1f356ced95891583173199787998b75728b0fceedd5401aa50b73e473 13 | assets/menu-aberto.png,1676051918619,0d865d33bcbc577a41117811d43adffc93264b94bb3641aea804a2de46a64a20 14 | assets/olho (1).png,1679422191846,8b70db2251a2a59351d0ca3c5d303e22b5608e2dc5ccf0fb00b997e93f9bfdcc 15 | assets/olho.png,1679422167096,adbb5b29320a87586fdcdbe87047a0f622536b33b088ec8c20c49a3e58cf1402 16 | assets/pipoca.png,1674836454826,f5cf84a8290c75df2a805b13711152255fa2ecf859a070eac87bcf4a361e5e26 17 | assets/pra-cima.png,1676140856715,b2d8462124a9ec453a6a97d968455c5da2c37e22c23dacdc05165194e706159f 18 | assets/sair.png,1675948443313,e7b5c1ee442d172863c58a68f495f7c92b5e9996b62577233a45a62e03c827ca 19 | assets/salvar-amarelo.png,1675370259902,5ae1a1d2d771554e12a3949f175e29f5bc3bc87557b6466a1d242dd1489eb9bf 20 | assets/salvar-cheio.png,1674946348028,d8a582c2e1b603e6db4da14f528bf9a3ef91979b92b8c089cc7f74a2145e2898 21 | assets/salvar.png,1674946305301,b2015de37d8f5fa2fe07383636156614802d66fcdb730433629c6dc65b8ff35c 22 | assets/salvo.png,1675012855945,6aa6088c70d69648d1c11e61156b25990bcefc65495792584d9a25e79a30b57d 23 | assets/seta-direita.png,1674836454827,a2f3aa3629ba5face28c2317ef350f6c7538907e8a4b56d2a64ede2c4ca92b46 24 | assets/seta-esquerda.png,1674836454827,5f1eb0c52d4eaa8fb029b548ad7b0560643d5713d6abc72b50ead814dd533ce8 25 | assets/tocar-video.png,1675446598129,b794ef8adee7db8c2bc36021ecf4c87156de3a45c34c492553c64d25df83f63d 26 | assets/img/1.png,1679341658279,a46312d3dafe330c241b7ff1b9c4e4cabd9be2e2579ad2d893404f5a2ceb6a81 27 | assets/img/1000_F_477056624_XAKvgSV5jgHHDEOyoyBAuOuPBJYySzHR (2).jpg,1675886502535,51835f4478b876cf1c8e76badfdd8bc14bd02a539bef94480ea23cd1be37b61f 28 | assets/img/1000_F_477056624_XAKvgSV5jgHHDEOyoyBAuOuPBJYySzHR (3).jpg,1675886884510,487dd34a55c49bbaf2097d4d730ab3d64c5630c54a8990334720955df77a60cf 29 | assets/img/1000_F_477056624_XAKvgSV5jgHHDEOyoyBAuOuPBJYySzHR (4).jpg,1675947152455,9b2e1ff124a8eba1c3a92ac8b0bf9b600720759fbcf2177c76263c1b6bae9478 30 | assets/img/1000_F_477056624_XAKvgSV5jgHHDEOyoyBAuOuPBJYySzHR (5).jpg,1675947217237,c34fa52f45c6521d6df2da96ff59b5e581c9eac28f7add152b67d71160ca4bbb 31 | assets/img/1000_F_477056624_XAKvgSV5jgHHDEOyoyBAuOuPBJYySzHR (6).jpg,1675947259660,c70b10c1961c57ce03613b6a7fb98accad075854033d2312cb51176b2ab34a30 32 | assets/img/1000_F_477056624_XAKvgSV5jgHHDEOyoyBAuOuPBJYySzHR (7).jpg,1675947309228,748af1617258e08edee4f119170214068072272b372ae361520c6980652189c0 33 | assets/img/1000_F_477056624_XAKvgSV5jgHHDEOyoyBAuOuPBJYySzHR (8).jpg,1675947341644,b67f82eb9f0a8051cdc8c6f0634e78e0656c95c0abdebd1a4d5bd4f91fc3f494 34 | assets/img/1000_F_477056624_XAKvgSV5jgHHDEOyoyBAuOuPBJYySzHR (9).jpg,1675947389094,989142d0b4e6001dbf6123066a309e10e83af9507b38cc36932cc8b66f4c5c37 35 | assets/img/2.png,1679341658280,ec472c3ac80fa6f315caa6f8fafac5a0950cb22df9ac2c7c02136d777ece166e 36 | assets/img/3.png,1679341658283,87c0b82c1e377440bbc029cc70521b2fe5c28b089afece018407d037ee1883fb 37 | assets/img/4.png,1679341658284,d1bb617a3e266f65f8207bc52d2cdf71470669379655854c68a528859a97fec0 38 | assets/img/5.png,1679341658285,60b47039ac1b626ac35751cd5cb1122aa11c6d780624bc436275844660eef9c1 39 | assets/img/movie-poster-people-1698949-wallhere.com.jpg,1675179397743,02202a40b68af2a0b41fa6a079a2606d5bd5397f35256c3a6259c99b7f1cc2ba 40 | index.html,1679501933016,be20361b1194117bb8c0ff1c8f2e9f2be7e89c652126126052fad69954b78d36 41 | 3rdpartylicenses.txt,1679501929219,f8da493a2b714a62ff26bff44ba537839e348ffc221f26ee04b4f39c22134279 42 | polyfills.ef5b10d98fdbfcd1.js,1679501929218,1bdaabef77b91840a2ad2b16879020e1e9f3ad3d9739e33e0e86e0dd6bc9b761 43 | runtime.c03c6ce8e759153f.js,1679501929219,82c64f4a2fec7a65bd0de9b8a823c56291145b576b8ad398190df3445a8e284e 44 | styles.546cc8b292cb9628.css,1679501929218,bb739dbc5e45437f1d5e2ffe0964cfe6eeec35176552e234e387444bc16c826a 45 | movie-poster-people-1698949-wallhere.com.cd1d7930edc3d9d7.jpg,1679501929218,02202a40b68af2a0b41fa6a079a2606d5bd5397f35256c3a6259c99b7f1cc2ba 46 | main.923e4bbc82639548.js,1679501929219,7d4d1daaf1df14a390e4f3128a962e3cf47ff8ca79885a26a6fef18dc45ac504 47 | -------------------------------------------------------------------------------- /src/app/Components/header/header.component.html: -------------------------------------------------------------------------------- 1 |
2 | 55 | 56 | 87 |
88 | 89 | 90 |
91 |
92 |

{{listaPesquisa.results.length}} resultados encontrados para "{{nomeFilme}}"

93 |
94 |
95 |
96 | 98 |
99 |
100 |
101 | 102 |

{{filme.vote_average | number}}

103 |
104 |
106 |
108 |
109 | 110 | 116 |
117 |
118 |
119 |
120 |
121 | 122 |
123 | -------------------------------------------------------------------------------- /src/app/Pages/lista-assistir-depois/lista-assistir-depois.component.html: -------------------------------------------------------------------------------- 1 | 2 | 3 |
4 |
5 |
6 | 7 |

Salvos para assistir depois

8 |

Assistidos

9 |
10 |
11 | 13 | 14 |
15 |
16 |
17 |
18 |

Nenhum filme por aqui...

19 |
20 |
21 | 23 |
24 |
25 |
26 |

{{ filme.title }}

27 | ( {{filme.release_date | date: "yyyy"}} ) 28 |
29 |
30 | 34 | 37 |
38 | 39 |
40 |
41 |
42 | 43 |

{{filme.vote_average | number}}

44 |
45 |
46 |

{{filme.overview}}

47 | 48 |
49 |
50 |
51 | 52 |
53 | 54 |
55 |
56 |
57 |

Nenhum filme por aqui...

58 |
59 |
60 | 62 |
63 |
64 |
65 |

{{ filme.title }}

66 | ( {{filme.release_date | date: "yyyy"}} ) 67 |
68 |
71 |
73 |
74 |
75 |
76 | 77 |

{{filme.vote_average | number}}

78 | 87 | 88 |
89 |
90 |

{{filme.overview}}

91 | 92 |
93 |
94 |
95 |
96 | 97 |
98 | 99 |
100 | 101 |
102 |
103 | -------------------------------------------------------------------------------- /src/app/Pages/lista-assistir-depois/lista-assistir-depois.component.css: -------------------------------------------------------------------------------- 1 | .container{ 2 | display: flex; 3 | flex-direction: column; 4 | align-items: center; 5 | width: 100%; 6 | margin-top: 110px; 7 | } 8 | 9 | h1{ 10 | color: whitesmoke; 11 | margin-top: 20px; 12 | text-align: center; 13 | font-size: 18px; 14 | width: 100%; 15 | } 16 | 17 | .subtitulo-lista{ 18 | display: flex; 19 | align-items: center; 20 | margin-top: 30px; 21 | color: whitesmoke; 22 | margin-bottom: 30px; 23 | } 24 | 25 | .header-section{ 26 | margin-bottom: 20px; 27 | width: 61%; 28 | } 29 | 30 | .btn-acoes{ 31 | background-color: transparent; 32 | color: var(--blue); 33 | cursor: pointer; 34 | border: none; 35 | } 36 | 37 | .btn-acoes:hover{ 38 | color: rgb(24, 100, 214); 39 | } 40 | 41 | .titulo-pesquisa{ 42 | color: white; 43 | margin-bottom: 20px; 44 | padding: 50px 100px; 45 | } 46 | 47 | .lista-filmes { 48 | display: flex; 49 | flex-direction: column; 50 | width: auto; 51 | flex-wrap: wrap; 52 | box-sizing: border-box; 53 | } 54 | 55 | .card-filme{ 56 | display: flex; 57 | background-color: var(--blue2); 58 | border: none; 59 | width: 880px; 60 | height: 170px; 61 | border-radius: 5px; 62 | box-sizing: border-box; 63 | margin-bottom: 20px; 64 | color: var(--font); 65 | } 66 | 67 | .poster{ 68 | width: 120px; 69 | height: 100%; 70 | border-radius: 5px 0 0 5px; 71 | margin-right: 30px; 72 | } 73 | 74 | .conteudo-card{ 75 | height: 100%; 76 | } 77 | 78 | 79 | .header{ 80 | display: flex; 81 | align-items: center; 82 | justify-content: space-between; 83 | width: 100%; 84 | height: 50px; 85 | margin: 0; 86 | } 87 | 88 | .header span{ 89 | font-size: 15px; 90 | } 91 | 92 | .botoes{ 93 | display: flex; 94 | align-items: flex-start; 95 | } 96 | 97 | .btn-assistido{ 98 | background-color: transparent; 99 | border: none; 100 | border-radius: 5px; 101 | color: aliceblue; 102 | font-size: 10px; 103 | cursor: pointer; 104 | display: flex; 105 | flex-direction: column; 106 | align-items: center; 107 | padding: 5px; 108 | margin: 10px 5px; 109 | } 110 | 111 | .btn-assistido:hover{ 112 | opacity: 0.8; 113 | } 114 | 115 | .btn-lixeira{ 116 | background-color: transparent; 117 | border: none; 118 | border-radius: 5px; 119 | color: aliceblue; 120 | font-size: 10px; 121 | cursor: pointer; 122 | padding: 5px; 123 | margin: 10px 5px; 124 | } 125 | 126 | .btn-lixeira:hover{ 127 | opacity: 0.8; 128 | } 129 | 130 | .titulo-filme{ 131 | display: flex; 132 | } 133 | 134 | .titulo-filme p{ 135 | font-size: 15px; 136 | color: whitesmoke; 137 | font-weight: bold; 138 | margin-right: 10px; 139 | } 140 | 141 | .avaliacao{ 142 | display: flex; 143 | width: 9%; 144 | height: 20px; 145 | align-items: center; 146 | color: white; 147 | font-size: 14px; 148 | margin-bottom: 10px; 149 | } 150 | 151 | .informacoes p{ 152 | font-size: 13px; 153 | padding: 0 20px 20px 0; 154 | width: 98%; 155 | height: 80px; 156 | overflow: hidden !important; 157 | text-overflow: ellipsis; 158 | box-sizing: border-box; 159 | } 160 | 161 | 162 | .icone-estrela{ 163 | margin-right: 10px; 164 | } 165 | 166 | .icone-estrela-azul{ 167 | cursor: pointer; 168 | display: flex; 169 | justify-content: center; 170 | background-color: transparent; 171 | border: none; 172 | border-radius: 4px; 173 | padding: 5px; 174 | width: auto; 175 | margin-left: 20px; 176 | } 177 | 178 | .icone-estrela-azul p{ 179 | color: rgb(215, 215, 215); 180 | font-size: 14px; 181 | margin: 0 0 0 5px; 182 | } 183 | 184 | .icone-estrela-azul:hover{ 185 | opacity: 0.8; 186 | } 187 | 188 | .icone-coracao{ 189 | margin-right: 10px; 190 | } 191 | 192 | .icone-coracao:hover{ 193 | cursor: pointer; 194 | } 195 | 196 | .btn-voltar{ 197 | visibility: hidden; 198 | } 199 | 200 | .visible{ 201 | visibility: visible; 202 | position: fixed; 203 | bottom: 10px; 204 | right: 0; 205 | background-color: transparent; 206 | border: none; 207 | cursor: pointer; 208 | } 209 | 210 | ::ng-deep #mat-select-value-1{ 211 | color: aliceblue; 212 | } 213 | 214 | @media only screen and (max-device-width: 900px) { 215 | 216 | .container{ 217 | align-items: start; 218 | } 219 | 220 | .lista-filmes { 221 | width: 100%; 222 | } 223 | 224 | .subtitulo-lista { 225 | margin-top: 5px; 226 | color: whitesmoke; 227 | margin-bottom: 30px; 228 | font-size: 14px; 229 | width: 300px; 230 | } 231 | 232 | .card-filme { 233 | width: 395px; 234 | height: 200px; 235 | box-sizing: border-box; 236 | margin: 0 5px 10px 10px; 237 | border-radius: 0; 238 | 239 | } 240 | 241 | .poster { 242 | width: 130px; 243 | height: 100%; 244 | border-radius: 0; 245 | margin-right: 25px; 246 | } 247 | 248 | .conteudo-card { 249 | height: 100%; 250 | align-self: center; 251 | } 252 | 253 | 254 | .header { 255 | display: flex; 256 | align-items: center; 257 | justify-content: space-between; 258 | width: 100%; 259 | height: 30px; 260 | margin: 10px 0; 261 | } 262 | 263 | .header span { 264 | display:none; 265 | } 266 | 267 | .botoes img{ 268 | width: 16px; 269 | } 270 | 271 | .btn-assistido{ 272 | margin: 5px 0; 273 | } 274 | 275 | 276 | .titulo-filme p { 277 | margin-right: 5px; 278 | font-size: 13px; 279 | color: rgb(229, 226, 226); 280 | } 281 | 282 | .informacoes p { 283 | font-size: 12.5px; 284 | height: 100px; 285 | } 286 | 287 | 288 | mat-paginator{ 289 | background-color: transparent; 290 | border: 1px solid #26405c; 291 | border-radius: 5px; 292 | color: aliceblue; 293 | width: 420px; 294 | } 295 | } 296 | 297 | 298 | 299 | -------------------------------------------------------------------------------- /src/app/Pages/filme/filme.component.css: -------------------------------------------------------------------------------- 1 | .container { 2 | width: 100%; 3 | height: auto; 4 | display: flex; 5 | flex-direction: column; 6 | justify-content: center; 7 | align-items: center; 8 | background-size: cover; 9 | margin-bottom: 50px; 10 | align-self: center; 11 | } 12 | 13 | .fundo-poster { 14 | object-fit: cover; 15 | object-position: top; 16 | position: absolute; 17 | left: 0; 18 | top: 0; 19 | margin: 0; 20 | width: 105%; 21 | height: 100%; 22 | opacity: 0.6; 23 | mask-image: linear-gradient(to top, transparent 25%, black 100%); 24 | } 25 | 26 | .caixa { 27 | position: relative; 28 | z-index: 2; 29 | display: flex; 30 | align-items: center; 31 | justify-content: center; 32 | width: 75%; 33 | height: 60%; 34 | margin: 90px; 35 | } 36 | 37 | .titulo { 38 | color: white; 39 | z-index: 2; 40 | position: relative; 41 | font-size: 40px; 42 | margin-bottom: 25px; 43 | } 44 | 45 | .conteudo { 46 | color: white; 47 | z-index: 2; 48 | position: relative; 49 | display: flex; 50 | flex-direction: column; 51 | justify-content: center; 52 | font-size: 17px; 53 | margin-left: 80px; 54 | } 55 | 56 | .conteudo h3 { 57 | margin-bottom: 10px; 58 | } 59 | 60 | .detalhes { 61 | display: flex; 62 | width: 100%; 63 | margin-bottom: 25px; 64 | font-size: 16px; 65 | } 66 | 67 | .separador { 68 | margin: 0 10px; 69 | } 70 | 71 | .generos { 72 | display: flex; 73 | width: auto; 74 | } 75 | 76 | .genero~.genero::before { 77 | content: ", "; 78 | } 79 | 80 | .poster { 81 | border-radius: 8px; 82 | width: 15rem; 83 | height: 22rem; 84 | z-index: 2; 85 | } 86 | 87 | .atores { 88 | display: flex; 89 | justify-content: center; 90 | color: white; 91 | } 92 | 93 | .titulo-section { 94 | display: flex; 95 | width: 75%; 96 | align-items: center; 97 | color: aliceblue; 98 | margin: 50px 0 30px 0; 99 | } 100 | 101 | .ator { 102 | display: flex; 103 | flex-direction: column; 104 | margin-right: 30px; 105 | width: 100px; 106 | height: 250px; 107 | border-radius: 5px; 108 | } 109 | 110 | .ator_info { 111 | padding: 10px 0; 112 | text-align: center; 113 | } 114 | 115 | .nome-ator { 116 | font-size: 15px; 117 | font-weight: bold; 118 | margin-bottom: 5px; 119 | } 120 | 121 | .papel { 122 | font-size: 12px; 123 | } 124 | 125 | .fotos-atores { 126 | border-radius: 50%; 127 | object-fit: cover; 128 | width: 100px; 129 | height: 100px; 130 | z-index: 2; 131 | } 132 | 133 | .onde-assistir { 134 | display: flex; 135 | flex-direction: row; 136 | color: aliceblue; 137 | } 138 | 139 | .logos { 140 | border-radius: 50%; 141 | width: 60px; 142 | height: 60px; 143 | margin-right: 10px; 144 | object-fit: cover; 145 | } 146 | 147 | img { 148 | color: aliceblue; 149 | } 150 | 151 | @media only screen and (max-device-width: 900px) { 152 | 153 | .container { 154 | align-items: flex-start; 155 | width: 100vw; 156 | } 157 | 158 | .fundo-poster { 159 | object-fit: contain; 160 | left: 0; 161 | top: 50px; 162 | width: 100%; 163 | height: auto; 164 | opacity: 0.7; 165 | } 166 | 167 | .caixa { 168 | width: 100%; 169 | height: auto; 170 | padding: 0; 171 | margin: 180px 0 30px 30px; 172 | box-sizing: border-box; 173 | flex-direction: column; 174 | align-items: flex-start; 175 | } 176 | 177 | .titulo { 178 | position: relative; 179 | font-size: 22px; 180 | margin-bottom: 25px; 181 | width: 80%; 182 | 183 | } 184 | 185 | .conteudo { 186 | color: var(--font); 187 | width: 80%; 188 | z-index: 1; 189 | position: relative; 190 | display: flex; 191 | flex-direction: column; 192 | justify-content: center; 193 | align-items: flex-start; 194 | font-size: 15px; 195 | margin-left: 0; 196 | box-sizing: border-box; 197 | } 198 | 199 | .detalhes { 200 | width: 240px; 201 | margin-bottom: 15px; 202 | font-size: 13px; 203 | flex-direction: column; 204 | line-height: 20px; 205 | } 206 | 207 | .separador { 208 | display: none; 209 | } 210 | 211 | .generos { 212 | flex-wrap: wrap; 213 | } 214 | 215 | .genero~.genero::before { 216 | content: ", "; 217 | } 218 | 219 | .poster { 220 | display: none; 221 | } 222 | 223 | h3 { 224 | font-size: 15px; 225 | } 226 | 227 | .sinopse { 228 | font-size: 13px; 229 | } 230 | 231 | .atores { 232 | display: flex; 233 | justify-content: flex-start; 234 | color: white; 235 | width: 90%; 236 | height: auto; 237 | overflow-x: scroll; 238 | -webkit-overflow-scrolling: touch; 239 | padding: 20px; 240 | margin: 0; 241 | } 242 | 243 | .titulo-section { 244 | font-size: 13px; 245 | 246 | } 247 | 248 | .ator { 249 | display: flex; 250 | flex-direction: column; 251 | margin-right: 20px; 252 | width: 80px; 253 | height: auto; 254 | border-radius: 5px; 255 | } 256 | 257 | .nome-ator { 258 | font-size: 14px; 259 | } 260 | 261 | .papel { 262 | font-size: 11px; 263 | } 264 | 265 | .fotos-atores { 266 | border-radius: 50%; 267 | object-fit: cover; 268 | width: 80px; 269 | height: 80px; 270 | z-index: 2; 271 | 272 | } 273 | 274 | .onde-assistir { 275 | display: flex; 276 | flex-direction: row; 277 | justify-content: flex-start; 278 | color: aliceblue; 279 | padding: 20px; 280 | overflow-x: scroll; 281 | -webkit-overflow-scrolling: touch; 282 | width: 90%; 283 | } 284 | 285 | .logos { 286 | border-radius: 50%; 287 | width: 50px; 288 | height: 50px; 289 | margin-right: 8px; 290 | object-fit: cover; 291 | } 292 | 293 | div{ 294 | width: 100%; 295 | } 296 | 297 | } 298 | -------------------------------------------------------------------------------- /src/app/Components/header/header.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, OnInit } from '@angular/core'; 2 | import { Router } from '@angular/router'; 3 | import { mergeMap } from 'rxjs'; 4 | import { FilmeLista } from 'src/app/Interfaces/FilmeLista'; 5 | import { Results } from 'src/app/Interfaces/Results'; 6 | import { User } from 'src/app/Interfaces/user'; 7 | import { Usuario } from 'src/app/Interfaces/usuario'; 8 | import { ApiFilmesService } from 'src/app/Services/api-filmes.service'; 9 | import { AuthService } from 'src/app/Services/auth.service'; 10 | import { FavoritosService } from 'src/app/Services/favoritos.service'; 11 | import { NotificationService } from 'src/app/Services/notificacao.service'; 12 | import { SalvosService } from 'src/app/Services/salvos.service'; 13 | 14 | @Component({ 15 | selector: 'app-header', 16 | templateUrl: './header.component.html', 17 | styleUrls: ['./header.component.css'] 18 | }) 19 | export class HeaderComponent implements OnInit { 20 | 21 | constructor( 22 | private filmeService: ApiFilmesService, 23 | private favoritosService: FavoritosService, 24 | private notificacao: NotificationService, 25 | private salvosService: SalvosService, 26 | private authService: AuthService, 27 | private router: Router 28 | ) { } 29 | 30 | /* usuario: any = { 31 | displayName: '', 32 | photoURL: '', 33 | } */ 34 | 35 | usuarioPhoto: any = localStorage.getItem('user-photo') 36 | usuarioName: any = localStorage.getItem('user-name') 37 | usuario: any 38 | 39 | ngOnInit(): void { 40 | this.getUser() 41 | 42 | } 43 | 44 | listaPesquisa!: Results 45 | listaFavoritos: FilmeLista[] = [] 46 | listaSalvos: FilmeLista[] = [] 47 | pesquisa: boolean = false 48 | nomeFilme: string = '' 49 | filmeJaAdicionado: boolean = false 50 | filmeJaSalvo: boolean = false 51 | 52 | avatares: string[] = ['/assets/img/1000_F_477056624_XAKvgSV5jgHHDEOyoyBAuOuPBJYySzHR (2).jpg','/assets/img/1000_F_477056624_XAKvgSV5jgHHDEOyoyBAuOuPBJYySzHR (3).jpg', '/assets/img/1000_F_477056624_XAKvgSV5jgHHDEOyoyBAuOuPBJYySzHR (4).jpg', '/assets/img/1000_F_477056624_XAKvgSV5jgHHDEOyoyBAuOuPBJYySzHR (5).jpg', '/assets/img/1000_F_477056624_XAKvgSV5jgHHDEOyoyBAuOuPBJYySzHR (6).jpg', '/assets/img/1000_F_477056624_XAKvgSV5jgHHDEOyoyBAuOuPBJYySzHR (7).jpg', '/assets/img/1000_F_477056624_XAKvgSV5jgHHDEOyoyBAuOuPBJYySzHR (8).jpg', '/assets/img/1000_F_477056624_XAKvgSV5jgHHDEOyoyBAuOuPBJYySzHR (9).jpg'] 53 | 54 | pesquisar(pesquisa: string) { 55 | this.filmeService.filtrarFilmes(pesquisa).subscribe( 56 | (filmes) => { 57 | this.listaPesquisa = filmes 58 | this.pesquisa = true 59 | this.verificarFavoritos(filmes) 60 | this.verificarSalvos(filmes) 61 | } 62 | ) 63 | } 64 | 65 | limparPesquisa() { 66 | this.listaPesquisa.results = [] 67 | this.pesquisa = false 68 | this.nomeFilme = '' 69 | } 70 | 71 | public favoritar(filmeFavorito: FilmeLista): void { 72 | filmeFavorito.isFavorite = true 73 | this.listaFavoritos.forEach(filme => { 74 | if (filme.id == filmeFavorito.id) { 75 | this.filmeJaAdicionado = true 76 | } 77 | }) 78 | 79 | if (this.filmeJaAdicionado) { 80 | this.notificacao.showmessage("Ops! Filme já consta na lista de favoritos!") 81 | } else { 82 | this.favoritosService.adicionarFavorito(filmeFavorito).subscribe( 83 | (resposta) => { 84 | this.notificacao.showmessage("Filme inserido na lista de favoritos!") 85 | } 86 | ) 87 | } 88 | } 89 | 90 | public listarFavoritos(): void { 91 | this.favoritosService.listarFavoritos().subscribe( 92 | (lista) => { 93 | this.listaFavoritos = lista 94 | }) 95 | } 96 | 97 | public verificarFavoritos(listaFilmes: Results): void { 98 | this.favoritosService.listarFavoritos().subscribe( 99 | (lista) => { 100 | for (let filme of lista) { 101 | for (let listaFilme of listaFilmes.results) { 102 | if (filme.id === listaFilme.id) { 103 | listaFilme.isFavorite = true 104 | } 105 | } 106 | 107 | } 108 | }) 109 | } 110 | 111 | public salvar(filmeSalvo: FilmeLista): void { 112 | filmeSalvo.isSave = true 113 | this.listaSalvos.forEach(filme => { 114 | if (filme.id == filmeSalvo.id) { 115 | this.filmeJaSalvo = true 116 | } 117 | }) 118 | 119 | if (this.filmeJaSalvo) { 120 | this.notificacao.showmessage("Ops! Filme já consta na lista de assistir depois!") 121 | } else { 122 | this.salvosService.adicionarFilme(filmeSalvo).subscribe( 123 | (resposta) => { 124 | this.notificacao.showmessage("Filme inserido na lista!") 125 | } 126 | ) 127 | } 128 | } 129 | 130 | public listarSalvos(): void { 131 | this.salvosService.listarFilmesSalvos().subscribe( 132 | (lista) => { 133 | this.listaSalvos = lista 134 | }) 135 | } 136 | 137 | public verificarSalvos(listaFilmes: Results): void { 138 | this.salvosService.listarFilmesSalvos().subscribe( 139 | (lista) => { 140 | for (let filme of lista) { 141 | for (let listaFilme of listaFilmes.results) { 142 | if (filme.id === listaFilme.id) { 143 | listaFilme.isSave = true 144 | } 145 | } 146 | 147 | } 148 | }) 149 | } 150 | 151 | public getUser(): void { 152 | this.authService.listarUsuarios().subscribe(resposta => { 153 | this.authService.getCurrentUser().subscribe(resp => { 154 | resposta.map((user: User) => { 155 | if(resp?.email == user.email){ 156 | this.usuarioName = user.displayName 157 | this.usuarioPhoto = user.photoURL 158 | this.usuario = user 159 | } 160 | }) 161 | }) 162 | }) 163 | } 164 | 165 | public mudarAvatar(avatar: string): void { 166 | this.usuarioPhoto = avatar 167 | this.usuario.photoURL = avatar 168 | localStorage.removeItem('user-photo'); 169 | localStorage.setItem("user-photo", avatar) 170 | this.authService.editarUsuario(this.usuario).subscribe() 171 | } 172 | 173 | public logout(): void { 174 | this.authService.logout().subscribe(() => { 175 | this.notificacao.showmessage("Até logo!") 176 | this.router.navigate(["/login"]) 177 | } 178 | ) 179 | } 180 | 181 | } 182 | -------------------------------------------------------------------------------- /src/app/Services/auth.service.ts: -------------------------------------------------------------------------------- 1 | import { Injectable } from '@angular/core'; 2 | import { AngularFireAuth } from '@angular/fire/compat/auth'; 3 | import { catchError, EMPTY, from, map, Observable, tap } from 'rxjs'; 4 | import { GoogleAuthProvider, getAuth, updateProfile } from 'firebase/auth'; 5 | import { NotificationService } from './notificacao.service'; 6 | import { User } from '../Interfaces/user'; 7 | import { ApiFilmesService } from './api-filmes.service'; 8 | import { Token } from '../Interfaces/token'; 9 | import { Router } from '@angular/router'; 10 | import { AngularFirestore } from '@angular/fire/compat/firestore'; 11 | import { Usuario } from '../Interfaces/usuario'; 12 | 13 | 14 | 15 | @Injectable({ 16 | providedIn: 'root' 17 | }) 18 | export class AuthService { 19 | 20 | constructor( 21 | private firebaseAuth: AngularFireAuth, 22 | private firestore: AngularFirestore, 23 | private notification: NotificationService, 24 | private apiTMDB: ApiFilmesService, 25 | private router: Router 26 | ) { } 27 | 28 | 29 | public autenticarPeloGoogle(): Observable { 30 | const provider = new GoogleAuthProvider() 31 | const promise = this.firebaseAuth.signInWithPopup(provider) 32 | const auth = getAuth(); 33 | const user = auth.currentUser; 34 | if (user != null) { 35 | const usuario= { 36 | displayName: user.displayName, 37 | email: user.email, 38 | photoURL: user.photoURL, 39 | uid: user.uid 40 | } 41 | let usuarioJaExiste: boolean = false 42 | this.listarUsuarios().subscribe(listaUsuarios => { 43 | listaUsuarios.map((usuario: User) => { 44 | if (usuario.email == user?.email) { 45 | usuarioJaExiste = true 46 | } 47 | }) 48 | if (usuarioJaExiste == false) { 49 | this.salvarUsuario(usuario) 50 | } 51 | }) 52 | } 53 | /* if(this.token.request_token != ''){ 54 | this.apiTMDB.createSession(this.token).subscribe(resposta => { 55 | localStorage.setItem('session', resposta.session_id) 56 | this.notification.showmessage("Bem vindo(a)!") 57 | }) 58 | }else{ 59 | this.apiTMDB.autenticarUsuarioPorToken().subscribe(resposta => { 60 | this.token = resposta 61 | window.open('https://www.themoviedb.org/authenticate/' + this.token.request_token) 62 | localStorage.setItem('token', this.token.request_token) 63 | 64 | }) 65 | } */ 66 | 67 | return from(promise).pipe( 68 | catchError(error => { 69 | this.notification.showmessage("Erro ao autenticar com o Google!") 70 | console.error(error) 71 | return EMPTY 72 | }) 73 | ) 74 | } 75 | 76 | public salvarUsuario(usuario: Usuario): Observable { 77 | const promise = this.firestore.collection('users').add({ 78 | uidUser:localStorage.getItem('uidUser'), 79 | ...usuario 80 | }) 81 | return from(promise).pipe( 82 | catchError(error => { 83 | console.error(error) 84 | this.notification.showmessage("Erro ao salvar usuário") 85 | return EMPTY 86 | }) 87 | ) 88 | } 89 | 90 | public listarUsuarios(): Observable { 91 | const promise = this.firestore.collection('users').get() 92 | return from(promise).pipe( 93 | map(resposta => { 94 | return resposta.docs.map(doc => { 95 | const user: User = doc.data() as User 96 | user.uid = doc.id 97 | return user 98 | }) 99 | }), 100 | catchError(error => { 101 | console.error(error) 102 | this.notification.showmessage("Erro ao listar usuários") 103 | return EMPTY 104 | }) 105 | ) 106 | } 107 | 108 | public getUser(uid: string): Observable{ 109 | const promise = this.firestore.collection('users').doc(uid).get() 110 | return from(promise).pipe( 111 | map(doc => { 112 | const user: User = doc.data() as User 113 | return user 114 | }), 115 | catchError(error => { 116 | this.notification.showmessage("Erro ao buscar dados de usuário") 117 | console.error(error) 118 | return EMPTY 119 | }) 120 | ) 121 | } 122 | 123 | public getCurrentUser() { 124 | return from(this.firebaseAuth.currentUser) 125 | } 126 | 127 | public editarUsuario(user: any){ 128 | const promise = this.firestore.collection('users').doc(user.uid).update(user) 129 | return from(promise).pipe( 130 | catchError((error) => { 131 | this.notification.showmessage("Erro ao editar.") 132 | console.error(error) 133 | return EMPTY; 134 | }) 135 | ) 136 | } 137 | 138 | public autenticarPorEmaileSenha(user: User): Observable { 139 | 140 | const { email, senha, displayName } = user; 141 | const promise = this.firebaseAuth.signInWithEmailAndPassword(email, senha) 142 | 143 | /* console.log(this.token) 144 | if(this.token.request_token != ''){ 145 | this.apiTMDB.createSession(this.token).subscribe(resposta => { 146 | localStorage.setItem('session', resposta.session_id) 147 | this.notification.showmessage("Bem vindo(a)!") 148 | this.router.navigate(["/filmes"]) 149 | }) 150 | }else{ 151 | this.apiTMDB.autenticarUsuarioPorToken().subscribe(resposta => { 152 | this.token = resposta 153 | window.open('https://www.themoviedb.org/authenticate/' + this.token.request_token) 154 | localStorage.setItem('token', this.token.request_token) 155 | 156 | }) 157 | } */ 158 | 159 | return from(promise).pipe( 160 | catchError(error => { 161 | if (error.code == "auth/user-not-found") { 162 | this.notification.showmessage("Usuário não cadstrado!") 163 | } else if (error.code == "auth/wrong-password") { 164 | this.notification.showmessage("Senha incorreta!") 165 | } else { 166 | this.notification.showmessage("Erro ao autenticar!") 167 | console.error(error) 168 | } 169 | return EMPTY 170 | }) 171 | ) 172 | 173 | } 174 | 175 | public criarUsuarioEmaileSenha(user: any): Observable { 176 | const { email, senha } = user; 177 | this.salvarUsuario(user) 178 | 179 | const promise = this.firebaseAuth.createUserWithEmailAndPassword(email, senha) 180 | return from(promise).pipe( 181 | catchError(error => { 182 | this.notification.showmessage("Erro ao cadastrar usuário!") 183 | console.error(error) 184 | return EMPTY 185 | }) 186 | ) 187 | } 188 | 189 | public logout() { 190 | const promise = this.firebaseAuth.signOut() 191 | localStorage.removeItem('uidUser'); 192 | localStorage.removeItem('user-name'); 193 | localStorage.removeItem('user-photo'); 194 | return from(promise) 195 | } 196 | 197 | } 198 | 199 | -------------------------------------------------------------------------------- /src/app/Components/header/header.component.css: -------------------------------------------------------------------------------- 1 | /*NAVBAR*/ 2 | header { 3 | position: fixed; 4 | top: 0; 5 | left: 0; 6 | width: 100vw; 7 | height: 50px; 8 | z-index: 3; 9 | } 10 | 11 | .mobile{ 12 | display: none; 13 | } 14 | 15 | .desktop { 16 | height: 70px; 17 | width: 100vw; 18 | background-color: var(--blue2); 19 | display: flex; 20 | align-items: center; 21 | justify-content: center; 22 | z-index: 3; 23 | position: relative; 24 | } 25 | 26 | ul { 27 | display: flex; 28 | } 29 | 30 | li { 31 | display: flex; 32 | align-items: center; 33 | list-style: none; 34 | margin-right: 1.5em; 35 | } 36 | 37 | .favoritos { 38 | color: rgb(255, 255, 255); 39 | font-weight: bold; 40 | background-color: var(--header); 41 | display: flex; 42 | border: none; 43 | border-radius: 5px; 44 | align-items: center; 45 | width: 110px; 46 | justify-content: space-between; 47 | padding: 10px; 48 | } 49 | 50 | a { 51 | text-decoration: none; 52 | } 53 | 54 | .favoritos:hover { 55 | cursor: pointer; 56 | background-color: var(--blue2); 57 | color: var(--yellow); 58 | } 59 | 60 | .salvos { 61 | color: rgb(255, 255, 255); 62 | font-weight: bold; 63 | background-color: var(--header); 64 | display: flex; 65 | border: none; 66 | border-radius: 5px; 67 | align-items: center; 68 | width: 150px; 69 | justify-content: space-between; 70 | padding: 10px; 71 | } 72 | 73 | a { 74 | text-decoration: none; 75 | } 76 | 77 | .salvos:hover { 78 | cursor: pointer; 79 | background-color: var(--blue2); 80 | color: var(--yellow); 81 | } 82 | 83 | .pesquisa input { 84 | width: 450px; 85 | background-color: var(--blue3); 86 | border: none; 87 | border-radius: 15px; 88 | color: var(--font); 89 | height: 28px; 90 | padding: 0 30px; 91 | } 92 | 93 | form { 94 | display: flex; 95 | align-items: center; 96 | } 97 | 98 | .botao-pesquisa { 99 | background-color: var(--blue2); 100 | border: none; 101 | color: aliceblue; 102 | cursor: pointer; 103 | margin-left: 10px; 104 | } 105 | 106 | input:focus { 107 | outline: 1px solid rgb(255, 233, 154); 108 | } 109 | 110 | .usuario { 111 | display: flex; 112 | } 113 | 114 | .nome-usuario { 115 | color: rgb(239, 239, 239); 116 | font-weight: 500; 117 | font-size: 14px; 118 | } 119 | 120 | .usuario img { 121 | width: 45px; 122 | height: 45px; 123 | border-radius: 50%; 124 | margin-left: 15px; 125 | object-fit: cover; 126 | cursor: pointer; 127 | } 128 | 129 | button { 130 | background-color: transparent; 131 | border: none; 132 | cursor: pointer; 133 | } 134 | 135 | .avatar { 136 | width: 50px; 137 | height: 50px; 138 | border-radius: 50%; 139 | margin-left: 10px; 140 | object-fit: cover; 141 | cursor: pointer; 142 | } 143 | 144 | ::ng-deep .mat-menu-content { 145 | width: 280px; 146 | height: 180px; 147 | 148 | } 149 | 150 | .titulo-menu { 151 | text-align: center; 152 | color: aliceblue; 153 | padding: 10px; 154 | font-size: 14px; 155 | } 156 | 157 | .menu { 158 | padding: 10px; 159 | justify-content: center; 160 | display: flex; 161 | flex-wrap: wrap; 162 | } 163 | 164 | mat-divider { 165 | background-color: var(--blue3); 166 | margin: 10px 0; 167 | } 168 | 169 | 170 | /*LISTA DE FILMES PESQUISA*/ 171 | 172 | .container { 173 | margin: 0; 174 | width: 100vw; 175 | height: auto; 176 | display: flex; 177 | flex-direction: column; 178 | box-sizing: border-box; 179 | } 180 | 181 | .titulo-pesquisa { 182 | color: rgb(226, 233, 240); 183 | padding: 100px 0 50px 60px; 184 | } 185 | 186 | .lista-filmes-pesquisa { 187 | display: flex; 188 | width: 100%; 189 | flex-wrap: wrap; 190 | box-sizing: border-box; 191 | padding: 0 50px; 192 | 193 | } 194 | 195 | .card-filme { 196 | background-color: var(--blue3); 197 | border: none; 198 | width: 170px; 199 | height: 350px; 200 | border-radius: 5px; 201 | box-sizing: border-box; 202 | margin: 8px; 203 | } 204 | 205 | .poster { 206 | width: 100%; 207 | height: 72%; 208 | border-radius: 5px 5px 0 0; 209 | } 210 | 211 | .conteudo-card { 212 | height: 25%; 213 | display: flex; 214 | flex-direction: column; 215 | justify-content: space-between; 216 | } 217 | 218 | .avaliacao { 219 | display: flex; 220 | width: 90%; 221 | height: auto; 222 | align-items: center; 223 | color: var(--font); 224 | font-size: 15px; 225 | } 226 | 227 | .avaliacao-e-favoritar { 228 | display: flex; 229 | align-items: center; 230 | justify-content: space-between; 231 | width: 90%; 232 | height: 50px; 233 | padding: 0 10px; 234 | margin-top: 5px; 235 | } 236 | 237 | .titulo-filme { 238 | font-size: 14px; 239 | color: white; 240 | overflow: hidden !important; 241 | text-overflow: ellipsis; 242 | padding: 10px; 243 | margin-bottom: 10px; 244 | } 245 | 246 | .icone-estrela { 247 | margin-right: 10px; 248 | width: 15px; 249 | } 250 | 251 | .icone-coracao:hover { 252 | cursor: pointer; 253 | } 254 | 255 | .assistir-mais-tarde { 256 | background-color: var(--blue2); 257 | color: var(--blue); 258 | font-weight: bold; 259 | font-size: 12px; 260 | border: none; 261 | border-radius: 5px; 262 | padding: 8px; 263 | margin: 10px; 264 | cursor: pointer; 265 | } 266 | 267 | .assistir-mais-tarde div { 268 | display: flex; 269 | justify-content: space-around; 270 | align-items: center; 271 | } 272 | 273 | .assistir-mais-tarde:hover { 274 | opacity: 0.8; 275 | } 276 | 277 | @media only screen and (max-device-width: 900px) { 278 | .desktop { 279 | display: none; 280 | } 281 | 282 | .mobile { 283 | background-color: var(--blue2); 284 | display: flex; 285 | justify-content: space-between; 286 | width: 100%; 287 | padding: 10px; 288 | } 289 | 290 | 291 | .pesquisa-mobile input { 292 | width: 130px; 293 | background-color: var(--blue3); 294 | border: none; 295 | border-radius: 15px; 296 | color: var(--font); 297 | height: 28px; 298 | padding: 0 15px; 299 | } 300 | 301 | .usuario-mobile{ 302 | display: flex; 303 | flex-direction: column; 304 | align-items: center; 305 | } 306 | 307 | .usuario-mobile img{ 308 | border-radius: 50%; 309 | width: 50px; 310 | height: 50px; 311 | } 312 | 313 | ::ng-deep .mat-menu-content{ 314 | width: auto; 315 | height: auto; 316 | } 317 | 318 | 319 | .titulo-pesquisa{ 320 | padding: 0; 321 | margin: 80px 0 30px 20px; 322 | } 323 | 324 | .lista-filmes-pesquisa { 325 | display: flex; 326 | width: 100%; 327 | flex-wrap: wrap; 328 | box-sizing: border-box; 329 | padding: 0 30px; 330 | 331 | } 332 | 333 | .card-filme { 334 | background-color: var(--blue3); 335 | border: none; 336 | width: 140px; 337 | height: 300px; 338 | border-radius: 5px; 339 | box-sizing: border-box; 340 | margin: 5px; 341 | } 342 | 343 | .poster { 344 | width: 100%; 345 | height: 65%; 346 | border-radius: 5px 5px 0 0; 347 | } 348 | 349 | .conteudo-card { 350 | height: 35%; 351 | display: flex; 352 | flex-direction: column; 353 | justify-content: space-between; 354 | } 355 | 356 | .avaliacao { 357 | display: flex; 358 | width: 90%; 359 | height: 20px; 360 | align-items: center; 361 | color: rgb(215, 215, 215); 362 | font-size: 14px; 363 | } 364 | 365 | .titulo-filme { 366 | display: none; 367 | } 368 | 369 | 370 | } 371 | -------------------------------------------------------------------------------- /src/app/Pages/lista-filmes/lista-filmes.component.css: -------------------------------------------------------------------------------- 1 | /*LISTA DE FILMES*/ 2 | .container { 3 | display: flex; 4 | flex-direction: column; 5 | padding: 70px 0; 6 | height: 100vh; 7 | width: 100vw; 8 | color: rgb(235, 235, 235); 9 | box-sizing: border-box; 10 | 11 | } 12 | 13 | .titulo-lista { 14 | color: var(--yellow); 15 | margin: 50px 0 20px 100px; 16 | } 17 | 18 | .sub { 19 | color: var(--font); 20 | margin-bottom: 30px; 21 | margin-left: 100px; 22 | } 23 | 24 | ::ng-deep .mat-tab-label .mat-tab-label-content { 25 | font-size: large; 26 | 27 | } 28 | 29 | ::ng-deep .mat-tab-label { 30 | opacity: 1 !important; 31 | color: whitesmoke; 32 | width: 10%; 33 | margin-left: 80px; 34 | } 35 | 36 | ::ng-deep .mat-tab-content { 37 | display: flex; 38 | justify-content: center; 39 | width: 100%; 40 | } 41 | 42 | ::ng-deep .mat-ink-bar { 43 | background-color: var(--yellow) !important; 44 | } 45 | 46 | .header-lista { 47 | display: flex; 48 | max-width: 1300px; 49 | height: 80px; 50 | justify-content: start; 51 | align-items: center; 52 | margin-top: 50px; 53 | margin-left: 100px; 54 | } 55 | 56 | .btn-acoes { 57 | background-color: transparent; 58 | color: var(--blue); 59 | cursor: pointer; 60 | border: none; 61 | margin-left: 30px; 62 | } 63 | 64 | .btn-acoes:hover { 65 | color: rgb(67, 123, 206); 66 | } 67 | 68 | 69 | .subtitulo-lista { 70 | display: flex; 71 | align-items: center; 72 | } 73 | 74 | .cards { 75 | display: flex; 76 | flex-wrap: wrap; 77 | box-sizing: border-box; 78 | margin: 20px 100px; 79 | max-width: 1350px; 80 | justify-content: center; 81 | } 82 | 83 | .seta-esquerda { 84 | background-color: rgba(0, 0, 0, 0); 85 | height: 400px; 86 | border: none; 87 | cursor: pointer; 88 | position: relative; 89 | left: 30px; 90 | } 91 | 92 | .seta-esquerda:hover { 93 | background-color: rgba(37, 37, 37, 0.436); 94 | } 95 | 96 | .seta-direita { 97 | background-color: rgba(0, 0, 0, 0); 98 | height: 400px; 99 | border: none; 100 | cursor: pointer; 101 | position: relative; 102 | left: -30px; 103 | } 104 | 105 | .seta-direita:hover { 106 | background-color: rgba(37, 37, 37, 0.436); 107 | } 108 | 109 | .card-filme { 110 | background-color: var(--blue3); 111 | border: none; 112 | width: 170px; 113 | height: 350px; 114 | border-radius: 5px; 115 | box-sizing: border-box; 116 | margin: 8px; 117 | } 118 | 119 | .poster { 120 | width: 100%; 121 | height: 72%; 122 | border-radius: 5px 5px 0 0; 123 | } 124 | 125 | .conteudo-card { 126 | height: 25%; 127 | display: flex; 128 | flex-direction: column; 129 | justify-content: space-between; 130 | } 131 | 132 | .avaliacao { 133 | display: flex; 134 | width: 90%; 135 | height: auto; 136 | align-items: center; 137 | color: var(--font); 138 | font-size: 15px; 139 | } 140 | 141 | .avaliacao p { 142 | margin-right: 20px; 143 | } 144 | 145 | .avaliacao-e-favoritar { 146 | display: flex; 147 | align-items: center; 148 | justify-content: space-between; 149 | width: 90%; 150 | height: auto; 151 | padding: 0 10px; 152 | margin-top: 5px; 153 | } 154 | 155 | .titulo-filme { 156 | font-size: 14px; 157 | color: whitesmoke; 158 | overflow: hidden !important; 159 | text-overflow: ellipsis; 160 | padding: 10px; 161 | margin-bottom: 10px; 162 | } 163 | 164 | .icone-estrela { 165 | margin-right: 7px; 166 | width: 15px; 167 | } 168 | 169 | .icone-coracao:hover { 170 | cursor: pointer; 171 | } 172 | 173 | .assistir-mais-tarde { 174 | background-color: var(--blue2); 175 | color: var(--blue); 176 | font-weight: bold; 177 | font-size: 12px; 178 | border: none; 179 | border-radius: 5px; 180 | padding: 8px; 181 | margin: 0 8px 8px 8px; 182 | cursor: pointer; 183 | } 184 | 185 | .assistir-mais-tarde div { 186 | display: flex; 187 | justify-content: space-around; 188 | align-items: center; 189 | } 190 | 191 | .assistir-mais-tarde:hover { 192 | opacity: 0.8; 193 | } 194 | 195 | .generos { 196 | display: flex; 197 | flex-wrap: wrap; 198 | justify-content: center; 199 | width: 50%; 200 | margin: 40px auto; 201 | } 202 | 203 | .genero { 204 | border-radius: 20px; 205 | background-color: var(--blue2); 206 | width: auto; 207 | padding: 12px; 208 | font-size: 13px; 209 | margin-right: 5px; 210 | margin-bottom: 5px; 211 | cursor: pointer; 212 | } 213 | 214 | .genero:hover { 215 | background-color: var(--yellow); 216 | color: black; 217 | } 218 | 219 | .focus { 220 | background-color: var(--yellow); 221 | color: black; 222 | } 223 | 224 | mat-paginator { 225 | background-color: transparent; 226 | border: 1px solid #26405c; 227 | border-radius: 5px; 228 | color: aliceblue; 229 | width: 90%; 230 | margin: 20px auto; 231 | } 232 | 233 | .carrossel { 234 | width: 95vw; 235 | height: auto; 236 | overflow-x: hidden; 237 | } 238 | 239 | .filmes-desktop { 240 | display: flex; 241 | scroll-behavior: smooth; 242 | margin-right: 0; 243 | justify-content: center; 244 | width: 100%; 245 | } 246 | 247 | .filmes-mobile, .lista-mobile{ 248 | display: none; 249 | } 250 | 251 | .btn-voltar{ 252 | visibility: hidden; 253 | } 254 | 255 | .visible{ 256 | visibility: visible; 257 | position: fixed; 258 | bottom: 10px; 259 | right: 0; 260 | background-color: transparent; 261 | border: none; 262 | cursor: pointer; 263 | } 264 | 265 | 266 | @media only screen and (max-device-width: 900px) { 267 | .titulo-lista { 268 | margin: 30px 0 20px 30px; 269 | font-size: 24px; 270 | } 271 | 272 | .sub { 273 | margin-left: 30px; 274 | font-size: 15px; 275 | width: 80%; 276 | } 277 | 278 | .filmes-desktop, .lista-desktop { 279 | display: none; 280 | } 281 | 282 | .lista-mobile{ 283 | display: flex; 284 | } 285 | 286 | 287 | .header-lista { 288 | display: flex; 289 | width: 100%; 290 | height: auto; 291 | justify-content: flex-start; 292 | align-items: center; 293 | margin-top: 50px; 294 | margin-bottom: 20px; 295 | margin-left: 0; 296 | } 297 | 298 | .subtitulo-lista h2 { 299 | font-size: 18px; 300 | } 301 | 302 | .cards { 303 | margin: 20px 10px; 304 | width: auto; 305 | } 306 | 307 | .card-filme { 308 | background-color: var(--blue3); 309 | border: none; 310 | width: 150px; 311 | height: 320px; 312 | border-radius: 5px; 313 | box-sizing: border-box; 314 | margin: 5px; 315 | 316 | } 317 | 318 | .poster { 319 | width: 150px; 320 | height: 70%; 321 | border-radius: 5px 5px 0 0; 322 | } 323 | 324 | .conteudo-card { 325 | height: 30%; 326 | display: flex; 327 | flex-direction: column; 328 | justify-content: space-between; 329 | } 330 | 331 | .avaliacao { 332 | display: flex; 333 | width: 100%; 334 | height: auto; 335 | align-items: center; 336 | color: rgb(215, 215, 215); 337 | font-size: 14px; 338 | } 339 | 340 | .titulo-filme { 341 | display: none; 342 | } 343 | 344 | .filmes-mobile { 345 | display: flex; 346 | scroll-behavior: smooth; 347 | margin: 0 0 20px 0; 348 | height: auto; 349 | width: 100%; 350 | justify-content: flex-start; 351 | overflow-x: scroll; 352 | -webkit-overflow-scrolling: touch; 353 | } 354 | 355 | mat-paginator { 356 | visibility: hidden; 357 | } 358 | 359 | .generos { 360 | width: 80%; 361 | margin: 50px 50px 0 50px; 362 | } 363 | 364 | .carrossel { 365 | height: auto; 366 | } 367 | 368 | } 369 | -------------------------------------------------------------------------------- /src/app/Pages/lista-filmes/lista-filmes.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, EventEmitter, HostListener, OnInit, Output } from '@angular/core'; 2 | import { PageEvent } from '@angular/material/paginator'; 3 | import { FilmeLista } from 'src/app/Interfaces/FilmeLista'; 4 | import { Genre } from 'src/app/Interfaces/genre'; 5 | import { Results } from 'src/app/Interfaces/Results'; 6 | import { ApiFilmesService } from 'src/app/Services/api-filmes.service'; 7 | import { FavoritosService } from 'src/app/Services/favoritos.service'; 8 | import { NotificationService } from 'src/app/Services/notificacao.service'; 9 | import { SalvosService } from 'src/app/Services/salvos.service'; 10 | import Swiper from 'swiper'; 11 | 12 | @Component({ 13 | selector: 'app-lista-filmes', 14 | templateUrl: './lista-filmes.component.html', 15 | styleUrls: ['./lista-filmes.component.css'] 16 | }) 17 | export class ListaFilmesComponent implements OnInit { 18 | 19 | constructor( 20 | private filmesService: ApiFilmesService, 21 | private favoritosService: FavoritosService, 22 | private notificacao: NotificationService, 23 | private salvosService: SalvosService 24 | 25 | ) { } 26 | 27 | 28 | listaTopFilmes!: Results 29 | listaTopFilmesCompleta: FilmeLista[] = [] 30 | listaPopulares!: Results 31 | listaPopularesCompleta: FilmeLista[] = [] 32 | listaFavoritos: FilmeLista[] = [] 33 | listaSalvos: FilmeLista[] = [] 34 | listaGeneros!: Genre 35 | filtrados: FilmeLista[] = [] 36 | listaFilmes!: Results 37 | verMaisMelhores: boolean = false 38 | verMaisPopulares: boolean = false 39 | 40 | filmeJaAdicionado: boolean = false 41 | filmeJaSalvo: boolean = false 42 | 43 | session: any = '' 44 | 45 | coracaoVazio: string = "../../../assets/coracaoVazio.png" 46 | coracaoCheio: string = "../../../assets/coracaoCheio.png" 47 | 48 | inicio = 0 49 | final = 7 50 | inicio2 = 0 51 | final2 = 7 52 | 53 | slidesContainer = document.getElementById("slides-container"); 54 | slide = document.querySelector(".slide"); 55 | prevButton = document.getElementById("slide-arrow-prev"); 56 | nextButton = document.getElementById("slide-arrow-next"); 57 | 58 | 59 | ngOnInit(): void { 60 | this.session = localStorage.getItem('session') 61 | this.listarFavoritos() 62 | this.listarSalvos() 63 | this.listarMelhoresAvaliados() 64 | this.listarPopulares() 65 | this.listarGeneros() 66 | this.listarFilmes() 67 | } 68 | 69 | public favoritar(filmeFavorito: FilmeLista): void { 70 | filmeFavorito.isFavorite = true 71 | this.listaFavoritos.forEach(filme => { 72 | if (filme.id == filmeFavorito.id) { 73 | this.filmeJaAdicionado = true 74 | } 75 | }) 76 | 77 | if (this.filmeJaAdicionado) { 78 | this.notificacao.showmessage("Ops! Filme já consta na lista de favoritos!") 79 | } else { 80 | this.favoritosService.adicionarFavorito(filmeFavorito).subscribe( 81 | (resposta) => { 82 | this.notificacao.showmessage("Filme inserido na lista de favoritos!") 83 | } 84 | ) 85 | } 86 | } 87 | 88 | public listarFavoritos(): void { 89 | this.favoritosService.listarFavoritos().subscribe( 90 | (lista) => { 91 | this.listaFavoritos = lista 92 | }) 93 | } 94 | 95 | public verificarFavoritos(listaFilmes: Results): void { 96 | this.favoritosService.listarFavoritos().subscribe( 97 | (lista) => { 98 | for (let filme of lista) { 99 | for (let listaFilme of listaFilmes.results) { 100 | if (filme.id === listaFilme.id) { 101 | listaFilme.isFavorite = true 102 | } 103 | } 104 | 105 | } 106 | }) 107 | } 108 | 109 | public salvar(filmeSalvo: FilmeLista): void { 110 | filmeSalvo.isSave = true 111 | this.listaSalvos.forEach(filme => { 112 | if (filme.id == filmeSalvo.id) { 113 | this.filmeJaSalvo = true 114 | } 115 | }) 116 | 117 | if (this.filmeJaSalvo) { 118 | this.notificacao.showmessage("Ops! Filme já consta na lista de assistir depois!") 119 | } else { 120 | this.salvosService.adicionarFilme(filmeSalvo).subscribe( 121 | (resposta) => { 122 | this.notificacao.showmessage("Filme inserido na lista!") 123 | } 124 | ) 125 | } 126 | } 127 | 128 | public listarSalvos(): void { 129 | this.salvosService.listarFilmesSalvos().subscribe( 130 | (lista) => { 131 | this.listaSalvos = lista 132 | }) 133 | } 134 | 135 | public verificarSalvos(listaFilmes: Results): void { 136 | this.salvosService.listarFilmesSalvos().subscribe( 137 | (lista) => { 138 | for (let filme of lista) { 139 | for (let listaFilme of listaFilmes.results) { 140 | if (filme.id === listaFilme.id) { 141 | listaFilme.isSave = true 142 | } 143 | } 144 | 145 | } 146 | }) 147 | } 148 | 149 | public listarMelhoresAvaliados(): void { 150 | this.filmesService.listarMelhoresAvaliados(1).subscribe( 151 | (lista) => { 152 | this.listaTopFilmes = lista 153 | this.verificarFavoritos(lista) 154 | this.verificarSalvos(lista) 155 | } 156 | ) 157 | } 158 | 159 | public listarTodosMelhoresAvaliados(): void { 160 | this.verMaisMelhores = true 161 | for (let index = 1; index < 5; index++) { 162 | this.filmesService.listarMelhoresAvaliados(index).subscribe( 163 | (lista) => { 164 | this.verificarFavoritos(lista) 165 | this.verificarSalvos(lista) 166 | lista.results.map(filme => { 167 | this.listaTopFilmesCompleta.push(filme) 168 | }) 169 | }) 170 | } 171 | } 172 | 173 | public voltarHome(): void { 174 | this.verMaisMelhores = false 175 | this.verMaisPopulares = false 176 | } 177 | 178 | public listarPopulares(): void { 179 | this.filmesService.listarFilmesPopulares(1).subscribe( 180 | (lista) => { 181 | this.listaPopulares = lista 182 | this.verificarFavoritos(lista) 183 | this.verificarSalvos(lista) 184 | } 185 | ) 186 | } 187 | 188 | public listarTodosPopulares(): void { 189 | this.verMaisPopulares = true 190 | for (let index = 1; index < 5; index++) { 191 | this.filmesService.listarFilmesPopulares(index).subscribe( 192 | (lista) => { 193 | this.verificarFavoritos(lista) 194 | this.verificarSalvos(lista) 195 | lista.results.map(filme => { 196 | this.listaPopularesCompleta.push(filme) 197 | }) 198 | }) 199 | } 200 | } 201 | 202 | 203 | public listarGeneros(): void { 204 | this.filmesService.getGenres().subscribe((lista) => { 205 | this.listaGeneros = lista 206 | }) 207 | } 208 | 209 | public listarFilmes(): void { 210 | for (let index = 1; index < 2; index++) { 211 | this.filmesService.discoverMovies(index).subscribe((lista) => { 212 | this.listaFilmes = lista 213 | 214 | }) 215 | } 216 | } 217 | 218 | public filtrarGenero(genero: number): void { 219 | this.filtrados = [] 220 | 221 | for (let index = 1; index < 40; index++) { 222 | this.filmesService.discoverMovies(index).subscribe((lista) => { 223 | this.verificarFavoritos(lista) 224 | this.verificarSalvos(lista) 225 | lista.results.filter(element => { 226 | if (element.genre_ids != undefined) { 227 | element.genre_ids.forEach(genre => { 228 | if (genre == genero) { 229 | this.filtrados.push(element) 230 | } 231 | }) 232 | } 233 | }) 234 | }); 235 | } 236 | } 237 | 238 | public mudarCor(genero: any): void { 239 | this.listaGeneros.genres.map((genero) => { 240 | genero.ativo = false 241 | }) 242 | genero.ativo = true 243 | 244 | } 245 | 246 | voltar() { 247 | if (this.inicio != 0 && this.final != 7) { 248 | this.inicio -= 7 249 | this.final -= 7 250 | } 251 | } 252 | 253 | avancar() { 254 | if (this.final < this.listaTopFilmes.results.length) { 255 | this.inicio += 7 256 | this.final += 7 257 | const slideWidth = this.slide?.clientWidth 258 | if(this.slidesContainer != null){ 259 | this.slidesContainer.scrollLeft += slideWidth as number; 260 | } 261 | } 262 | } 263 | 264 | voltar2() { 265 | if (this.inicio2 != 0 && this.final2 != 7) { 266 | this.inicio2 -= 7 267 | this.final2 -= 7 268 | } 269 | } 270 | 271 | avancar2() { 272 | if (this.final2 < this.listaTopFilmes.results.length) { 273 | this.inicio2 += 7 274 | this.final2 += 7 275 | } 276 | } 277 | 278 | 279 | public voltarAoTopo(): void{ 280 | window.scroll(0, 0) 281 | } 282 | 283 | @HostListener('window:scroll') onWindowScroll(): void{ 284 | const botao = document.querySelector(".btn-voltar") 285 | if(window.scrollY > 7.5){ 286 | botao?.classList.add("visible") 287 | 288 | }else { 289 | botao?.classList.remove("visible") 290 | } 291 | } 292 | 293 | } 294 | 295 | -------------------------------------------------------------------------------- /src/app/Components/dialogs/dialog-voto/dialog-voto.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, OnInit, Inject } from '@angular/core'; 2 | import { MatDialogRef, MAT_DIALOG_DATA } from '@angular/material/dialog'; 3 | import { FilmeLista } from 'src/app/Interfaces/FilmeLista'; 4 | import { ApiFilmesService } from 'src/app/Services/api-filmes.service'; 5 | import { FavoritosService } from 'src/app/Services/favoritos.service'; 6 | import { NotificationService } from 'src/app/Services/notificacao.service'; 7 | import { SalvosService } from 'src/app/Services/salvos.service'; 8 | 9 | @Component({ 10 | selector: 'app-dialog-voto', 11 | templateUrl: './dialog-voto.component.html', 12 | styleUrls: ['./dialog-voto.component.css'] 13 | }) 14 | export class DialogVotoComponent implements OnInit { 15 | 16 | constructor( 17 | public dialogRef: MatDialogRef, 18 | @Inject(MAT_DIALOG_DATA) 19 | public filme: FilmeLista, 20 | private favoritosService: FavoritosService, 21 | private salvosService: SalvosService, 22 | private notification: NotificationService 23 | ) { } 24 | 25 | session: any = '' 26 | nota: any = "?" 27 | 28 | estrelaContorno: string = '/assets/estrela-cinza.png' 29 | estrelaCheia: string = '/assets/estrela-azul-cheia.png' 30 | 31 | estrela: string = this.estrelaContorno 32 | estrela2: string = this.estrelaContorno 33 | estrela3: string = this.estrelaContorno 34 | estrela4: string = this.estrelaContorno 35 | estrela5: string = this.estrelaContorno 36 | estrela6: string = this.estrelaContorno 37 | estrela7: string = this.estrelaContorno 38 | estrela8: string = this.estrelaContorno 39 | estrela9: string = this.estrelaContorno 40 | estrela10: string = this.estrelaContorno 41 | 42 | ngOnInit(): void { 43 | this.session = localStorage.getItem('session') 44 | this.verificarTamanhoTela() 45 | } 46 | 47 | verificarTamanhoTela(){ 48 | var largura = window.screen.width; 49 | if(largura < 500){ 50 | this.dialogRef.updateSize('90%', '38%'); 51 | } 52 | } 53 | 54 | onNoClick(): void { 55 | this.dialogRef.close(); 56 | } 57 | 58 | mudarEstrela1() { 59 | this.estrela = this.estrelaCheia 60 | } 61 | 62 | mudarEstrela2() { 63 | this.estrela = this.estrelaCheia 64 | this.estrela2 = this.estrelaCheia 65 | } 66 | 67 | mudarEstrela3() { 68 | this.estrela = this.estrelaCheia 69 | this.estrela2 = this.estrelaCheia 70 | this.estrela3 = this.estrelaCheia 71 | } 72 | 73 | mudarEstrela4() { 74 | this.estrela = this.estrelaCheia 75 | this.estrela2 = this.estrelaCheia 76 | this.estrela3 = this.estrelaCheia 77 | this.estrela4 = this.estrelaCheia 78 | } 79 | 80 | mudarEstrela5() { 81 | this.estrela = this.estrelaCheia 82 | this.estrela2 = this.estrelaCheia 83 | this.estrela3 = this.estrelaCheia 84 | this.estrela4 = this.estrelaCheia 85 | this.estrela5 = this.estrelaCheia 86 | } 87 | 88 | mudarEstrela6() { 89 | this.estrela = this.estrelaCheia 90 | this.estrela2 = this.estrelaCheia 91 | this.estrela3 = this.estrelaCheia 92 | this.estrela4 = this.estrelaCheia 93 | this.estrela5 = this.estrelaCheia 94 | this.estrela6 = this.estrelaCheia 95 | } 96 | 97 | mudarEstrela7() { 98 | this.estrela = this.estrelaCheia 99 | this.estrela2 = this.estrelaCheia 100 | this.estrela3 = this.estrelaCheia 101 | this.estrela4 = this.estrelaCheia 102 | this.estrela5 = this.estrelaCheia 103 | this.estrela6 = this.estrelaCheia 104 | this.estrela7 = this.estrelaCheia 105 | } 106 | 107 | mudarEstrela8() { 108 | this.estrela = this.estrelaCheia 109 | this.estrela2 = this.estrelaCheia 110 | this.estrela3 = this.estrelaCheia 111 | this.estrela4 = this.estrelaCheia 112 | this.estrela5 = this.estrelaCheia 113 | this.estrela6 = this.estrelaCheia 114 | this.estrela7 = this.estrelaCheia 115 | this.estrela8 = this.estrelaCheia 116 | } 117 | 118 | mudarEstrela9() { 119 | this.estrela = this.estrelaCheia 120 | this.estrela2 = this.estrelaCheia 121 | this.estrela3 = this.estrelaCheia 122 | this.estrela4 = this.estrelaCheia 123 | this.estrela5 = this.estrelaCheia 124 | this.estrela6 = this.estrelaCheia 125 | this.estrela7 = this.estrelaCheia 126 | this.estrela8 = this.estrelaCheia 127 | this.estrela9 = this.estrelaCheia 128 | } 129 | 130 | mudarEstrela10() { 131 | this.estrela = this.estrelaCheia 132 | this.estrela2 = this.estrelaCheia 133 | this.estrela3 = this.estrelaCheia 134 | this.estrela4 = this.estrelaCheia 135 | this.estrela5 = this.estrelaCheia 136 | this.estrela6 = this.estrelaCheia 137 | this.estrela7 = this.estrelaCheia 138 | this.estrela8 = this.estrelaCheia 139 | this.estrela9 = this.estrelaCheia 140 | this.estrela10 = this.estrelaCheia 141 | } 142 | 143 | receberNota1() { 144 | let botao = document.querySelector('#btn-avaliar') 145 | botao?.classList.add('btn-ativo') 146 | this.nota = 1.0 147 | this.estrela = this.estrelaCheia 148 | this.estrela2 = this.estrelaContorno 149 | this.estrela3 = this.estrelaContorno 150 | this.estrela4 = this.estrelaContorno 151 | this.estrela5 = this.estrelaContorno 152 | this.estrela6 = this.estrelaContorno 153 | this.estrela7 = this.estrelaContorno 154 | this.estrela8 = this.estrelaContorno 155 | this.estrela9 = this.estrelaContorno 156 | this.estrela10 = this.estrelaContorno 157 | } 158 | 159 | receberNota2() { 160 | let botao = document.querySelector('#btn-avaliar') 161 | botao?.classList.add('btn-ativo') 162 | this.nota = 2.0 163 | this.estrela = this.estrelaCheia 164 | this.estrela2 = this.estrelaCheia 165 | this.estrela3 = this.estrelaContorno 166 | this.estrela4 = this.estrelaContorno 167 | this.estrela5 = this.estrelaContorno 168 | this.estrela6 = this.estrelaContorno 169 | this.estrela7 = this.estrelaContorno 170 | this.estrela8 = this.estrelaContorno 171 | this.estrela9 = this.estrelaContorno 172 | this.estrela10 = this.estrelaContorno 173 | } 174 | 175 | receberNota3() { 176 | let botao = document.querySelector('#btn-avaliar') 177 | botao?.classList.add('btn-ativo') 178 | this.nota = 3.0 179 | this.estrela = this.estrelaCheia 180 | this.estrela2 = this.estrelaCheia 181 | this.estrela3 = this.estrelaCheia 182 | this.estrela4 = this.estrelaContorno 183 | this.estrela5 = this.estrelaContorno 184 | this.estrela6 = this.estrelaContorno 185 | this.estrela7 = this.estrelaContorno 186 | this.estrela8 = this.estrelaContorno 187 | this.estrela9 = this.estrelaContorno 188 | this.estrela10 = this.estrelaContorno 189 | } 190 | 191 | receberNota4() { 192 | let botao = document.querySelector('#btn-avaliar') 193 | botao?.classList.add('btn-ativo') 194 | this.nota = 4.0 195 | this.estrela = this.estrelaCheia 196 | this.estrela2 = this.estrelaCheia 197 | this.estrela3 = this.estrelaCheia 198 | this.estrela4 = this.estrelaCheia 199 | this.estrela5 = this.estrelaContorno 200 | this.estrela6 = this.estrelaContorno 201 | this.estrela7 = this.estrelaContorno 202 | this.estrela8 = this.estrelaContorno 203 | this.estrela9 = this.estrelaContorno 204 | this.estrela10 = this.estrelaContorno 205 | } 206 | 207 | receberNota5() { 208 | let botao = document.querySelector('#btn-avaliar') 209 | botao?.classList.add('btn-ativo') 210 | this.nota = 5.0 211 | this.estrela = this.estrelaCheia 212 | this.estrela2 = this.estrelaCheia 213 | this.estrela3 = this.estrelaCheia 214 | this.estrela4 = this.estrelaCheia 215 | this.estrela5 = this.estrelaCheia 216 | this.estrela6 = this.estrelaContorno 217 | this.estrela7 = this.estrelaContorno 218 | this.estrela8 = this.estrelaContorno 219 | this.estrela9 = this.estrelaContorno 220 | this.estrela10 = this.estrelaContorno 221 | } 222 | 223 | receberNota6() { 224 | let botao = document.querySelector('#btn-avaliar') 225 | botao?.classList.add('btn-ativo') 226 | this.nota = 6.0 227 | this.estrela = this.estrelaCheia 228 | this.estrela2 = this.estrelaCheia 229 | this.estrela3 = this.estrelaCheia 230 | this.estrela4 = this.estrelaCheia 231 | this.estrela5 = this.estrelaCheia 232 | this.estrela6 = this.estrelaCheia 233 | this.estrela7 = this.estrelaContorno 234 | this.estrela8 = this.estrelaContorno 235 | this.estrela9 = this.estrelaContorno 236 | this.estrela10 = this.estrelaContorno 237 | } 238 | 239 | receberNota7() { 240 | let botao = document.querySelector('#btn-avaliar') 241 | botao?.classList.add('btn-ativo') 242 | this.nota = 7.0 243 | this.estrela = this.estrelaCheia 244 | this.estrela2 = this.estrelaCheia 245 | this.estrela3 = this.estrelaCheia 246 | this.estrela4 = this.estrelaCheia 247 | this.estrela5 = this.estrelaCheia 248 | this.estrela6 = this.estrelaCheia 249 | this.estrela7 = this.estrelaCheia 250 | this.estrela8 = this.estrelaContorno 251 | this.estrela9 = this.estrelaContorno 252 | this.estrela10 = this.estrelaContorno 253 | } 254 | 255 | receberNota8() { 256 | let botao = document.querySelector('#btn-avaliar') 257 | botao?.classList.add('btn-ativo') 258 | this.nota = 8.0 259 | this.estrela = this.estrelaCheia 260 | this.estrela2 = this.estrelaCheia 261 | this.estrela3 = this.estrelaCheia 262 | this.estrela4 = this.estrelaCheia 263 | this.estrela5 = this.estrelaCheia 264 | this.estrela6 = this.estrelaCheia 265 | this.estrela7 = this.estrelaCheia 266 | this.estrela8 = this.estrelaCheia 267 | this.estrela9 = this.estrelaContorno 268 | this.estrela10 = this.estrelaContorno 269 | } 270 | 271 | receberNota9() { 272 | let botao = document.querySelector('#btn-avaliar') 273 | botao?.classList.add('btn-ativo') 274 | this.nota = 9.0 275 | this.estrela = this.estrelaCheia 276 | this.estrela2 = this.estrelaCheia 277 | this.estrela3 = this.estrelaCheia 278 | this.estrela4 = this.estrelaCheia 279 | this.estrela5 = this.estrelaCheia 280 | this.estrela6 = this.estrelaCheia 281 | this.estrela7 = this.estrelaCheia 282 | this.estrela8 = this.estrelaCheia 283 | this.estrela9 = this.estrelaCheia 284 | this.estrela10 = this.estrelaContorno 285 | } 286 | 287 | receberNota10() { 288 | let botao = document.querySelector('#btn-avaliar') 289 | botao?.classList.add('btn-ativo') 290 | this.nota = 10.0 291 | this.estrela = this.estrelaCheia 292 | this.estrela2 = this.estrelaCheia 293 | this.estrela3 = this.estrelaCheia 294 | this.estrela4 = this.estrelaCheia 295 | this.estrela5 = this.estrelaCheia 296 | this.estrela6 = this.estrelaCheia 297 | this.estrela7 = this.estrelaCheia 298 | this.estrela8 = this.estrelaCheia 299 | this.estrela9 = this.estrelaCheia 300 | this.estrela10 = this.estrelaCheia 301 | } 302 | 303 | avaliar() { 304 | if (this.nota != 0) { 305 | this.filme.voto = this.nota 306 | this.notification.showmessage("Filme avaliado!") 307 | this.favoritosService.editarFilmeFavorito(this.filme).subscribe(resposta => { 308 | setTimeout(function () { 309 | location.reload(); 310 | }, 2000) 311 | }) 312 | 313 | this.salvosService.editarFilmeSalvo(this.filme).subscribe(resposta => { 314 | setTimeout(function () { 315 | location.reload(); 316 | }, 2000) 317 | }) 318 | 319 | 320 | } 321 | } 322 | } 323 | -------------------------------------------------------------------------------- /src/app/Pages/lista-filmes/lista-filmes.component.html: -------------------------------------------------------------------------------- 1 | 2 | 3 |
4 |

Lançamentos

5 |

Confira os últimos lançamentos nos cinemas brasileiros:

6 | 7 |

O que assistir

8 |

Está em busca de um novo filme para assistir? Encontre nas listas abaixo ou busque por gênero:

9 | 10 | 11 |
12 |
13 | 14 |

Melhores Avaliados

15 |
16 | 18 | 19 |
20 | 21 |
22 |
23 | 25 |
26 | 29 |
30 |
31 |
32 | 33 |

{{ filme.vote_average }}

34 |
35 |
38 |
40 |
41 | 42 | 48 |
49 |
50 | 51 | 53 | 54 |
55 |
56 |
57 | 60 |
61 |
62 |
63 | 64 |

{{ filme.vote_average }}

65 |
66 |
69 |
71 |
72 | 73 | 79 |
80 |
81 |
82 | 83 |
84 |
85 |
87 | 90 |
91 |
92 |
93 | 94 |

{{ filme.vote_average }}

95 |
96 |
99 |
101 |
102 | 103 | 109 |
110 |
111 | 112 |
113 | 114 |
115 | 116 |
118 | 121 |
122 |
123 |
124 | 125 |

{{ filme.vote_average }}

126 |
127 |
130 |
132 |
133 | 134 | 140 | 141 |
142 |
143 | 144 |
145 | 146 | 147 |
148 |
149 | 150 |

Os Mais Populares

151 |
152 | 154 | 155 |
156 | 157 |
158 |
159 | 161 |
162 | 165 |
166 |
167 |
168 | 169 |

{{filme.vote_average | number}}

170 |
171 |
173 |
175 |
176 | 177 | 183 |
184 |
185 | 187 |
188 |
189 |
190 | 193 |
194 |
195 |
196 | 197 |

{{filme.vote_average | number}}

198 |
199 |
201 |
203 |
204 | 205 | 211 |
212 |
213 | 214 |
215 | 216 |
217 |
218 |
220 | 223 |
224 |
225 |
226 | 227 |

{{ filme.vote_average | number}}

228 |
229 |
232 |
234 |
235 | 236 | 242 |
243 |
244 | 245 |
246 | 247 |
248 |
250 | 253 |
254 |
255 |
256 | 257 |

{{ filme.vote_average | number}}

258 |
259 |
262 |
264 |
265 | 266 | 272 | 273 |
274 |
275 | 276 |
277 |
278 | 279 |
280 |
281 |

{{genero.name}}

283 |
284 |
285 |
286 |
287 | 290 |
291 |
292 |
293 | 294 |

{{filme.vote_average | number}}

295 |
296 |
298 |
300 |
301 | 302 | 308 |
309 |
310 |
311 | 312 |
313 |
314 | 317 |
318 |
319 |
320 | 321 |

{{filme.vote_average | number}}

322 |
323 |
325 |
327 |
328 | 329 | 335 | 336 |
337 |
338 |
339 | 340 |
341 |
342 |
343 |
344 |
345 | --------------------------------------------------------------------------------