First comit
This commit is contained in:
23
src/app/core/graphql/graphql.provider.ts
Normal file
23
src/app/core/graphql/graphql.provider.ts
Normal file
@@ -0,0 +1,23 @@
|
||||
import { ApplicationConfig, inject } from '@angular/core';
|
||||
import { Apollo, APOLLO_OPTIONS } from 'apollo-angular';
|
||||
import { HttpLink } from 'apollo-angular/http';
|
||||
import { ApolloClientOptions, InMemoryCache } from '@apollo/client/core';
|
||||
import { environment } from '../../../environments/environment';
|
||||
|
||||
const uri = environment.apiGraphqlUrl;
|
||||
|
||||
export function apolloOptionsFactory(): ApolloClientOptions<any> {
|
||||
const httpLink = inject(HttpLink);
|
||||
return {
|
||||
link: httpLink.create({ uri }),
|
||||
cache: new InMemoryCache(),
|
||||
};
|
||||
}
|
||||
|
||||
export const graphqlProvider: ApplicationConfig['providers'] = [
|
||||
Apollo,
|
||||
{
|
||||
provide: APOLLO_OPTIONS,
|
||||
useFactory: apolloOptionsFactory,
|
||||
},
|
||||
];
|
||||
13
src/app/core/graphql/graphql.queries.ts
Normal file
13
src/app/core/graphql/graphql.queries.ts
Normal file
@@ -0,0 +1,13 @@
|
||||
import { gql } from 'apollo-angular';
|
||||
|
||||
export const ANALYZE_MOVIE_QUERY = gql`
|
||||
query AnalyzeMovie($movieId: ID!) {
|
||||
analyzeMovie(movieId: $movieId) {
|
||||
id
|
||||
aiSummary
|
||||
aiOpinionSummary
|
||||
aiBestGenre
|
||||
aiTags
|
||||
}
|
||||
}
|
||||
`;
|
||||
43
src/app/core/layout/header/header.component.scss
Normal file
43
src/app/core/layout/header/header.component.scss
Normal file
@@ -0,0 +1,43 @@
|
||||
:host {
|
||||
display: block;
|
||||
background-color: #1a1a1a;
|
||||
color: #fff;
|
||||
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.2);
|
||||
}
|
||||
|
||||
.header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: 1rem 2rem;
|
||||
max-width: 1200px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.header-nav {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 2rem;
|
||||
}
|
||||
|
||||
.logo {
|
||||
font-size: 1.5rem;
|
||||
font-weight: bold;
|
||||
text-decoration: none;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.nav-link {
|
||||
text-decoration: none;
|
||||
color: #ccc;
|
||||
font-size: 1rem;
|
||||
padding-bottom: 0.25rem;
|
||||
border-bottom: 2px solid transparent;
|
||||
transition: color 0.3s ease, border-color 0.3s ease;
|
||||
|
||||
&:hover,
|
||||
&.active {
|
||||
color: #fff;
|
||||
border-bottom-color: #e50914;
|
||||
}
|
||||
}
|
||||
20
src/app/core/layout/header/header.component.ts
Normal file
20
src/app/core/layout/header/header.component.ts
Normal file
@@ -0,0 +1,20 @@
|
||||
import { ChangeDetectionStrategy, Component } from '@angular/core';
|
||||
import { RouterLink } from '@angular/router';
|
||||
|
||||
@Component({
|
||||
selector: 'app-header',
|
||||
template: `
|
||||
<header class="header">
|
||||
<nav class="header-nav">
|
||||
<a class="logo" routerLink="/">🍿 Vidéothèque</a>
|
||||
<a class="nav-link" routerLink="/movies" routerLinkActive="active">
|
||||
Films
|
||||
</a>
|
||||
</nav>
|
||||
</header>
|
||||
`,
|
||||
styleUrls: ['./header.component.scss'],
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
imports: [RouterLink],
|
||||
})
|
||||
export class HeaderComponent {}
|
||||
61
src/app/core/models/api.models.ts
Normal file
61
src/app/core/models/api.models.ts
Normal file
@@ -0,0 +1,61 @@
|
||||
// Interfaces pour l'API REST
|
||||
|
||||
export interface Genre {
|
||||
id: number;
|
||||
label: string;
|
||||
}
|
||||
|
||||
export interface Person {
|
||||
id: number;
|
||||
last_name: string;
|
||||
first_name: string | null;
|
||||
}
|
||||
|
||||
export interface Member {
|
||||
id: number;
|
||||
login: string;
|
||||
}
|
||||
|
||||
export interface Opinion {
|
||||
id: number;
|
||||
note: number;
|
||||
comment: string;
|
||||
movie_id: number;
|
||||
member: Member;
|
||||
}
|
||||
|
||||
export interface Movie {
|
||||
id: number;
|
||||
title: string;
|
||||
year: number;
|
||||
duration: number | null;
|
||||
synopsis: string | null;
|
||||
genre: Genre;
|
||||
director: Person;
|
||||
actors: Person[];
|
||||
opinions: Opinion[];
|
||||
}
|
||||
|
||||
export interface MovieCreate {
|
||||
title: string;
|
||||
year: number;
|
||||
duration: number | null;
|
||||
synopsis: string | null;
|
||||
genre_id: number;
|
||||
director_id: number;
|
||||
actors_ids: number[];
|
||||
}
|
||||
|
||||
// Interface pour l'API GraphQL
|
||||
export interface MovieAnalysis {
|
||||
id: string;
|
||||
aiSummary: string | null;
|
||||
aiOpinionSummary: string | null;
|
||||
aiBestGenre: string | null;
|
||||
aiTags: string[] | null;
|
||||
}
|
||||
|
||||
// Interface pour les réponses GraphQL
|
||||
export interface AnalyzeMovieResponse {
|
||||
analyzeMovie: MovieAnalysis;
|
||||
}
|
||||
23
src/app/core/services/ai-api.service.ts
Normal file
23
src/app/core/services/ai-api.service.ts
Normal file
@@ -0,0 +1,23 @@
|
||||
import { inject, Injectable } from '@angular/core';
|
||||
import { Apollo } from 'apollo-angular';
|
||||
import { map, Observable } from 'rxjs';
|
||||
import { ANALYZE_MOVIE_QUERY } from '../graphql/graphql.queries';
|
||||
import { AnalyzeMovieResponse, MovieAnalysis } from '../models/api.models';
|
||||
|
||||
@Injectable({ providedIn: 'root' })
|
||||
export class AiApiService {
|
||||
private readonly apollo = inject(Apollo);
|
||||
|
||||
getMovieAnalysis(movieId: number): Observable<MovieAnalysis> {
|
||||
return this.apollo
|
||||
.query<AnalyzeMovieResponse>({
|
||||
query: ANALYZE_MOVIE_QUERY,
|
||||
variables: {
|
||||
movieId: movieId.toString(),
|
||||
},
|
||||
// Optionnel mais recommandé : 'network-only' pour toujours avoir des données fraîches
|
||||
fetchPolicy: 'network-only'
|
||||
})
|
||||
.pipe(map((result) => result.data.analyzeMovie));
|
||||
}
|
||||
}
|
||||
15
src/app/core/services/genre-api.service.ts
Normal file
15
src/app/core/services/genre-api.service.ts
Normal file
@@ -0,0 +1,15 @@
|
||||
import { inject, Injectable } from '@angular/core';
|
||||
import { HttpClient } from '@angular/common/http';
|
||||
import { Observable } from 'rxjs';
|
||||
import { environment } from '../../../environments/environment';
|
||||
import { Genre } from '../models/api.models';
|
||||
|
||||
@Injectable({ providedIn: 'root' })
|
||||
export class GenreApiService {
|
||||
private readonly http = inject(HttpClient);
|
||||
private readonly apiUrl = `${environment.apiRestUrl}/genres`;
|
||||
|
||||
getGenres(): Observable<Genre[]> {
|
||||
return this.http.get<Genre[]>(this.apiUrl);
|
||||
}
|
||||
}
|
||||
23
src/app/core/services/movie-api.service.ts
Normal file
23
src/app/core/services/movie-api.service.ts
Normal file
@@ -0,0 +1,23 @@
|
||||
import { inject, Injectable } from '@angular/core';
|
||||
import { HttpClient } from '@angular/common/http';
|
||||
import { Observable } from 'rxjs';
|
||||
import { environment } from '../../../environments/environment';
|
||||
import { Movie, MovieCreate } from '../models/api.models';
|
||||
|
||||
@Injectable({ providedIn: 'root' })
|
||||
export class MovieApiService {
|
||||
private readonly http = inject(HttpClient);
|
||||
private readonly apiUrl = `${environment.apiRestUrl}/movies`;
|
||||
|
||||
getMovies(): Observable<Movie[]> {
|
||||
return this.http.get<Movie[]>(this.apiUrl);
|
||||
}
|
||||
|
||||
getMovieById(id: number): Observable<Movie> {
|
||||
return this.http.get<Movie>(`${this.apiUrl}/${id}`);
|
||||
}
|
||||
|
||||
createMovie(movie: MovieCreate): Observable<Movie> {
|
||||
return this.http.post<Movie>(this.apiUrl, movie);
|
||||
}
|
||||
}
|
||||
15
src/app/core/services/participant-api.service.ts
Normal file
15
src/app/core/services/participant-api.service.ts
Normal file
@@ -0,0 +1,15 @@
|
||||
import { inject, Injectable } from '@angular/core';
|
||||
import { HttpClient } from '@angular/common/http';
|
||||
import { Observable } from 'rxjs';
|
||||
import { environment } from '../../../environments/environment';
|
||||
import { Person } from '../models/api.models';
|
||||
|
||||
@Injectable({ providedIn: 'root' })
|
||||
export class ParticipantApiService {
|
||||
private readonly http = inject(HttpClient);
|
||||
private readonly apiUrl = `${environment.apiRestUrl}/participants`;
|
||||
|
||||
getParticipants(): Observable<Person[]> {
|
||||
return this.http.get<Person[]>(this.apiUrl);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user