- 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>
97 lines
2.7 KiB
Dart
97 lines
2.7 KiB
Dart
import 'package:auto_route/auto_route.dart';
|
|
import 'package:flutter/material.dart';
|
|
import 'package:flutter_spinkit/flutter_spinkit.dart';
|
|
|
|
import '../../../common/theme/theme.dart';
|
|
import '../../../domain/wallet/wallet.dart';
|
|
import '../../../injection.dart';
|
|
import '../../components/toast/flushbar.dart';
|
|
import '../../router/app_router.gr.dart';
|
|
import '../wallet/wallet_ui.dart';
|
|
|
|
/// Memastikan customer siap memasukkan PIN (ยง6.1) sebelum aksi yang butuh PIN.
|
|
///
|
|
/// - Belum punya PIN: buka alur buat PIN, lalu lanjut bila berhasil dibuat.
|
|
/// - PIN terkunci: tampilkan jam buka kunci dan tawarkan "Lupa PIN".
|
|
///
|
|
/// Mengembalikan `true` bila aksi boleh dilanjutkan ke input PIN.
|
|
Future<bool> ensurePinReady(BuildContext context) async {
|
|
showDialog<void>(
|
|
context: context,
|
|
barrierDismissible: false,
|
|
builder: (_) => const Center(
|
|
child: SpinKitFadingCircle(color: AppColor.white, size: 40),
|
|
),
|
|
);
|
|
|
|
final result = await getIt<IPinRepository>().getStatus();
|
|
|
|
if (!context.mounted) return false;
|
|
Navigator.of(context, rootNavigator: true).pop();
|
|
|
|
final failure = result.fold((f) => f, (_) => null);
|
|
if (failure != null) {
|
|
AppFlushbar.showError(context, walletFailureMessage(failure));
|
|
return false;
|
|
}
|
|
|
|
final status = result.getOrElse(() => const PinStatus(hasPin: false));
|
|
|
|
if (!status.hasPin) {
|
|
final created = await context.router.push<bool>(
|
|
PinSetupRoute(purpose: PinOtpPurpose.setup),
|
|
);
|
|
return created == true;
|
|
}
|
|
|
|
if (status.isLocked) {
|
|
await showPinLockedDialog(context, status.lockedUntil!);
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
Future<void> showPinLockedDialog(
|
|
BuildContext context,
|
|
DateTime lockedUntil,
|
|
) async {
|
|
final forgot = await showDialog<bool>(
|
|
context: context,
|
|
builder: (dialogContext) => AlertDialog(
|
|
backgroundColor: AppColor.white,
|
|
title: Text(
|
|
'PIN terkunci',
|
|
style: AppStyle.lg.copyWith(fontWeight: FontWeight.w700),
|
|
),
|
|
content: Text(
|
|
'PIN terkunci sampai ${formatWibTime(lockedUntil)}.',
|
|
style: AppStyle.md,
|
|
),
|
|
actions: [
|
|
TextButton(
|
|
onPressed: () => Navigator.of(dialogContext).pop(false),
|
|
child: Text(
|
|
'Tutup',
|
|
style: AppStyle.md.copyWith(color: AppColor.textSecondary),
|
|
),
|
|
),
|
|
TextButton(
|
|
onPressed: () => Navigator.of(dialogContext).pop(true),
|
|
child: Text(
|
|
'Lupa PIN',
|
|
style: AppStyle.md.copyWith(
|
|
color: AppColor.primary,
|
|
fontWeight: FontWeight.w700,
|
|
),
|
|
),
|
|
),
|
|
],
|
|
),
|
|
);
|
|
|
|
if (forgot == true && context.mounted) {
|
|
context.router.push(PinSetupRoute(purpose: PinOtpPurpose.reset));
|
|
}
|
|
}
|