diff --git a/.fvm/fvm_config.json b/.fvm/fvm_config.json
index 160b5b2..e7b55eb 100644
--- a/.fvm/fvm_config.json
+++ b/.fvm/fvm_config.json
@@ -1,4 +1,3 @@
{
- "flutterSdkVersion": "3.22.3",
- "flavors": {}
+ "flutterSdkVersion": "3.22.3"
}
\ No newline at end of file
diff --git a/.fvmrc b/.fvmrc
new file mode 100644
index 0000000..e03e940
--- /dev/null
+++ b/.fvmrc
@@ -0,0 +1,4 @@
+{
+ "flutter": "3.22.3",
+ "flavors": {}
+}
\ No newline at end of file
diff --git a/.gitignore b/.gitignore
index 1be2d87..7040cb0 100644
--- a/.gitignore
+++ b/.gitignore
@@ -46,4 +46,6 @@ app.*.map.json
/android/app/release
# fvm
-.fvm/flutter_sdk
\ No newline at end of file
+
+# FVM Version Cache
+.fvm/
\ No newline at end of file
diff --git a/.vscode/settings.json b/.vscode/settings.json
index f285aa4..c959187 100644
--- a/.vscode/settings.json
+++ b/.vscode/settings.json
@@ -1,9 +1,9 @@
{
- "dart.flutterSdkPath": ".fvm/flutter_sdk",
- "search.exclude": {
- "**/.fvm": true
- },
- "files.watcherExclude": {
- "**/.fvm": true
- }
+ "dart.flutterSdkPath": ".fvm/versions/3.22.3",
+ "search.exclude": {
+ "**/.fvm": true
+ },
+ "files.watcherExclude": {
+ "**/.fvm": true
+ }
}
\ No newline at end of file
diff --git a/android/app/build.gradle b/android/app/build.gradle
index 57d5cc6..08f2222 100644
--- a/android/app/build.gradle
+++ b/android/app/build.gradle
@@ -38,7 +38,7 @@ android {
applicationId = "com.example.restaurant_tour"
// You can update the following values to match your application needs.
// For more information, see: https://docs.flutter.dev/deployment/android#reviewing-the-gradle-build-configuration.
- minSdk = flutter.minSdkVersion
+ minSdk = 23
targetSdk = flutter.targetSdkVersion
versionCode = flutterVersionCode.toInteger()
versionName = flutterVersionName
diff --git a/assets/icons/heart_empty.svg b/assets/icons/heart_empty.svg
new file mode 100644
index 0000000..9a62af1
--- /dev/null
+++ b/assets/icons/heart_empty.svg
@@ -0,0 +1,3 @@
+
diff --git a/assets/icons/heart_filled.svg b/assets/icons/heart_filled.svg
new file mode 100644
index 0000000..67a7799
--- /dev/null
+++ b/assets/icons/heart_filled.svg
@@ -0,0 +1,3 @@
+
diff --git a/lib/core/utils/app_exceptions.dart b/lib/core/utils/app_exceptions.dart
new file mode 100644
index 0000000..00ed917
--- /dev/null
+++ b/lib/core/utils/app_exceptions.dart
@@ -0,0 +1,11 @@
+class AppException implements Exception {
+ final String? message;
+
+ AppException({this.message});
+}
+
+class ServerException implements Exception {
+ final String? message;
+
+ ServerException({this.message});
+}
diff --git a/lib/core/utils/app_failures.dart b/lib/core/utils/app_failures.dart
new file mode 100644
index 0000000..b33887d
--- /dev/null
+++ b/lib/core/utils/app_failures.dart
@@ -0,0 +1,13 @@
+abstract class Failure {
+ final String? message;
+
+ Failure({this.message});
+}
+
+class ServerFailure extends Failure {
+ ServerFailure({super.message});
+}
+
+class AppFailure extends Failure {
+ AppFailure({super.message});
+}
diff --git a/lib/core/utils/app_keys.dart b/lib/core/utils/app_keys.dart
new file mode 100644
index 0000000..badec7c
--- /dev/null
+++ b/lib/core/utils/app_keys.dart
@@ -0,0 +1,6 @@
+class AppKeys {
+ static const loadingRestaurantsIndicator = "LoadingRestaurantsIndicator";
+ static const listRestaurantsFetched = "ListRestaurantsFetched";
+ static const listRestaurantsError = "ListRestaurantsErrorWidget";
+ static const restaurantListIsEmpty = "RestaurantListIsEmpty";
+}
diff --git a/lib/di.dart b/lib/di.dart
new file mode 100644
index 0000000..c9658e4
--- /dev/null
+++ b/lib/di.dart
@@ -0,0 +1,48 @@
+import 'package:dio/dio.dart';
+import 'package:get_it/get_it.dart';
+import 'package:restaurant_tour/features/restaurant/data/data_sources/remote_datasource.dart';
+import 'package:restaurant_tour/features/restaurant/data/repositories/yelp_repository_impl.dart';
+import 'package:restaurant_tour/features/restaurant/domain/repositories/yelp_repository.dart';
+import 'package:restaurant_tour/features/restaurant/domain/use_cases/get_favorites.dart';
+import 'package:restaurant_tour/features/restaurant/domain/use_cases/get_restaurants.dart';
+import 'package:restaurant_tour/features/restaurant/domain/use_cases/mark_favorite.dart';
+import 'package:restaurant_tour/features/restaurant/presentation/manager/home_cubit.dart';
+
+final getIt = GetIt.instance;
+
+void setupDependencies() {
+ const _apiKey =
+ 'jvWqxC5xhVHIwruAaM4dgsO9Gk6j_nfPeeErabJvh6LllVAVNj1fr4GcWzHXq5JIRlCgiPudUO45KW7g8Wsxmx_sJcwx3YMbD8yAcvbm_0bF_zyMzNbb8UgdE07aZnYx';
+ getIt.registerLazySingleton(
+ () => Dio(
+ BaseOptions(
+ baseUrl: 'https://api.yelp.com',
+ headers: {
+ 'Authorization': 'Bearer $_apiKey',
+ 'Content-Type': 'application/graphql',
+ },
+ ),
+ ),
+ );
+ getIt.registerLazySingleton(
+ () => RemoteDatasourceImpl(dio: getIt()),
+ );
+
+ getIt.registerLazySingleton(
+ () => YelpRepositoryImpl(datasource: getIt()),
+ );
+
+ getIt.registerFactory(() => GetRestaurants(getIt()));
+
+ getIt.registerFactory(() => GetFavorites(getIt()));
+
+ getIt.registerFactory(() => MarkFavorite(getIt()));
+
+ getIt.registerFactory(
+ () => HomeCubit(
+ getIt(),
+ getIt(),
+ getIt(),
+ ),
+ );
+}
diff --git a/lib/features/restaurant/data/data_sources/remote_datasource.dart b/lib/features/restaurant/data/data_sources/remote_datasource.dart
new file mode 100644
index 0000000..02ec56e
--- /dev/null
+++ b/lib/features/restaurant/data/data_sources/remote_datasource.dart
@@ -0,0 +1,61 @@
+import 'package:dio/dio.dart';
+import 'package:restaurant_tour/core/utils/app_exceptions.dart';
+
+abstract class RemoteDatasource {
+ Future