Commit 52f12f5e authored by Faizol's avatar Faizol

phase 1

parent 27b799c0
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectRootManager" version="2" languageLevel="JDK_11" default="true" project-jdk-name="11" project-jdk-type="JavaSDK" />
<component name="ProjectRootManager" version="2" languageLevel="JDK_17" default="true" project-jdk-name="11" project-jdk-type="JavaSDK" />
<component name="ProjectType">
<option name="id" value="io.flutter" />
</component>
</project>
\ No newline at end of file
......@@ -6,3 +6,19 @@ A new Flutter project Self Service.
This project is a starting point for a Flutter application.
## Version App Change Log 1.6.10
** Added mode by config topup dan check balance ✅
** Added wording title following the selected mode ✅
** Added Logo following app version prefix & default no merchant logo ✅
** Added Timer can be set in config ✅
** Adjust Funtion Timer to ui ✅
** Added Home Page Check Balance ✅
** Added Card history endpoint ticket & balance ✅
** Added UI Card history endpoint ticket & balance ✅
** Adjust Ui check balance ✅
** Added function print card history
** Added Ui print card history
** Update mifare mdd lib to version version: 0.1.36 ✅
** Added isCheckHistory to getcardinfo ✅
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="CompilerConfiguration">
<bytecodeTargetLevel target="11" />
<bytecodeTargetLevel target="17" />
</component>
</project>
\ No newline at end of file
......@@ -41,5 +41,10 @@
<option name="name" value="maven" />
<option name="url" value="https://mobile-repo.mdd.co.id:8081/artifactory/android-library/" />
</remote-repository>
<remote-repository>
<option name="id" value="maven" />
<option name="name" value="maven" />
<option name="url" value="https://mobile-repo.mdd.co.id/artifactory/android-library/" />
</remote-repository>
</component>
</project>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ExternalStorageConfigurationManager" enabled="true" />
<component name="ProjectRootManager" version="2" languageLevel="JDK_11" default="true" project-jdk-name="Android Studio default JDK" project-jdk-type="JavaSDK">
<component name="ProjectRootManager" version="2" languageLevel="JDK_17" default="true" project-jdk-name="jbr-17" project-jdk-type="JavaSDK">
<output url="file://$PROJECT_DIR$/build/classes" />
</component>
<component name="ProjectType">
......
......@@ -12,7 +12,7 @@
"filters": [],
"attributes": [],
"versionCode": 1,
"versionName": "1.0.0",
"versionName": "SS.23.1.WWW.SB",
"outputFile": "app-debug.apk"
}
],
......
......@@ -12,7 +12,7 @@
"filters": [],
"attributes": [],
"versionCode": 1,
"versionName": "1.0.0",
"versionName": "SS.23.1.WWW.SB",
"outputFile": "app-profile.apk"
}
],
......
......@@ -11,8 +11,8 @@
"type": "SINGLE",
"filters": [],
"attributes": [],
"versionCode": 1,
"versionName": "SS.3.WHO",
"versionCode": 16,
"versionName": "SS.23.1.WWW.SB",
"outputFile": "app-release.apk"
}
],
......
......@@ -17,42 +17,42 @@ public final class GeneratedPluginRegistrant {
public static void registerWith(@NonNull FlutterEngine flutterEngine) {
try {
flutterEngine.getPlugins().add(new dev.fluttercommunity.plus.connectivity.ConnectivityPlugin());
} catch(Exception e) {
} catch (Exception e) {
Log.e(TAG, "Error registering plugin connectivity_plus, dev.fluttercommunity.plus.connectivity.ConnectivityPlugin", e);
}
try {
flutterEngine.getPlugins().add(new dev.fluttercommunity.plus.device_info.DeviceInfoPlusPlugin());
} catch(Exception e) {
} catch (Exception e) {
Log.e(TAG, "Error registering plugin device_info_plus, dev.fluttercommunity.plus.device_info.DeviceInfoPlusPlugin", e);
}
try {
flutterEngine.getPlugins().add(new dev.fluttercommunity.plus.packageinfo.PackageInfoPlugin());
} catch(Exception e) {
} catch (Exception e) {
Log.e(TAG, "Error registering plugin package_info_plus, dev.fluttercommunity.plus.packageinfo.PackageInfoPlugin", e);
}
try {
flutterEngine.getPlugins().add(new io.flutter.plugins.pathprovider.PathProviderPlugin());
} catch(Exception e) {
} catch (Exception e) {
Log.e(TAG, "Error registering plugin path_provider_android, io.flutter.plugins.pathprovider.PathProviderPlugin", e);
}
try {
flutterEngine.getPlugins().add(new com.baseflow.permissionhandler.PermissionHandlerPlugin());
} catch(Exception e) {
} catch (Exception e) {
Log.e(TAG, "Error registering plugin permission_handler_android, com.baseflow.permissionhandler.PermissionHandlerPlugin", e);
}
try {
flutterEngine.getPlugins().add(new io.sentry.flutter.SentryFlutterPlugin());
} catch(Exception e) {
} catch (Exception e) {
Log.e(TAG, "Error registering plugin sentry_flutter, io.sentry.flutter.SentryFlutterPlugin", e);
}
try {
flutterEngine.getPlugins().add(new io.flutter.plugins.sharedpreferences.SharedPreferencesPlugin());
} catch(Exception e) {
} catch (Exception e) {
Log.e(TAG, "Error registering plugin shared_preferences_android, io.flutter.plugins.sharedpreferences.SharedPreferencesPlugin", e);
}
try {
flutterEngine.getPlugins().add(new com.tekartik.sqflite.SqflitePlugin());
} catch(Exception e) {
} catch (Exception e) {
Log.e(TAG, "Error registering plugin sqflite, com.tekartik.sqflite.SqflitePlugin", e);
}
}
......
......@@ -168,7 +168,8 @@ class MainActivity : MethodChannel.MethodCallHandler, FlutterActivity(), MifareT
mifareTicketingV3.getCardInfo(
isSync = true,
isCheckValidation = false,
isCheckMin = true
isCheckMin = true,
isCheckListHistory = true
)
}
}
......
......@@ -44,6 +44,6 @@ subprojects {
project.evaluationDependsOn(':app')
}
task clean(type: Delete) {
tasks.register("clean", Delete) {
delete rootProject.buildDir
}
// This is a generated file; do not edit or check into version control.
FLUTTER_ROOT=/Users/macbookpro/Developments/flutter
FLUTTER_APPLICATION_PATH=/Users/macbookpro/Desktop/MDD Project /flutter app/dolan-selfservice-topup
FLUTTER_ROOT=C:\Users\MDD HP\flutter
FLUTTER_APPLICATION_PATH=C:\Users\MDD HP\Documents\dolan-selfservice-topup
COCOAPODS_PARALLEL_CODE_SIGN=true
FLUTTER_TARGET=lib/main.dart
FLUTTER_TARGET=lib\main.dart
FLUTTER_BUILD_DIR=build
FLUTTER_BUILD_NAME=1.0.0
FLUTTER_BUILD_NUMBER=1
......
#!/bin/sh
# This is a generated file; do not edit or check into version control.
export "FLUTTER_ROOT=/Users/macbookpro/Developments/flutter"
export "FLUTTER_APPLICATION_PATH=/Users/macbookpro/Desktop/MDD Project /flutter app/dolan-selfservice-topup"
export "FLUTTER_ROOT=C:\Users\MDD HP\flutter"
export "FLUTTER_APPLICATION_PATH=C:\Users\MDD HP\Documents\dolan-selfservice-topup"
export "COCOAPODS_PARALLEL_CODE_SIGN=true"
export "FLUTTER_TARGET=lib/main.dart"
export "FLUTTER_TARGET=lib\main.dart"
export "FLUTTER_BUILD_DIR=build"
export "FLUTTER_BUILD_NAME=1.0.0"
export "FLUTTER_BUILD_NUMBER=1"
......
......@@ -18,3 +18,9 @@ TextEditingController maxTapController = TextEditingController(text: Preferences
TextEditingController validate = TextEditingController(text: PreferencesHelper.getString(kUserData));
TextEditingController? amountController = TextEditingController(text: '');
TextEditingController outletName = TextEditingController(text: '');
// text Controller check balance
TextEditingController urlDolanCheckBalanceController = TextEditingController(text: PreferencesHelper.getString(kUrlDolanCheckBalance));
TextEditingController urlCloseLoopCheckBalanceController = TextEditingController(text: PreferencesHelper.getString(kUrlCloseLoopCheckBalance));
TextEditingController urlPrepaidCheckBalanceController = TextEditingController(text: PreferencesHelper.getString(kUrlPrePaidCheckBalance));
TextEditingController idleCheckBalanceController = TextEditingController(text: PreferencesHelper.getString(kIdleCheckBalance));
......@@ -11,6 +11,7 @@ import 'dart:convert';
import 'package:flutter/foundation.dart';
import 'package:logging/logging.dart';
import 'package:provider/provider.dart';
import 'package:self_service_3/ui/pages/home_page_check_balance.dart';
import 'package:self_service_3/ui/pages/topup/top_up_page.dart';
import 'package:self_service_3/ui/pages/home_page.dart';
......@@ -106,6 +107,7 @@ class _MyAppState extends State<MyApp> {
'/set-merchant': (context) => const SetMerchant(),
'/input-url': (context) => const Dialog(),
'/home': (context) => const HomePage(),
'/home-check-balance': (context) => const HomePageCheckBalance(),
'/tap-card': (context) => const TapCard(),
'/tap-card-aktivasi': (context) => const TapCardAktivasi(),
// '/top-up': (context) => const TopUpPage(),
......
......@@ -13,6 +13,7 @@ import '../shared/preferences_helper.dart';
import 'exception_service.dart';
class ServiceApi {
Future<Map<String, dynamic>> getMultiOutlet(
String url,
String companyName,
......@@ -69,8 +70,6 @@ class ServiceApi {
}
}
static String _getBaseUrl() {
String _protocol = PreferencesHelper.getString(kProtocol);
String _host = PreferencesHelper.getString(kHost);
......@@ -257,4 +256,30 @@ class ServiceApi {
print("${response.body.toString()}");
return json.decode(response.body.toString());
}
static Future<Map<String, dynamic>> fetchAuditHistory(String cardUid, String regDb, String type) async {
print("fetchAuditHistory dipanggil dengan cardUid: $cardUid, regDb: $regDb, type: $type");
final String baseUrlAudit = "https://oss.dev.dolanapp.com/library/v1/audit-history";
final url = Uri.parse(baseUrlAudit);
final body = {
"card_uid": cardUid,
"reg_db": regDb,
"type": type,
};
final response = await http.post(
url,
headers: <String, String>{
'Content-Type': 'application/json; charset=UTF-8',
},
body: jsonEncode(body),
).timeout(Duration(seconds: 10));
if (response.statusCode == 200) {
return jsonDecode(response.body);
} else {
throw Exception('Gagal mengambil data dari API: ${response.statusCode}');
}
}
}
// ignore_for_file: unnecessary_nullable_for_final_variable_declarations
const kUrlDolan = "url_dolan";
const kMode = "mode";
const kIsHashMode = "is_hash_mode";
const kUrlDolanCheckBalance = "url_dolan_check_balance";
const kTerminalId = "terminal_id";
const kUrlCorePayment = "core_payment";
// const kUrlStatusQr = "url_status_qr";
const kUrlCloseLoop = "url_close_loop";
const kUrlCloseLoopCheckBalance = "url_close_loop_check_balance";
const kMerchantName = "merchant_name";
const kUserName = "user_name";
const kUserData = "user_data";
const kUrlPrePaid = "url_prepaid";
const kUrlPrePaidCheckBalance = "url_prepaid_check_balance";
const kVersionApp = "version_app";
const kMax = "max";
const kMin = "min";
const kIdle ="idle";
const kIdleCheckBalance ="idle_check_balance";
const kMaxTap = "maxTap";
const kMultiOutletName = "multioutletname";
const kMultiOutletServiceCharge = "multioutletservicecharge";
......@@ -37,6 +43,7 @@ const kUrlTopup = "url_topup";
const kIsDoneActivation = "is_done_activation";
const kIsDoneConfig = "is_done_config";
const kIsDoneConfigCheckBalance = "is_done_config_check_balance";
const kIsTap = "is_tap_config";
const kIsLoad = "is_load_config";
const kIsGetOutlet = "is_get_outlet";
......
......@@ -18,6 +18,7 @@ import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:lottie/lottie.dart';
import 'package:package_info_plus/package_info_plus.dart';
import 'package:self_service_3/blocs/api_bloc.dart';
import 'package:self_service_3/database/database_helper.dart';
......@@ -103,25 +104,11 @@ class _HomePageState extends State<HomePage> implements AlertDialogCallback {
late Timer timerPageHome;
var infoCard,
prevInfoCard,
balance,
cardExpirity,
cardType,
deposit,
cardNumber,
name,
lastBalance,
approvalCode,
trxId,
amount,
report,
infoM,
dateTimeCardExpirity,
infoMulti,
companyAddress,
num,
reffNo,
var infoCard, prevInfoCard, balance, cardExpirity,
cardType, deposit, cardNumber, name,
lastBalance, approvalCode, trxId,
amount, report, infoM, dateTimeCardExpirity,
infoMulti, companyAddress, num, reffNo,
plainCardExpirity;
Map<String, dynamic>? dataQris;
......@@ -133,9 +120,12 @@ class _HomePageState extends State<HomePage> implements AlertDialogCallback {
var message = "Silakan Letakkan Wristband Anda Di Reader";
var success = "Tempel dan tahan wristband anda di reader";
var wordingTap = "Mesin Isi Ulang Wristband Dengan Pembayaran ";
// var wordingTap = "Mesin Isi Ulang Wristband Dengan Pembayaran ";
late String wordingTap;
late String imageLogoShowTap;
Timer? timerCheckStatus;
// String idle = PreferencesHelper.getString("idle");
String idle = PreferencesHelper.getString("idle");
bool isHitApi = false;
bool _isLoading = false;
......@@ -940,14 +930,10 @@ class _HomePageState extends State<HomePage> implements AlertDialogCallback {
2,
);
// NOTE merubah tanggal
var change = DateTime.fromMillisecondsSinceEpoch(
int.parse(infoMap['cardExpirity']) * 1000);
var change = DateTime.fromMillisecondsSinceEpoch(int.parse(infoMap['cardExpirity']) * 1000);
final DateFormat formatter = DateFormat('dd-MMM-yyyy');
cardExpirity = formatter.format(change);
deposit = CurrencyFormat.convertToIdr(
infoMap["deposit"],
2,
);
deposit = CurrencyFormat.convertToIdr(infoMap["deposit"], 2,);
cardNumber = infoMap["cardNumber"];
String cardNo = cardNumber.toString();
String targetMasked = cardNo.substring(0, 12);
......@@ -987,6 +973,7 @@ class _HomePageState extends State<HomePage> implements AlertDialogCallback {
}
// ValueNotifier<int> idleDuration = ValueNotifier<int>(0); // buat ValueNotifier untuk idleDuration
// int _maxDuration = int.parse(PreferencesHelper.getString("idle"));
int _maxDuration = int.parse(PreferencesHelper.getString("idle"));
int _minDuration = 3;
late ValueNotifier<int> idleDuration;
......@@ -1309,7 +1296,37 @@ class _HomePageState extends State<HomePage> implements AlertDialogCallback {
});
}
Future<void> _showTap() {
Future<String> _getSelectMode() async {
String selectMode = await PreferencesHelper.getString(kMode);
return selectMode;
}
Future<String> _getImageLogoShowTap() async {
PackageInfo packageInfo = await PackageInfo.fromPlatform();
String appVersion = packageInfo.version;
print('APP VERSION SELFSERVICE: $appVersion');
RegExp regExp = RegExp(r'www', caseSensitive: false);
String imageLogoShowTap = regExp.hasMatch(appVersion) ? 'assets/wahoo.png' : '';
print('imageLogoShowTap: $imageLogoShowTap');
return imageLogoShowTap;
}
Future<String> _getWordingTap(String selectMode) async {
if (selectMode == "topup") {
return "Mesin Isi Ulang Wristband Dengan Pembayaran";
} else if (selectMode == "checkbalance") {
return "Customer Balance Check";
} else {
return "Default Wording";
}
}
Future<void> _showTap() async {
String imageLogoShowTap =await _getImageLogoShowTap();
String selectMode = await _getSelectMode();
String wordingTap = await _getWordingTap(selectMode);
print('imageLogoShowTap before _showTap: $imageLogoShowTap');
return showDialog<void>(
context: context,
barrierDismissible: false, // user must tap button!
......@@ -1341,13 +1358,19 @@ class _HomePageState extends State<HomePage> implements AlertDialogCallback {
width: 120,
// fit:,
),
SizedBox(
width: 90,
Visibility(
visible: imageLogoShowTap.isNotEmpty,
child: SizedBox(
width: 90,
),
),
Image.asset(
"assets/wahoo.png",
height: 90,
width: 115,
Visibility(
visible: imageLogoShowTap.isNotEmpty,
child: Image.asset(
imageLogoShowTap,
height: 90,
width: 115,
),
),
],
),
......@@ -1363,24 +1386,30 @@ class _HomePageState extends State<HomePage> implements AlertDialogCallback {
),
textAlign: TextAlign.center,
),
Image.asset(
"assets/qris.png",
width: 60,
height: 60,
Visibility(
visible: selectMode != "checkbalance",
child: Image.asset(
"assets/qris.png",
width: 60,
height: 60,
),
),
],
),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(
"wristband topup machine with qr payment",
style: greyTextStyle.copyWith(
fontSize: 15,
fontStyle: FontStyle.italic,
fontWeight: light,
Visibility(
visible: selectMode != "checkbalance",
child: Text(
"wristband topup machine with qr payment",
style: greyTextStyle.copyWith(
fontSize: 15,
fontStyle: FontStyle.italic,
fontWeight: light,
),
textAlign: TextAlign.center,
),
textAlign: TextAlign.center,
),
]),
Column(
......@@ -2614,7 +2643,8 @@ class _HomePageState extends State<HomePage> implements AlertDialogCallback {
),
],
);
}),
},
),
SizedBox(height: 2),
Text(
"${getDate()}",
......
import 'dart:async';
import 'dart:convert';
import 'package:awesome_dialog/awesome_dialog.dart';
import 'package:connectivity_plus/connectivity_plus.dart';
import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart';
import 'package:flutter_spinkit/flutter_spinkit.dart';
import 'package:package_info_plus/package_info_plus.dart';
import 'package:self_service_3/AlertDialogCallback.dart';
import 'package:self_service_3/services/api_helpert.dart';
import 'package:self_service_3/shared/theme.dart';
import 'package:self_service_3/ui/widgets/backgroundBalanceCheck.dart';
import 'package:timer_builder/timer_builder.dart';
import '../../reader/reader_flutter.dart';
import '../../shared/preference_constant.dart';
import '../../shared/preferences_helper.dart';
import '../widgets/currency.dart';
class HomePageCheckBalance extends StatefulWidget {
final Map<String, dynamic>? cardInfo;
const HomePageCheckBalance({Key? key, this.cardInfo}) : super(key: key);
@override
State<HomePageCheckBalance> createState() => _HomePageCheckBalanceState();
}
class _HomePageCheckBalanceState extends State<HomePageCheckBalance> implements AlertDialogCallback{
var regDb,cardUid,balance,cardNumber,name,cardType,cardExpirity,deposit,infoCard,plainCardExpirity,dateTimeCardExpirity;
String? prevBalance, maskedText, getRegDb;
late Timer? timerPage;
late Timer? timer;
String idle = PreferencesHelper.getString("idle_check_balance");
int _maxDuration = 0;
late ValueNotifier<int> idleDuration;
bool isShowingDialog = false;
bool checkCountZero = false;
bool isDenomDialogShowing = false;
var message = "Silakan Letakkan Wristband Anda Di Reader";
late ConnectivityResult _connectivityResult;
int _activeContainerIndex = 1;
List<Map<String, dynamic>> balanceHistoryData = [];
List<Map<String, dynamic>> ticketHistoryData = [];
@override
void initState() {
super.initState();
WidgetsBinding.instance.addPostFrameCallback((_) {
isShowingDialog = true;
checkCountZero = false;
_showTap(context);
tapDial(context);
});
_maxDuration = int.parse(idle);
idleDuration = ValueNotifier<int>(_maxDuration);
double _maxDurationPage = 5; // Durasi maksimum (dalam detik)
ValueNotifier<double> progressValue = ValueNotifier<double>(0);
ValueNotifier<int> displayValue = ValueNotifier<int>(0);
timerPage = Timer.periodic(Duration(seconds: 1), (timer) {
if (progressValue.value < _maxDurationPage) {
progressValue.value += 1;
displayValue.value -= 1;
} else {
timer.cancel();
}
});
Connectivity()
.onConnectivityChanged
.listen((ConnectivityResult connectivityResult) {
_checkInternetStatus();
});
}
@override
void dispose() {
timerPage?.cancel();
idleDuration.dispose();
// timer?.cancel();
super.dispose();
}
String getSystemTime() {
var now = DateTime.now();
return DateFormat("HH:mm:ss").format(now);
}
String getDate() {
var nowt = new DateTime.now();
return DateFormat('dd-MMM-yyyy').format(nowt);
}
_getInfoCard(var info, BuildContext context) {
setState((){
if (info.toString().toLowerCase().contains('failed')) {
print('ini pesan salah');
message = "Silakan Tempel Wristband Anda Di Reader";
tapDial(context);
if (timer != null) timer?.cancel();
// tapIdle();
} else {
infoCard = info;
var infoMap = jsonDecode(info);
switch (infoMap["cardType"]) {
case 1:
// Perubahan cardType 1 baru menjadi
cardType = "Kartu Belum Aktif";
break;
case 2:
// Perubahan cardType 2 Belum aktif menjadi
cardType = "Kartu Aktif";
break;
case 3:
// Perubahan cardType 3 aktif menjadi
cardType = "Binding Customer";
break;
case 4:
cardType = "On Customer";
break;
case 5:
cardType = "Refund";
break;
default:
cardType = "Tidak Terdaftar";
break;
}
balance = CurrencyFormat.convertToIdr(
infoMap["balance"],
2,
);
// NOTE merubah tanggal
var change = DateTime.fromMillisecondsSinceEpoch(
int.parse(infoMap['cardExpirity']) * 1000);
final DateFormat formatter = DateFormat('dd-MMM-yyyy');
cardExpirity = formatter.format(change);
deposit = CurrencyFormat.convertToIdr(
infoMap["deposit"],
2,
);
cardNumber = infoMap["cardNumber"];
String cardNo = cardNumber.toString();
String targetMasked = cardNo.substring(0, 12);
maskedText = cardNo.replaceAll(targetMasked, '************');
name = infoMap["name"].toString().split("-")[0];
cardUid = infoMap["cardUid"];
regDb= infoMap["regDb"];
}
});
}
Future<void> getAuditHistoryBalance(String cardUid, String regDb) async {
try {
var auditHistory = await ServiceApi.fetchAuditHistory(cardUid, regDb, "balance");
print("AUDIT HISTORY BALANCE: $auditHistory");
// Your data is already a Map, so you don't need to decode it
List<dynamic> data = auditHistory['data'];
// Tambahkan data dari respons ke dalam balanceHistoryData
for (var item in data) {
balanceHistoryData.add(item);
}
} catch (error) {
print("AUDIT BALANCE ERROR: $error");
}
}
Future<void> getAuditHistoryTicket(String cardUid, String regDb) async {
try {
var auditHistory = await ServiceApi.fetchAuditHistory(cardUid, regDb, "ticket");
print("AUDIT HISTORY TICKET: $auditHistory");
List<dynamic> data = auditHistory['data'];
for (var item in data) {
ticketHistoryData.add(item);
}
} catch (error) {
print("AUDIT TICKET ERROR: $error");
}
}
void tapIdle(BuildContext context) {
var connectivityResult = Connectivity().checkConnectivity();
if (connectivityResult == ConnectivityResult.none) {
AwesomeDialog(
context: context,
dialogType: DialogType.error,
animType: AnimType.rightSlide,
dismissOnTouchOutside: false,
headerAnimationLoop: true,
title: 'Internet Tidak Tersedia',
desc:
'Tidak ada koneksi internet. Pastikan Anda terhubung ke internet untuk melanjutkan.',
btnOkOnPress: () {
tapIdle(context);
},
btnOkIcon: Icons.error,
btnOkColor: Colors.red,
).show();
return; // Exit the method if no internet
}
int duration = int.parse(idle);
idleDuration.value = duration; // set nilai awal untuk idleDuration
int count = 0;
// tambahkan variabel untuk menghitung durasi
timer = Timer.periodic(Duration(seconds: 1), (timer) {
// set timer dengan durasi 1 detik
duration -= 1;
idleDuration.value = duration;
count += 1;
if (duration == 0 && !isShowingDialog) {
isShowingDialog = true;
timer.cancel();
_showTap(context);
tapDial(context);
}
});
}
void tapDial(BuildContext context) async {
var connectivityResult = await Connectivity().checkConnectivity();
if (connectivityResult == ConnectivityResult.none) {
AwesomeDialog(
context: context,
dialogType: DialogType.error,
animType: AnimType.rightSlide,
dismissOnTouchOutside: false,
headerAnimationLoop: true,
title: 'Internet Tidak Tersedia',
desc:
'Tidak ada koneksi internet. Pastikan Anda terhubung ke internet untuk melanjutkan.',
btnOkOnPress: () {
tapDial(context);
},
btnOkIcon: Icons.error,
btnOkColor: Colors.red,
).show();
return; // Exit the method if no internet
}
Future.delayed(const Duration(milliseconds: 500), () async {
var isTap = await StartService.getCard();
try {
_getInfoCard(isTap, context);
await Future.wait([
getAuditHistoryTicket(cardUid, regDb),
getAuditHistoryBalance(cardUid, regDb),
]);
isShowingDialog = false;
isDenomDialogShowing = false;
checkCountZero = false;
tapIdle(context);
Navigator.pop(context);
} catch (e) {
print("Error $isTap");
tapDial(context);
}
});
}
Future<String> _getSelectMode() async {
String selectMode = await PreferencesHelper.getString(kMode);
return selectMode;
}
Future<String> _getImageLogoShowTap() async {
PackageInfo packageInfo = await PackageInfo.fromPlatform();
String appVersion = packageInfo.version;
print('APP VERSION SELFSERVICE: $appVersion');
RegExp regExp = RegExp(r'www', caseSensitive: false);
String imageLogoShowTap = regExp.hasMatch(appVersion) ? 'assets/wahoo.png' : '';
print('imageLogoShowTap: $imageLogoShowTap');
return imageLogoShowTap;
}
Future<String> _getWordingTap(String selectMode) async {
if (selectMode == "topup") {
return "Mesin Isi Ulang Wristband Dengan Pembayaran";
} else if (selectMode == "checkbalance") {
return "Customer Balance Check";
} else {
return "Default Wording";
}
}
Future<void> _showTap(BuildContext context) async {
String imageLogoShowTap =await _getImageLogoShowTap();
String selectMode = await _getSelectMode();
String wordingTap = await _getWordingTap(selectMode);
print('imageLogoShowTap before _showTap: $imageLogoShowTap');
return showDialog<void>(
context: context,
barrierDismissible: false, // user must tap button!
builder: (BuildContext context) {
var message = "Silakan Letakkan Wristband Anda Di Reader";
return Center(
child: Container(
padding: const EdgeInsets.symmetric(horizontal: 70, vertical: 50),
decoration: BoxDecoration(
image: const DecorationImage(
fit: BoxFit.cover,
image: AssetImage(
'assets/img_bg_card.png',
),
),
),
child: AlertDialog(
title: SizedBox(
width: 1000,
height: 520,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Image.asset(
"assets/logo.png",
height: 60,
width: 120,
// fit:,
),
Visibility(
visible: imageLogoShowTap.isNotEmpty,
child: SizedBox(
width: 90,
),
),
Visibility(
visible: imageLogoShowTap.isNotEmpty,
child: Image.asset(
imageLogoShowTap,
height: 90,
width: 115,
),
),
],
),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(
wordingTap,
style: blackTextStyle.copyWith(
fontSize: 30,
fontWeight: bold,
/* letterSpacing: 2,*/
),
textAlign: TextAlign.center,
),
Visibility(
visible: selectMode != "checkbalance",
child: Image.asset(
"assets/qris.png",
width: 60,
height: 60,
),
),
],
),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Visibility(
visible: selectMode != "checkbalance",
child: Text(
"wristband topup machine with qr payment",
style: greyTextStyle.copyWith(
fontSize: 15,
fontStyle: FontStyle.italic,
fontWeight: light,
),
textAlign: TextAlign.center,
),
),
]),
Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Image.asset(
"assets/wristband.gif",
width: 230,
height: 230,
),
Text(
message,
style: blackTextStyle.copyWith(
fontSize: 30,
fontWeight: semiBold,
),
textAlign: TextAlign.center,
),
SizedBox(
height: 10,
),
Text(
"Please put your wristband in reader",
style: greyTextStyle.copyWith(
fontSize: 15,
fontWeight: light,
fontStyle: FontStyle.italic,
),
textAlign: TextAlign.center,
),
SizedBox(
height: 20,
),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
SpinKitDoubleBounce(
color: Colors.greenAccent,
size: 20,
duration: const Duration(milliseconds: 1000),
),
SizedBox(width: 20),
SpinKitDoubleBounce(
color: Colors.blueAccent,
size: 20,
duration: const Duration(milliseconds: 2000),
),
SizedBox(width: 20),
SpinKitDoubleBounce(
color: Colors.redAccent,
size: 20,
duration: const Duration(milliseconds: 3000),
),
],
),
],
),
],
),
),
content: SizedBox(
height: 20,
),
),
),
);
});
}
void _changeColor() {
if (_activeContainerIndex == 1) {
setState(() {
_activeContainerIndex = 2;
});
} else if (_activeContainerIndex == 2) {
setState(() {
_activeContainerIndex = 3;
});
} else if (_activeContainerIndex == 3) {
setState(() {
_activeContainerIndex = 1;
});
}
}
Future<void> _checkInternetStatus() async {
final connectivityResult = await Connectivity().checkConnectivity();
setState(() {
_connectivityResult = connectivityResult;
if (_connectivityResult == ConnectivityResult.none) {
_activeContainerIndex = 1;
} else if (_connectivityResult == ConnectivityResult.mobile ||
_connectivityResult == ConnectivityResult.wifi) {
_changeColor();
} else {
_activeContainerIndex = 2;
}
});
}
Future<bool> onWillPop() {
return Future.value(false);
}
@override
Widget build(BuildContext context) {
double screenWidth = MediaQuery.of(context).size.width;
double screenHeight = MediaQuery.of(context).size.height;
return WillPopScope(
onWillPop: onWillPop,
child: Scaffold(
backgroundColor: Colors.white,
body: Stack(
children: [
SingleChildScrollView(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
GestureDetector(
onTap: () {
if (timer != null) timer?.cancel();
tapIdle(context);
},
child: Column(
children: [
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Container(
width: screenWidth * 0.01, // Container untuk spasi di kiri
),
Container(
width: screenWidth * 0.45,
height: screenHeight * 6,
child: buildWellcomeCustomer(),
),
Container(
margin: EdgeInsets.fromLTRB(0,50,0,80 ),
width: screenWidth * 0.45,
height: screenHeight * 6, // Container untuk "balance section"
child: Column(children: [buildBalanceSection(),buildTicketSection()]),
),
],
),
SizedBox(height: 20),
SizedBox(height: 20),
buildTicketSection(),
SizedBox(height: 20),
],
),
),
],
),
),
Positioned(
bottom: 20.0, // Adjust the position as needed
right: 20.0, // Adjust the position as needed
child: FloatingActionButton(
onPressed: () {
// Add the action for your floating button
isShowingDialog = true;
timer?.cancel();
_showTap(context);
tapDial(context);
},
child: Icon(Icons.search),
),
),
Positioned(
bottom: 20.0, // Adjust the position as needed
right: 30.0, // Adjust the position as needed
child: buildTimerSection(context),
),
],
),
),
);
}
buildWellcomeCustomer(){
double screenWidth = MediaQuery.of(context).size.width;
double textScaleFactor = screenWidth / 1700;
return Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text(
'Halo ${name != null ? '$name' : 'Teman Dolan'}',
style: TextStyle(
fontSize: 26,
fontWeight: FontWeight.bold,
),
textAlign: TextAlign.start,
),
Text(
'Selamat datang di mesin point check balance',
style: TextStyle(
fontSize: 24,
fontWeight: FontWeight.bold,
),
),
Column(
children: [
ListTile(
title: Text(
(balance != null) ? 'Saldo $balance' : 'Saldo 0',
style: TextStyle(
fontSize: 28 * textScaleFactor,
fontWeight: FontWeight.w500,
),
),
subtitle: Text(
'balance',
style: TextStyle(
fontSize: 15 * textScaleFactor,
fontStyle: FontStyle.italic,
),
),
),
Divider(),
ListTile(
title: Text('Nama/name'),
subtitle: Text((name != null) ? ': $name' : ': -'),
),
ListTile(
title: Text('Nomor Wristband/wristband no'),
subtitle: Text((maskedText != null) ? ': $maskedText' : ': -'),
),
ListTile(
title: Text('Status'),
subtitle: Text((cardType != null) ? ': $cardType' : ': -'),
),
ListTile(
title: Text('Masa Berlaku/expirity'),
subtitle: Text((cardExpirity != null) ? ': $cardExpirity' : ': -'),
),
ListTile(
title: Text('Deposit'),
subtitle: Text((deposit != null) ? ': $deposit' : ': -'),
),
Divider(),
Text(
'Saldo dan deposit wristband bisa dikembalikan di Refund Center',
style: TextStyle(
fontSize: 16 * textScaleFactor,
fontWeight: FontWeight.w500,
),
),
Text(
'Wristband balance and deposit can be returned at the Refund Center',
style: TextStyle(
fontSize: 12 * textScaleFactor,
fontStyle: FontStyle.italic,
),
),
],
),
],
);
}
buildNewCard(){
return Container(
child: Column(
children: [
Text(
"Informasi History Balance",
style: TextStyle(
fontSize: 18,
fontWeight: FontWeight.bold,
),
),
SingleChildScrollView(
child: Container(
child: ListView.builder(
shrinkWrap: true, // Make sure to set shrinkWrap to true
itemCount: balanceHistoryData.length,
itemBuilder: (context, index) {
final data = balanceHistoryData[index];
return Card(
// Customize card appearance as needed
child:
ListTile(
title: Text('Card UID: ${data['card_uid']}'),
subtitle: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text('Card Number: ${data['card_number']}'),
Text('Terminal: ${data['terminal']}'),
Text('Reff Number: ${data['reff_no']}'),
Text('Ticket: ${data['ticket']}'),
Text('Type: ${data['type']}'),
Text('Previous Balance: ${data['prev_balance']}'),
Text('Last Balance: ${data['last_balance']}'),
SizedBox(height: 20),
],
),
),
);
},
),
),
),
]
),
);
}
buildCardInfoSection() {
return Center(
child: Container(
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Image.asset(
"assets/logo.png",
height: 50,
width: 100,
),
SizedBox(
width: 31,
),
Column(
children: [
TimerBuilder.periodic(Duration(seconds: 1), builder: (context) {
return Row(
children: [
Text(
"${getSystemTime()}",
style: TextStyle(
color: darkBackgroundColor,
fontSize: 27,
fontWeight: bold,
),
),
],
);
},
),
SizedBox(height: 2),
Text(
"${getDate()}",
style: TextStyle(
color: blackColor,
fontSize: 20,
fontWeight: semiBold,
),
),
],
),
SizedBox(
width: 31,
),
Image.asset(
"assets/wahoo.png",
height: 70,
width: 100,
),
],
),
width: double.infinity,
),
);
}
// buildWalletSection() {
// double screenWidth = MediaQuery.of(context).size.width;
// double screenHeight = MediaQuery.of(context).size.height;
// double textScaleFactor = screenWidth / 1700;
// return
// Center(
// child: Padding(
// padding: const EdgeInsets.all(8.0),
// child: Container(
// width: screenWidth * 0.9,
// height: screenHeight * 0.5,
// decoration: BoxDecoration(
// borderRadius: BorderRadius.circular(28),
// image: const DecorationImage(
// fit: BoxFit.cover,
// image: AssetImage('assets/img_bg_card.png'),
// ),
// ),
// child: Column(
// crossAxisAlignment: CrossAxisAlignment.center,
// mainAxisAlignment: MainAxisAlignment.center,
// children: [
// Text(
// (balance != null) ? 'Saldo $balance' : 'Saldo 0',
// style: whiteTextStyle.copyWith(
// fontSize: 28 * textScaleFactor,
// fontWeight: medium,
// letterSpacing: 3,
// ),
// ),
// Text(
// 'balance',
// style: whiteTextStyle.copyWith(
// fontSize: 15 * textScaleFactor,
// fontWeight: light,
// fontStyle: FontStyle.italic,
// letterSpacing: 3,
// ),
// ),
// const SizedBox(
// height: 10,
// ),
// Text(
// '-----------------------------',
// style: whiteTextStyle.copyWith(
// fontSize: 30 * textScaleFactor,
// fontWeight: semiBold,
// letterSpacing: 16,
// ),
// ),
// const SizedBox(
// height: 15,
// ),
// Row(
// crossAxisAlignment: CrossAxisAlignment.center,
// mainAxisAlignment: MainAxisAlignment.center,
// children: [
// Column(
// crossAxisAlignment: CrossAxisAlignment.start,
// mainAxisAlignment: MainAxisAlignment.start,
// children: [
// Text(
// 'Nama/name' ,
// style: whiteTextStyle.copyWith(
// fontSize: 20 * textScaleFactor,
// fontWeight: medium,
// letterSpacing: 3,
// ),
// ),
// Text(
// 'Nomor Wristband/wristband no',
// style: whiteTextStyle.copyWith(
// fontSize: 20 * textScaleFactor,
// fontWeight: medium,
// letterSpacing: 3,
// ),
// ),
// Text(
// 'Status',
// style: whiteTextStyle.copyWith(
// fontSize: 20 * textScaleFactor,
// fontWeight: medium,
// letterSpacing: 3,
// ),
// ),
// Text(
// 'Masa Berlaku/expirity',
// style: whiteTextStyle.copyWith(
// fontSize: 20 * textScaleFactor,
// fontWeight: medium,
// letterSpacing: 3,
// ),
// ),
// Text(
// 'Deposit',
// style: whiteTextStyle.copyWith(
// fontSize: 20 * textScaleFactor,
// letterSpacing: 3,
// fontWeight: medium,
// ),
// ),
// ],
// ),
// const SizedBox(
// width: 50,
// ),
// Column(
// crossAxisAlignment: CrossAxisAlignment.start,
// mainAxisAlignment: MainAxisAlignment.start,
// children: [
// Text(
// (name != null) ? ': $name' : ': -',
// style: whiteTextStyle.copyWith(
// fontSize: 20 * textScaleFactor,
// fontWeight: medium,
// letterSpacing: 3,
// ),
// ),
// Text(
// (maskedText != null) ? ': $maskedText' : ': -',
// style: whiteTextStyle.copyWith(
// fontSize: 20 * textScaleFactor,
// fontWeight: medium,
// letterSpacing: 3,
// ),
// ),
// Text(
// (cardType != null) ? ': $cardType' : ': -',
// style: whiteTextStyle.copyWith(
// fontSize: 20 * textScaleFactor,
// fontWeight: medium,
// letterSpacing: 3,
// ),
// ),
// Text(
// (cardExpirity != null) ? ': $cardExpirity' : ': -',
// style: whiteTextStyle.copyWith(
// fontSize: 20 * textScaleFactor,
// fontWeight: medium,
// letterSpacing: 3,
// ),
// ),
// Text(
// (deposit != null) ? ': $deposit' : ': -',
// style: whiteTextStyle.copyWith(
// fontSize: 20 * textScaleFactor,
// letterSpacing: 3,
// fontWeight: medium,
// ),
// ),
// ],
// ),
// ],
// ),
// const SizedBox(
// height: 25,
// ),
// Text(
// '-----------------------------',
// style: whiteTextStyle.copyWith(
// fontSize: 30 * textScaleFactor,
// fontWeight: semiBold,
// letterSpacing: 16,
// ),
// ),
// Text(
// 'Saldo dan deposit wristband bisa dikembalikan di Refund Center',
// style: whiteTextStyle.copyWith(
// fontSize: 20 * textScaleFactor,
// fontWeight: medium,
// ),
// ),
// Text(
// 'Wristband balance and deposit can be returned at the Refund Center',
// style: greyTextStyle.copyWith(
// fontSize: 15 * textScaleFactor,
// fontWeight: light,
// fontStyle: FontStyle.italic,
// ),
// ),
// const SizedBox(
// height: 25,
// ),
// ],
// ),
// ),
// ),
// );
// }
Widget buildWalletSection() {
double screenWidth = MediaQuery.of(context).size.width;
double textScaleFactor = screenWidth / 1700;
return Center(
child: Card(
elevation: 8, // Add a shadow to the card
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(16.0),
),
child: Container(
width: screenWidth * 0.9,
padding: const EdgeInsets.all(16),
child:
Column(
children: [
ListTile(
title: Text(
(balance != null) ? 'Saldo $balance' : 'Saldo 0',
style: TextStyle(
fontSize: 28 * textScaleFactor,
fontWeight: FontWeight.w500,
),
),
subtitle: Text(
'balance',
style: TextStyle(
fontSize: 15 * textScaleFactor,
fontStyle: FontStyle.italic,
),
),
),
Divider(),
ListTile(
title: Text('Nama/name'),
subtitle: Text((name != null) ? ': $name' : ': -'),
),
ListTile(
title: Text('Nomor Wristband/wristband no'),
subtitle: Text((maskedText != null) ? ': $maskedText' : ': -'),
),
ListTile(
title: Text('Status'),
subtitle: Text((cardType != null) ? ': $cardType' : ': -'),
),
ListTile(
title: Text('Masa Berlaku/expirity'),
subtitle: Text((cardExpirity != null) ? ': $cardExpirity' : ': -'),
),
ListTile(
title: Text('Deposit'),
subtitle: Text((deposit != null) ? ': $deposit' : ': -'),
),
Divider(),
Text(
'Saldo dan deposit wristband bisa dikembalikan di Refund Center',
style: TextStyle(
fontSize: 16 * textScaleFactor,
fontWeight: FontWeight.w500,
),
),
Text(
'Wristband balance and deposit can be returned at the Refund Center',
style: TextStyle(
fontSize: 12 * textScaleFactor,
fontStyle: FontStyle.italic,
),
),
],
),
),
),
);
}
Widget buildBalanceSection() {
double screenWidth = MediaQuery.of(context).size.width;
double textScaleFactor = screenWidth / 1700;
return Visibility(
visible: balanceHistoryData.isNotEmpty,
child: SingleChildScrollView(
child: Container(
width: screenWidth * 40,
height: 500,
padding: EdgeInsets.only(bottom: 20),//
margin: EdgeInsets.all(20), // Add margin to the outer Container
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(28),
image: const DecorationImage(
fit: BoxFit.cover,
image: AssetImage('assets/img_bg_card.png'),
),
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.start,
children: [
SizedBox(height: 20),
Text(
"History Saldo Kartu",
style: whiteTextStyle.copyWith(
fontSize: 28,
fontWeight: medium,
letterSpacing: 3,
),
),
Text(
'history card balance',
style: whiteTextStyle.copyWith(
fontSize: 15,
fontWeight: light,
fontStyle: FontStyle.italic,
letterSpacing: 3,
),
),
Expanded(
child: Container(
margin: EdgeInsets.symmetric(horizontal: 10), // Add margin to the ListView.builder
child:
ListView.builder(
shrinkWrap: true, // Make sure to set shrinkWrap to true
itemCount: balanceHistoryData.length,
itemBuilder: (context, index) {
final data = balanceHistoryData[index];
return Card(
// Customize card appearance as needed
child:
ListTile(
title: Text('Card UID: ${data['card_uid']}'),
subtitle: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text('Card Number: ${data['card_number']}'),
Text('Terminal: ${data['terminal']}'),
Text('Reff Number: ${data['reff_no']}'),
Text('Ticket: ${data['ticket']}'),
Text('Type: ${data['type']}'),
Text('Previous Balance: ${data['prev_balance']}'),
Text('Last Balance: ${data['last_balance']}'),
SizedBox(height: 20),
],
),
),
);
},
),
),
),
],
),
),
),
);
}
Widget buildTicketSection() {
double screenWidth = MediaQuery.of(context).size.width;
double textScaleFactor = screenWidth / 1700;
return SingleChildScrollView(
child: Container(
width: screenWidth * 40,
height: 500,
margin: EdgeInsets.all(20),
padding: EdgeInsets.only(bottom: 20),// Add margin to the outer Container
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(28),
image: const DecorationImage(
fit: BoxFit.cover,
image: AssetImage('assets/img_bg_card.png'),
),
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.center,
children: [
SizedBox(height: 20),
Text(
"History Card Ticket",
style: whiteTextStyle.copyWith(
fontSize: 28,
fontWeight: medium,
letterSpacing: 3,
),
),
Text(
'history card ticket',
style: whiteTextStyle.copyWith(
fontSize: 15,
fontWeight: light,
fontStyle: FontStyle.italic,
letterSpacing: 3,
),
),
Expanded(
child: Container(
margin: EdgeInsets.symmetric(horizontal: 10), // Add margin to the ListView.builder
child: ListView.builder(
shrinkWrap: true, // Make sure to set shrinkWrap to true
itemCount: ticketHistoryData.length,
itemBuilder: (context, index) {
final data = ticketHistoryData[index];
return Card(
// Customize card appearance as needed
child: ListTile(
title: Text('Card UID: ${data['card_uid']}'),
subtitle: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text('Card Number: ${data['card_number']}'),
Text('Terminal: ${data['terminal']}'),
Text('Reff Number: ${data['reff_no']}'),
Text('Ticket: ${data['ticket']}'),
Text('Type: ${data['type']}'),
Text('Previous Balance: ${data['prev_balance']}'),
Text('Last Balance: ${data['last_balance']}'),
SizedBox(height: 20),
],
),
),
);
},
),
),
),
],
),
),
);
}
buildTimerSection(BuildContext context) {
return Container(
height: 80,
margin: const EdgeInsets.only(
top: 25,
bottom: 25,
),
child: Stack(
children: [
Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
GestureDetector(
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Stack(
alignment: Alignment.center,
children: [
ValueListenableBuilder(
valueListenable: idleDuration,
builder: (context, value, child) =>
CircularProgressIndicator(
strokeWidth: 5,
value: value / _maxDuration,
// Menggunakan nilai langsung dari value
valueColor:
AlwaysStoppedAnimation<Color>(Colors.blue),
),
),
RotatedBox(
quarterTurns: 4, // Menggunakan nilai bulat dari value
child: ValueListenableBuilder(
valueListenable: idleDuration,
builder: (context, value, child) => Text(
(value.toInt() % _maxDuration).toString(),
// Menggunakan nilai bulat dari value
style: TextStyle(fontSize: 19),
),
),
),
],
),
],
),
)
],
),
],
),
);
}
@override
void onNegative() {
// TODO: implement onNegative
}
@override
void onPositive(Object object) {
// TODO: implement onPositive
}
}
......@@ -65,6 +65,8 @@ class _SetMerchantState extends State<SetMerchant> {
ServiceApi service = ServiceApi();
String get newRouteName => '/tap-card-aktivasi';
bool isSet = false;
String selectMode = "";
void setConfig() {
String urlDolan = urlDolanController.text;
......@@ -112,7 +114,7 @@ class _SetMerchantState extends State<SetMerchant> {
PreferencesHelper.setString(kMaxTap, maxTap);
PreferencesHelper.setBool(kIsDoneConfig, true);
//
PreferencesHelper.setBool(kIsTap, true);
bool isDoneConfig = PreferencesHelper.getBool(kIsDoneConfig, false);
......@@ -137,6 +139,36 @@ class _SetMerchantState extends State<SetMerchant> {
}
}
void setConfigCheckBalance() {
String urlDolan = urlDolanController.text;
String urlCloseLoop = urlCloseLoopController.text;
String urlPrepaid = urlPrePaidController.text;
String idleCheckBalance = idleCheckBalanceController.text;
if (urlDolan.isNotEmpty && urlCloseLoop.isNotEmpty &&
urlPrepaid.isNotEmpty && idleCheckBalance.isNotEmpty) {
PreferencesHelper.setString(kUrlDolan, urlDolan);
PreferencesHelper.setString(kUrlPrePaid, urlPrepaid);
PreferencesHelper.setString(kUrlCloseLoop, urlCloseLoop);
PreferencesHelper.setString(kIdleCheckBalance, idleCheckBalance);
PreferencesHelper.setBool(kIsDoneConfigCheckBalance, true);
PreferencesHelper.setBool(kIsTap, true);
bool isDoneConfigCheckBalance = PreferencesHelper.getBool(kIsDoneConfigCheckBalance, false);
StartService.baseUrl(urlDolan, urlCloseLoop, urlPrepaid);
print('CONFIGURATION MESSAGE :$isDoneConfigCheckBalance');
if (isDoneConfigCheckBalance){
_showDialSuccessCheckBalance();
} else{
_showDialFail();
}
} else {
_showDialFail();
}
}
void getListOutlet() async {
String urlDolan = urlDolanController.text;
String corePayment = urlCorePaymentController.text;
......@@ -242,6 +274,74 @@ class _SetMerchantState extends State<SetMerchant> {
);
}
Future<void> _showDialSuccessCheckBalance() async {
return showDialog<void>(
context: context,
barrierDismissible: false, // user must tap button!
builder: (BuildContext context) {
return Center(
child: Container(
decoration: BoxDecoration(
border: Border.all(
color: Colors.white10.withAlpha(80),
),
borderRadius: BorderRadius.circular(20),
boxShadow: [
BoxShadow(
color: Colors.white10.withAlpha(100),
blurRadius: 10,
spreadRadius: 0,
),
],
color: Colors.white10.withAlpha(2),
),
child: AlertDialog(
title: Center(
child: IconButton(
icon: Icon(
Icons.done_all_rounded,
color: purpleColor,
),
onPressed: () {},
),
),
content: SingleChildScrollView(
child: ListBody(
children: <Widget>[
Center(
child: Text(
'Data Berhasil Tersimpan',
style: blackTextStyle.copyWith(
fontSize: 16, fontWeight: semiBold,
),
),
),
SizedBox(height: 20),
Text('URL/HOST/TREND : ${urlDolanController.text}'),
Text('URL/HOST/DOLAN : ${urlCloseLoopController.text}'),
Text('URL/HOST/PREPAID : ${urlPrePaidController.text}'),
Text('IDLE/PERDETIK : ${idleCheckBalanceController.text}'),
],
),
),
actions: <Widget>[
Center(
child: TextButton(
child: const Text('Ok'),
onPressed: () {
Navigator.pushNamedAndRemoveUntil(
context, newRouteName, (route) => false);
},
),
),
],
),
),
);
},
);
}
Future<void> _showDialFail() async {
return showDialog<void>(
context: context,
......@@ -322,7 +422,7 @@ class _SetMerchantState extends State<SetMerchant> {
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(
"Konfigurasi Self-Service !",
"Konfigurasi Self-Service Topup",
textAlign: TextAlign.center,
style: TextStyle(
fontSize: 20,
......@@ -371,7 +471,6 @@ class _SetMerchantState extends State<SetMerchant> {
title: "Minimal isi ulang topup",
isShowTitle: false,
),
],
),
),
......@@ -434,6 +533,7 @@ class _SetMerchantState extends State<SetMerchant> {
const SizedBox(
height: 40,
),
Row(
mainAxisAlignment: MainAxisAlignment.end,
children: [
......@@ -486,13 +586,174 @@ class _SetMerchantState extends State<SetMerchant> {
);
}
Future<void> showDialMode() async {
showDialog<String>(
barrierDismissible: false,
context: context,
builder: (BuildContext context) {
return AlertDialog(
title: Text("Pilih Mode"),
content: Row(
mainAxisSize: MainAxisSize.min,
children: [
ElevatedButton(
onPressed: () {
selectMode = "topup";
PreferencesHelper.setBool(kIsHashMode, true);
PreferencesHelper.setString(kMode, selectMode);
Navigator.pop(context);
showDialConfig(); // Tampilkan konfigurasi topup
},
child: Text("Topup"),
),
SizedBox(width: 20),
ElevatedButton(
onPressed: () {
selectMode = "checkbalance";
PreferencesHelper.setBool(kIsHashMode, true);
PreferencesHelper.setString(kMode, selectMode);
Navigator.pop(context);
showDialBalance(); // Tampilkan dialog balance
},
child: Text("Check Balance"),
),
],
),
backgroundColor: lightBackgroundColor,
elevation: 50,
);
},
);
}
Future<void> showDialBalance() async {
showDialog<String>(
// Tambahkan dialog balance
barrierDismissible: false,
context: context,
builder: (BuildContext context) => Center(
child: SingleChildScrollView(
physics: AlwaysScrollableScrollPhysics(),
child: Center(
child: SingleChildScrollView(
physics: AlwaysScrollableScrollPhysics(),
child: AlertDialog(
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(30)),
title: Center(),
actions: <Widget>[
Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(
"Konfigurasi Self-Service Check Balance",
textAlign: TextAlign.center,
style: TextStyle(
fontSize: 20,
fontWeight: FontWeight.bold,
color: blackColor,
),
),
SizedBox(height: 20),
SingleChildScrollView(
physics: AlwaysScrollableScrollPhysics(),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
Expanded(
child: Column(
children: [
CustomFormField(
controller: urlDolanController,
title: 'Url Host Trend',
isShowTitle: false,
validator: (value) {},
),
SizedBox(height: 20),
CustomFormField(
controller: urlCloseLoopController,
title: 'Url Host Dolan',
isShowTitle: false,
validator: (value) {},
),
SizedBox(height: 20),
],
),
),
SizedBox(width: 30),
Expanded(
child: Column(
children: [
CustomFormField(
controller: urlPrePaidController,
title: 'Url Host Prepaid',
isShowTitle: false,
validator: (value) {},
),
SizedBox(height: 20),
CustomNumberField(
controller: idleCheckBalanceController,
title: "Waktu siaga beranda (detik)",
isShowTitle: false,
),
SizedBox(height: 20),
],
),
),
],
),
)
],
),
const SizedBox(
height: 40,
),
Row(
mainAxisAlignment: MainAxisAlignment.end,
children: [
TextButton(
onPressed: (){
setState(() {
Navigator.pop(context);
setConfigCheckBalance();
});
},
style: TextButton.styleFrom(
padding: EdgeInsets.zero,
),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(
'Lanjut',
style: greyTextStyle.copyWith(
color: purpleColor,
fontSize: 17,
fontWeight: semiBold,
),
),
],
),
),
],
),
],
backgroundColor: lightBackgroundColor,
elevation: 50,
),
),
),
),
),
);
}
@override
void initState() {
StartService.initLibrary();
_initPackageInfo();
getListOutlet();
super.initState();
WidgetsBinding.instance.addPostFrameCallback((_) => showDialConfig());
WidgetsBinding.instance.addPostFrameCallback((_) => showDialMode());
}
@override
......@@ -539,7 +800,7 @@ class _SetMerchantState extends State<SetMerchant> {
Icons.settings,
color: purpleColor,
),
onPressed: () => showDialConfig()),
onPressed: () => showDialMode()),
],
),
),
......
......@@ -125,11 +125,14 @@ class _SplashPageState extends State<SplashPage> with TickerProviderStateMixin{
}
void checkActivation() {
bool isDoneConfig = PreferencesHelper.getBool(kIsDoneConfig);
// bool isDoneConfig = PreferencesHelper.getBool(kIsDoneConfig);
// bool isDoneConfigCheckBalance = PreferencesHelper.getBool(kIsDoneConfigCheckBalance);
bool isTapConfig = PreferencesHelper.getBool(kIsTap);
String isMode = PreferencesHelper.getString(kMode);
bool isHasMode = PreferencesHelper.getBool(kIsHashMode);
if (isDoneConfig) {
if (isTapConfig && isDoneConfig) {
if (isHasMode) {
if (isTapConfig) {
navigationToActivation();
} else {
navigationToGetOutlet();
......
import 'dart:ui';
import 'package:flutter/material.dart';
class GlassMorphism extends StatelessWidget {
final Widget child;
final double start;
final double end;
const GlassMorphism({
Key? key,
required this.child,
required this.start,
required this.end,
}) : super(key: key);
@override
Widget build(BuildContext context) {
return ClipRRect(
child: BackdropFilter(
filter: ImageFilter.blur(sigmaX: 3, sigmaY: 3),
child: Container(
decoration: BoxDecoration(
gradient: LinearGradient(
colors: [
Colors.blue.withOpacity(start),
Colors.blue.withOpacity(end),
],
begin: AlignmentDirectional.topStart,
end: AlignmentDirectional.bottomEnd,
),
borderRadius: BorderRadius.all(Radius.circular(10)),
border: Border.all(
width: 1.5,
color: Colors.white.withOpacity(0.2),
),
),
child: child,
),
),
);
}
}
\ No newline at end of file
......@@ -11,6 +11,7 @@ import 'package:self_service_3/services/api_helpert.dart';
import 'package:self_service_3/shared/theme.dart';
import 'package:self_service_3/ui/widgets/buttons.dart';
import 'package:self_service_3/ui/widgets/glassmorphism.dart';
import '../../shared/preference_constant.dart';
import '../../shared/theme.dart';
import '../../shared/preferences_helper.dart';
import 'forms.dart';
......@@ -29,7 +30,6 @@ class TapCardAktivasi extends StatefulWidget {
class _TapCardAktivasiState extends State<TapCardAktivasi>
with TickerProviderStateMixin {
String newRouteName = '/home';
ServiceApi service = ServiceApi();
bool isDoneActivateKey =
PreferencesHelper.getBool("IS_DONE_ACTIVATE_WORKING_KEY");
......@@ -140,6 +140,16 @@ class _TapCardAktivasiState extends State<TapCardAktivasi>
}
Future<void> _showDialSuccess() async {
String mode = PreferencesHelper.getString(kMode); // Mengambil mode dari Shared Preferences
String newRouteName;
if (mode == 'topup') {
newRouteName = '/home';
} else if (mode == 'checkbalance') {
newRouteName = '/home-check-balance';
} else {
// Mode default jika tidak sesuai dengan 'topup' atau 'checkbalance'
newRouteName = '/default-route'; // Ganti dengan rute default yang sesuai
}
return showDialog<void>(
context: context,
barrierDismissible: false, // user must tap button!
......
/Users/macbookpro/.pub-cache/hosted/pub.dev/connectivity_plus-3.0.3/
\ No newline at end of file
C:/Users/MDD HP/AppData/Local/Pub/Cache/hosted/pub.dev/connectivity_plus-3.0.3/
\ No newline at end of file
/Users/macbookpro/.pub-cache/hosted/pub.dev/device_info_plus-8.1.0/
\ No newline at end of file
C:/Users/MDD HP/AppData/Local/Pub/Cache/hosted/pub.dev/device_info_plus-8.1.0/
\ No newline at end of file
/Users/macbookpro/.pub-cache/hosted/pub.dev/package_info_plus-3.0.3/
\ No newline at end of file
C:/Users/MDD HP/AppData/Local/Pub/Cache/hosted/pub.dev/package_info_plus-3.0.3/
\ No newline at end of file
/Users/macbookpro/.pub-cache/hosted/pub.dev/path_provider_linux-2.1.10/
\ No newline at end of file
C:/Users/MDD HP/AppData/Local/Pub/Cache/hosted/pub.dev/path_provider_linux-2.1.10/
\ No newline at end of file
/Users/macbookpro/.pub-cache/hosted/pub.dev/sentry_flutter-7.2.0/
\ No newline at end of file
C:/Users/MDD HP/AppData/Local/Pub/Cache/hosted/pub.dev/sentry_flutter-7.10.1/
\ No newline at end of file
/Users/macbookpro/.pub-cache/hosted/pub.dev/shared_preferences_linux-2.1.5/
\ No newline at end of file
C:/Users/MDD HP/AppData/Local/Pub/Cache/hosted/pub.dev/shared_preferences_linux-2.1.5/
\ No newline at end of file
......@@ -45,10 +45,10 @@ packages:
dependency: transitive
description:
name: async
sha256: bfe67ef28df125b7dddcea62755991f807aa39a2492a23e1550161692950bbe0
sha256: "947bfcf187f74dbc5e146c9eb9c0f10c9f8b30743e341481c1e2ed3ecc18c20c"
url: "https://pub.dev"
source: hosted
version: "2.10.0"
version: "2.11.0"
awesome_dialog:
dependency: "direct main"
description:
......@@ -149,10 +149,10 @@ packages:
dependency: transitive
description:
name: characters
sha256: e6a326c8af69605aec75ed6c187d06b349707a27fbff8222ca9cc2cff167975c
sha256: "04a925763edad70e8443c99234dc3328f442e811f1d8fd1a72f1c8ad0f69a605"
url: "https://pub.dev"
source: hosted
version: "1.2.1"
version: "1.3.0"
checked_yaml:
dependency: transitive
description:
......@@ -197,10 +197,10 @@ packages:
dependency: transitive
description:
name: collection
sha256: cfc915e6923fe5ce6e153b0723c753045de46de1b4d63771530504004a45fae0
sha256: f092b211a4319e98e5ff58223576de6c2803db36221657b46c82574721240687
url: "https://pub.dev"
source: hosted
version: "1.17.0"
version: "1.17.2"
connectivity_plus:
dependency: "direct main"
description:
......@@ -386,10 +386,10 @@ packages:
dependency: "direct main"
description:
name: flutter_layout_grid
sha256: "1df27a2e9cd34faa0c0a33148c8bb9d9259e87cc5b934c989a59a77e1a4c0d6b"
sha256: "3529b7aa7ed2cb9861a0bbaa5c14d4be2beaf5a070ce0176077159f80c5de094"
url: "https://pub.dev"
source: hosted
version: "2.0.1"
version: "2.0.5"
flutter_localizations:
dependency: "direct main"
description: flutter
......@@ -497,10 +497,10 @@ packages:
dependency: "direct main"
description:
name: intl
sha256: "910f85bce16fb5c6f614e117efa303e85a1731bb0081edf3604a2ae6e9a3cc91"
sha256: "3bc132a9dbce73a7e4a21a17d06e1878839ffbf975568bc875c60537824b0c4d"
url: "https://pub.dev"
source: hosted
version: "0.17.0"
version: "0.18.1"
io:
dependency: transitive
description:
......@@ -513,10 +513,10 @@ packages:
dependency: transitive
description:
name: js
sha256: "5528c2f391ededb7775ec1daa69e65a2d61276f7552de2b5f7b8d34ee9fd4ab7"
sha256: f2c445dce49627136094980615a031419f7f3eb393237e4ecd97ac15dea343f3
url: "https://pub.dev"
source: hosted
version: "0.6.5"
version: "0.6.7"
json_annotation:
dependency: transitive
description:
......@@ -553,26 +553,26 @@ packages:
dependency: transitive
description:
name: matcher
sha256: "16db949ceee371e9b99d22f88fa3a73c4e59fd0afed0bd25fc336eb76c198b72"
sha256: "1803e76e6653768d64ed8ff2e1e67bea3ad4b923eb5c56a295c3e634bad5960e"
url: "https://pub.dev"
source: hosted
version: "0.12.13"
version: "0.12.16"
material_color_utilities:
dependency: transitive
description:
name: material_color_utilities
sha256: d92141dc6fe1dad30722f9aa826c7fbc896d021d792f80678280601aff8cf724
sha256: "9528f2f296073ff54cb9fee677df673ace1218163c3bc7628093e7eed5203d41"
url: "https://pub.dev"
source: hosted
version: "0.2.0"
version: "0.5.0"
meta:
dependency: transitive
description:
name: meta
sha256: "6c268b42ed578a53088d834796959e4a1814b5e9e164f147f580a386e5decf42"
sha256: "3c74dbf8763d36539f114c799d8a2d87343b5067e9d796ca22b5eb8437090ee3"
url: "https://pub.dev"
source: hosted
version: "1.8.0"
version: "1.9.1"
mime:
dependency: transitive
description:
......@@ -641,10 +641,10 @@ packages:
dependency: transitive
description:
name: path
sha256: db9d4f58c908a4ba5953fcee2ae317c94889433e5024c27ce74a37f94267945b
sha256: "8829d8a55c13fc0e37127c29fedf290c102f4e40ae94ada574091fe0ff96c917"
url: "https://pub.dev"
source: hosted
version: "1.8.2"
version: "1.8.3"
path_parsing:
dependency: transitive
description:
......@@ -857,18 +857,18 @@ packages:
dependency: transitive
description:
name: sentry
sha256: faecda9087cd6d1c2b95bd5e16cce0adeef2e9aa34b8016b150b314be7b5c642
sha256: "830667eadc0398fea3a3424ed1b74568e2db603a42758d0922e2f2974ce55a60"
url: "https://pub.dev"
source: hosted
version: "7.2.0"
version: "7.10.1"
sentry_flutter:
dependency: "direct main"
description:
name: sentry_flutter
sha256: "038607c578d2601c63ced78a503c23d7b25f24bd3c24492cadfc47bc9cbb6636"
sha256: "6730f41b304c6fb0fa590dacccaf73ba11082fc64b274cfe8a79776f2b95309c"
url: "https://pub.dev"
source: hosted
version: "7.2.0"
version: "7.10.1"
shared_preferences:
dependency: "direct main"
description:
......@@ -966,10 +966,10 @@ packages:
dependency: transitive
description:
name: source_span
sha256: dd904f795d4b4f3b870833847c461801f6750a9fa8e61ea5ac53f9422b31f250
sha256: "53e943d4206a5e30df338fd4c6e7a077e02254531b138a15aec3bd143c1a8b3c"
url: "https://pub.dev"
source: hosted
version: "1.9.1"
version: "1.10.0"
sqflite:
dependency: "direct main"
description:
......@@ -1062,10 +1062,10 @@ packages:
dependency: transitive
description:
name: test_api
sha256: ad540f65f92caa91bf21dfc8ffb8c589d6e4dc0c2267818b4cc2792857706206
sha256: "75760ffd7786fffdfb9597c35c5b27eaeec82be8edfb6d71d32651128ed7aab8"
url: "https://pub.dev"
source: hosted
version: "0.4.16"
version: "0.6.0"
timer_builder:
dependency: "direct main"
description:
......@@ -1170,6 +1170,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "1.0.2"
web:
dependency: transitive
description:
name: web
sha256: dc8ccd225a2005c1be616fe02951e2e342092edf968cf0844220383757ef8f10
url: "https://pub.dev"
source: hosted
version: "0.1.4-beta"
web_socket_channel:
dependency: transitive
description:
......@@ -1211,5 +1219,5 @@ packages:
source: hosted
version: "3.1.1"
sdks:
dart: ">=2.19.0 <3.0.0"
dart: ">=3.1.0-185.0.dev <4.0.0"
flutter: ">=3.7.0-0"
......@@ -55,7 +55,7 @@ dependencies:
flutter_spinkit: ^5.1.0
simple_animations: ^5.0.0+2
flutter_svg: ^2.0.4
flutter_layout_grid: ^2.0.1
flutter_layout_grid: ^2.0.5
flutter_staggered_grid_view: ^0.6.2
timer_count_down: ^2.2.1
easy_localization: ^3.0.0
......@@ -70,7 +70,7 @@ dependencies:
package_info_plus: ^3.0.3
otp_text_field: ^1.1.3
timer_builder: ^2.0.0
sentry_flutter: ^7.2.0
sentry_flutter: ^7.10.1
dev_dependencies:
......@@ -108,6 +108,7 @@ flutter:
assets:
- assets/
- assets/translate/
- assets/wahoo.png
# An image asset can refer to one or more resolution-specific "variants", see
# https://flutter.dev/assets-and-images/#resolution-aware
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment