first commit

This commit is contained in:
sartron_Northblue
2025-09-17 11:50:34 +04:00
commit 95afac750a
196 changed files with 6821 additions and 0 deletions
+102
View File
@@ -0,0 +1,102 @@
import 'dart:convert';
import 'package:http/http.dart' as http;
import '../models/movie.dart';
class ApiService {
static const String apiKey = '70101da29bbd7fafb66f0ed06dd88794';
static const String accessToken = 'eyJhbGciOiJIUzI1NiJ9.eyJhdWQiOiI3MDEwMWRhMjliYmQ3ZmFmYjY2ZjBlZDA2ZGQ4ODc5NCIsIm5iZiI6MTc0NzgxNDY5MS44NDA5OTk4LCJzdWIiOiI2ODJkODkyMzYyOTliNjFlNzM2NDk2ODkiLCJzY29wZXMiOlsiYXBpX3JlYWQiXSwidmVyc2lvbiI6MX0.nGl7SvvrI6FlcQ7uOGJzrejN-_s7G0kdvnVCzSGGwm8';
static const String baseUrl = 'https://api.themoviedb.org/3';
static const String imageBaseUrl = 'https://image.tmdb.org/t/p/w500';
static Future<List<Movie>> getPopularMovies() async {
try {
final response = await http.get(
Uri.parse('$baseUrl/movie/popular?api_key=$apiKey'),
headers: {
'Authorization': 'Bearer $accessToken',
'Content-Type': 'application/json',
},
);
if (response.statusCode == 200) {
final data = json.decode(response.body);
final List<dynamic> movies = data['results'];
return movies.map((movie) => Movie.fromJson(movie)).toList();
} else {
throw Exception('Échec du chargement des films: ${response.statusCode}');
}
} catch (e) {
throw Exception('Erreur lors de la récupération des films: $e');
}
}
static Future<List<Movie>> getTopRatedMovies() async {
try {
final response = await http.get(
Uri.parse('$baseUrl/movie/top_rated?api_key=$apiKey'),
headers: {
'Authorization': 'Bearer $accessToken',
'Content-Type': 'application/json',
},
);
if (response.statusCode == 200) {
final data = json.decode(response.body);
final List<dynamic> movies = data['results'];
return movies.map((movie) => Movie.fromJson(movie)).toList();
} else {
throw Exception('Échec du chargement des films: ${response.statusCode}');
}
} catch (e) {
throw Exception('Erreur lors de la récupération des films: $e');
}
}
static Future<List<Movie>> getNowPlayingMovies() async {
try {
final response = await http.get(
Uri.parse('$baseUrl/movie/now_playing?api_key=$apiKey'),
headers: {
'Authorization': 'Bearer $accessToken',
'Content-Type': 'application/json',
},
);
if (response.statusCode == 200) {
final data = json.decode(response.body);
final List<dynamic> movies = data['results'];
return movies.map((movie) => Movie.fromJson(movie)).toList();
} else {
throw Exception('Échec du chargement des films: ${response.statusCode}');
}
} catch (e) {
throw Exception('Erreur lors de la récupération des films: $e');
}
}
static Future<List<Movie>> getUpcomingMovies() async {
try {
final response = await http.get(
Uri.parse('$baseUrl/movie/upcoming?api_key=$apiKey'),
headers: {
'Authorization': 'Bearer $accessToken',
'Content-Type': 'application/json',
},
);
if (response.statusCode == 200) {
final data = json.decode(response.body);
final List<dynamic> movies = data['results'];
return movies.map((movie) => Movie.fromJson(movie)).toList();
} else {
throw Exception('Échec du chargement des films: ${response.statusCode}');
}
} catch (e) {
throw Exception('Erreur lors de la récupération des films: $e');
}
}
}
+168
View File
@@ -0,0 +1,168 @@
import 'package:postgres/postgres.dart';
import '../models/movie.dart';
import 'local_storage_service.dart';
class DatabaseService {
static const String host = 'localhost';
static const String database = 'flutterBDD';
static const String username = 'postgres';
static const String password = 'root';
static const int port = 5432;
static Connection? _connection;
static bool _useLocalStorage = false;
static Future<Connection> get connection async {
if (_connection == null && !_useLocalStorage) {
try {
_connection = await Connection.open(
Endpoint(
host: host,
port: port,
database: database,
username: username,
password: password,
),
);
await _createTables();
} catch (e) {
print('Erreur de connexion à PostgreSQL: $e');
print('Utilisation du stockage local à la place...');
_useLocalStorage = true;
throw Exception('PostgreSQL non disponible, utilisation du stockage local');
}
}
if (_useLocalStorage) {
throw Exception('Utilisation du stockage local');
}
return _connection!;
}
static Future<void> _createTables() async {
final conn = await connection;
await conn.execute('''
CREATE TABLE IF NOT EXISTS favorites (
id SERIAL PRIMARY KEY,
movie_id INTEGER NOT NULL,
title TEXT NOT NULL,
description TEXT,
image_url TEXT,
category TEXT,
director TEXT,
release_date TEXT,
rating REAL,
original_title TEXT,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
)
''');
}
static Future<bool> addToFavorites(Movie movie) async {
try {
final conn = await connection;
final existing = await conn.execute(
Sql.named('SELECT id FROM favorites WHERE movie_id = @movieId'),
parameters: {'movieId': movie.id},
);
if (existing.isNotEmpty) {
return false;
}
await conn.execute(
Sql.named('''
INSERT INTO favorites (
movie_id, title, description, image_url, category,
director, release_date, rating, original_title
) VALUES (
@movieId, @title, @description, @imageUrl, @category,
@director, @releaseDate, @rating, @originalTitle
)
'''),
parameters: {
'movieId': movie.id,
'title': movie.title,
'description': movie.description,
'imageUrl': movie.imageUrl,
'category': movie.category,
'director': movie.director,
'releaseDate': movie.releaseDate,
'rating': movie.rating,
'originalTitle': movie.originalTitle,
},
);
return true;
} catch (e) {
print('Erreur PostgreSQL, utilisation du stockage local: $e');
return await LocalStorageService.addToFavorites(movie);
}
}
static Future<bool> removeFromFavorites(int movieId) async {
try {
final conn = await connection;
final result = await conn.execute(
Sql.named('DELETE FROM favorites WHERE movie_id = @movieId'),
parameters: {'movieId': movieId},
);
return result.length > 0;
} catch (e) {
print('Erreur PostgreSQL, utilisation du stockage local: $e');
return await LocalStorageService.removeFromFavorites(movieId);
}
}
static Future<bool> isFavorite(int movieId) async {
try {
final conn = await connection;
final result = await conn.execute(
Sql.named('SELECT id FROM favorites WHERE movie_id = @movieId'),
parameters: {'movieId': movieId},
);
return result.isNotEmpty;
} catch (e) {
print('Erreur PostgreSQL, utilisation du stockage local: $e');
return await LocalStorageService.isFavorite(movieId);
}
}
static Future<List<Movie>> getFavorites() async {
try {
final conn = await connection;
final results = await conn.execute(
Sql('SELECT * FROM favorites ORDER BY created_at DESC'),
);
return results.map((row) => Movie(
id: row[1] as int,
title: row[2] as String,
description: row[3] as String,
imageUrl: row[4] as String,
category: row[5] as String,
director: row[6] as String,
releaseDate: row[7] as String,
rating: (row[8] as double?) ?? 0.0,
originalTitle: row[9] as String,
isFeatured: false,
)).toList();
} catch (e) {
print('Erreur PostgreSQL, utilisation du stockage local: $e');
return await LocalStorageService.getFavorites();
}
}
static Future<void> close() async {
if (_connection != null) {
await _connection!.close();
_connection = null;
}
}
}
+108
View File
@@ -0,0 +1,108 @@
import 'dart:convert';
import 'package:shared_preferences/shared_preferences.dart';
import '../models/movie.dart';
class LocalStorageService {
static const String _favoritesKey = 'favorite_movies';
static Future<bool> addToFavorites(Movie movie) async {
try {
final prefs = await SharedPreferences.getInstance();
final favoritesJson = prefs.getStringList(_favoritesKey) ?? [];
final existing = favoritesJson.any((json) {
final movieData = jsonDecode(json);
return movieData['id'] == movie.id;
});
if (existing) {
return false;
}
final movieJson = jsonEncode({
'id': movie.id,
'title': movie.title,
'description': movie.description,
'imageUrl': movie.imageUrl,
'category': movie.category,
'director': movie.director,
'releaseDate': movie.releaseDate,
'rating': movie.rating,
'originalTitle': movie.originalTitle,
'addedAt': DateTime.now().toIso8601String(),
});
favoritesJson.add(movieJson);
await prefs.setStringList(_favoritesKey, favoritesJson);
return true;
} catch (e) {
print('Erreur lors de l\'ajout aux favoris: $e');
return false;
}
}
static Future<bool> removeFromFavorites(int movieId) async {
try {
final prefs = await SharedPreferences.getInstance();
final favoritesJson = prefs.getStringList(_favoritesKey) ?? [];
final updatedFavorites = favoritesJson.where((json) {
final movieData = jsonDecode(json);
return movieData['id'] != movieId;
}).toList();
if (updatedFavorites.length != favoritesJson.length) {
await prefs.setStringList(_favoritesKey, updatedFavorites);
return true;
}
return false;
} catch (e) {
print('Erreur lors de la suppression des favoris: $e');
return false;
}
}
static Future<bool> isFavorite(int movieId) async {
try {
final prefs = await SharedPreferences.getInstance();
final favoritesJson = prefs.getStringList(_favoritesKey) ?? [];
return favoritesJson.any((json) {
final movieData = jsonDecode(json);
return movieData['id'] == movieId;
});
} catch (e) {
print('Erreur lors de la vérification des favoris: $e');
return false;
}
}
static Future<List<Movie>> getFavorites() async {
try {
final prefs = await SharedPreferences.getInstance();
final favoritesJson = prefs.getStringList(_favoritesKey) ?? [];
return favoritesJson.map((json) {
final movieData = jsonDecode(json);
return Movie(
id: movieData['id'],
title: movieData['title'],
description: movieData['description'],
imageUrl: movieData['imageUrl'],
category: movieData['category'],
director: movieData['director'],
releaseDate: movieData['releaseDate'],
rating: (movieData['rating'] ?? 0.0).toDouble(),
originalTitle: movieData['originalTitle'] ?? '',
isFeatured: false,
);
}).toList();
} catch (e) {
print('Erreur lors de la récupération des favoris: $e');
return [];
}
}
}