add cross login from other regional

This commit is contained in:
2024-12-24 10:01:51 +07:00
parent c0e21811c0
commit 3692ba55eb
10 changed files with 364 additions and 14 deletions

View File

@@ -262,11 +262,11 @@ class Constant {
prt = "https://"; prt = "https://";
} }
// baseUrl = "$protocol//devbandungraya.aplikasi.web.id/one-api/one_mitra/"; baseUrl = "$protocol//devbandungraya.aplikasi.web.id/one-api/one_mitra/";
// ipAddress = "devbandungraya.aplikasi.web.id"; ipAddress = "devbandungraya.aplikasi.web.id";
// protocol = protocol; protocol = protocol;
baseUrl = "$protocol//$text/one-api/one_mitra/"; // baseUrl = "$protocol//$text/one-api/one_mitra/";
ipAddress = text; // ipAddress = text;
print(baseUrl); print(baseUrl);
} }
} }

View File

@@ -0,0 +1,44 @@
class AliasesModel {
String? userAliasesID;
String? userAliasesUserID;
String? userAliasesTargetIP;
String? userAliasesTargetUserID;
String? userAliasesTargetUsername;
String? userAliasesTargetUrl;
String? userAliasesTargetRegionalID;
String? userAliasesTargetRegionalName;
AliasesModel(
{this.userAliasesID,
this.userAliasesUserID,
this.userAliasesTargetIP,
this.userAliasesTargetUserID,
this.userAliasesTargetUsername,
this.userAliasesTargetUrl,
this.userAliasesTargetRegionalID,
this.userAliasesTargetRegionalName});
AliasesModel.fromJson(Map<String, dynamic> json) {
userAliasesID = json['userAliasesID'];
userAliasesUserID = json['userAliasesUserID'];
userAliasesTargetIP = json['userAliasesTargetIP'];
userAliasesTargetUserID = json['userAliasesTargetUserID'];
userAliasesTargetUsername = json['userAliasesTargetUsername'];
userAliasesTargetUrl = json['userAliasesTargetUrl'];
userAliasesTargetRegionalID = json['userAliasesTargetRegionalID'];
userAliasesTargetRegionalName = json['userAliasesTargetRegionalName'];
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = <String, dynamic>{};
data['userAliasesID'] = userAliasesID;
data['userAliasesUserID'] = userAliasesUserID;
data['userAliasesTargetIP'] = userAliasesTargetIP;
data['userAliasesTargetUserID'] = userAliasesTargetUserID;
data['userAliasesTargetUsername'] = userAliasesTargetUsername;
data['userAliasesTargetUrl'] = userAliasesTargetUrl;
data['userAliasesTargetRegionalID'] = userAliasesTargetRegionalID;
data['userAliasesTargetRegionalName'] = userAliasesTargetRegionalName;
return data;
}
}

View File

@@ -0,0 +1,59 @@
import 'package:equatable/equatable.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'dio_provider.dart';
import '../repository/aliases_repository.dart';
import '../repository/base_repository.dart';
import '../model/aliases_model.dart';
abstract class AliasesState extends Equatable {
final DateTime date;
const AliasesState(this.date);
@override
List<Object?> get props => [date];
}
class AliasesStateInit extends AliasesState {
AliasesStateInit() : super(DateTime.now());
}
class AliasesStateLoading extends AliasesState {
AliasesStateLoading() : super(DateTime.now());
}
class AliasesStateError extends AliasesState {
final String? message;
AliasesStateError({
required this.message,
}) : super(DateTime.now());
}
class AliasesStateDone extends AliasesState {
final List<AliasesModel> model;
AliasesStateDone({
required this.model,
}) : super(DateTime.now());
}
class AliasesNotifier extends StateNotifier<AliasesState> {
final Ref ref;
AliasesNotifier({
required this.ref,
}) : super(AliasesStateInit());
void getAliases({required String token}) async {
try {
state = AliasesStateLoading();
final resp = await AliasesRepository(dio: ref.read(dioProvider)).getAliases(token: token);
state = AliasesStateDone(model: resp);
} catch (e) {
if (e is BaseRepositoryException) {
state = AliasesStateError(message: e.message ?? "");
} else {
state = AliasesStateError(message: e.toString());
}
}
}
}
final aliasesDataProvider = StateNotifierProvider<AliasesNotifier, AliasesState>((ref) => AliasesNotifier(ref: ref));

View File

