Skip to content

Commit

Permalink
feat: auth login and logout
Browse files Browse the repository at this point in the history
  • Loading branch information
RaffyJO committed May 12, 2024
1 parent 6f6acd2 commit 1bf3132
Show file tree
Hide file tree
Showing 24 changed files with 2,496 additions and 90 deletions.
Empty file added ,
Empty file.
12 changes: 12 additions & 0 deletions config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"modules": [],
"module_directory_name": "module",
"experimental_mode": false,
"learning_mode": false,
"unfreezed": true,
"use_cubit": false,
"ignore_core_generator_for_directories": [
"lib/model",
"lib/models"
]
}
1 change: 1 addition & 0 deletions devtools_options.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
extensions:
36 changes: 36 additions & 0 deletions lib/data/datasource/local_datasources/auth_local_datasources.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import 'dart:convert';

import 'package:shared_preferences/shared_preferences.dart';

import '../../dto/login_response.dart';

class AuthLocalDataSource {
Future<void> saveAuthData(AuthResponseModel authResponseModel) async {
// Save auth data to local storage
final prefs = await SharedPreferences.getInstance();
await prefs.setString('auth_data', jsonEncode(authResponseModel.toJson()));
}

Future<void> removeAuthData() async {
// Remove auth data from local storage
final prefs = await SharedPreferences.getInstance();
await prefs.remove('auth_data');
}

Future<AuthResponseModel?> getAuthData() async {
// Get auth data from local storage
final prefs = await SharedPreferences.getInstance();
final authData = prefs.getString('auth_data');
if (authData != null) {
return AuthResponseModel.fromJson(jsonDecode(authData));
} else {
return null;
}
}

Future<bool> isUserLoggedIn() async {
// Check if user is logged in
final prefs = await SharedPreferences.getInstance();
return prefs.containsKey('auth_data');
}
}
45 changes: 45 additions & 0 deletions lib/data/datasource/remote_datasources/auth_remote_datasource.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import 'dart:convert';

import 'package:dartz/dartz.dart';
import 'package:http/http.dart' as http;

import '../../../presentation/extension/strings.dart';
import '../../dto/login_response.dart';
import '../local_datasources/auth_local_datasources.dart';

class AuthRemoteDatasource {
Future<Either<String, AuthResponseModel>> login(
String email, String password) async {
final url = Uri.parse('$baseUrl/api/login');
final response = await http.post(
url,
body: {
'email': email,
'password': password,
},
);

if (response.statusCode == 200) {
await AuthLocalDataSource()
.saveAuthData(AuthResponseModel.fromJson(jsonDecode(response.body)));
return Right(AuthResponseModel.fromJson(jsonDecode(response.body)));
} else {
return const Left('Gagal login');
}
}

Future<Either<String, String>> logout() async {
final authDataModel = await AuthLocalDataSource().getAuthData();
final url = Uri.parse('$baseUrl/api/logout');
final response = await http.post(url, headers: {
'Authorization': 'Bearer ${authDataModel?.token}',
});

if (response.statusCode == 200) {
await AuthLocalDataSource().removeAuthData();
return const Right('Logout berhasil');
} else {
return const Left('Logout gagal');
}
}
}
27 changes: 27 additions & 0 deletions lib/data/dto/login_response.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import '../../domain/entities/user.dart';

class AuthResponseModel {
final User? user;
final String? token;

AuthResponseModel({
this.user,
this.token,
});

factory AuthResponseModel.fromJson(Map<String, dynamic> json) {
// Jika json["user"] null atau tidak ada, kembalikan null untuk user
final userData = json["user"];
final user = userData != null ? User.fromJson(userData) : null;

return AuthResponseModel(
user: user,
token: json["token"],
);
}

Map<String, dynamic> toJson() => {
"user": user?.toJson(),
"token": token,
};
}
16 changes: 16 additions & 0 deletions lib/domain/entities/user.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import 'package:freezed_annotation/freezed_annotation.dart';

part 'user.freezed.dart';
part 'user.g.dart';

@freezed
class User with _$User {
const factory User({
required String name,
required String email,
required String phone,
required String role,
}) = _User;

factory User.fromJson(Map<String, dynamic> json) => _$UserFromJson(json);
}
202 changes: 202 additions & 0 deletions lib/domain/entities/user.freezed.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,202 @@
// coverage:ignore-file
// GENERATED CODE - DO NOT MODIFY BY HAND
// ignore_for_file: type=lint
// ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides, invalid_annotation_target, unnecessary_question_mark

part of 'user.dart';

// **************************************************************************
// FreezedGenerator
// **************************************************************************

T _$identity<T>(T value) => value;

final _privateConstructorUsedError = UnsupportedError(
'It seems like you constructed your class using `MyClass._()`. This constructor is only meant to be used by freezed and you are not supposed to need it nor use it.\nPlease check the documentation here for more information: https://github.com/rrousselGit/freezed#adding-getters-and-methods-to-our-models');

User _$UserFromJson(Map<String, dynamic> json) {
return _User.fromJson(json);
}

/// @nodoc
mixin _$User {
String get name => throw _privateConstructorUsedError;
String get email => throw _privateConstructorUsedError;
String get phone => throw _privateConstructorUsedError;
String get role => throw _privateConstructorUsedError;

Map<String, dynamic> toJson() => throw _privateConstructorUsedError;
@JsonKey(ignore: true)
$UserCopyWith<User> get copyWith => throw _privateConstructorUsedError;
}

/// @nodoc
abstract class $UserCopyWith<$Res> {
factory $UserCopyWith(User value, $Res Function(User) then) =
_$UserCopyWithImpl<$Res, User>;
@useResult
$Res call({String name, String email, String phone, String role});
}

/// @nodoc
class _$UserCopyWithImpl<$Res, $Val extends User>
implements $UserCopyWith<$Res> {
_$UserCopyWithImpl(this._value, this._then);

// ignore: unused_field
final $Val _value;
// ignore: unused_field
final $Res Function($Val) _then;

@pragma('vm:prefer-inline')
@override
$Res call({
Object? name = null,
Object? email = null,
Object? phone = null,
Object? role = null,
}) {
return _then(_value.copyWith(
name: null == name
? _value.name
: name // ignore: cast_nullable_to_non_nullable
as String,
email: null == email
? _value.email
: email // ignore: cast_nullable_to_non_nullable
as String,
phone: null == phone
? _value.phone
: phone // ignore: cast_nullable_to_non_nullable
as String,
role: null == role
? _value.role
: role // ignore: cast_nullable_to_non_nullable
as String,
) as $Val);
}
}

/// @nodoc
abstract class _$$UserImplCopyWith<$Res> implements $UserCopyWith<$Res> {
factory _$$UserImplCopyWith(
_$UserImpl value, $Res Function(_$UserImpl) then) =
__$$UserImplCopyWithImpl<$Res>;
@override
@useResult
$Res call({String name, String email, String phone, String role});
}

/// @nodoc
class __$$UserImplCopyWithImpl<$Res>
extends _$UserCopyWithImpl<$Res, _$UserImpl>
implements _$$UserImplCopyWith<$Res> {
__$$UserImplCopyWithImpl(_$UserImpl _value, $Res Function(_$UserImpl) _then)
: super(_value, _then);

@pragma('vm:prefer-inline')
@override
$Res call({
Object? name = null,
Object? email = null,
Object? phone = null,
Object? role = null,
}) {
return _then(_$UserImpl(
name: null == name
? _value.name
: name // ignore: cast_nullable_to_non_nullable
as String,
email: null == email
? _value.email
: email // ignore: cast_nullable_to_non_nullable
as String,
phone: null == phone
? _value.phone
: phone // ignore: cast_nullable_to_non_nullable
as String,
role: null == role
? _value.role
: role // ignore: cast_nullable_to_non_nullable
as String,
));
}
}

/// @nodoc
@JsonSerializable()
class _$UserImpl implements _User {
const _$UserImpl(
{required this.name,
required this.email,
required this.phone,
required this.role});

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

@override
final String name;
@override
final String email;
@override
final String phone;
@override
final String role;

@override
String toString() {
return 'User(name: $name, email: $email, phone: $phone, role: $role)';
}

@override
bool operator ==(Object other) {
return identical(this, other) ||
(other.runtimeType == runtimeType &&
other is _$UserImpl &&
(identical(other.name, name) || other.name == name) &&
(identical(other.email, email) || other.email == email) &&
(identical(other.phone, phone) || other.phone == phone) &&
(identical(other.role, role) || other.role == role));
}

@JsonKey(ignore: true)
@override
int get hashCode => Object.hash(runtimeType, name, email, phone, role);

@JsonKey(ignore: true)
@override
@pragma('vm:prefer-inline')
_$$UserImplCopyWith<_$UserImpl> get copyWith =>
__$$UserImplCopyWithImpl<_$UserImpl>(this, _$identity);

@override
Map<String, dynamic> toJson() {
return _$$UserImplToJson(
this,
);
}
}

abstract class _User implements User {
const factory _User(
{required final String name,
required final String email,
required final String phone,
required final String role}) = _$UserImpl;

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

@override
String get name;
@override
String get email;
@override
String get phone;
@override
String get role;
@override
@JsonKey(ignore: true)
_$$UserImplCopyWith<_$UserImpl> get copyWith =>
throw _privateConstructorUsedError;
}
22 changes: 22 additions & 0 deletions lib/domain/entities/user.g.dart

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

Loading

0 comments on commit 1bf3132

Please sign in to comment.