Skip to content

Commit a5e49b9

Browse files
authored
Merge pull request #104 from stakepoint/dev
Fix
2 parents b1bbc1a + 193284d commit a5e49b9

19 files changed

Lines changed: 744 additions & 173 deletions

android/gradle/wrapper/gradle-wrapper.properties

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,4 @@ distributionBase=GRADLE_USER_HOME
22
distributionPath=wrapper/dists
33
zipStoreBase=GRADLE_USER_HOME
44
zipStorePath=wrapper/dists
5-
distributionUrl=https\://services.gradle.org/distributions/gradle-8.2-all.zip
5+
distributionUrl=https\://services.gradle.org/distributions/gradle-8.4-all.zip

android/settings.gradle

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ pluginManagement {
1818

1919
plugins {
2020
id "dev.flutter.flutter-plugin-loader" version "1.0.0"
21-
id "com.android.application" version "8.2.1" apply false
21+
id "com.android.application" version "8.3.0" apply false
2222
id "org.jetbrains.kotlin.android" version "2.0.0" apply false
2323

2424
}
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
import 'package:dio/dio.dart';
2+
import '../../core/error/failures.dart';
3+
import '../../core/network/api_client.dart';
4+
import '../../domain/models/category.dart';
5+
import '../../presentation/providers/auth_provider.dart';
6+
import '../../presentation/states/auth_state.dart';
7+
import 'package:flutter_riverpod/flutter_riverpod.dart';
8+
9+
abstract class CategoryRemoteDatasource {
10+
Future<CategoriesResponse> getAllCategories();
11+
}
12+
13+
class CategoryRemoteDatasourceImpl implements CategoryRemoteDatasource {
14+
final ApiClient apiClient;
15+
final Ref ref;
16+
17+
CategoryRemoteDatasourceImpl(this.apiClient, this.ref);
18+
19+
@override
20+
Future<CategoriesResponse> getAllCategories() async {
21+
try {
22+
// Check if the user is authenticated
23+
final authState = ref.read(authNotifierProvider);
24+
if (authState is! AuthSuccess) {
25+
throw ServerFailure(
26+
message: 'Authentication required to fetch categories',
27+
);
28+
}
29+
30+
// Get the access token
31+
final token = authState.response.tokens.accessToken;
32+
33+
// Make the API request with the token
34+
final response = await apiClient.get(
35+
'/categories/all',
36+
options: Options(
37+
headers: {
38+
'Authorization': 'Bearer $token',
39+
},
40+
),
41+
);
42+
43+
// Pass the direct response data to the fromJson method
44+
return CategoriesResponse.fromJson(response.data);
45+
} on DioException catch (e) {
46+
throw ServerFailure(
47+
message: e.message ?? 'An error occurred while fetching categories',
48+
code: e.response?.statusCode,
49+
);
50+
} catch (e) {
51+
if (e is ServerFailure) {
52+
rethrow;
53+
}
54+
throw ServerFailure(message: e.toString());
55+
}
56+
}
57+
}
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
import 'package:dio/dio.dart';
2+
import '../../core/error/failures.dart';
3+
import '../../core/network/api_client.dart';
4+
import '../../domain/models/hashtag.dart';
5+
import '../../presentation/providers/auth_provider.dart';
6+
import '../../presentation/states/auth_state.dart';
7+
import 'package:flutter_riverpod/flutter_riverpod.dart';
8+
9+
abstract class HashtagRemoteDatasource {
10+
Future<HashtagsResponse> getAllHashtags();
11+
}
12+
13+
class HashtagRemoteDatasourceImpl implements HashtagRemoteDatasource {
14+
final ApiClient apiClient;
15+
final Ref ref;
16+
17+
HashtagRemoteDatasourceImpl(this.apiClient, this.ref);
18+
19+
@override
20+
Future<HashtagsResponse> getAllHashtags() async {
21+
try {
22+
// Check if the user is authenticated
23+
final authState = ref.read(authNotifierProvider);
24+
if (authState is! AuthSuccess) {
25+
throw ServerFailure(
26+
message: 'Authentication required to fetch hashtags',
27+
);
28+
}
29+
30+
// Get the access token
31+
final token = authState.response.tokens.accessToken;
32+
33+
// Make the API request with the token
34+
final response = await apiClient.get(
35+
'/hashtags',
36+
options: Options(
37+
headers: {
38+
'Authorization': 'Bearer $token',
39+
},
40+
),
41+
);
42+
43+
// Pass the direct response data to the fromJson method
44+
return HashtagsResponse.fromJson(response.data);
45+
} on DioException catch (e) {
46+
throw ServerFailure(
47+
message: e.message ?? 'An error occurred while fetching hashtags',
48+
code: e.response?.statusCode,
49+
);
50+
} catch (e) {
51+
if (e is ServerFailure) {
52+
rethrow;
53+
}
54+
throw ServerFailure(message: e.toString());
55+
}
56+
}
57+
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
import '../../domain/models/category.dart';
2+
import '../../domain/repositories/category_repository.dart';
3+
import '../datasources/category_remote_datasource.dart';
4+
5+
class CategoryRepositoryImpl implements CategoryRepository {
6+
final CategoryRemoteDatasource remoteDatasource;
7+
8+
CategoryRepositoryImpl(this.remoteDatasource);
9+
10+
@override
11+
Future<CategoriesResponse> getAllCategories() {
12+
return remoteDatasource.getAllCategories();
13+
}
14+
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
import '../../domain/models/hashtag.dart';
2+
import '../../domain/repositories/hashtag_repository.dart';
3+
import '../datasources/hashtag_remote_datasource.dart';
4+
5+
class HashtagRepositoryImpl implements HashtagRepository {
6+
final HashtagRemoteDatasource remoteDatasource;
7+
8+
HashtagRepositoryImpl(this.remoteDatasource);
9+
10+
@override
11+
Future<HashtagsResponse> getAllHashtags() {
12+
return remoteDatasource.getAllHashtags();
13+
}
14+
}

lib/domain/models/category.dart

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
class Category {
2+
final String id;
3+
final String name;
4+
final String createdAt;
5+
final String updatedAt;
6+
7+
Category({
8+
required this.id,
9+
required this.name,
10+
required this.createdAt,
11+
required this.updatedAt,
12+
});
13+
14+
factory Category.fromJson(Map<String, dynamic> json) => Category(
15+
id: json['id'] ?? '',
16+
name: json['name'] ?? '',
17+
createdAt: json['createdAt'] ?? '',
18+
updatedAt: json['updatedAt'] ?? '',
19+
);
20+
}
21+
22+
class CategoriesResponse {
23+
final List<Category> categories;
24+
25+
CategoriesResponse({required this.categories});
26+
27+
factory CategoriesResponse.fromJson(dynamic json) {
28+
// Handle both array response and object with data field
29+
List<dynamic> categoriesData = [];
30+
31+
if (json is List) {
32+
// Direct array response
33+
categoriesData = json;
34+
} else if (json is Map<String, dynamic>) {
35+
// Response with data field
36+
categoriesData = json['data'] ?? [];
37+
}
38+
39+
final categories = categoriesData
40+
.map((categoryJson) => Category.fromJson(categoryJson))
41+
.toList();
42+
return CategoriesResponse(categories: categories);
43+
}
44+
}

lib/domain/models/hashtag.dart

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
class Hashtag {
2+
final String id;
3+
final String name;
4+
final String createdAt;
5+
final String updatedAt;
6+
7+
Hashtag({
8+
required this.id,
9+
required this.name,
10+
required this.createdAt,
11+
required this.updatedAt,
12+
});
13+
14+
factory Hashtag.fromJson(Map<String, dynamic> json) => Hashtag(
15+
id: json['id'] ?? '',
16+
name: json['name'] ?? '',
17+
createdAt: json['createdAt'] ?? '',
18+
updatedAt: json['updatedAt'] ?? '',
19+
);
20+
}
21+
22+
class HashtagsResponse {
23+
final List<Hashtag> hashtags;
24+
25+
HashtagsResponse({required this.hashtags});
26+
27+
factory HashtagsResponse.fromJson(dynamic json) {
28+
// Handle both array response and object with data field
29+
List<dynamic> hashtagsData = [];
30+
31+
if (json is List) {
32+
// Direct array response
33+
hashtagsData = json;
34+
} else if (json is Map<String, dynamic>) {
35+
// Response with data field
36+
hashtagsData = json['data'] ?? [];
37+
}
38+
39+
final hashtags = hashtagsData
40+
.map((hashtagJson) => Hashtag.fromJson(hashtagJson))
41+
.toList();
42+
return HashtagsResponse(hashtags: hashtags);
43+
}
44+
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
import '../models/category.dart';
2+
3+
abstract class CategoryRepository {
4+
Future<CategoriesResponse> getAllCategories();
5+
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
import '../models/hashtag.dart';
2+
3+
abstract class HashtagRepository {
4+
Future<HashtagsResponse> getAllHashtags();
5+
}

0 commit comments

Comments
 (0)