Commit 5cde9512 authored by Dio Maulana's avatar Dio Maulana

all api implemented

parent 12f09488
import 'dart:convert';
import 'package:tour_travel_agr/api/response_api.dart';
import 'package:tour_travel_agr/helper/function/replace_date.dart';
import 'package:tour_travel_agr/helper/prefs.dart';
import 'package:tour_travel_agr/main.dart';
import 'package:tour_travel_agr/models/profile_model.dart';
import 'package:tour_travel_agr/models/reimburse_model.dart';
import 'package:tour_travel_agr/models/transaction_model.dart';
import 'package:tour_travel_agr/resource/routes.dart';
import 'package:tour_travel_agr/resource/strings.dart';
......@@ -51,7 +55,7 @@ class Api {
Map<String, dynamic> data = {
"name": name,
"nik": nik,
"mobile_phoen": mobile,
"mobile_phone": mobile,
"password": password,
"confirm_password": cPassword,
"brand_code": brandCode,
......@@ -70,6 +74,7 @@ class Api {
if (jsonObject['status'] == 'ok') {
Map<String, dynamic> returnData = {
"register_id": jsonObject['data']['register_id'],
"can_resend_after": jsonObject['data']['can_resend_after'],
};
return ApiResponse(
error: false,
......@@ -100,7 +105,7 @@ class Api {
"brand_code": brandCode,
};
String bodies = jsonEncode(data);
dynamic jsonObject = httpRequest(
dynamic jsonObject = await httpRequest(
typePost,
apiUrl,
"forgotPassword",
......@@ -146,7 +151,10 @@ class Api {
return ApiResponse(error: true, msg: Strings.cantConnectToServer);
} else {
if (jsonObject['status'] == 'ok') {
return ApiResponse(error: false, msg: "Success");
Map<String, dynamic> returnData = {
"can_resend_after": jsonObject['data']['can_resend_after'],
};
return ApiResponse(error: false, msg: "Success", data: returnData);
} else {
return ApiResponse(
error: true,
......@@ -224,4 +232,257 @@ class Api {
return ApiResponse(error: true, msg: Strings.serverError);
}
}
static Future<ApiResponse> confirmRegistration(
String regId, String code) async {
String apiUrl = "$baseUrl${endPoint}confirm_registration";
try {
Map<String, dynamic> data = {
"registration_id": regId,
"confirmation_number": code,
"brand_code": brandCode,
};
String bodies = jsonEncode(data);
dynamic jsonObject = await httpRequest(
typePost,
apiUrl,
"confirmRegistration",
bodies: bodies,
);
if (jsonObject == false) {
return ApiResponse(error: true, msg: Strings.cantConnectToServer);
} else {
if (jsonObject['status'] == 'ok') {
return ApiResponse(error: false, msg: "Success");
} else {
return ApiResponse(
error: true,
msg: jsonObject['msg'],
);
}
}
} catch (e) {
return ApiResponse(error: true, msg: Strings.serverError);
}
}
static Future<ApiResponse> getProfile() async {
String apiUrl = "$baseUrl${endPoint}profile";
try {
Map<String, dynamic> data = {
"session_id": getSessionId(),
"brand_code": brandCode,
};
String bodies = jsonEncode(data);
dynamic jsonObject = await httpRequest(
typePost,
apiUrl,
"getProfile",
bodies: bodies,
);
if (jsonObject == false) {
return ApiResponse(error: true, msg: Strings.cantConnectToServer);
} else {
if (jsonObject['status'] == 'ok') {
ProfileModel profile = ProfileModel.json(jsonObject['data']);
return ApiResponse(
error: false,
msg: jsonObject['msg'],
data: profile,
);
} else {
return ApiResponse(error: true, msg: jsonObject['msg'], data: {
"code": jsonObject["code"],
});
}
}
} catch (e) {
return ApiResponse(error: true, msg: Strings.serverError);
}
}
static Future<ApiResponse> reimburse(String? dateFrom, String? dateTo) async {
String apiUrl = "$baseUrl${endPoint}reimburse_list";
try {
Map<String, dynamic> data = {
"session_id": getSessionId(),
"date_from": (dateFrom == null)
? getOnlyDate(toInternationFormat(
dateLocal(DateTime.now().toLocal().toString())))
: getOnlyDate(toInternationFormat(dateFrom)),
"date_to": (dateTo == null)
? getOnlyDate(toInternationFormat(
dateLocal(DateTime.now().toLocal().toString())))
: getOnlyDate(toInternationFormat(dateTo)),
"brand_code": brandCode,
};
String bodies = jsonEncode(data);
dynamic jsonObject = await httpRequest(
typePost,
apiUrl,
"reimburse",
bodies: bodies,
);
if (jsonObject == false) {
return ApiResponse(error: true, msg: Strings.cantConnectToServer);
} else {
if (jsonObject['status'] == 'ok') {
List<ReimburseModel> dataReimburse = [];
List<dynamic> reimburse = jsonObject['data']['reimburses'];
for (int i = 0; i < reimburse.length; i++) {
dataReimburse.add(
ReimburseModel.json(
reimburse[i],
),
);
}
return ApiResponse(
error: false,
msg: jsonObject['msg'],
data: dataReimburse,
);
} else {
return ApiResponse(error: true, msg: jsonObject['msg'], data: {
"code": jsonObject["code"],
});
}
}
} catch (e) {
return ApiResponse(error: true, msg: Strings.serverError);
}
}
static Future<ApiResponse> transaction(
String? dateFrom, String? dateTo) async {
String apiUrl = "$baseUrl${endPoint}summary_list";
try {
Map<String, dynamic> data = {
"session_id": getSessionId(),
"date_from": (dateFrom == null)
? getOnlyDate(toInternationFormat(
dateLocal(DateTime.now().toLocal().toString())))
: getOnlyDate(toInternationFormat(dateFrom)),
"date_to": (dateTo == null)
? getOnlyDate(toInternationFormat(
dateLocal(DateTime.now().toLocal().toString())))
: getOnlyDate(toInternationFormat(dateTo)),
"brand": brandCode,
};
String bodies = jsonEncode(data);
dynamic jsonObject = await httpRequest(
typePost,
apiUrl,
"transaction",
bodies: bodies,
);
if (jsonObject == false) {
return ApiResponse(error: true, msg: Strings.cantConnectToServer);
} else {
if (jsonObject['status'] == 'ok') {
List<ListTransactionModel> listTransaction = [];
List<dynamic> transactions = jsonObject['data']['transactions'];
for (int i = 0; i < transactions.length; i++) {
listTransaction.add(ListTransactionModel.json(transactions[i]));
}
Map<String, dynamic> mapTransactionModel = {
"count_transaction":
jsonObject['data']['count_transaction'].toString(),
"total_transaction":
jsonObject['data']['total_transaction'].toString(),
"transactions": listTransaction,
};
TransactionModel dataTransaction =
TransactionModel.json(mapTransactionModel);
return ApiResponse(
error: false,
msg: jsonObject['msg'],
data: dataTransaction,
);
} else {
return ApiResponse(error: true, msg: jsonObject['msg'], data: {
"code": jsonObject["code"],
});
}
}
} catch (e) {
return ApiResponse(error: true, msg: Strings.serverError);
}
}
static Future<ApiResponse> changePassword(
String oldPassword, String newPassword, String cNewPassword) async {
String apiUrl = "$baseUrl${endPoint}change_password";
try {
Map<String, dynamic> data = {
"session_id": getSessionId(),
"old_password": oldPassword,
"password": newPassword,
"password_confirmation": cNewPassword,
"brand_code": brandCode,
};
String bodies = jsonEncode(data);
dynamic jsonObject = await httpRequest(
typePost,
apiUrl,
"changePassword",
bodies: bodies,
);
if (jsonObject == false) {
return ApiResponse(error: true, msg: Strings.cantConnectToServer);
} else {
if (jsonObject['status'] == 'ok') {
return ApiResponse(
error: false,
msg: "Berhasil ganti password",
);
} else {
return ApiResponse(error: true, msg: jsonObject['msg'], data: {
"code": jsonObject["code"],
});
}
}
} catch (e) {
return ApiResponse(error: true, msg: Strings.serverError);
}
}
static Future<ApiResponse> changeProfile(
String name, String nik, String phone, String? photo) async {
String apiUrl = "$baseUrl${endPoint}profile/edit";
try {
Map<String, dynamic> data = {
"session_id": getSessionId(),
"brand_code": brandCode,
"name": name,
"nik": nik,
"mobile_phone": phone,
"photo_base64": photo,
};
String bodies = jsonEncode(data);
dynamic jsonObject = await httpRequest(
typePost,
apiUrl,
"changeProfile",
bodies: bodies,
);
if (jsonObject == false) {
return ApiResponse(error: true, msg: Strings.cantConnectToServer);
} else {
if (jsonObject['status'] == 'ok') {
return ApiResponse(
error: false,
msg: "Berhasil ubah profile",
);
} else {
return ApiResponse(error: true, msg: jsonObject['msg'], data: {
"code": jsonObject["code"],
});
}
}
} catch (e) {
return ApiResponse(error: true, msg: Strings.serverError);
}
}
}
import 'package:tour_travel_agr/models/profile_model.dart';
class EditProfileArguments {
ProfileModel profile;
void Function(bool)? onSuccessUpdate;
EditProfileArguments({
required this.profile,
this.onSuccessUpdate,
});
}
import 'package:tour_travel_agr/models/profile_model.dart';
class ProfileArguments {
ProfileModel profile;
ProfileArguments({required this.profile});
}
class VerificationArguments {
String id;
String phone;
String otpExpiredTime;
VerificationArguments({
required this.id,
required this.phone,
required this.otpExpiredTime,
});
}
import 'package:flutter/material.dart';
import 'package:shimmer/shimmer.dart';
import 'package:tour_travel_agr/resource/assets.dart';
import 'package:tour_travel_agr/resource/colors.dart';
import 'package:tour_travel_agr/resource/font.dart';
......@@ -8,14 +9,14 @@ import 'package:tour_travel_agr/resource/style.dart';
class ListTransaction extends StatelessWidget {
const ListTransaction({
super.key,
required this.date,
required this.title,
required this.subtitle,
this.date,
this.title,
this.subtitle,
});
final String date;
final String title;
final String subtitle;
final String? date;
final String? title;
final String? subtitle;
@override
Widget build(BuildContext context) {
......@@ -53,14 +54,27 @@ class ListTransaction extends StatelessWidget {
Row(
children: [
const Spacer(),
Text(
date,
style: getRegularStyle(
color: ColorManager.grey,
fontFamily: FontConstants.openSans,
fontSize: FontSize.s12,
),
)
(date != null)
? Text(
date!,
style: getRegularStyle(
color: ColorManager.grey,
fontFamily: FontConstants.openSans,
fontSize: FontSize.s12,
),
)
: Shimmer.fromColors(
baseColor: ColorManager.baseColorShimmer,
highlightColor: ColorManager.highlightColorShimmer,
child: Container(
width: 50,
height: 10,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(10),
color: ColorManager.primary,
),
),
)
],
),
Row(
......@@ -93,21 +107,50 @@ class ListTransaction extends StatelessWidget {
mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
title,
style: getBoldStyle(
color: Colors.black,
fontFamily: FontConstants.mulish,
fontSize: 18,
),
),
Text(
subtitle,
style: getSemiBoldStyle(
color: ColorManager.primary,
fontFamily: FontConstants.openSans,
),
),
(title != null)
? Text(
title!,
style: getBoldStyle(
color: Colors.black,
fontFamily: FontConstants.mulish,
fontSize: 18,
),
)
: Shimmer.fromColors(
baseColor: ColorManager.baseColorShimmer,
highlightColor: ColorManager.highlightColorShimmer,
child: Container(
width: 80,
height: 15,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(10),
color: ColorManager.primary,
),
),
),
(subtitle != null)
? Text(
subtitle!,
style: getSemiBoldStyle(
color: ColorManager.primary,
fontFamily: FontConstants.openSans,
),
)
: Shimmer.fromColors(
baseColor: ColorManager.baseColorShimmer,
highlightColor: ColorManager.highlightColorShimmer,
child: Container(
margin: const EdgeInsets.only(
top: 10,
),
width: 70,
height: 13,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(10),
color: ColorManager.primary,
),
),
),
],
),
)
......
// memberikan format number untuk setiap ribuan,
import 'package:intl/intl.dart';
const String separatorThousand = '.';
NumberFormat formatNumber() {
// tentukan separator di file constanta.dart
if (separatorThousand == ',') {
return NumberFormat('#,###');
} else if (separatorThousand == '.') {
return NumberFormat.currency(locale: 'id', symbol: '', decimalDigits: 0);
} else {
return NumberFormat('#,###');
}
}
// parsing amount dari String backend, contoh string 10000.00
String parsingAmountBackend(String amount) {
double d = double.tryParse(amount) ?? 0.0;
int result = d.toInt();
return formatNumber().format(result);
}
......@@ -69,14 +69,17 @@ String dateLocal(String dateTime, {bool fullDateTime = false}) {
String year = splitDate[0];
String month = DateFormatCustom.monthLocal(splitDate[1]);
String tgl = splitDate[2];
String result;
if (fullDateTime) {
return "$tgl $month $year ${split[1]}";
result = "$tgl $month $year ${split[1]}";
} else {
return "$tgl $month $year";
result = "$tgl $month $year";
}
return result;
}
DateTime toInternationFormat(String dateLocal, {bool fullDateTime = false}) {
DateTime toInternationFormat(String dateLocal,
{bool fullDateTime = false, timeInclude = true}) {
List<String> splitDate = dateLocal.split(" ");
String? time;
if (fullDateTime) {
......@@ -94,3 +97,9 @@ DateTime toInternationFormat(String dateLocal, {bool fullDateTime = false}) {
}
return result!;
}
String getOnlyDate(DateTime fullDateTime) {
String f = fullDateTime.toString();
List<String> s = f.split(" ");
return s[0];
}
import 'package:tour_travel_agr/helper/prefs.dart';
Future<bool> checkSession() async {
if (getSessionId() == "") {
return false;
}
return true;
}
Map<String, dynamic> differenceTimeFromNow(String time) {
DateTime from = DateTime.now().toLocal();
DateTime to = DateTime.parse(time).toLocal();
int hours = to.difference(from).inHours % 60;
int minutes = to.difference(from).inMinutes % 60;
int seconds = to.difference(from).inSeconds % 60;
Map<String, dynamic> results = {
"hour": hours.toString().padLeft(2, '0'),
"minutes": minutes.toString().padLeft(2, '0'),
"seconds": seconds.toString().padLeft(2, '0'),
// "time_left": (hours > 0)
// ? "${hours.toString().padLeft(2, '0')}:${minutes.toString().padLeft(2, '0')}:${seconds.toString().padLeft(2, '0')}"
// : "${minutes.toString().padLeft(2, '0')}:${seconds.toString().padLeft(2, '0')}",
};
return results;
}
......@@ -10,7 +10,7 @@ late SharedPreferences prefs;
bool debug = true;
String titleApp = 'Tour & Travel Agency';
String brandCode = 'AGR';
String baseUrl = "https://hibiscus-dev.ravku.com/";
String baseUrl = "https://neo-agr.ravku.com/";
String endPoint = "agency/api/";
String initialRoute = Routes.splashRoute;
......
......@@ -2,11 +2,13 @@ class ProfileModel {
String fullName;
String mobilePhone;
String nik;
String avatarUrl;
ProfileModel({
required this.fullName,
required this.mobilePhone,
required this.nik,
required this.avatarUrl,
});
factory ProfileModel.json(Map<String, dynamic> json) {
......@@ -14,6 +16,7 @@ class ProfileModel {
fullName: json['full_name'],
mobilePhone: json['mobile_phone'],
nik: json['nik'],
avatarUrl: json['image_profile_url'] ?? "",
);
}
}
class TransactionModel {
int transactionCount;
String transactionCount;
String totalTransaction;
List<ListTransactionModel> listTransaction;
......
// ignore_for_file: avoid_unnecessary_containers
import 'package:flutter/material.dart';
import 'package:flutter_easyloading/flutter_easyloading.dart';
import 'package:tour_travel_agr/api/all_api.dart';
import 'package:tour_travel_agr/helper/components_widget/custom_appbar.dart';
import 'package:tour_travel_agr/helper/components_widget/widget_button.dart';
......@@ -10,6 +11,7 @@ import 'package:tour_travel_agr/helper/widget_responsive.dart';
import 'package:tour_travel_agr/resource/assets.dart';
import 'package:tour_travel_agr/resource/colors.dart';
import 'package:tour_travel_agr/resource/size.dart';
import 'package:tour_travel_agr/resource/strings.dart';
import 'package:tour_travel_agr/resource/style.dart';
class ForgotPasswordView extends StatefulWidget {
......@@ -146,10 +148,15 @@ class _ForgotPasswordViewState extends State<ForgotPasswordView> {
CustomButton(
text: "Submit",
colorButton: (!buttonActive) ? Colors.grey : null,
onTap: () {
onTap: () async {
if (buttonActive) {
await EasyLoading.show(
status: Strings.pleaseWait,
maskType: EasyLoadingMaskType.none,
);
Api.forgotPassword(whatsappController.text)
.then((response) {
EasyLoading.dismiss();
modalDialogGlobal(
context: context,
title: (response.error) ? "Gagal" : "Berhasil",
......
import 'package:flutter/material.dart';
import 'package:shimmer/shimmer.dart';
import 'package:tour_travel_agr/api/all_api.dart';
import 'package:tour_travel_agr/helper/components_widget/custom_appbar.dart';
import 'package:tour_travel_agr/helper/components_widget/modal_select_date.dart';
import 'package:tour_travel_agr/helper/components_widget/transaction_list.dart';
import 'package:tour_travel_agr/helper/function/number.dart';
import 'package:tour_travel_agr/helper/function/replace_date.dart';
import 'package:tour_travel_agr/helper/function/session_check.dart';
import 'package:tour_travel_agr/helper/modal_dialog.dart';
import 'package:tour_travel_agr/helper/prefs.dart';
import 'package:tour_travel_agr/helper/widget_responsive.dart';
import 'package:tour_travel_agr/models/transaction_model.dart';
import 'package:tour_travel_agr/resource/assets.dart';
import 'package:tour_travel_agr/resource/colors.dart';
import 'package:tour_travel_agr/resource/constanta_string.dart';
import 'package:tour_travel_agr/resource/font.dart';
import 'package:tour_travel_agr/resource/routes.dart';
import 'package:tour_travel_agr/resource/size.dart';
import 'package:tour_travel_agr/resource/strings.dart';
import 'package:tour_travel_agr/resource/style.dart';
class HistoryView extends StatelessWidget {
......@@ -43,10 +51,23 @@ class _BodyWidgetState extends State<BodyWidget> {
bool? customDateActive;
String? startDate;
String? endDate;
TransactionModel? transactions;
@override
void initState() {
resetFilter();
checkSession().then((isLogin) {
if (isLogin) {
resetFilter().then((_) {
getTransactionData(startDate, endDate);
});
} else {
Navigator.pushNamedAndRemoveUntil(
context,
Routes.loginRoute,
(route) => false,
);
}
});
super.initState();
}
......@@ -56,7 +77,7 @@ class _BodyWidgetState extends State<BodyWidget> {
super.dispose();
}
void resetFilter() {
Future<void> resetFilter() async {
String reimburseDate = getHistoryDate();
if (reimburseDate != '') {
List<String> split = reimburseDate.split(" - ");
......@@ -79,6 +100,44 @@ class _BodyWidgetState extends State<BodyWidget> {
}
}
void getTransactionData(String? start, String? end) {
Api.transaction(start, end).then((apiResponse) {
if (apiResponse.error) {
if (apiResponse.data["code"] == "WRONG_SESSION_ID") {
modalDialogGlobal(
context: context,
title: "Session Expired",
contentBody: Strings.sessionExpired,
buttonText: "OK",
tapButton: () {
removeSessionId();
Navigator.pushNamedAndRemoveUntil(
context,
Routes.loginRoute,
(route) => false,
);
},
);
} else {
modalDialogGlobal(
context: context,
title: "Error",
contentBody: apiResponse.msg,
buttonText: "OK",
tapButton: () {
Navigator.pop(context);
Navigator.pop(context);
},
);
}
} else {
setState(() {
transactions = apiResponse.data as TransactionModel;
});
}
});
}
@override
Widget build(BuildContext context) {
return Container(
......@@ -130,10 +189,13 @@ class _BodyWidgetState extends State<BodyWidget> {
builder: (context) {
return ModalSelectDate(
onTapWidget: () {
Navigator.pop(context);
resetFilter();
setState(() {
dateSelected = getHistoryDate();
transactions = null;
});
Navigator.pop(context);
resetFilter().then((_) {
getTransactionData(startDate, endDate);
});
},
todayActive: todayActive!,
......@@ -160,7 +222,9 @@ class _BodyWidgetState extends State<BodyWidget> {
text: "Transaksi",
icon: Assets.moneyIcon,
iconColor: ColorManager.pink,
countText: "10",
countText: (transactions == null)
? null
: transactions?.transactionCount.toString(),
countTextColor: ColorManager.primary,
),
SizedBox(
......@@ -170,7 +234,10 @@ class _BodyWidgetState extends State<BodyWidget> {
text: "Total",
icon: Assets.totalIcon,
iconColor: ColorManager.softGreen,
countText: "Rp 1.200.000",
countText: (transactions == null)
? null
: parsingAmountBackend(
"Rp ${transactions?.totalTransaction}"),
countTextColor: ColorManager.green,
),
],
......@@ -179,17 +246,50 @@ class _BodyWidgetState extends State<BodyWidget> {
height: AppMargin.m20,
),
Expanded(
child: ListView.builder(
padding: EdgeInsets.zero,
itemCount: 10,
itemBuilder: (c, index) {
return const ListTransaction(
date: "10 Maret 2023",
title: "AGR Surabaya",
subtitle: "Rp 520.000",
);
},
),
child: (transactions == null)
? ListView.builder(
padding: EdgeInsets.zero,
itemCount: 10,
itemBuilder: (c, index) {
return const ListTransaction(
date: null,
title: null,
subtitle: null,
);
},
)
: (transactions!.listTransaction.isEmpty)
? Container(
width: double.infinity,
height: double.infinity,
padding: EdgeInsets.symmetric(
horizontal: AppPadding.p20,
),
child: Center(
child: Text(
Strings.transactionNotFound,
style: getSemiBoldStyle(
color: Colors.grey,
fontSize: FontSize.s20,
),
textAlign: TextAlign.center,
),
),
)
: ListView.builder(
padding: EdgeInsets.zero,
itemCount: transactions!.listTransaction.length,
itemBuilder: (c, index) {
return ListTransaction(
date: dateLocal(transactions!
.listTransaction[index].bussinesDate),
title:
transactions!.listTransaction[index].brandCode,
subtitle:
"Rp ${transactions!.listTransaction[index].total}",
);
},
),
),
],
),
......@@ -202,7 +302,7 @@ class WidgetHead extends StatelessWidget {
super.key,
required this.text,
required this.icon,
required this.countText,
this.countText,
required this.iconColor,
required this.countTextColor,
});
......@@ -210,7 +310,7 @@ class WidgetHead extends StatelessWidget {
final String text;
final String icon;
final Color iconColor;
final String countText;
final String? countText;
final Color countTextColor;
@override
Widget build(BuildContext context) {
......@@ -270,14 +370,24 @@ class WidgetHead extends StatelessWidget {
Row(
children: [
const Spacer(),
Text(
countText,
style: getSemiBoldStyle(
color: countTextColor,
fontSize: 16,
fontFamily: FontConstants.openSans,
),
)
(countText != null)
? Text(
countText!,
style: getSemiBoldStyle(
color: countTextColor,
fontSize: 16,
fontFamily: FontConstants.openSans,
),
)
: Shimmer.fromColors(
baseColor: ColorManager.baseColorShimmer,
highlightColor: ColorManager.highlightColorShimmer,
child: Container(
width: 25,
height: 15,
color: ColorManager.primary,
),
)
],
)
],
......
......@@ -49,8 +49,10 @@ class BodyWidget extends StatefulWidget {
class _BodyWidgetState extends State<BodyWidget> {
bool buttonLoginActive = false;
bool alreadyLogin = true;
@override
void initState() {
getProfileUser();
super.initState();
}
......@@ -59,184 +61,208 @@ class _BodyWidgetState extends State<BodyWidget> {
super.dispose();
}
void getProfileUser() async {
Api.getProfile().then((apiResponse) {
if (apiResponse.error == false) {
Navigator.pushNamedAndRemoveUntil(
context,
Routes.homeRoute,
(route) => false,
);
} else {
setState(() {
alreadyLogin = false;
});
}
});
}
@override
Widget build(BuildContext context) {
return Stack(
children: [
Container(
padding: EdgeInsets.only(
left: AppPadding.p20,
right: AppPadding.p20,
top: AppPadding.safeAreaTop(context),
bottom: AppPadding.safeAreaBot(context),
),
child: Column(
return (alreadyLogin == false)
? Stack(
children: [
Center(
child: Container(
padding: const EdgeInsets.only(
top: 40,
),
child: Image(
width: 197,
height: 73,
image: AssetImage(
Assets.logoGreen,
),
),
Container(
padding: EdgeInsets.only(
left: AppPadding.p20,
right: AppPadding.p20,
top: AppPadding.safeAreaTop(context),
bottom: AppPadding.safeAreaBot(context),
),
),
Expanded(
child: SingleChildScrollView(
child: Column(
children: [
const SizedBox(
height: 148,
),
InputTextField(
controller: widget.whatsappController,
labelText: "No. Whatsapp",
hintText: "628...",
marginActive: false,
onChanged: (val) {
if (widget.whatsappController.text.length >= 7 &&
widget.passwordController.text.isNotEmpty) {
setState(() {
buttonLoginActive = true;
});
} else {
setState(() {
buttonLoginActive = false;
});
}
},
),
SizedBox(
height: AppMargin.m20,
),
PasswordInput(
passwordController: widget.passwordController,
onChanged: (val) {
if (widget.whatsappController.text.length >= 7 &&
widget.passwordController.text.isNotEmpty) {
setState(() {
buttonLoginActive = true;
});
} else {
setState(() {
buttonLoginActive = false;
});
}
},
),
Container(
margin: EdgeInsets.only(
top: AppMargin.m20,
bottom: AppMargin.m25,
child: Column(
children: [
Center(
child: Container(
padding: const EdgeInsets.only(
top: 40,
),
child: Row(
children: [
const Spacer(),
GestureDetector(
onTap: () {
Navigator.pushNamed(
context,
Routes.forgotPasswordRoute,
);
},
child: Text(
"Lupa kata sandi",
style: getRegularStyle(
color: ColorManager.primary,
),
),
),
],
child: Image(
width: 197,
height: 73,
image: AssetImage(
Assets.logoGreen,
),
),
),
CustomButton(
text: "Login",
colorButton: buttonLoginActive
? ColorManager.primary
: Colors.grey,
onTap: () async {
if (buttonLoginActive) {
await EasyLoading.show(
status: Strings.pleaseWait,
maskType: EasyLoadingMaskType.none,
);
Api.login(
widget.whatsappController.text,
widget.passwordController.text,
).then((apiResponse) {
EasyLoading.dismiss();
if (apiResponse.error) {
modalDialogGlobal(
context: context,
size: MediaQuery.of(context).size,
title: "Gagal",
contentBody: apiResponse.msg,
buttonText: 'Ok',
tapButton: () {
Navigator.pop(context);
},
);
} else {
Navigator.pushNamedAndRemoveUntil(context,
Routes.homeRoute, (route) => false);
}
});
}
},
),
Container(
margin: const EdgeInsets.only(
top: 28,
),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
),
Expanded(
child: SingleChildScrollView(
child: Column(
children: [
Text(
"Belum mempunyai akun ? ",
style: getRegularStyle(
color: Colors.black,
),
const SizedBox(
height: 148,
),
GestureDetector(
onTap: () {
Navigator.pushNamed(
context,
Routes.registerRoute,
);
InputTextField(
controller: widget.whatsappController,
labelText: "No. Whatsapp",
hintText: "628...",
marginActive: false,
onChanged: (val) {
if (widget.whatsappController.text.length >=
7 &&
widget.passwordController.text.isNotEmpty) {
setState(() {
buttonLoginActive = true;
});
} else {
setState(() {
buttonLoginActive = false;
});
}
},
child: Text(
"Daftar",
style: getSemiBoldStyle(
color: ColorManager.link,
),
),
SizedBox(
height: AppMargin.m20,
),
PasswordInput(
passwordController: widget.passwordController,
onChanged: (val) {
if (widget.whatsappController.text.length >=
7 &&
widget.passwordController.text.isNotEmpty) {
setState(() {
buttonLoginActive = true;
});
} else {
setState(() {
buttonLoginActive = false;
});
}
},
),
Container(
margin: EdgeInsets.only(
top: AppMargin.m20,
bottom: AppMargin.m25,
),
child: Row(
children: [
const Spacer(),
GestureDetector(
onTap: () {
Navigator.pushNamed(
context,
Routes.forgotPasswordRoute,
);
},
child: Text(
"Lupa kata sandi",
style: getRegularStyle(
color: ColorManager.primary,
),
),
),
],
),
),
CustomButton(
text: "Login",
colorButton: buttonLoginActive
? ColorManager.primary
: Colors.grey,
onTap: () async {
if (buttonLoginActive) {
await EasyLoading.show(
status: Strings.pleaseWait,
maskType: EasyLoadingMaskType.none,
);
Api.login(
widget.whatsappController.text,
widget.passwordController.text,
).then((apiResponse) {
EasyLoading.dismiss();
if (apiResponse.error) {
modalDialogGlobal(
context: context,
size: MediaQuery.of(context).size,
title: "Gagal",
contentBody: apiResponse.msg,
buttonText: 'Ok',
tapButton: () {
Navigator.pop(context);
},
);
} else {
Navigator.pushNamedAndRemoveUntil(context,
Routes.homeRoute, (route) => false);
}
});
}
},
),
Container(
margin: const EdgeInsets.only(
top: 28,
),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(
"Belum mempunyai akun ? ",
style: getRegularStyle(
color: Colors.black,
),
),
GestureDetector(
onTap: () {
Navigator.pushNamed(
context,
Routes.registerRoute,
);
},
child: Text(
"Daftar",
style: getSemiBoldStyle(
color: ColorManager.link,
),
),
),
],
),
)
],
),
)
],
),
)
],
),
),
Positioned(
top: 0,
left: 0,
child: Image(
height: 150,
image: AssetImage(
Assets.elipse,
),
),
)
),
],
),
),
Positioned(
top: 0,
left: 0,
child: Image(
height: 150,
image: AssetImage(
Assets.elipse,
)
: Center(
child: CircularProgressIndicator(
color: ColorManager.primary,
),
),
),
],
);
);
}
}
// ignore_for_file: sized_box_for_whitespace, avoid_unnecessary_containers
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:flutter_easyloading/flutter_easyloading.dart';
import 'package:tour_travel_agr/api/all_api.dart';
import 'package:tour_travel_agr/helper/components_widget/custom_appbar.dart';
import 'package:tour_travel_agr/helper/function/timer_date.dart';
import 'package:tour_travel_agr/helper/modal_dialog.dart';
import 'package:tour_travel_agr/helper/widget_responsive.dart';
import 'package:tour_travel_agr/resource/assets.dart';
......@@ -19,10 +22,12 @@ class OtpVerificationView extends StatefulWidget {
super.key,
required this.id,
required this.phone,
required this.otpExpiredTime,
});
final String id;
final String phone;
final String otpExpiredTime;
@override
State<OtpVerificationView> createState() => _OtpVerificationViewState();
......@@ -113,7 +118,10 @@ class _OtpVerificationViewState extends State<OtpVerificationView> {
),
),
),
const CountDownTimeOtp(),
CountDownTimeOtp(
idRegistration: widget.id,
otpExpiredTime: widget.otpExpiredTime,
),
Container(
margin: EdgeInsets.only(
top: AppMargin.m16,
......@@ -184,7 +192,10 @@ class _OtpVerificationViewState extends State<OtpVerificationView> {
});
// ignore: use_build_context_synchronously
FocusScope.of(context).unfocus();
Api.resendOtpVerification(widget.id).then((apiResponse) {
Api.confirmRegistration(
widget.id,
finalText,
).then((apiResponse) {
EasyLoading.dismiss();
if (apiResponse.error) {
setState(() {
......@@ -229,13 +240,61 @@ class _OtpVerificationViewState extends State<OtpVerificationView> {
class CountDownTimeOtp extends StatefulWidget {
const CountDownTimeOtp({
Key? key,
required this.idRegistration,
required this.otpExpiredTime,
}) : super(key: key);
final String idRegistration;
final String otpExpiredTime;
@override
State<CountDownTimeOtp> createState() => _CountDownTimeOtpState();
}
class _CountDownTimeOtpState extends State<CountDownTimeOtp> {
late Timer? _timer;
late String hours = "00";
late String minutes = "00";
late String seconds = "00";
late bool isTimerExpired = false;
late String? timerExpired;
@override
void initState() {
timerExpired = widget.otpExpiredTime;
startTimer();
super.initState();
}
@override
void dispose() {
_timer?.cancel();
super.dispose();
}
void startTimer() {
Duration oneSec = const Duration(seconds: 1);
_timer = Timer.periodic(
oneSec,
(Timer timer) {
setState(() {
Map<String, dynamic> diffTime = differenceTimeFromNow(timerExpired!);
hours = diffTime['hour'];
minutes = diffTime['minutes'];
seconds = diffTime['seconds'];
if (hours == "00" && minutes == "00" && seconds == "00") {
isTimerExpired = true;
cancelTimer();
}
});
},
);
}
void cancelTimer() {
_timer?.cancel();
}
@override
Widget build(BuildContext context) {
return Container(
......@@ -245,42 +304,70 @@ class _CountDownTimeOtpState extends State<CountDownTimeOtp> {
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Text(
"00 :",
style: getRegularStyle(
color: ColorManager.primary,
fontSize: 20,
fontFamily: FontConstants.mulish,
),
),
Text(
" 02 :",
style: getRegularStyle(
color: ColorManager.primary,
fontSize: 20,
fontFamily: FontConstants.mulish,
),
),
Text(
" 59",
style: getRegularStyle(
color: ColorManager.primary,
fontSize: 20,
fontFamily: FontConstants.mulish,
(isTimerExpired == false)
? Row(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Text(
"$hours :",
style: getRegularStyle(
color: ColorManager.primary,
fontSize: 20,
fontFamily: FontConstants.mulish,
),
),
Text(
" $minutes :",
style: getRegularStyle(
color: ColorManager.primary,
fontSize: 20,
fontFamily: FontConstants.mulish,
),
),
Text(
" $seconds",
style: getRegularStyle(
color: ColorManager.primary,
fontSize: 20,
fontFamily: FontConstants.mulish,
),
)
],
)
: GestureDetector(
onTap: () async {
await EasyLoading.show(
status: Strings.pleaseWait,
maskType: EasyLoadingMaskType.none,
);
Api.resendOtpVerification(widget.idRegistration)
.then((apiResponse) {
EasyLoading.dismiss();
if (apiResponse.error) {
modalDialogGlobal(
context: context,
title: "Gagal",
contentBody: apiResponse.msg,
buttonText: "Ok",
tapButton: () => Navigator.pop(context),
);
return;
}
setState(() {
isTimerExpired = false;
timerExpired = apiResponse.data["can_resend_after"];
startTimer();
});
});
},
child: Text(
"Resend otp",
style: getRegularStyle(
color: ColorManager.primary,
fontSize: FontSize.s16,
),
),
),
)
],
),
// Text(
// "Resend otp",
// style: getRegularStyle(
// color: ColorManager.primary,
// fontSize: FontSize.s16,
// ),
// ),
],
),
);
......
// ignore_for_file: use_build_context_synchronously
import 'package:flutter/material.dart';
import 'package:flutter_easyloading/flutter_easyloading.dart';
import 'package:tour_travel_agr/api/all_api.dart';
import 'package:tour_travel_agr/helper/components_widget/custom_appbar.dart';
import 'package:tour_travel_agr/helper/components_widget/password_input.dart';
import 'package:tour_travel_agr/helper/components_widget/widget_button.dart';
import 'package:tour_travel_agr/helper/function/session_check.dart';
import 'package:tour_travel_agr/helper/modal_dialog.dart';
import 'package:tour_travel_agr/helper/prefs.dart';
import 'package:tour_travel_agr/helper/widget_responsive.dart';
import 'package:tour_travel_agr/resource/colors.dart';
import 'package:tour_travel_agr/resource/font.dart';
import 'package:tour_travel_agr/resource/routes.dart';
import 'package:tour_travel_agr/resource/size.dart';
import 'package:tour_travel_agr/resource/strings.dart';
import 'package:tour_travel_agr/resource/style.dart';
class ChangePasswordView extends StatefulWidget {
......@@ -26,6 +35,15 @@ class _ChangePasswordViewState extends State<ChangePasswordView> {
bool buttonActive = false;
@override
void initState() {
checkSession().then((isLogin) {
if (isLogin == false) {
Navigator.pushNamedAndRemoveUntil(
context,
Routes.loginRoute,
(route) => false,
);
}
});
super.initState();
}
......@@ -130,7 +148,9 @@ class _ChangePasswordViewState extends State<ChangePasswordView> {
buttonActive = true;
});
} else {
buttonActive = false;
setState(() {
buttonActive = false;
});
}
},
),
......@@ -141,9 +161,69 @@ class _ChangePasswordViewState extends State<ChangePasswordView> {
child: CustomButton(
text: "Update",
colorButton: (buttonActive) ? null : Colors.grey,
onTap: () {
onTap: () async {
if (buttonActive) {
// TODO: do something here
if (newPasswordController.text !=
confirmNewPasswordController.text) {
modalDialogGlobal(
context: context,
title: "Informasi",
contentBody: "Konfirmasi password tidak cocok",
buttonText: "Ok",
tapButton: () => Navigator.pop(context),
);
}
await EasyLoading.show(
status: Strings.pleaseWait,
maskType: EasyLoadingMaskType.none,
);
Api.changePassword(
nowPasswordController.text,
newPasswordController.text,
confirmNewPasswordController.text)
.then(
(apiresponse) {
EasyLoading.dismiss();
if (apiresponse.error) {
if (apiresponse.data['code'] ==
"WRONG_SESSION_ID") {
modalDialogGlobal(
context: context,
title: "Session Expired",
contentBody: Strings.sessionExpired,
buttonText: "OK",
tapButton: () {
removeSessionId();
Navigator.pushNamedAndRemoveUntil(
context,
Routes.loginRoute,
(route) => false,
);
},
);
} else {
modalDialogGlobal(
context: context,
title: "Gagal",
contentBody: apiresponse.msg,
buttonText: "OK",
tapButton: () => Navigator.pop(context),
);
}
} else {
modalDialogGlobal(
context: context,
title: "Sukses",
contentBody: apiresponse.msg,
buttonText: "Ok",
tapButton: () {
Navigator.pop(context);
Navigator.pop(context);
},
);
}
},
);
}
},
),
......
import 'dart:convert';
import 'package:file_picker/file_picker.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter_easyloading/flutter_easyloading.dart';
import 'package:tour_travel_agr/api/all_api.dart';
import 'package:tour_travel_agr/helper/components_widget/custom_appbar.dart';
import 'package:tour_travel_agr/helper/components_widget/widget_button.dart';
import 'package:tour_travel_agr/helper/components_widget/widget_text_field.dart';
import 'package:tour_travel_agr/helper/modal_dialog.dart';
import 'package:tour_travel_agr/helper/prefs.dart';
import 'package:tour_travel_agr/helper/widget_responsive.dart';
import 'package:tour_travel_agr/models/profile_model.dart';
import 'package:tour_travel_agr/resource/assets.dart';
import 'package:tour_travel_agr/resource/colors.dart';
import 'package:tour_travel_agr/resource/routes.dart';
import 'package:tour_travel_agr/resource/size.dart';
import 'package:tour_travel_agr/resource/strings.dart';
class EditProfileView extends StatefulWidget {
const EditProfileView({super.key});
const EditProfileView({
super.key,
required this.profile,
this.onSuccessUpdate,
});
final ProfileModel profile;
final void Function(bool)? onSuccessUpdate;
@override
State<EditProfileView> createState() => _EditProfileViewState();
}
class _EditProfileViewState extends State<EditProfileView> {
final TextEditingController nameController = TextEditingController();
final TextEditingController nikController = TextEditingController();
final TextEditingController hpController = TextEditingController();
TextEditingController nameController = TextEditingController();
TextEditingController nikController = TextEditingController();
TextEditingController hpController = TextEditingController();
Uint8List? byteImage;
String? base64Image;
@override
void initState() {
setState(() {
nameController.text = widget.profile.fullName;
nikController.text = widget.profile.nik;
hpController.text = widget.profile.mobilePhone;
});
super.initState();
}
@override
Widget build(BuildContext context) {
......@@ -64,6 +91,7 @@ class _EditProfileViewState extends State<EditProfileView> {
// print(file);
setState(() {
byteImage = file.bytes;
base64Image = base64Encode(byteImage!);
});
// print(file.path);
} else {
......@@ -124,8 +152,62 @@ class _EditProfileViewState extends State<EditProfileView> {
),
Container(
margin: const EdgeInsets.only(top: 30),
child: const CustomButton(
child: CustomButton(
text: "Update",
onTap: () async {
await EasyLoading.show(
status: Strings.pleaseWait,
maskType: EasyLoadingMaskType.none,
);
Api.changeProfile(
nameController.text,
nikController.text,
hpController.text,
base64Image,
).then((apiResponse) {
EasyLoading.dismiss();
if (apiResponse.error) {
if (apiResponse.data["code"] ==
"WRONG_SESSION_ID") {
modalDialogGlobal(
context: context,
title: "Session Expired",
contentBody: Strings.sessionExpired,
buttonText: "OK",
tapButton: () {
removeSessionId();
Navigator.pushNamedAndRemoveUntil(
context,
Routes.loginRoute,
(route) => false,
);
},
);
} else {
modalDialogGlobal(
context: context,
title: "Error",
contentBody: apiResponse.msg,
buttonText: "OK",
tapButton: () {
Navigator.pop(context);
},
);
}
} else {
modalDialogGlobal(
context: context,
title: "Success",
contentBody: apiResponse.msg,
buttonText: "Ok",
tapButton: () {
widget.onSuccessUpdate!(true);
Navigator.pop(context);
Navigator.pop(context);
});
}
});
},
),
)
],
......
// ignore_for_file: avoid_unnecessary_containers, sized_box_for_whitespace
import 'package:flutter/material.dart';
import 'package:shimmer/shimmer.dart';
import 'package:tour_travel_agr/api/all_api.dart';
import 'package:tour_travel_agr/helper/argument_route/edit_profile_arguments.dart';
import 'package:tour_travel_agr/helper/function/session_check.dart';
import 'package:tour_travel_agr/helper/modal_dialog.dart';
import 'package:tour_travel_agr/helper/prefs.dart';
import 'package:tour_travel_agr/helper/widget_responsive.dart';
import 'package:tour_travel_agr/models/profile_model.dart';
import 'package:tour_travel_agr/resource/assets.dart';
import 'package:tour_travel_agr/resource/colors.dart';
import 'package:tour_travel_agr/resource/font.dart';
import 'package:tour_travel_agr/resource/routes.dart';
import 'package:tour_travel_agr/resource/size.dart';
import 'package:tour_travel_agr/resource/strings.dart';
import 'package:tour_travel_agr/resource/style.dart';
class ProfileView extends StatelessWidget {
const ProfileView({super.key});
const ProfileView({
super.key,
});
@override
Widget build(BuildContext context) {
......@@ -25,11 +34,77 @@ class ProfileView extends StatelessWidget {
}
}
class BodyWidget extends StatelessWidget {
class BodyWidget extends StatefulWidget {
const BodyWidget({
Key? key,
}) : super(key: key);
@override
State<BodyWidget> createState() => _BodyWidgetState();
}
class _BodyWidgetState extends State<BodyWidget> {
ProfileModel? profile;
@override
void initState() {
checkSession().then((isLogin) {
if (isLogin) {
getProfileUser();
} else {
Navigator.pushNamedAndRemoveUntil(
context,
Routes.loginRoute,
(route) => false,
);
}
});
super.initState();
}
@override
void dispose() {
super.dispose();
}
void getProfileUser() async {
Api.getProfile().then((apiResponse) {
if (apiResponse.error) {
if (apiResponse.data["code"] == "WRONG_SESSION_ID") {
modalDialogGlobal(
context: context,
title: "Session Expired",
contentBody: Strings.sessionExpired,
buttonText: "OK",
tapButton: () {
removeSessionId();
Navigator.pushNamedAndRemoveUntil(
context,
Routes.loginRoute,
(route) => false,
);
},
);
} else {
modalDialogGlobal(
context: context,
title: "Error",
contentBody: apiResponse.msg,
buttonText: "OK",
tapButton: () {
Navigator.pop(context);
Navigator.pop(context);
});
}
} else {
setState(() {
profile = apiResponse.data as ProfileModel;
});
}
});
}
@override
Widget build(BuildContext context) {
return Stack(
......@@ -94,10 +169,22 @@ class BodyWidget extends StatelessWidget {
const Spacer(),
GestureDetector(
onTap: () {
Navigator.pushNamed(
context,
Routes.editProfileRoute,
);
if (profile != null) {
Navigator.pushNamed(
context,
Routes.editProfileRoute,
arguments: EditProfileArguments(
profile: profile!,
onSuccessUpdate: ((isSuccess) {
if (isSuccess) {
setState(() {
profile == null;
});
getProfileUser();
}
})),
);
}
},
child: Container(
width: 24,
......@@ -116,41 +203,90 @@ class BodyWidget extends StatelessWidget {
],
),
),
Container(
width: 120,
height: 120,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(
100,
),
image: DecorationImage(
fit: BoxFit.fill,
image: AssetImage(
Assets.profileSample,
(profile != null)
? Container(
width: 120,
height: 120,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(
100,
),
image: (profile!.avatarUrl == "")
? DecorationImage(
fit: BoxFit.fill,
image: AssetImage(Assets.profileSample),
)
: DecorationImage(
fit: BoxFit.fill,
image: NetworkImage(profile!.avatarUrl),
),
),
)
: Shimmer.fromColors(
baseColor: ColorManager.baseColorShimmer,
highlightColor: ColorManager.highlightColorShimmer,
child: Container(
width: 120,
height: 120,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(
100,
),
image: DecorationImage(
fit: BoxFit.fill,
image: AssetImage(
Assets.profileSample,
),
),
),
),
),
),
),
),
SizedBox(
height: AppMargin.m16,
),
Text(
"Dio Maulana",
style: getSemiBoldStyle(
color: Colors.white,
fontSize: 20,
),
),
(profile != null)
? Text(
profile!.fullName,
style: getSemiBoldStyle(
color: Colors.white,
fontSize: 20,
),
)
: Shimmer.fromColors(
baseColor: ColorManager.baseColorShimmer,
highlightColor: ColorManager.highlightColorShimmer,
child: Container(
width: 200,
height: 15,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(10),
color: ColorManager.green,
),
),
),
SizedBox(
height: AppMargin.m8,
),
Text(
"ID 33040000000000000083",
style: getRegularStyle(
color: Colors.white,
fontSize: 12,
),
),
(profile != null)
? Text(
"NIK: ${profile!.nik}",
style: getRegularStyle(
color: Colors.white,
fontSize: 12,
),
)
: Shimmer.fromColors(
baseColor: ColorManager.baseColorShimmer,
highlightColor: ColorManager.highlightColorShimmer,
child: Container(
width: 200,
height: 15,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(10),
color: ColorManager.green,
),
),
),
const SizedBox(
height: 40,
),
......@@ -164,12 +300,26 @@ class BodyWidget extends StatelessWidget {
Assets.phoneIcon,
),
),
Text(
"+62-8127-535-1256",
style: getRegularStyle(
color: Colors.white,
),
)
(profile != null)
? Text(
"+${profile!.mobilePhone}",
style: getRegularStyle(
color: Colors.white,
),
)
: Shimmer.fromColors(
baseColor: ColorManager.baseColorShimmer,
highlightColor:
ColorManager.highlightColorShimmer,
child: Container(
width: 150,
height: 15,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(10),
color: ColorManager.green,
),
),
)
],
)
],
......@@ -177,10 +327,12 @@ class BodyWidget extends StatelessWidget {
),
GestureDetector(
onTap: () {
Navigator.pushNamed(
context,
Routes.changePasswordRoute,
);
if (profile != null) {
Navigator.pushNamed(
context,
Routes.changePasswordRoute,
);
}
},
child: ProfileButton(
marginTop: 32,
......@@ -190,12 +342,14 @@ class BodyWidget extends StatelessWidget {
),
GestureDetector(
onTap: () {
removeSessionId();
Navigator.pushNamedAndRemoveUntil(
context,
Routes.loginRoute,
(route) => false,
);
if (profile != null) {
removeSessionId();
Navigator.pushNamedAndRemoveUntil(
context,
Routes.loginRoute,
(route) => false,
);
}
},
child: ProfileButton(
marginTop: 16,
......
......@@ -36,7 +36,7 @@ class _RegisterViewState extends State<RegisterView> {
TextEditingController();
bool isChecked = false;
bool buttonRregisterActive = false;
bool buttonRegisterActive = false;
@override
Widget build(BuildContext context) {
......@@ -121,7 +121,7 @@ class _RegisterViewState extends State<RegisterView> {
value: isChecked,
onChanged: (bool? value) {
setState(() {
buttonRregisterActive = value!;
buttonRegisterActive = value!;
isChecked = value;
});
},
......@@ -151,11 +151,11 @@ class _RegisterViewState extends State<RegisterView> {
),
child: CustomButton(
text: "Register",
colorButton: buttonRregisterActive
colorButton: buttonRegisterActive
? ColorManager.primary
: Colors.grey,
onTap: () async {
if (buttonRregisterActive) {
if (buttonRegisterActive) {
if (nameController.text.isEmpty ||
nikController.text.isEmpty ||
noHpController.text.isEmpty ||
......@@ -212,8 +212,10 @@ class _RegisterViewState extends State<RegisterView> {
context,
Routes.verificationRoute,
arguments: VerificationArguments(
id: "ASAS",
id: apiResponse.data['register_id'],
phone: noHpController.text,
otpExpiredTime:
apiResponse.data['can_resend_after'],
),
);
});
......
// ignore_for_file: sized_box_for_whitespace
import 'package:flutter/material.dart';
import 'package:tour_travel_agr/api/all_api.dart';
import 'package:tour_travel_agr/helper/components_widget/custom_appbar.dart';
import 'package:tour_travel_agr/helper/components_widget/modal_select_date.dart';
import 'package:tour_travel_agr/helper/components_widget/transaction_list.dart';
import 'package:tour_travel_agr/helper/function/number.dart';
import 'package:tour_travel_agr/helper/function/replace_date.dart';
import 'package:tour_travel_agr/helper/function/session_check.dart';
import 'package:tour_travel_agr/helper/modal_dialog.dart';
import 'package:tour_travel_agr/helper/prefs.dart';
import 'package:tour_travel_agr/helper/widget_responsive.dart';
import 'package:tour_travel_agr/models/reimburse_model.dart';
import 'package:tour_travel_agr/resource/assets.dart';
import 'package:tour_travel_agr/resource/colors.dart';
import 'package:tour_travel_agr/resource/constanta_string.dart';
import 'package:tour_travel_agr/resource/font.dart';
import 'package:tour_travel_agr/resource/routes.dart';
import 'package:tour_travel_agr/resource/size.dart';
import 'package:tour_travel_agr/resource/strings.dart';
import 'package:tour_travel_agr/resource/style.dart';
class ReimbursementView extends StatelessWidget {
......@@ -45,10 +52,25 @@ class _BodyWidgetState extends State<BodyWidget> {
bool? customDateActive;
String? startDate;
String? endDate;
List<ReimburseModel>? dataReimburse;
bool responseApiError = false;
@override
void initState() {
resetFilter();
checkSession().then((isLogin) {
if (isLogin) {
resetFilter().then((_) {
getReimburseData(startDate, endDate);
});
} else {
Navigator.pushNamedAndRemoveUntil(
context,
Routes.loginRoute,
(route) => false,
);
}
});
super.initState();
}
......@@ -58,7 +80,45 @@ class _BodyWidgetState extends State<BodyWidget> {
super.dispose();
}
void resetFilter() {
void getReimburseData(String? start, String? end) {
Api.reimburse(start, end).then((apiResponse) {
if (apiResponse.error) {
if (apiResponse.data["code"] == "WRONG_SESSION_ID") {
modalDialogGlobal(
context: context,
title: "Session Expired",
contentBody: Strings.sessionExpired,
buttonText: "OK",
tapButton: () {
removeSessionId();
Navigator.pushNamedAndRemoveUntil(
context,
Routes.loginRoute,
(route) => false,
);
},
);
} else {
modalDialogGlobal(
context: context,
title: "Error",
contentBody: apiResponse.msg,
buttonText: "OK",
tapButton: () {
Navigator.pop(context);
Navigator.pop(context);
},
);
}
} else {
setState(() {
dataReimburse = apiResponse.data as List<ReimburseModel>;
});
}
});
}
Future<void> resetFilter() async {
String reimburseDate = getReimburseDate();
if (reimburseDate != '') {
List<String> split = reimburseDate.split(" - ");
......@@ -131,10 +191,13 @@ class _BodyWidgetState extends State<BodyWidget> {
builder: (context) {
return ModalSelectDate(
onTapWidget: () {
Navigator.pop(context);
resetFilter();
setState(() {
dateSelected = getReimburseDate();
dataReimburse = null;
});
Navigator.pop(context);
resetFilter().then((_) {
getReimburseData(startDate, endDate);
});
},
todayActive: todayActive!,
......@@ -159,17 +222,50 @@ class _BodyWidgetState extends State<BodyWidget> {
height: 12,
),
Expanded(
child: ListView.builder(
padding: EdgeInsets.zero,
itemCount: 10,
itemBuilder: (c, index) {
return const ListTransaction(
date: "24 Maret 2023",
title: "15 Transaksi",
subtitle: "Rp 320.000",
);
},
),
child: (dataReimburse == null)
? ListView.builder(
padding: EdgeInsets.zero,
itemCount: 5,
itemBuilder: (c, index) {
return const ListTransaction(
date: null,
title: null,
subtitle: null,
);
},
)
: (dataReimburse!.isEmpty)
? Container(
width: double.infinity,
height: double.infinity,
padding: EdgeInsets.symmetric(
horizontal: AppPadding.p20,
),
child: Center(
child: Text(
Strings.reimbursementNotFound,
style: getSemiBoldStyle(
color: Colors.grey,
fontSize: FontSize.s20,
),
textAlign: TextAlign.center,
),
),
)
: ListView.builder(
padding: EdgeInsets.zero,
itemCount: dataReimburse!.length,
itemBuilder: (c, index) {
return ListTransaction(
date: dateLocal(dataReimburse![index].date),
title:
"${dataReimburse![index].transactionCount} Transaksi",
subtitle: "Rp ${parsingAmountBackend(
dataReimburse![index].comissionAmount,
)}",
);
},
),
),
],
),
......
// ignore_for_file: use_build_context_synchronously
import 'package:flutter/material.dart';
import 'package:flutter_easyloading/flutter_easyloading.dart';
import 'package:tour_travel_agr/api/all_api.dart';
import 'package:tour_travel_agr/helper/argument_route/error_arguments.dart';
import 'package:tour_travel_agr/helper/components_widget/custom_appbar.dart';
......@@ -10,6 +13,7 @@ import 'package:tour_travel_agr/resource/assets.dart';
import 'package:tour_travel_agr/resource/colors.dart';
import 'package:tour_travel_agr/resource/routes.dart';
import 'package:tour_travel_agr/resource/size.dart';
import 'package:tour_travel_agr/resource/strings.dart';
import 'package:tour_travel_agr/resource/style.dart';
class ResetPasswordView extends StatefulWidget {
......@@ -166,14 +170,41 @@ class _ResetPasswordViewState extends State<ResetPasswordView> {
CustomButton(
text: "Submit",
colorButton: (!buttonActive) ? Colors.grey : null,
onTap: () {
onTap: () async {
if (buttonActive) {
if (newPasswordController.text.isEmpty) {
modalDialogGlobal(
context: context,
title: "Info",
contentBody: "Password tidak boleh kosong",
buttonText: "Ok",
tapButton: () => Navigator.pop(context),
);
return;
}
if (newPasswordController.text !=
passwordController.text) {
modalDialogGlobal(
context: context,
title: "Info",
contentBody: "Password tidak sama",
buttonText: "Ok",
tapButton: () => Navigator.pop(context),
);
return;
}
await EasyLoading.show(
status: Strings.pleaseWait,
maskType: EasyLoadingMaskType.none,
);
Api.resetPassword(
widget.idPath,
passwordController.text,
newPasswordController.text,
).then(
(apiResponse) {
EasyLoading.dismiss();
if (apiResponse.error) {
modalDialogGlobal(
context: context,
......
......@@ -8,4 +8,6 @@ class ColorManager {
static Color grey = const Color(0xff595959);
static Color softGreen = const Color(0xffA4D8C8);
static Color green = const Color(0xff3CA786);
static Color baseColorShimmer = Colors.grey;
static Color highlightColorShimmer = const Color.fromARGB(255, 226, 225, 225);
}
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:tour_travel_agr/helper/argument_route/edit_profile_arguments.dart';
import 'package:tour_travel_agr/helper/argument_route/error_arguments.dart';
import 'package:tour_travel_agr/helper/argument_route/verification_otp.dart';
import 'package:tour_travel_agr/main.dart';
......@@ -54,6 +55,7 @@ class RouteGenerator {
OtpVerificationView(
id: args.id,
phone: args.phone,
otpExpiredTime: args.otpExpiredTime,
),
nameRoute: Routes.verificationRoute,
routeSettings: routeSettings,
......@@ -92,8 +94,16 @@ class RouteGenerator {
return pageRouteCustom(const ChangePasswordView(),
nameRoute: Routes.changePasswordRoute);
} else if (routeSettings.name == Routes.editProfileRoute) {
return pageRouteCustom(const EditProfileView(),
nameRoute: Routes.editProfileRoute);
EditProfileArguments args =
routeSettings.arguments as EditProfileArguments;
return pageRouteCustom(
EditProfileView(
profile: args.profile,
onSuccessUpdate: args.onSuccessUpdate,
),
nameRoute: Routes.editProfileRoute,
routeSettings: routeSettings,
);
} else if (routeSettings.name == Routes.reimburseRoute) {
return pageRouteCustom(const ReimbursementView(),
nameRoute: Routes.reimburseRoute);
......@@ -134,6 +144,7 @@ class RouteGenerator {
pageBuilder: (context, a, b) => OtpVerificationView(
id: args.id,
phone: args.phone,
otpExpiredTime: args.otpExpiredTime,
),
transitionDuration: Duration.zero,
reverseTransitionDuration: Duration.zero,
......@@ -153,6 +164,20 @@ class RouteGenerator {
settings: RouteSettings(name: nameRoute.replaceFirst("/", "")),
);
}
if (nameRoute == Routes.editProfileRoute) {
EditProfileArguments args =
routeSettings!.arguments as EditProfileArguments;
return PageRouteBuilder(
pageBuilder: (context, a, b) => EditProfileView(
profile: args.profile,
onSuccessUpdate: args.onSuccessUpdate,
),
transitionDuration: Duration.zero,
reverseTransitionDuration: Duration.zero,
settings: RouteSettings(name: nameRoute.replaceFirst("/", "")),
);
}
return PageRouteBuilder(
pageBuilder: (context, a, b) => target,
transitionDuration: Duration.zero,
......
......@@ -14,4 +14,11 @@ class Strings {
static String succesGetData = "Success get data";
static String pleaseWait = "Please wait...";
static String notFoundPage = 'Halaman yang anda cari tidak ditemukan';
static String sessionExpired =
"Sesi anda telah berakhir, silakan login kembali";
static String reimbursementNotFound =
"Reimbursement tidak ditemukan, silakan pilih filter tanggal yang lain";
static String transactionNotFound =
"Transaksi tidak ditemukan, silakan pilih filter tanggal yang lain";
}
......@@ -216,6 +216,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "4.0.17"
intl:
dependency: "direct main"
description:
name: intl
sha256: "3bc132a9dbce73a7e4a21a17d06e1878839ffbf975568bc875c60537824b0c4d"
url: "https://pub.dev"
source: hosted
version: "0.18.1"
js:
dependency: transitive
description:
......@@ -408,6 +416,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "2.2.0"
shimmer:
dependency: "direct main"
description:
name: shimmer
sha256: "5f88c883a22e9f9f299e5ba0e4f7e6054857224976a5d9f839d4ebdc94a14ac9"
url: "https://pub.dev"
source: hosted
version: "3.0.0"
sky_engine:
dependency: transitive
description: flutter
......
......@@ -37,8 +37,10 @@ dependencies:
flutter_native_splash: ^2.3.1
go_router: ^7.1.1
http: ^1.0.0
intl: ^0.18.1
package_info_plus: ^4.0.2
shared_preferences: ^2.1.1
shimmer: ^3.0.0
url_strategy: ^0.2.0
dev_dependencies:
......
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