EnakPoint & EnakCoin wallet, PIN, outlet, order, community, reward

- Wallet EnakPoint & EnakCoin: beranda, riwayat, saldo kedaluwarsa, kode
  bayar, tukar EnakCoin, transfer
- PIN (buat, ganti, lupa), outlet, riwayat order, game spin
- Halaman community, webview, coming soon, dan ikon menu beranda baru
- Redesign Reward Saya: kartu tiket, filter chip, detail kode + QR
- Hapus customer point loader, menu, dan checkout lama
- Base URL ke enaklo-pos-api.altru.id

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
efrilm
2026-10-01 01:43:22 +07:00
co-authored by Claude Opus 5.5
parent 5954510b93
commit f5e3075205
253 changed files with 47212 additions and 17437 deletions
File diff suppressed because it is too large Load Diff
@@ -1,7 +1,7 @@
part of '../auth.dart';
@freezed
class CheckPhone with _$CheckPhone {
abstract class CheckPhone with _$CheckPhone {
const factory CheckPhone({
required CheckPhoneStatus status,
required String message,
+2 -2
View File
@@ -1,7 +1,7 @@
part of '../auth.dart';
@freezed
class Login with _$Login {
abstract class Login with _$Login {
const factory Login({
required String status,
required String message,
@@ -20,7 +20,7 @@ class Login with _$Login {
}
@freezed
class User with _$User {
abstract class User with _$User {
const factory User({
required String id,
required String name,
@@ -1,7 +1,7 @@
part of '../auth.dart';
@freezed
class Register with _$Register {
abstract class Register with _$Register {
const factory Register({
required String status,
required String message,
+1 -1
View File
@@ -1,7 +1,7 @@
part of '../auth.dart';
@freezed
class Resend with _$Resend {
abstract class Resend with _$Resend {
const factory Resend({
required ResendStatus status,
required String message,
+1 -1
View File
@@ -1,7 +1,7 @@
part of '../auth.dart';
@freezed
class Verify with _$Verify {
abstract class Verify with _$Verify {
const factory Verify({
required String status,
required String message,
-10
View File
@@ -1,10 +0,0 @@
import 'package:dartz/dartz.dart';
import 'package:freezed_annotation/freezed_annotation.dart';
import '../../common/api/api_failure.dart';
part 'customer.freezed.dart';
part 'entities/customer_point_entity.dart';
part 'failures/customer_failures.dart';
part 'repositories/i_customer_repository.dart';
-713
View File
@@ -1,713 +0,0 @@
// 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 'customer.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',
);
/// @nodoc
mixin _$CustomerPoint {
String get status => throw _privateConstructorUsedError;
String get message => throw _privateConstructorUsedError;
int get totalPoints => throw _privateConstructorUsedError;
String get lastUpdated => throw _privateConstructorUsedError;
/// Create a copy of CustomerPoint
/// with the given fields replaced by the non-null parameter values.
@JsonKey(includeFromJson: false, includeToJson: false)
$CustomerPointCopyWith<CustomerPoint> get copyWith =>
throw _privateConstructorUsedError;
}
/// @nodoc
abstract class $CustomerPointCopyWith<$Res> {
factory $CustomerPointCopyWith(
CustomerPoint value,
$Res Function(CustomerPoint) then,
) = _$CustomerPointCopyWithImpl<$Res, CustomerPoint>;
@useResult
$Res call({
String status,
String message,
int totalPoints,
String lastUpdated,
});
}
/// @nodoc
class _$CustomerPointCopyWithImpl<$Res, $Val extends CustomerPoint>
implements $CustomerPointCopyWith<$Res> {
_$CustomerPointCopyWithImpl(this._value, this._then);
// ignore: unused_field
final $Val _value;
// ignore: unused_field
final $Res Function($Val) _then;
/// Create a copy of CustomerPoint
/// with the given fields replaced by the non-null parameter values.
@pragma('vm:prefer-inline')
@override
$Res call({
Object? status = null,
Object? message = null,
Object? totalPoints = null,
Object? lastUpdated = null,
}) {
return _then(
_value.copyWith(
status: null == status
? _value.status
: status // ignore: cast_nullable_to_non_nullable
as String,
message: null == message
? _value.message
: message // ignore: cast_nullable_to_non_nullable
as String,
totalPoints: null == totalPoints
? _value.totalPoints
: totalPoints // ignore: cast_nullable_to_non_nullable
as int,
lastUpdated: null == lastUpdated
? _value.lastUpdated
: lastUpdated // ignore: cast_nullable_to_non_nullable
as String,
)
as $Val,
);
}
}
/// @nodoc
abstract class _$$CustomerPointImplCopyWith<$Res>
implements $CustomerPointCopyWith<$Res> {
factory _$$CustomerPointImplCopyWith(
_$CustomerPointImpl value,
$Res Function(_$CustomerPointImpl) then,
) = __$$CustomerPointImplCopyWithImpl<$Res>;
@override
@useResult
$Res call({
String status,
String message,
int totalPoints,
String lastUpdated,
});
}
/// @nodoc
class __$$CustomerPointImplCopyWithImpl<$Res>
extends _$CustomerPointCopyWithImpl<$Res, _$CustomerPointImpl>
implements _$$CustomerPointImplCopyWith<$Res> {
__$$CustomerPointImplCopyWithImpl(
_$CustomerPointImpl _value,
$Res Function(_$CustomerPointImpl) _then,
) : super(_value, _then);
/// Create a copy of CustomerPoint
/// with the given fields replaced by the non-null parameter values.
@pragma('vm:prefer-inline')
@override
$Res call({
Object? status = null,
Object? message = null,
Object? totalPoints = null,
Object? lastUpdated = null,
}) {
return _then(
_$CustomerPointImpl(
status: null == status
? _value.status
: status // ignore: cast_nullable_to_non_nullable
as String,
message: null == message
? _value.message
: message // ignore: cast_nullable_to_non_nullable
as String,
totalPoints: null == totalPoints
? _value.totalPoints
: totalPoints // ignore: cast_nullable_to_non_nullable
as int,
lastUpdated: null == lastUpdated
? _value.lastUpdated
: lastUpdated // ignore: cast_nullable_to_non_nullable
as String,
),
);
}
}
/// @nodoc
class _$CustomerPointImpl implements _CustomerPoint {
const _$CustomerPointImpl({
required this.status,
required this.message,
required this.totalPoints,
required this.lastUpdated,
});
@override
final String status;
@override
final String message;
@override
final int totalPoints;
@override
final String lastUpdated;
@override
String toString() {
return 'CustomerPoint(status: $status, message: $message, totalPoints: $totalPoints, lastUpdated: $lastUpdated)';
}
@override
bool operator ==(Object other) {
return identical(this, other) ||
(other.runtimeType == runtimeType &&
other is _$CustomerPointImpl &&
(identical(other.status, status) || other.status == status) &&
(identical(other.message, message) || other.message == message) &&
(identical(other.totalPoints, totalPoints) ||
other.totalPoints == totalPoints) &&
(identical(other.lastUpdated, lastUpdated) ||
other.lastUpdated == lastUpdated));
}
@override
int get hashCode =>
Object.hash(runtimeType, status, message, totalPoints, lastUpdated);
/// Create a copy of CustomerPoint
/// with the given fields replaced by the non-null parameter values.
@JsonKey(includeFromJson: false, includeToJson: false)
@override
@pragma('vm:prefer-inline')
_$$CustomerPointImplCopyWith<_$CustomerPointImpl> get copyWith =>
__$$CustomerPointImplCopyWithImpl<_$CustomerPointImpl>(this, _$identity);
}
abstract class _CustomerPoint implements CustomerPoint {
const factory _CustomerPoint({
required final String status,
required final String message,
required final int totalPoints,
required final String lastUpdated,
}) = _$CustomerPointImpl;
@override
String get status;
@override
String get message;
@override
int get totalPoints;
@override
String get lastUpdated;
/// Create a copy of CustomerPoint
/// with the given fields replaced by the non-null parameter values.
@override
@JsonKey(includeFromJson: false, includeToJson: false)
_$$CustomerPointImplCopyWith<_$CustomerPointImpl> get copyWith =>
throw _privateConstructorUsedError;
}
/// @nodoc
mixin _$CustomerFailure {
@optionalTypeArgs
TResult when<TResult extends Object?>({
required TResult Function(ApiFailure failure) serverError,
required TResult Function() unexpectedError,
required TResult Function(String erroMessage) dynamicErrorMessage,
}) => throw _privateConstructorUsedError;
@optionalTypeArgs
TResult? whenOrNull<TResult extends Object?>({
TResult? Function(ApiFailure failure)? serverError,
TResult? Function()? unexpectedError,
TResult? Function(String erroMessage)? dynamicErrorMessage,
}) => throw _privateConstructorUsedError;
@optionalTypeArgs
TResult maybeWhen<TResult extends Object?>({
TResult Function(ApiFailure failure)? serverError,
TResult Function()? unexpectedError,
TResult Function(String erroMessage)? dynamicErrorMessage,
required TResult orElse(),
}) => throw _privateConstructorUsedError;
@optionalTypeArgs
TResult map<TResult extends Object?>({
required TResult Function(_ServerError value) serverError,
required TResult Function(_UnexpectedError value) unexpectedError,
required TResult Function(_DynamicErrorMessage value) dynamicErrorMessage,
}) => throw _privateConstructorUsedError;
@optionalTypeArgs
TResult? mapOrNull<TResult extends Object?>({
TResult? Function(_ServerError value)? serverError,
TResult? Function(_UnexpectedError value)? unexpectedError,
TResult? Function(_DynamicErrorMessage value)? dynamicErrorMessage,
}) => throw _privateConstructorUsedError;
@optionalTypeArgs
TResult maybeMap<TResult extends Object?>({
TResult Function(_ServerError value)? serverError,
TResult Function(_UnexpectedError value)? unexpectedError,
TResult Function(_DynamicErrorMessage value)? dynamicErrorMessage,
required TResult orElse(),
}) => throw _privateConstructorUsedError;
}
/// @nodoc
abstract class $CustomerFailureCopyWith<$Res> {
factory $CustomerFailureCopyWith(
CustomerFailure value,
$Res Function(CustomerFailure) then,
) = _$CustomerFailureCopyWithImpl<$Res, CustomerFailure>;
}
/// @nodoc
class _$CustomerFailureCopyWithImpl<$Res, $Val extends CustomerFailure>
implements $CustomerFailureCopyWith<$Res> {
_$CustomerFailureCopyWithImpl(this._value, this._then);
// ignore: unused_field
final $Val _value;
// ignore: unused_field
final $Res Function($Val) _then;
/// Create a copy of CustomerFailure
/// with the given fields replaced by the non-null parameter values.
}
/// @nodoc
abstract class _$$ServerErrorImplCopyWith<$Res> {
factory _$$ServerErrorImplCopyWith(
_$ServerErrorImpl value,
$Res Function(_$ServerErrorImpl) then,
) = __$$ServerErrorImplCopyWithImpl<$Res>;
@useResult
$Res call({ApiFailure failure});
$ApiFailureCopyWith<$Res> get failure;
}
/// @nodoc
class __$$ServerErrorImplCopyWithImpl<$Res>
extends _$CustomerFailureCopyWithImpl<$Res, _$ServerErrorImpl>
implements _$$ServerErrorImplCopyWith<$Res> {
__$$ServerErrorImplCopyWithImpl(
_$ServerErrorImpl _value,
$Res Function(_$ServerErrorImpl) _then,
) : super(_value, _then);
/// Create a copy of CustomerFailure
/// with the given fields replaced by the non-null parameter values.
@pragma('vm:prefer-inline')
@override
$Res call({Object? failure = null}) {
return _then(
_$ServerErrorImpl(
null == failure
? _value.failure
: failure // ignore: cast_nullable_to_non_nullable
as ApiFailure,
),
);
}
/// Create a copy of CustomerFailure
/// with the given fields replaced by the non-null parameter values.
@override
@pragma('vm:prefer-inline')
$ApiFailureCopyWith<$Res> get failure {
return $ApiFailureCopyWith<$Res>(_value.failure, (value) {
return _then(_value.copyWith(failure: value));
});
}
}
/// @nodoc
class _$ServerErrorImpl implements _ServerError {
const _$ServerErrorImpl(this.failure);
@override
final ApiFailure failure;
@override
String toString() {
return 'CustomerFailure.serverError(failure: $failure)';
}
@override
bool operator ==(Object other) {
return identical(this, other) ||
(other.runtimeType == runtimeType &&
other is _$ServerErrorImpl &&
(identical(other.failure, failure) || other.failure == failure));
}
@override
int get hashCode => Object.hash(runtimeType, failure);
/// Create a copy of CustomerFailure
/// with the given fields replaced by the non-null parameter values.
@JsonKey(includeFromJson: false, includeToJson: false)
@override
@pragma('vm:prefer-inline')
_$$ServerErrorImplCopyWith<_$ServerErrorImpl> get copyWith =>
__$$ServerErrorImplCopyWithImpl<_$ServerErrorImpl>(this, _$identity);
@override
@optionalTypeArgs
TResult when<TResult extends Object?>({
required TResult Function(ApiFailure failure) serverError,
required TResult Function() unexpectedError,
required TResult Function(String erroMessage) dynamicErrorMessage,
}) {
return serverError(failure);
}
@override
@optionalTypeArgs
TResult? whenOrNull<TResult extends Object?>({
TResult? Function(ApiFailure failure)? serverError,
TResult? Function()? unexpectedError,
TResult? Function(String erroMessage)? dynamicErrorMessage,
}) {
return serverError?.call(failure);
}
@override
@optionalTypeArgs
TResult maybeWhen<TResult extends Object?>({
TResult Function(ApiFailure failure)? serverError,
TResult Function()? unexpectedError,
TResult Function(String erroMessage)? dynamicErrorMessage,
required TResult orElse(),
}) {
if (serverError != null) {
return serverError(failure);
}
return orElse();
}
@override
@optionalTypeArgs
TResult map<TResult extends Object?>({
required TResult Function(_ServerError value) serverError,
required TResult Function(_UnexpectedError value) unexpectedError,
required TResult Function(_DynamicErrorMessage value) dynamicErrorMessage,
}) {
return serverError(this);
}
@override
@optionalTypeArgs
TResult? mapOrNull<TResult extends Object?>({
TResult? Function(_ServerError value)? serverError,
TResult? Function(_UnexpectedError value)? unexpectedError,
TResult? Function(_DynamicErrorMessage value)? dynamicErrorMessage,
}) {
return serverError?.call(this);
}
@override
@optionalTypeArgs
TResult maybeMap<TResult extends Object?>({
TResult Function(_ServerError value)? serverError,
TResult Function(_UnexpectedError value)? unexpectedError,
TResult Function(_DynamicErrorMessage value)? dynamicErrorMessage,
required TResult orElse(),
}) {
if (serverError != null) {
return serverError(this);
}
return orElse();
}
}
abstract class _ServerError implements CustomerFailure {
const factory _ServerError(final ApiFailure failure) = _$ServerErrorImpl;
ApiFailure get failure;
/// Create a copy of CustomerFailure
/// with the given fields replaced by the non-null parameter values.
@JsonKey(includeFromJson: false, includeToJson: false)
_$$ServerErrorImplCopyWith<_$ServerErrorImpl> get copyWith =>
throw _privateConstructorUsedError;
}
/// @nodoc
abstract class _$$UnexpectedErrorImplCopyWith<$Res> {
factory _$$UnexpectedErrorImplCopyWith(
_$UnexpectedErrorImpl value,
$Res Function(_$UnexpectedErrorImpl) then,
) = __$$UnexpectedErrorImplCopyWithImpl<$Res>;
}
/// @nodoc
class __$$UnexpectedErrorImplCopyWithImpl<$Res>
extends _$CustomerFailureCopyWithImpl<$Res, _$UnexpectedErrorImpl>
implements _$$UnexpectedErrorImplCopyWith<$Res> {
__$$UnexpectedErrorImplCopyWithImpl(
_$UnexpectedErrorImpl _value,
$Res Function(_$UnexpectedErrorImpl) _then,
) : super(_value, _then);
/// Create a copy of CustomerFailure
/// with the given fields replaced by the non-null parameter values.
}
/// @nodoc
class _$UnexpectedErrorImpl implements _UnexpectedError {
const _$UnexpectedErrorImpl();
@override
String toString() {
return 'CustomerFailure.unexpectedError()';
}
@override
bool operator ==(Object other) {
return identical(this, other) ||
(other.runtimeType == runtimeType && other is _$UnexpectedErrorImpl);
}
@override
int get hashCode => runtimeType.hashCode;
@override
@optionalTypeArgs
TResult when<TResult extends Object?>({
required TResult Function(ApiFailure failure) serverError,
required TResult Function() unexpectedError,
required TResult Function(String erroMessage) dynamicErrorMessage,
}) {
return unexpectedError();
}
@override
@optionalTypeArgs
TResult? whenOrNull<TResult extends Object?>({
TResult? Function(ApiFailure failure)? serverError,
TResult? Function()? unexpectedError,
TResult? Function(String erroMessage)? dynamicErrorMessage,
}) {
return unexpectedError?.call();
}
@override
@optionalTypeArgs
TResult maybeWhen<TResult extends Object?>({
TResult Function(ApiFailure failure)? serverError,
TResult Function()? unexpectedError,
TResult Function(String erroMessage)? dynamicErrorMessage,
required TResult orElse(),
}) {
if (unexpectedError != null) {
return unexpectedError();
}
return orElse();
}
@override
@optionalTypeArgs
TResult map<TResult extends Object?>({
required TResult Function(_ServerError value) serverError,
required TResult Function(_UnexpectedError value) unexpectedError,
required TResult Function(_DynamicErrorMessage value) dynamicErrorMessage,
}) {
return unexpectedError(this);
}
@override
@optionalTypeArgs
TResult? mapOrNull<TResult extends Object?>({
TResult? Function(_ServerError value)? serverError,
TResult? Function(_UnexpectedError value)? unexpectedError,
TResult? Function(_DynamicErrorMessage value)? dynamicErrorMessage,
}) {
return unexpectedError?.call(this);
}
@override
@optionalTypeArgs
TResult maybeMap<TResult extends Object?>({
TResult Function(_ServerError value)? serverError,
TResult Function(_UnexpectedError value)? unexpectedError,
TResult Function(_DynamicErrorMessage value)? dynamicErrorMessage,
required TResult orElse(),
}) {
if (unexpectedError != null) {
return unexpectedError(this);
}
return orElse();
}
}
abstract class _UnexpectedError implements CustomerFailure {
const factory _UnexpectedError() = _$UnexpectedErrorImpl;
}
/// @nodoc
abstract class _$$DynamicErrorMessageImplCopyWith<$Res> {
factory _$$DynamicErrorMessageImplCopyWith(
_$DynamicErrorMessageImpl value,
$Res Function(_$DynamicErrorMessageImpl) then,
) = __$$DynamicErrorMessageImplCopyWithImpl<$Res>;
@useResult
$Res call({String erroMessage});
}
/// @nodoc
class __$$DynamicErrorMessageImplCopyWithImpl<$Res>
extends _$CustomerFailureCopyWithImpl<$Res, _$DynamicErrorMessageImpl>
implements _$$DynamicErrorMessageImplCopyWith<$Res> {
__$$DynamicErrorMessageImplCopyWithImpl(
_$DynamicErrorMessageImpl _value,
$Res Function(_$DynamicErrorMessageImpl) _then,
) : super(_value, _then);
/// Create a copy of CustomerFailure
/// with the given fields replaced by the non-null parameter values.
@pragma('vm:prefer-inline')
@override
$Res call({Object? erroMessage = null}) {
return _then(
_$DynamicErrorMessageImpl(
null == erroMessage
? _value.erroMessage
: erroMessage // ignore: cast_nullable_to_non_nullable
as String,
),
);
}
}
/// @nodoc
class _$DynamicErrorMessageImpl implements _DynamicErrorMessage {
const _$DynamicErrorMessageImpl(this.erroMessage);
@override
final String erroMessage;
@override
String toString() {
return 'CustomerFailure.dynamicErrorMessage(erroMessage: $erroMessage)';
}
@override
bool operator ==(Object other) {
return identical(this, other) ||
(other.runtimeType == runtimeType &&
other is _$DynamicErrorMessageImpl &&
(identical(other.erroMessage, erroMessage) ||
other.erroMessage == erroMessage));
}
@override
int get hashCode => Object.hash(runtimeType, erroMessage);
/// Create a copy of CustomerFailure
/// with the given fields replaced by the non-null parameter values.
@JsonKey(includeFromJson: false, includeToJson: false)
@override
@pragma('vm:prefer-inline')
_$$DynamicErrorMessageImplCopyWith<_$DynamicErrorMessageImpl> get copyWith =>
__$$DynamicErrorMessageImplCopyWithImpl<_$DynamicErrorMessageImpl>(
this,
_$identity,
);
@override
@optionalTypeArgs
TResult when<TResult extends Object?>({
required TResult Function(ApiFailure failure) serverError,
required TResult Function() unexpectedError,
required TResult Function(String erroMessage) dynamicErrorMessage,
}) {
return dynamicErrorMessage(erroMessage);
}
@override
@optionalTypeArgs
TResult? whenOrNull<TResult extends Object?>({
TResult? Function(ApiFailure failure)? serverError,
TResult? Function()? unexpectedError,
TResult? Function(String erroMessage)? dynamicErrorMessage,
}) {
return dynamicErrorMessage?.call(erroMessage);
}
@override
@optionalTypeArgs
TResult maybeWhen<TResult extends Object?>({
TResult Function(ApiFailure failure)? serverError,
TResult Function()? unexpectedError,
TResult Function(String erroMessage)? dynamicErrorMessage,
required TResult orElse(),
}) {
if (dynamicErrorMessage != null) {
return dynamicErrorMessage(erroMessage);
}
return orElse();
}
@override
@optionalTypeArgs
TResult map<TResult extends Object?>({
required TResult Function(_ServerError value) serverError,
required TResult Function(_UnexpectedError value) unexpectedError,
required TResult Function(_DynamicErrorMessage value) dynamicErrorMessage,
}) {
return dynamicErrorMessage(this);
}
@override
@optionalTypeArgs
TResult? mapOrNull<TResult extends Object?>({
TResult? Function(_ServerError value)? serverError,
TResult? Function(_UnexpectedError value)? unexpectedError,
TResult? Function(_DynamicErrorMessage value)? dynamicErrorMessage,
}) {
return dynamicErrorMessage?.call(this);
}
@override
@optionalTypeArgs
TResult maybeMap<TResult extends Object?>({
TResult Function(_ServerError value)? serverError,
TResult Function(_UnexpectedError value)? unexpectedError,
TResult Function(_DynamicErrorMessage value)? dynamicErrorMessage,
required TResult orElse(),
}) {
if (dynamicErrorMessage != null) {
return dynamicErrorMessage(this);
}
return orElse();
}
}
abstract class _DynamicErrorMessage implements CustomerFailure {
const factory _DynamicErrorMessage(final String erroMessage) =
_$DynamicErrorMessageImpl;
String get erroMessage;
/// Create a copy of CustomerFailure
/// with the given fields replaced by the non-null parameter values.
@JsonKey(includeFromJson: false, includeToJson: false)
_$$DynamicErrorMessageImplCopyWith<_$DynamicErrorMessageImpl> get copyWith =>
throw _privateConstructorUsedError;
}
@@ -1,18 +0,0 @@
part of '../customer.dart';
@freezed
class CustomerPoint with _$CustomerPoint {
const factory CustomerPoint({
required String status,
required String message,
required int totalPoints,
required String lastUpdated,
}) = _CustomerPoint;
factory CustomerPoint.empty() => const CustomerPoint(
status: '',
message: '',
totalPoints: 0,
lastUpdated: '',
);
}
@@ -1,9 +0,0 @@
part of '../customer.dart';
@freezed
sealed class CustomerFailure with _$CustomerFailure {
const factory CustomerFailure.serverError(ApiFailure failure) = _ServerError;
const factory CustomerFailure.unexpectedError() = _UnexpectedError;
const factory CustomerFailure.dynamicErrorMessage(String erroMessage) =
_DynamicErrorMessage;
}
@@ -1,5 +0,0 @@
part of '../customer.dart';
abstract class ICustomerRepository {
Future<Either<CustomerFailure, CustomerPoint>> getPoints();
}
+10 -1
View File
@@ -1,7 +1,9 @@
part of '../game.dart';
@freezed
class Game with _$Game {
abstract class Game with _$Game {
const Game._();
const factory Game({
required String id,
required String name,
@@ -23,4 +25,11 @@ class Game with _$Game {
createdAt: '',
updatedAt: '',
);
/// Biaya sekali main dalam EnakCoin (`metadata.coin_cost`), default 1.
int get coinCost {
final value = metadata['coin_cost'];
final cost = value is num ? value.toInt() : int.tryParse('$value');
return cost == null || cost <= 0 ? 1 : cost;
}
}
@@ -1,7 +1,7 @@
part of '../game.dart';
@freezed
class GamePrize with _$GamePrize {
abstract class GamePrize with _$GamePrize {
const factory GamePrize({
required String id,
required String gameId,
@@ -0,0 +1,12 @@
part of '../game.dart';
@freezed
abstract class SpinResult with _$SpinResult {
const factory SpinResult({
required String gamePlayId,
required int coinsUsed,
required String prizeId,
required String prizeName,
required int coinsRemaining,
}) = _SpinResult;
}
+1
View File
@@ -7,5 +7,6 @@ part 'game.freezed.dart';
part 'entity/game_entity.dart';
part 'entity/game_prize_entity.dart';
part 'entity/spin_result_entity.dart';
part 'failures/game_failure.dart';
part 'repositories/i_game_repository.dart';
File diff suppressed because it is too large Load Diff
@@ -2,4 +2,7 @@ part of '../game.dart';
abstract class IGameRepository {
Future<Either<GameFailure, Game>> ferrisWheel();
/// Main satu kali; memotong EnakCoin sebesar biaya game. Tanpa PIN.
Future<Either<GameFailure, SpinResult>> spin({required String gameId});
}
@@ -0,0 +1,88 @@
part of '../wallet.dart';
/// Order milik customer di daftar riwayat (§4.5).
@freezed
abstract class CustomerOrder with _$CustomerOrder {
const CustomerOrder._();
const factory CustomerOrder({
required String id,
required String orderNumber,
required String outletName,
required String orderType,
required String status,
required String paymentStatus,
required int totalAmount,
required int itemCount,
required bool isVoid,
required bool isRefund,
required int pointsEarned,
required int coinsEarned,
DateTime? createdAt,
}) = _CustomerOrder;
bool get isDineIn => orderType == 'dine_in';
}
@freezed
abstract class CustomerOrderPage with _$CustomerOrderPage {
const factory CustomerOrderPage({
required List<CustomerOrder> items,
required int page,
required int totalPages,
}) = _CustomerOrderPage;
}
/// Detail order: field [order] ditambah rincian item dan pembayaran.
@freezed
abstract class CustomerOrderDetail with _$CustomerOrderDetail {
const factory CustomerOrderDetail({
required CustomerOrder order,
String? tableNumber,
required int subtotal,
required int discountAmount,
required int taxAmount,
required int refundAmount,
required List<CustomerOrderItem> items,
required List<CustomerOrderPayment> payments,
}) = _CustomerOrderDetail;
}
@freezed
abstract class CustomerOrderItem with _$CustomerOrderItem {
const CustomerOrderItem._();
const factory CustomerOrderItem({
required String id,
required String productName,
String? variantName,
required int quantity,
/// Hanya untuk item timbangan, mis. 4,2 [unitName].
double? weight,
String? unitName,
required int unitPrice,
required int totalPrice,
required int refundQuantity,
}) = _CustomerOrderItem;
bool get isWeighted => weight != null;
}
@freezed
abstract class CustomerOrderPayment with _$CustomerOrderPayment {
const CustomerOrderPayment._();
const factory CustomerOrderPayment({
required String id,
required String methodName,
required String methodType,
required int amount,
required int refundAmount,
/// Hanya pada pembayaran EnakPoint.
int? pointsUsed,
}) = _CustomerOrderPayment;
bool get isPoint => methodType == 'point';
}
@@ -0,0 +1,33 @@
part of '../wallet.dart';
@freezed
abstract class ExchangePreview with _$ExchangePreview {
const factory ExchangePreview({
required int coinAmount,
required int pointAmount,
required int coinBalance,
required int coins,
required int points,
required bool valid,
String? reason,
}) = _ExchangePreview;
}
@freezed
abstract class ExchangeResult with _$ExchangeResult {
const factory ExchangeResult({
required int coins,
required int points,
required int coinBalance,
required int pointBalance,
required List<WalletLot> lots,
required bool replayed,
}) = _ExchangeResult;
}
/// Bagian saldo dengan tanggal kedaluwarsanya sendiri.
@freezed
abstract class WalletLot with _$WalletLot {
const factory WalletLot({required int amount, DateTime? expiresAt}) =
_WalletLot;
}
@@ -0,0 +1,20 @@
part of '../wallet.dart';
/// Outlet aktif di organisasi customer, tempat saldo berlaku (§4.4).
@freezed
abstract class Outlet with _$Outlet {
const factory Outlet({
required String id,
required String name,
String? address,
/// Kasir di outlet ini menerima pembayaran EnakPoint.
required bool acceptsPointPayment,
/// Belanja di outlet ini memberi EnakPoint.
required bool earnsPoints,
/// Belanja di outlet ini memberi EnakCoin.
required bool earnsCoins,
}) = _Outlet;
}
@@ -0,0 +1,10 @@
part of '../wallet.dart';
@freezed
abstract class PaymentCode with _$PaymentCode {
const factory PaymentCode({
required String code,
required String qrPayload,
required DateTime expiresAt,
}) = _PaymentCode;
}
@@ -0,0 +1,24 @@
part of '../wallet.dart';
@freezed
abstract class PinStatus with _$PinStatus {
const PinStatus._();
const factory PinStatus({
required bool hasPin,
DateTime? lockedUntil,
DateTime? transferBlockedUntil,
}) = _PinStatus;
bool get isLocked =>
lockedUntil != null && lockedUntil!.isAfter(DateTime.now());
}
@freezed
abstract class PinOtp with _$PinOtp {
const factory PinOtp({
required PinOtpPurpose purpose,
required String otpToken,
DateTime? expiresAt,
}) = _PinOtp;
}
@@ -0,0 +1,22 @@
part of '../wallet.dart';
/// Penerima transfer; [name] dan [phoneNumber] sudah disamarkan oleh server.
@freezed
abstract class TransferRecipient with _$TransferRecipient {
const factory TransferRecipient({
required String name,
required String phoneNumber,
}) = _TransferRecipient;
}
@freezed
abstract class TransferResult with _$TransferResult {
const factory TransferResult({
required WalletCurrency currency,
required int amount,
required TransferRecipient recipient,
required List<WalletLot> lots,
required int balance,
required bool replayed,
}) = _TransferResult;
}
@@ -0,0 +1,51 @@
part of '../wallet.dart';
enum WalletCurrency {
point('POINT', 'EnakPoint'),
coin('COIN', 'EnakCoin');
const WalletCurrency(this.apiValue, this.label);
final String apiValue;
final String label;
static WalletCurrency fromApi(String? value) =>
value == coin.apiValue ? coin : point;
}
enum WalletTransactionType {
earn('EARN', 'Dari belanja'),
earnReversal('EARN_REVERSAL', 'Dibatalkan (order di-void/refund)'),
payment('PAYMENT', 'Bayar pesanan'),
paymentRefund('PAYMENT_REFUND', 'Pengembalian pembayaran'),
exchangeOut('EXCHANGE_OUT', 'Ditukar ke EnakPoint'),
exchangeIn('EXCHANGE_IN', 'Hasil tukar EnakCoin'),
transferOut('TRANSFER_OUT', 'Transfer keluar'),
transferIn('TRANSFER_IN', 'Transfer masuk'),
gameSpend('GAME_SPEND', 'Main game'),
expire('EXPIRE', 'Kedaluwarsa'),
adjustment('ADJUSTMENT', 'Koreksi'),
migration('MIGRATION', 'Saldo awal'),
unknown('', 'Transaksi');
const WalletTransactionType(this.apiValue, this.label);
final String apiValue;
final String label;
/// Tipe yang bisa dipilih di filter riwayat.
static List<WalletTransactionType> get filterable =>
values.where((e) => e != unknown).toList();
static WalletTransactionType fromApi(String? value) =>
values.firstWhere((e) => e.apiValue == value, orElse: () => unknown);
}
enum PinOtpPurpose {
setup('pin_setup'),
reset('pin_reset');
const PinOtpPurpose(this.apiValue);
final String apiValue;
}
@@ -0,0 +1,11 @@
part of '../wallet.dart';
@freezed
abstract class WalletExpiring with _$WalletExpiring {
const factory WalletExpiring({
required List<ExpiringAmount> point,
required List<ExpiringAmount> coin,
}) = _WalletExpiring;
factory WalletExpiring.empty() => const WalletExpiring(point: [], coin: []);
}
@@ -0,0 +1,30 @@
part of '../wallet.dart';
@freezed
abstract class WalletSummary with _$WalletSummary {
const factory WalletSummary({
required int pointBalance,
required int coinBalance,
required int pointValue,
required int pointDiscountValue,
ExpiringAmount? nearestExpiringPoint,
ExpiringAmount? nearestExpiringCoin,
required List<WalletTransaction> recentTransactions,
}) = _WalletSummary;
factory WalletSummary.empty() => const WalletSummary(
pointBalance: 0,
coinBalance: 0,
pointValue: 0,
pointDiscountValue: 0,
recentTransactions: [],
);
}
/// Jumlah saldo yang akan hangus pada [date] (tanggal WIB, berlaku sampai
/// 23:59:59 WIB di tanggal itu).
@freezed
abstract class ExpiringAmount with _$ExpiringAmount {
const factory ExpiringAmount({required int amount, required DateTime date}) =
_ExpiringAmount;
}
@@ -0,0 +1,30 @@
part of '../wallet.dart';
@freezed
abstract class WalletTransaction with _$WalletTransaction {
const WalletTransaction._();
const factory WalletTransaction({
required String id,
required WalletCurrency currency,
required WalletTransactionType type,
required int amount,
required int balanceAfter,
required String description,
String? groupId,
DateTime? expiresAt,
DateTime? createdAt,
}) = _WalletTransaction;
bool get isIncoming => amount > 0;
}
@freezed
abstract class WalletTransactionPage with _$WalletTransactionPage {
const factory WalletTransactionPage({
required List<WalletTransaction> items,
required int page,
required int totalPages,
required int totalCount,
}) = _WalletTransactionPage;
}
@@ -0,0 +1,54 @@
part of '../wallet.dart';
@freezed
sealed class WalletFailure with _$WalletFailure {
const WalletFailure._();
/// Gagal di level transport (jaringan, timeout, parsing).
const factory WalletFailure.serverError(ApiFailure failure) = _ServerError;
const factory WalletFailure.unexpectedError() = _UnexpectedError;
const factory WalletFailure.unauthorized() = _Unauthorized;
/// `303`, `310`: request tidak lengkap / salah format.
const factory WalletFailure.invalidRequest() = _InvalidRequest;
/// `304`: ditolak aturan bisnis. [cause] berbahasa Inggris, jangan ditampilkan
/// mentah ke customer.
const factory WalletFailure.rejected(String cause) = _Rejected;
/// `404`.
const factory WalletFailure.notFound() = _NotFound;
/// `429`: minta OTP terlalu cepat.
const factory WalletFailure.tooManyRequests(int retryAfterSeconds) =
_TooManyRequests;
/// `900`.
const factory WalletFailure.internalError() = _InternalError;
const factory WalletFailure.pinNotSet() = _PinNotSet;
const factory WalletFailure.pinInvalid(int? remainingAttempts) = _PinInvalid;
const factory WalletFailure.pinLocked(DateTime? lockedUntil) = _PinLocked;
const factory WalletFailure.transferBlocked(DateTime? transferBlockedUntil) =
_TransferBlocked;
bool get isPinError => maybeMap(
pinNotSet: (_) => true,
pinInvalid: (_) => true,
pinLocked: (_) => true,
transferBlocked: (_) => true,
orElse: () => false,
);
/// Request mungkin tidak sampai / jawaban tidak diterima, sehingga hasilnya
/// tidak diketahui. Hanya pada kondisi ini `Idempotency-Key` dipakai ulang.
bool get isNetworkError => maybeMap(
serverError: (value) => value.failure.maybeMap(
connectionError: (_) => true,
connectionTimeout: (_) => true,
serverError: (e) => e.statusCode == 0,
orElse: () => false,
),
orElse: () => false,
);
}
@@ -0,0 +1,15 @@
part of '../wallet.dart';
/// Registrasi device untuk push notification (FCM).
abstract class IDeviceRepository {
/// Dipanggil setelah login dan setiap kali FCM memberi token baru.
Future<Either<WalletFailure, Unit>> register({
required String fcmToken,
required String platform,
required String appVersion,
});
/// Dipanggil saat logout, sebelum token login dihapus. Tidak memanggil API
/// bila device ini belum pernah diregistrasi.
Future<Either<WalletFailure, Unit>> unregister();
}
@@ -0,0 +1,12 @@
part of '../wallet.dart';
/// Riwayat order customer. App hanya melihat order; tidak membuat atau
/// membayarnya (§7).
abstract class IOrderRepository {
Future<Either<WalletFailure, CustomerOrderPage>> getOrders({
required int page,
int limit = 20,
});
Future<Either<WalletFailure, CustomerOrderDetail>> getOrderDetail(String id);
}
@@ -0,0 +1,6 @@
part of '../wallet.dart';
abstract class IOutletRepository {
/// Outlet aktif di organisasi customer, urut nama.
Future<Either<WalletFailure, List<Outlet>>> getOutlets();
}
@@ -0,0 +1,30 @@
part of '../wallet.dart';
abstract class IPinRepository {
Future<Either<WalletFailure, PinStatus>> getStatus();
/// Mengirim OTP ke WhatsApp customer.
Future<Either<WalletFailure, PinOtp>> requestOtp(PinOtpPurpose purpose);
Future<Either<WalletFailure, PinStatus>> setup({
required String otpToken,
required String otpCode,
required String pin,
required String confirmPin,
});
Future<Either<WalletFailure, Unit>> change({
required String oldPin,
required String pin,
required String confirmPin,
});
/// Reset juga membuka PIN yang terkunci; setelahnya transfer keluar ditahan
/// 24 jam.
Future<Either<WalletFailure, Unit>> reset({
required String otpToken,
required String otpCode,
required String pin,
required String confirmPin,
});
}
@@ -0,0 +1,42 @@
part of '../wallet.dart';
abstract class IWalletRepository {
Future<Either<WalletFailure, WalletSummary>> getWallet();
Future<Either<WalletFailure, WalletTransactionPage>> getTransactions({
required int page,
int limit = 20,
WalletCurrency? currency,
List<WalletTransactionType> types = const [],
DateTime? from,
DateTime? to,
});
Future<Either<WalletFailure, WalletExpiring>> getExpiring();
Future<Either<WalletFailure, PaymentCode>> createPaymentCode({
required String pin,
});
Future<Either<WalletFailure, ExchangePreview>> previewExchange({
required int coins,
});
Future<Either<WalletFailure, ExchangeResult>> exchange({
required int coins,
required String pin,
required String idempotencyKey,
});
Future<Either<WalletFailure, TransferRecipient>> checkRecipient({
required String phone,
});
Future<Either<WalletFailure, TransferResult>> transfer({
required WalletCurrency currency,
required int amount,
required String recipientPhone,
required String pin,
required String idempotencyKey,
});
}
+23
View File
@@ -0,0 +1,23 @@
import 'package:dartz/dartz.dart';
import 'package:freezed_annotation/freezed_annotation.dart';
import '../../common/api/api_failure.dart';
part 'wallet.freezed.dart';
part 'entities/wallet_enum.dart';
part 'entities/wallet_summary_entity.dart';
part 'entities/wallet_transaction_entity.dart';
part 'entities/wallet_expiring_entity.dart';
part 'entities/payment_code_entity.dart';
part 'entities/exchange_entity.dart';
part 'entities/transfer_entity.dart';
part 'entities/pin_entity.dart';
part 'entities/outlet_entity.dart';
part 'entities/customer_order_entity.dart';
part 'failures/wallet_failure.dart';
part 'repositories/i_wallet_repository.dart';
part 'repositories/i_pin_repository.dart';
part 'repositories/i_device_repository.dart';
part 'repositories/i_outlet_repository.dart';
part 'repositories/i_order_repository.dart';
File diff suppressed because it is too large Load Diff