├── 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 |
0">
8 |
9 |

10 |
Lista de favoritos
11 |
12 |
13 |
14 |
![]()
16 |
17 |
27 |
28 |
29 |

30 |
{{filme.vote_average | number}}
31 |
39 |
40 |
41 |
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 |
16 |
17 |
18 |
Nenhum filme por aqui...
19 |
20 |
21 |
![]()
23 |
24 |
40 |
41 |
42 |

43 |
{{filme.vote_average | number}}
44 |
45 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
Nenhum filme por aqui...
58 |
59 |
60 |
![]()
62 |
63 |
74 |
75 |
76 |

77 |
{{filme.vote_average | number}}
78 |
87 |
88 |
89 |
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 |
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 |
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 |
--------------------------------------------------------------------------------