First comit

This commit is contained in:
Johan
2025-12-17 09:56:42 +01:00
commit f8979701ae
43 changed files with 11907 additions and 0 deletions

View 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,
},
];

View 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
}
}
`;

View 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;
}
}

View 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 {}

View 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;
}

View 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));
}
}

View 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);
}
}

View 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);
}
}

View 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);
}
}