@@ -0,0 +1,62 @@
import 'package:equatable/equatable.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'dio_provider.dart';
import '../repository/aliases_repository.dart';
import '../repository/base_repository.dart';
abstract class ReqCabangState extends Equatable {
final DateTime date;
const ReqCabangState(this.date);
@override
List<Object?> get props => [date];
}
class ReqCabangStateInit extends ReqCabangState {
ReqCabangStateInit() : super(DateTime.now());
}
class ReqCabangStateLoading extends ReqCabangState {
ReqCabangStateLoading() : super(DateTime.now());
}
class ReqCabangStateError extends ReqCabangState {
final String? message;
ReqCabangStateError({
required this.message,
}) : super(DateTime.now());
}
class ReqCabangStateDone extends ReqCabangState {
final String model;
ReqCabangStateDone({
required this.model,
}) : super(DateTime.now());
}
class ReqCabangNotifier extends StateNotifier<ReqCabangState> {
final Ref ref;
ReqCabangNotifier({
required this.ref,
}) : super(ReqCabangStateInit());
void requestTokenCabang({
required String token,
required String userID,
required String username,
required String targetUrl
}) async {
try {
state = ReqCabangStateLoading();
final resp = await AliasesRepository(dio: ref.read(dioProvider)).requestToken(token: token, userID: userID, username: username, targetUrl: targetUrl);
state = ReqCabangStateDone(model: resp);
} catch (e) {
if (e is BaseRepositoryException) {
state = ReqCabangStateError(message: e.message ?? "");
} else {
state = ReqCabangStateError(message: e.toString());
}
}
}
}
final reqCabangTokenProvider = StateNotifierProvider<ReqCabangNotifier, ReqCabangState>((ref) => ReqCabangNotifier(ref: ref));

View File

@@ -0,0 +1,49 @@
import '../app/constant.dart';
import '../model/aliases_model.dart';
import 'base_repository.dart';
class AliasesRepository extends BaseRepository {
AliasesRepository({required super.dio});
Future<List<AliasesModel>> getAliases({required String token}) async {
final param = {"token": token};
final service = "${Constant.baseUrl}authchange/getuseraliases";
final resp = await post(param: param, service: service);
var aliases = <AliasesModel>[];
if (resp['status'] == 'OK') {
resp['data'].forEach((v) {
aliases.add(AliasesModel.fromJson(v));
});
} else {
}
return aliases;
}
Future<String> requestToken({
required String token,
required String userID,
required String username,
required String targetUrl,
}) async {
final param = {
"token": token,
"userID": userID,
"username": username,
"targetUrl": targetUrl
};
final service = "${Constant.baseUrl}authchange/request_mitra_token";
final resp = await post(param: param, service: service);
if (resp['status'] == "OK") {
return resp['data'];
} else {
return resp['message'];
}
}
}

View File

