Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# untitled2
# Github App

A new Flutter project.

Expand Down
38 changes: 16 additions & 22 deletions lib/data/data_sources/user_remote_data_source.dart
Original file line number Diff line number Diff line change
@@ -1,37 +1,27 @@
import 'dart:convert';
import 'package:get_it/get_it.dart';
import 'package:http/http.dart' as http;
import '../models/user_list_model.dart';
import '../models/user_model.dart';

abstract class UserRemoteDataSource {
Future<UserModel> getUser(int id);
Future<List<UserModel>> searchUsersByLocation(String location, int page);
Future<List<UserListModel>> searchUsersByLocation(String location, int page);
Future<UserModel> getUserDetail(String username);
Future<UserModel> searchUserByUsername(String username);
Future<List<UserListModel>> searchUserByUsername(String name);
}

class UserRemoteDataSourceImpl implements UserRemoteDataSource {
final http.Client client;
final http.Client client = GetIt.instance<http.Client>();

UserRemoteDataSourceImpl({required this.client});
//UserRemoteDataSourceImpl({required this.client});

@override
Future<UserModel> getUser(int id) async {
final response = await client.get(Uri.parse('https://api.github.com/users/$id'));

if (response.statusCode == 200) {
return UserModel.fromJson(json.decode(response.body));
} else {
throw Exception('Failed to load User');
}
}

@override
Future<List<UserModel>> searchUsersByLocation(String location, int page) async {
Future<List<UserListModel>> searchUsersByLocation(String location, int page) async {
final response = await client.get(Uri.parse('https://api.github.com/search/users?q=location:$location'));

if (response.statusCode == 200) {
final data = json.decode(response.body);
return (data['items'] as List).map((json) => UserModel.fromJson(json)).toList();
return (data['items'] as List).map((json) => UserListModel.fromJson(json)).toList();
} else {
throw Exception('Failed to load users');
}
Expand All @@ -49,13 +39,17 @@ class UserRemoteDataSourceImpl implements UserRemoteDataSource {
}

@override
Future<UserModel> searchUserByUsername(String username) async {
final response = await client.get(Uri.parse('https://api.github.com/users/$username'));
Future<List<UserListModel>> searchUserByUsername(String name) async {
// final response = await client.get(Uri.parse('https://api.github.com/search/users?q=$name'));
final response = await client.get(Uri.parse('https://api.github.com/search/users?q=$name'));


if (response.statusCode == 200) {
return UserModel.fromJson(json.decode(response.body));
//return UserModel.fromJson(json.decode(response.body));
final data = json.decode(response.body);
return (data['items'] as List).map((json) => UserListModel.fromJson(json)).toList();
} else {
throw Exception('Failed to load User');
}
}
}
}
34 changes: 34 additions & 0 deletions lib/data/models/user_list_model.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import '../../domain/entities/user_list_entity.dart';

import 'package:json_annotation/json_annotation.dart';
part 'user_list_model.g.dart';

@JsonSerializable()
class UserListModel{
final String login;

@JsonKey(name: "avatar_url")
final String avatarUrl;

@JsonKey(name: "email")
final String? email;

@JsonKey(name: "type")
final String? type;

UserListModel( this.login, this.email, this.type, this.avatarUrl);

factory UserListModel.fromJson(Map<String, dynamic> json) => _$UserListModelFromJson(json);

Map<String, dynamic> toJson() => _$UserListModelToJson(this);

// Convert User listModel to User list entity
UserListEntity toEntity() {
return UserListEntity(
login: login,
avatarUrl: avatarUrl,
type: type ?? '',
email: email ?? '',
);
}
}
23 changes: 23 additions & 0 deletions lib/data/models/user_list_model.g.dart

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

101 changes: 54 additions & 47 deletions lib/data/models/user_model.dart
Original file line number Diff line number Diff line change
@@ -1,57 +1,64 @@
import 'package:githubUsers/data/models/user_list_model.dart';

import '../../domain/entities/user.dart';
import 'package:json_annotation/json_annotation.dart';

class UserModel extends User {
UserModel({
required String login,
required String avatarUrl,
required String name,
required String followers,
required String following,
required String type,
required String bio,
}) : super(
login: login,
avatarUrl: avatarUrl,
name: name,
followers: followers,
following: following,
type: type,
bio: bio,
);

factory UserModel.fromJson(Map<String, dynamic> json) {
return UserModel(
login: json['login'],
avatarUrl: json['avatar_url'],
name: json['name'] ?? '',
followers: json['followers'].toString(),
following: json['following'].toString() ,
type: json['type'],
bio: json['bio'] ?? '',
);
}
part 'user_model.g.dart';

Map<String, dynamic> toJson() {
return {
'login': login,
'avatar_url': avatarUrl,
'name': name,
'followers': followers,
'following': following,
'type': type,
'bio': bio,
};
}
@JsonSerializable()
class UserModel {


final String login;

@JsonKey(name: "avatar_url")
final String avatarUrl;

@JsonKey(name: "subscriptions_url")
final String? subscriptionsUrl;

@JsonKey(name: "repos_url")
final String? reposUrl;

@JsonKey(name: "name")
final String? name;

@JsonKey(name: "bio")
final String? bio;

@JsonKey(name: "followers")
final int? followers;

@JsonKey(name: "following")
final int? following;

@JsonKey(name: "email")
final String? email;

@JsonKey(name: "type")
final String? type;

UserModel(this.login, this.avatarUrl, this.subscriptionsUrl, this.reposUrl, this.name, this.bio, this.followers, this.following, this.email, this.type);

factory UserModel.fromJson(Map<String, dynamic> json) => _$UserModelFromJson(json);

Map<String, dynamic> toJson() => _$UserModelToJson(this);

// Convert UserModel to User entity
User toEntity() {
return User(
login: login,
avatarUrl: avatarUrl,
name: name,
followers: followers,
following: following,
type: type,
bio: bio,
// url: url ?? '',
subscriptionsUrl: subscriptionsUrl ?? '',
reposUrl: reposUrl ?? '',
name: name ?? '',
type: type ?? '',
followers: followers ?? 0,
following: following ?? 0,
bio: bio ?? '',
email: email ?? '',
);
}
}

}
33 changes: 33 additions & 0 deletions lib/data/models/user_model.g.dart

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

31 changes: 12 additions & 19 deletions lib/data/repositories/user_repository_impl.dart
Original file line number Diff line number Diff line change
@@ -1,30 +1,22 @@
import 'package:dartz/dartz.dart';
import 'package:get_it/get_it.dart';
import 'package:githubUsers/domain/entities/user_list_entity.dart';
import '../../domain/entities/user.dart';
import '../../domain/repositories/user_repository.dart';
import '../../data/data_sources/user_remote_data_source.dart';
import '../models/user_model.dart';

class UserRepositoryImpl implements UserRepository {
final UserRemoteDataSource remoteDataSource;
final UserRemoteDataSource remoteDataSource = GetIt.instance<UserRemoteDataSource>();

UserRepositoryImpl({required this.remoteDataSource});
//UserRepositoryImpl({required this.remoteDataSource});

@override
Future<Either<Exception, User>> getUser(int id) async {
try {
final model = await remoteDataSource.getUser(id);
return Right(model.toEntity());
} catch (e) {
return Left(Exception('Failed to fetch data'));
}
}

@override
Future<Either<Exception, List<User>>> searchUsersByLocation(String location, int page) async {
Future<Either<Exception, List<UserListEntity>>> searchUsersByLocation(String location, int page) async {
try {
final models = await remoteDataSource.searchUsersByLocation(location, page);
final users = models.map((model) => model.toEntity()).toList();
return Right(users);
final userlist = models.map((model) => model.toEntity()).toList();
return Right(userlist);
} catch (e) {
return Left(Exception('Failed to fetch data'));
}
Expand All @@ -41,12 +33,13 @@ class UserRepositoryImpl implements UserRepository {
}

@override
Future<Either<Exception, User>> searchUsersByUsername(String username, int page) async {
Future<Either<Exception, List<UserListEntity>>> searchUsersByUsername(String name) async {
try {
final model = await remoteDataSource.searchUserByUsername(username);
return Right(model.toEntity());
final models = await remoteDataSource.searchUserByUsername(name);
final users = models.map((model) => model.toEntity()).toList();
return Right(users);
} catch (e) {
return Left(Exception('Failed to fetch data'));
}
}
}
}
14 changes: 9 additions & 5 deletions lib/domain/entities/user.dart
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
// domain/entities/user.dart
class User {
final String login;
final String avatarUrl;
final String reposUrl;
final String subscriptionsUrl;
final String name;
final String followers;
final String following;
final int followers;
final int following;
final String type;
final String bio;

final String email;
User({
required this.login,
required this.avatarUrl,
Expand All @@ -16,5 +17,8 @@ class User {
required this.following,
required this.type,
required this.bio,
required this.reposUrl,
required this.email,
required this.subscriptionsUrl,
});
}
}
14 changes: 14 additions & 0 deletions lib/domain/entities/user_list_entity.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import 'package:githubUsers/domain/entities/user.dart';

class UserListEntity {
final String login;
final String avatarUrl;
final String type;
final String email;
UserListEntity({
required this.login,
required this.avatarUrl,
required this.type,
required this.email,
});
}
Loading