@@ -1,5 +1,7 @@
import 'dart:convert'; import 'dart:convert';
import 'dart:html' as html;
import 'package:dart_jsonwebtoken/dart_jsonwebtoken.dart';
import 'package:eva_icons_flutter/eva_icons_flutter.dart'; import 'package:eva_icons_flutter/eva_icons_flutter.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_hooks/flutter_hooks.dart'; import 'package:flutter_hooks/flutter_hooks.dart';
@@ -36,14 +38,28 @@ class LoginBox extends HookConsumerWidget {
final regionalLoading = useState(false); final regionalLoading = useState(false);
final isLoading = useState(false); final isLoading = useState(false);
final errorMsg = useState(""); final errorMsg = useState("");
getPref() async { getPref() async {
final SharedPreferences prefs = await SharedPreferences.getInstance(); final SharedPreferences prefs = await SharedPreferences.getInstance();
final String? getData = prefs.getString(Constant.tokenName); final Uri currentUrl = Uri.parse(html.window.location.href);
print(getData); final String? token = currentUrl.queryParameters['token'];
if (getData != null) {
ref.read(authProvider.notifier).state = if (token != null) {
AuthModel.fromJson(jsonDecode(getData)); final jwt = JWT.decode(token);
final payload = jwt.payload;
AuthModel user = AuthModel.fromJson(payload);
user.token = token;
ref.read(authProvider.notifier).state = user;
Navigator.pushNamed(context, homeRoute); Navigator.pushNamed(context, homeRoute);
} else {
final String? getData = prefs.getString(Constant.tokenName);
print(getData);
if (getData != null) {
ref.read(authProvider.notifier).state =
AuthModel.fromJson(jsonDecode(getData));
Navigator.pushNamed(context, homeRoute);
}
} }
} }

View File

@@ -1,10 +1,11 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:mitra_corporate/screen/login/login_box.dart'; import 'login_box.dart';
import '../../app/constant.dart'; import '../../app/constant.dart';
class LoginScreen extends StatelessWidget { class LoginScreen extends StatelessWidget {
const LoginScreen({super.key}); const LoginScreen({super.key});
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Material( return Material(

View File

@@ -4,7 +4,10 @@ import 'package:flutter_hooks/flutter_hooks.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:intl/date_symbol_data_local.dart'; import 'package:intl/date_symbol_data_local.dart';
import 'package:intl/intl.dart'; import 'package:intl/intl.dart';
import 'package:mitra_corporate/model/aliases_model.dart';
import 'package:mitra_corporate/provider/aliases_provider.dart';
import 'package:mitra_corporate/provider/menu_provider.dart'; import 'package:mitra_corporate/provider/menu_provider.dart';
import 'package:mitra_corporate/provider/pindah_branch_provider.dart';
import 'package:mitra_corporate/widgets/custom_text_field.dart'; import 'package:mitra_corporate/widgets/custom_text_field.dart';
import 'package:loading_animation_widget/loading_animation_widget.dart'; import 'package:loading_animation_widget/loading_animation_widget.dart';
import 'package:shared_preferences/shared_preferences.dart'; import 'package:shared_preferences/shared_preferences.dart';
@@ -14,6 +17,7 @@ import '../app/route.dart';
import '../provider/auth_provider.dart'; import '../provider/auth_provider.dart';
import '../screen/login/change_password_provider.dart'; import '../screen/login/change_password_provider.dart';
import '../screen/login/logout_provider.dart'; import '../screen/login/logout_provider.dart';
import 'dart:html' as html;
import 'custom_snackbar_widget.dart'; import 'custom_snackbar_widget.dart';
class Header extends HookConsumerWidget { class Header extends HookConsumerWidget {
@@ -27,6 +31,8 @@ class Header extends HookConsumerWidget {
final isExpand = ref.watch(sideBarExpandProvider); final isExpand = ref.watch(sideBarExpandProvider);
final auth = ref.watch(authProvider); final auth = ref.watch(authProvider);
final date = useState(""); final date = useState("");
final listAliases = useState<List<AliasesModel>>(List.empty());
ref.listen(logoutProvider, (prev, next) async { ref.listen(logoutProvider, (prev, next) async {
if (next is LogoutStateLoading) { if (next is LogoutStateLoading) {
} else if (next is LogoutStateError) { } else if (next is LogoutStateError) {
@@ -41,6 +47,13 @@ class Header extends HookConsumerWidget {
} }
} }
}); });
fetchAliases() async {
String token = auth?.token ?? "0";
ref.read(aliasesDataProvider.notifier).getAliases(token: token);
}
useEffect(() { useEffect(() {
WidgetsBinding.instance.addPostFrameCallback((timeStamp) async { WidgetsBinding.instance.addPostFrameCallback((timeStamp) async {
DateTime now = DateTime.now(); DateTime now = DateTime.now();
@@ -48,9 +61,45 @@ class Header extends HookConsumerWidget {
date.value = DateFormat('EEEE, d MMMM yyyy', "id").format(now); date.value = DateFormat('EEEE, d MMMM yyyy', "id").format(now);
print(DateFormat('EEEE, d MMMM yyyy', "id").format(now)); print(DateFormat('EEEE, d MMMM yyyy', "id").format(now));
}); });
fetchAliases();
}); });
return () {}; return () {};
}, []); }, []);
ref.listen(aliasesDataProvider, (pref, next) {
if (next is AliasesStateInit) {
} else if (next is AliasesStateLoading) {
} else if (next is AliasesStateError) {
SanckbarWidget(context, next.message ?? "", snackbarType.error);
} else if (next is AliasesStateDone) {
listAliases.value = next.model;
}
});
void openNewTab(String url) {
html.window.open(url, '_blank');
}
moveBranch(String userID, String username, String targetUrl) {
String token = auth?.token ?? "0";
ref.read(reqCabangTokenProvider.notifier).requestTokenCabang(token: token, userID: userID, username: username, targetUrl: targetUrl);
}
ref.listen(reqCabangTokenProvider, (prev, next) {
if (next is ReqCabangStateInit) {
} else if (next is ReqCabangStateLoading) {
} else if (next is ReqCabangStateError) {
SanckbarWidget(context, next.message ?? "", snackbarType.error);
} else if (next is ReqCabangStateDone) {
var url = next.model;
openNewTab("http://${url}");
}
});
return Container( return Container(
color: Colors.white, color: Colors.white,
alignment: Alignment.center, alignment: Alignment.center,
@@ -185,6 +234,27 @@ class Header extends HookConsumerWidget {
style: Constant.body3_400(context: context), style: Constant.body3_400(context: context),
), ),
), ),
...listAliases.value.isEmpty
? []
: listAliases.value.map((alias) {
return MenuItemButton(
leadingIcon: Icon(
EvaIcons.globe2Outline,
color: Constant.primaryRed,
),
child: Text(
alias.userAliasesTargetRegionalName ?? '',
style: Constant.body3_400(context: context),
),
onPressed: () {
moveBranch(
alias.userAliasesTargetUserID ?? "",
alias.userAliasesTargetUsername ?? "",
alias.userAliasesTargetIP ?? ""
);
},
);
}).toList(),
Container( Container(
margin: EdgeInsets.only(top: 10, bottom: 10), margin: EdgeInsets.only(top: 10, bottom: 10),
child: Center( child: Center(

View File

@@ -1,6 +1,14 @@
# Generated by pub # Generated by pub
# See https://dart.dev/tools/pub/glossary#lockfile # See https://dart.dev/tools/pub/glossary#lockfile
packages: packages:
adaptive_number:
dependency: transitive
description:
name: adaptive_number
sha256: "3a567544e9b5c9c803006f51140ad544aedc79604fd4f3f2c1380003f97c1d77"
url: "https://pub.dev"
source: hosted
version: "1.0.0"
age_calculator: age_calculator:
dependency: "direct main" dependency: "direct main"
description: description:
@@ -81,6 +89,14 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "1.18.0" version: "1.18.0"
convert:
dependency: transitive
description:
name: convert
sha256: b30acd5944035672bc15c6b7a8b47d773e41e2f17de064350988c5d02adb1c68
url: "https://pub.dev"
source: hosted
version: "3.1.2"
crypto: crypto:
dependency: transitive dependency: transitive
description: description:
@@ -97,6 +113,14 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "1.0.0" version: "1.0.0"
dart_jsonwebtoken:
dependency: "direct main"
description:
name: dart_jsonwebtoken
sha256: "866787dc17afaef46a9ea7dd33eefe60c6d82084b4a36d70e8e788d091cd04ef"
url: "https://pub.dev"
source: hosted
version: "2.14.2"
data_table_2: data_table_2:
dependency: "direct main" dependency: "direct main"
description: description:
@@ -145,6 +169,14 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.0.0" version: "2.0.0"
ed25519_edwards:
dependency: transitive
description:
name: ed25519_edwards
sha256: "6ce0112d131327ec6d42beede1e5dfd526069b18ad45dcf654f15074ad9276cd"
url: "https://pub.dev"
source: hosted
version: "0.3.1"
equatable: equatable:
dependency: "direct main" dependency: "direct main"
description: description:
@@ -405,6 +437,14 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "6.3.1" version: "6.3.1"
js:
dependency: transitive
description:
name: js
sha256: c1b2e9b5ea78c45e1a0788d29606ba27dc5f71f019f32ca5140f61ef071838cf
url: "https://pub.dev"
source: hosted
version: "0.7.1"
just_the_tooltip: just_the_tooltip:
dependency: "direct main" dependency: "direct main"
description: description:
@@ -629,6 +669,14 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "0.10.2+1" version: "0.10.2+1"
pointycastle:
dependency: transitive
description:
name: pointycastle
sha256: "4be0097fcf3fd3e8449e53730c631200ebc7b88016acecab2b0da2f0149222fe"
url: "https://pub.dev"
source: hosted
version: "3.9.1"
riverpod: riverpod:
dependency: transitive dependency: transitive
description: description:
@@ -910,10 +958,10 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: vm_service name: vm_service
sha256: f652077d0bdf60abe4c1f6377448e8655008eef28f128bc023f7b5e8dfeb48fc sha256: "5c5f338a667b4c644744b661f309fb8080bb94b18a7e91ef1dbd343bed00ed6d"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "14.2.4" version: "14.2.5"
web: web:
dependency: transitive dependency: transitive
description: description:

View File

@@ -46,6 +46,7 @@ dependencies:
# Use with the CupertinoIcons class for iOS style icons. # Use with the CupertinoIcons class for iOS style icons.
eva_icons_flutter: ^3.1.0 eva_icons_flutter: ^3.1.0
url_launcher: ^6.1.11 url_launcher: ^6.1.11
dart_jsonwebtoken: ^2.14.2
dev_dependencies: dev_dependencies:
flutter_test: flutter_test: