step 11 : proses clock in, clock out

This commit is contained in:
sindhu
2024-01-26 15:10:36 +07:00
parent 1af974881a
commit c551ee2cdb
16 changed files with 1590 additions and 712 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.9 KiB

View File

@@ -13,6 +13,9 @@ class Constant {
static double designHeightPhone = 844;
static double designWidthPhone = 390;
// NOTE VERSI HARUS SAMA DENGAN PUBSPEC.YAML
static String version = "1.0.1";
// color theme
static Color textTrueBlack = const Color(0xff000000);
static Color textBlack = const Color(0xff212B36);

View File

@@ -0,0 +1,36 @@
class CheckPresensiJamModel {
String? status;
String? message;
String? jamClockIn;
String? jamClockOut;
String? isAbsenClockIn;
String? isAbsenClockOut;
CheckPresensiJamModel(
{this.status,
this.message,
this.jamClockIn,
this.jamClockOut,
this.isAbsenClockIn,
this.isAbsenClockOut});
CheckPresensiJamModel.fromJson(Map<String, dynamic> json) {
status = json['status'];
message = json['message'];
jamClockIn = json['jam_clock_in'];
jamClockOut = json['jam_clock_out'];
isAbsenClockIn = json['is_absen_clock_in'];
isAbsenClockOut = json['is_absen_clock_out'];
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['status'] = this.status;
data['message'] = this.message;
data['jam_clock_in'] = this.jamClockIn;
data['jam_clock_out'] = this.jamClockOut;
data['is_absen_clock_in'] = this.isAbsenClockIn;
data['is_absen_clock_out'] = this.isAbsenClockOut;
return data;
}
}

View File

@@ -0,0 +1,4 @@
import 'package:absensi_sas_flutter/model/check_presensi_jam_model.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
final currentCheckJamPresensiProvider = StateProvider<CheckPresensiJamModel?>((ref) => null);

View File

@@ -0,0 +1,3 @@
import 'package:flutter_riverpod/flutter_riverpod.dart';
final currentPageProvider = StateProvider<int?>((ref) => null);

View File

@@ -5,6 +5,9 @@ import '../app/constant.dart';
final graphqlProvider = Provider.family<GraphQLClient, String>(
(_, token) {
final policies = Policies(
fetch: FetchPolicy.noCache,
);
return GraphQLClient(
link: (token != "")
? HttpLink(
@@ -17,6 +20,11 @@ final graphqlProvider = Provider.family<GraphQLClient, String>(
Constant.baseURLGraphQl,
),
cache: GraphQLCache(),
defaultPolicies: DefaultPolicies(
watchQuery: policies,
query: policies,
mutate: policies,
),
);
},
);

View File

@@ -1,4 +1,5 @@
import 'package:absensi_sas_flutter/model/check_distance_model.dart';
import 'package:absensi_sas_flutter/model/check_presensi_jam_model.dart';
import 'base_repository.dart';
class PresensiRepository extends BaseRepository {
@@ -23,7 +24,7 @@ class PresensiRepository extends BaseRepository {
final resp = await postGraphQlMutation(query, inpVariables);
// final loginData = AuthModel.fromJson(resp['userLogin']);
print(inpVariables);
// print(inpVariables);
print('obj queryCheckDistance : ${resp["queryCheckDistance"]}');
@@ -33,12 +34,145 @@ class PresensiRepository extends BaseRepository {
// );
final result = CheckDistanceModel(
currentDistance: resp['queryCheckDistance']['current_distance'],
maxDistance: resp['queryCheckDistance']['max_distance'],
message: resp['queryCheckDistance']['message'],
selfie: resp['queryCheckDistance']['selfie'],
status: resp['queryCheckDistance']['status'],
unit: resp['queryCheckDistance']['unit']
currentDistance: resp['queryCheckDistance']['current_distance'],
maxDistance: resp['queryCheckDistance']['max_distance'],
message: resp['queryCheckDistance']['message'],
selfie: resp['queryCheckDistance']['selfie'],
status: resp['queryCheckDistance']['status'],
unit: resp['queryCheckDistance']['unit']);
return result;
}
// presensi normal Clock In
Future<String> presensiNormalClockIn(
String T_TransactionM_StaffID,
String T_TransactionM_CompanyID,
String T_TransactionCurrentLatitude,
String T_TransactionCurrentLongitude,
String T_TransactionCurrentDistance,
String T_TransactionSelfiePhoto,
String token,
String isSelfie,
Map<String, dynamic> paramInpVariables) async {
const String query =
r'''mutation($T_TransactionM_StaffID:String!, $T_TransactionM_CompanyID:String!, $T_TransactionCurrentLatitude:String!, $T_TransactionCurrentLongitude:String!, $T_TransactionCurrentDistance:String!, $T_TransactionSelfiePhoto:String, $token:String!, $isSelfie:String!){ mutationClockInAttendance(T_TransactionM_StaffID:$T_TransactionM_StaffID, T_TransactionM_CompanyID:$T_TransactionM_CompanyID, T_TransactionCurrentLatitude:$T_TransactionCurrentLatitude, T_TransactionCurrentLongitude:$T_TransactionCurrentLongitude, T_TransactionCurrentDistance:$T_TransactionCurrentDistance, T_TransactionSelfiePhoto:$T_TransactionSelfiePhoto, token:$token, isSelfie:$isSelfie){ status message } }''';
Map<String, dynamic> inpVariables = paramInpVariables;
print(paramInpVariables);
final resp = await postGraphQlMutation(query, inpVariables);
// print(inpVariables);
print(
'obj mutationClockInAttendance : ${resp["mutationClockInAttendance"]}');
// final result = AuthModel(
// token: resp["loginAttendance"]["token"],
// model: StaffModel.fromJson(resp["loginAttendance"]),
// );
final result = resp["mutationClockInAttendance"]['status'];
return result;
}
// presensi normal clock Out
Future<String> presensiNormalClockOut(
String T_TransactionM_StaffID,
String T_TransactionM_CompanyID,
String T_TransactionCurrentLatitude,
String T_TransactionCurrentLongitude,
String T_TransactionCurrentDistance,
String T_TransactionSelfiePhoto,
String token,
String isSelfie,
Map<String, dynamic> paramInpVariables) async {
const String query =
r'''mutation(
$T_TransactionM_StaffID:String!,
$T_TransactionM_CompanyID:String!,
$T_TransactionCurrentLatitude:String!,
$T_TransactionCurrentLongitude:String!,
$T_TransactionCurrentDistance:String!,
$T_TransactionSelfiePhoto:String,
$token:String!,
$isSelfie:String!
){
mutationClockOutAttendance(
T_TransactionM_StaffID:$T_TransactionM_StaffID,
T_TransactionM_CompanyID:$T_TransactionM_CompanyID,
T_TransactionCurrentLatitude:$T_TransactionCurrentLatitude,
T_TransactionCurrentLongitude:$T_TransactionCurrentLongitude,
T_TransactionCurrentDistance:$T_TransactionCurrentDistance,
T_TransactionSelfiePhoto:$T_TransactionSelfiePhoto,
token:$token, isSelfie:$isSelfie
){
status
message
}
}''';
Map<String, dynamic> inpVariables = paramInpVariables;
print(paramInpVariables);
final resp = await postGraphQlMutation(query, inpVariables);
// print(inpVariables);
print(
'obj mutationClockOutAttendance : ${resp["mutationClockOutAttendance"]}');
// final result = AuthModel(
// token: resp["loginAttendance"]["token"],
// model: StaffModel.fromJson(resp["loginAttendance"]),
// );
final result = resp["mutationClockOutAttendance"]['status'];
return result;
}
// check presensi jam
Future<CheckPresensiJamModel> checkPresensiJam(
String M_StaffID,
String M_CompanyID,
String token,
Map<String, dynamic> paramInpVariables,
) async {
const String query =
r'''query($M_StaffID:String!, $M_CompanyID:String!, $token:String!){
queryCheckTimeAttendance(M_StaffID:$M_StaffID, M_CompanyID:$M_CompanyID, token:$token){
status
message
jam_clock_in
jam_clock_out
is_absen_clock_in
is_absen_clock_out
}
}''';
// Map<String, dynamic> inpVariables = paramInpVariables;
// Map<String, dynamic> inpVariables = {
// "M_StaffID": M_StaffID,
// "M_CompanyID": M_CompanyID,
// "token": token,
// };
print(paramInpVariables);
final resp = await postGraphQlQuery(query, paramInpVariables);
// print(inpVariables);
print('obj queryCheckTimeAttendance : ${resp["queryCheckTimeAttendance"]}');
final result = CheckPresensiJamModel(
isAbsenClockIn: resp['queryCheckTimeAttendance']['is_absen_clock_in'],
isAbsenClockOut: resp['queryCheckTimeAttendance']['is_absen_clock_out'],
jamClockIn: resp['queryCheckTimeAttendance']['jam_clock_in'],
jamClockOut: resp['queryCheckTimeAttendance']['jam_clock_out'],
message: resp['queryCheckTimeAttendance']['message'],
status: resp['queryCheckTimeAttendance']['status'],
);
return result;
}

File diff suppressed because it is too large Load Diff

View File

@@ -11,6 +11,7 @@ import 'package:shared_preferences/shared_preferences.dart';
import '../../app/constant.dart';
import '../../app/route.dart';
import '../../model/auth_model.dart';
import '../../provider/current_menu_provider.dart';
import '../../provider/current_user_provider.dart';
import '../../provider/google_login_provider.dart';
@@ -92,6 +93,7 @@ class LoginScreen extends HookConsumerWidget {
.read(currentUserGoogleProvider.notifier)
.update((state) => account);
ref.read(currentUserProvider.notifier).state = authModel;
ref.read(currentPageProvider.state).update((state) => 0);
Navigator.of(context).pushNamedAndRemoveUntil(
homeRoute,
(route) => false,
@@ -121,7 +123,7 @@ class LoginScreen extends HookConsumerWidget {
} else if (next is LoginStateDone) {
isLoading.value = false;
isSuccess.value = true;
// ref.read(currentPageProvider.state).update((state) => 0);
ref.read(currentPageProvider.state).update((state) => 0);
Navigator.of(context)
.pushNamedAndRemoveUntil(homeRoute, (route) => false);
}

View File

@@ -1,3 +1,4 @@
import 'package:absensi_sas_flutter/provider/current_user_provider.dart';
import 'package:absensi_sas_flutter/repository/presensi_repository.dart';
import 'package:equatable/equatable.dart';
@@ -7,6 +8,7 @@ import '../../provider/current_check_distance_provider.dart';
import '../../provider/dio_provider.dart';
import '../../provider/graphql_provider.dart';
import '../../repository/base_repository.dart';
import 'check_presensi_jam_provider.dart';
abstract class CheckDistanceState extends Equatable {
final DateTime date;
@@ -63,6 +65,21 @@ class CheckDistanceNotifier extends StateNotifier<CheckDistanceState> {
);
// set ke global state provider
ref.read(currentCheckDistanceProvider.notifier).update((state) => resp);
// panggil provider cek jam masuk dan pulang (checkPresensiJamProvider)
final user = ref.read(currentUserProvider);
Map<String, dynamic> inpVariablesCheckPresensiJam = {
"M_StaffID": M_StaffID,
"M_CompanyID": M_CompanyID,
"token": user?.token ?? "",
};
ref.read(checkPresensiJamProvider.notifier).checkPresensiJam(
M_StaffID,
M_CompanyID,
user?.token ?? "",
inpVariablesCheckPresensiJam,
);
state = CheckDistanceStateDone(model: resp);
} catch (e) {
if (e is BaseRepositoryException) {

View File

@@ -0,0 +1,81 @@
import 'package:absensi_sas_flutter/model/check_presensi_jam_model.dart';
import 'package:absensi_sas_flutter/repository/presensi_repository.dart';
import 'package:equatable/equatable.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import '../../provider/current_check_jam_presensi_provider.dart';
import '../../provider/dio_provider.dart';
import '../../provider/graphql_provider.dart';
import '../../repository/base_repository.dart';
abstract class CheckPresensiJamState extends Equatable {
final DateTime date;
const CheckPresensiJamState(this.date);
@override
List<Object?> get props => [date];
}
class CheckPresensiJamStateInit extends CheckPresensiJamState {
CheckPresensiJamStateInit() : super(DateTime.now());
}
class CheckPresensiJamStateLoading extends CheckPresensiJamState {
CheckPresensiJamStateLoading() : super(DateTime.now());
}
class CheckPresensiJamStateError extends CheckPresensiJamState {
final String message;
CheckPresensiJamStateError({
required this.message,
}) : super(DateTime.now());
}
class CheckPresensiJamStateDone extends CheckPresensiJamState {
final CheckPresensiJamModel model;
CheckPresensiJamStateDone({
required this.model,
}) : super(DateTime.now());
}
//notifier
class CheckPresensiJamNotifier extends StateNotifier<CheckPresensiJamState> {
final Ref ref;
CheckPresensiJamNotifier({
required this.ref,
}) : super(CheckPresensiJamStateInit());
void checkPresensiJam(
String M_StaffID,
String M_CompanyID,
String token,
Map<String, dynamic> paramInpVariables,
) async {
try {
state = CheckPresensiJamStateLoading();
final graphql = ref.read(graphqlProvider(''));
final dio = ref.read(dioProvider);
final resp = await PresensiRepository(graphql: graphql, dio: dio)
.checkPresensiJam(
M_StaffID,
M_CompanyID,
token,
paramInpVariables,
);
// set ke global state provider currentCheckJamPresensiProvider
ref.read(currentCheckJamPresensiProvider.notifier).update((state) => resp);
state = CheckPresensiJamStateDone(model: resp);
} catch (e) {
if (e is BaseRepositoryException) {
state = CheckPresensiJamStateError(message: e.message ?? "");
} else {
state = CheckPresensiJamStateError(message: e.toString());
}
}
}
}
// provider
final checkPresensiJamProvider =
StateNotifierProvider<CheckPresensiJamNotifier, CheckPresensiJamState>(
(ref) => CheckPresensiJamNotifier(ref: ref),
);

View File

@@ -0,0 +1,102 @@
import 'package:absensi_sas_flutter/repository/presensi_repository.dart';
import 'package:equatable/equatable.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import '../../provider/dio_provider.dart';
import '../../provider/graphql_provider.dart';
import '../../repository/base_repository.dart';
import 'check_presensi_jam_provider.dart';
abstract class PresensiClockInState extends Equatable {
final DateTime date;
const PresensiClockInState(this.date);
@override
List<Object?> get props => [date];
}
class PresensiClockInStateInit extends PresensiClockInState {
PresensiClockInStateInit() : super(DateTime.now());
}
class PresensiClockInStateLoading extends PresensiClockInState {
PresensiClockInStateLoading() : super(DateTime.now());
}
class PresensiClockInStateError extends PresensiClockInState {
final String message;
PresensiClockInStateError({
required this.message,
}) : super(DateTime.now());
}
class PresensiClockInStateDone extends PresensiClockInState {
final String model;
PresensiClockInStateDone({
required this.model,
}) : super(DateTime.now());
}
//notifier
class PresensiClockInNotifier extends StateNotifier<PresensiClockInState> {
final Ref ref;
PresensiClockInNotifier({
required this.ref,
}) : super(PresensiClockInStateInit());
void presensiClockIn(
String T_TransactionM_StaffID,
String T_TransactionM_CompanyID,
String T_TransactionCurrentLatitude,
String T_TransactionCurrentLongitude,
String T_TransactionCurrentDistance,
String T_TransactionSelfiePhoto,
String token,
String isSelfie,
Map<String, dynamic> paramInpVariables,
) async {
try {
state = PresensiClockInStateLoading();
final graphql = ref.read(graphqlProvider(''));
final dio = ref.read(dioProvider);
final resp = await PresensiRepository(graphql: graphql, dio: dio)
.presensiNormalClockIn(
T_TransactionM_StaffID,
T_TransactionM_CompanyID,
T_TransactionCurrentLatitude,
T_TransactionCurrentLongitude,
T_TransactionCurrentDistance,
T_TransactionSelfiePhoto,
token,
isSelfie,
paramInpVariables,
);
// panggil provider cek jam masuk dan pulang (checkPresensiJamProvider)
Map<String, dynamic> inpVariablesCheckPresensiJam = {
"M_StaffID": T_TransactionM_StaffID,
"M_CompanyID": T_TransactionM_CompanyID,
"token": token,
};
ref.read(checkPresensiJamProvider.notifier).checkPresensiJam(
T_TransactionM_StaffID,
T_TransactionM_CompanyID,
token,
inpVariablesCheckPresensiJam,
);
print('call check presensi');
state = PresensiClockInStateDone(model: resp);
} catch (e) {
if (e is BaseRepositoryException) {
state = PresensiClockInStateError(message: e.message ?? "");
} else {
state = PresensiClockInStateError(message: e.toString());
}
}
}
}
// provider
final presensiClockInProvider =
StateNotifierProvider<PresensiClockInNotifier, PresensiClockInState>(
(ref) => PresensiClockInNotifier(ref: ref),
);

View File

@@ -0,0 +1,102 @@
import 'package:absensi_sas_flutter/repository/presensi_repository.dart';
import 'package:equatable/equatable.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import '../../provider/dio_provider.dart';
import '../../provider/graphql_provider.dart';
import '../../repository/base_repository.dart';
import 'check_presensi_jam_provider.dart';
abstract class PresensiClockOutState extends Equatable {
final DateTime date;
const PresensiClockOutState(this.date);
@override
List<Object?> get props => [date];
}
class PresensiClockOutStateInit extends PresensiClockOutState {
PresensiClockOutStateInit() : super(DateTime.now());
}
class PresensiClockOutStateLoading extends PresensiClockOutState {
PresensiClockOutStateLoading() : super(DateTime.now());
}
class PresensiClockOutStateError extends PresensiClockOutState {
final String message;
PresensiClockOutStateError({
required this.message,
}) : super(DateTime.now());
}
class PresensiClockOutStateDone extends PresensiClockOutState {
final String model;
PresensiClockOutStateDone({
required this.model,
}) : super(DateTime.now());
}
//notifier
class PresensiClockOutNotifier extends StateNotifier<PresensiClockOutState> {
final Ref ref;
PresensiClockOutNotifier({
required this.ref,
}) : super(PresensiClockOutStateInit());
void presensiClockOut(
String T_TransactionM_StaffID,
String T_TransactionM_CompanyID,
String T_TransactionCurrentLatitude,
String T_TransactionCurrentLongitude,
String T_TransactionCurrentDistance,
String T_TransactionSelfiePhoto,
String token,
String isSelfie,
Map<String, dynamic> paramInpVariables,
) async {
try {
state = PresensiClockOutStateLoading();
final graphql = ref.read(graphqlProvider(''));
final dio = ref.read(dioProvider);
final resp = await PresensiRepository(graphql: graphql, dio: dio)
.presensiNormalClockOut(
T_TransactionM_StaffID,
T_TransactionM_CompanyID,
T_TransactionCurrentLatitude,
T_TransactionCurrentLongitude,
T_TransactionCurrentDistance,
T_TransactionSelfiePhoto,
token,
isSelfie,
paramInpVariables,
);
// panggil provider cek jam masuk dan pulang (checkPresensiJamProvider)
Map<String, dynamic> inpVariablesCheckPresensiJam = {
"M_StaffID": T_TransactionM_StaffID,
"M_CompanyID": T_TransactionM_CompanyID,
"token": token,
};
ref.read(checkPresensiJamProvider.notifier).checkPresensiJam(
T_TransactionM_StaffID,
T_TransactionM_CompanyID,
token,
inpVariablesCheckPresensiJam,
);
print('call check presensi clockout');
state = PresensiClockOutStateDone(model: resp);
} catch (e) {
if (e is BaseRepositoryException) {
state = PresensiClockOutStateError(message: e.message ?? "");
} else {
state = PresensiClockOutStateError(message: e.toString());
}
}
}
}
// provider
final presensiClockOutProvider =
StateNotifierProvider<PresensiClockOutNotifier, PresensiClockOutState>(
(ref) => PresensiClockOutNotifier(ref: ref),
);

View File

@@ -1,4 +1,9 @@
import 'dart:convert';
import 'package:absensi_sas_flutter/provider/current_check_jam_presensi_provider.dart';
import 'package:absensi_sas_flutter/screen/presensi/check_distance_provider.dart';
import 'package:absensi_sas_flutter/screen/presensi/check_presensi_jam_provider.dart';
import 'package:absensi_sas_flutter/screen/presensi/presensi_clock_in_provider.dart';
import 'package:absensi_sas_flutter/widget/real_date.dart';
import 'package:absensi_sas_flutter/widget/sankbar_widget.dart';
import 'package:flutter/material.dart';
@@ -12,7 +17,9 @@ import '../../app/constant.dart';
import '../../app/route.dart';
import '../../provider/current_check_distance_provider.dart';
import '../../provider/current_user_provider.dart';
import '../../widget/custom_drawer.dart';
import '../../widget/real_time.dart';
import 'presensi_clock_out_provider.dart';
class PresensiScreen extends HookConsumerWidget {
const PresensiScreen({super.key});
@@ -23,7 +30,9 @@ class PresensiScreen extends HookConsumerWidget {
final isLoadingAddressUserLocation = useState<bool>(false);
final isLoadingProsesCheckDistance = useState<bool>(false);
final varCurrentDistanceProvider = ref.watch(currentCheckDistanceProvider);
final selectedUser = ref.read(currentUserProvider);
final varCurrentCheckJamProvider =
ref.watch(currentCheckJamPresensiProvider);
final selectedUser = ref.watch(currentUserProvider);
final positionLatitude = useState<String>("");
final positionLongitude = useState<String>("");
@@ -78,6 +87,7 @@ class PresensiScreen extends HookConsumerWidget {
if (positionLatitude.value.isNotEmpty &&
positionLongitude.value.isNotEmpty) {
print('check distance provider');
// panggil check distance provider
ref.read(checkDistanceProvider.notifier).checkDistance(
selectedUser?.model.staffId ?? "",
@@ -130,6 +140,64 @@ class PresensiScreen extends HookConsumerWidget {
}
});
// check jam presensi
ref.listen(checkPresensiJamProvider, (prev, next) {
if (next is CheckPresensiJamStateLoading) {
isLoadingProsesCheckDistance.value = true;
} else if (next is CheckPresensiJamStateError) {
isLoadingProsesCheckDistance.value = false;
SanckbarWidget(
context, "Error : " + next.toString(), snackbarType.warning);
} else if (next is CheckPresensiJamStateDone) {
isLoadingProsesCheckDistance.value = false;
}
});
// proses presensi clock in
ref.listen(presensiClockInProvider, (prev, next) {
if (next is PresensiClockInStateLoading) {
isLoadingProsesCheckDistance.value = true;
} else if (next is PresensiClockInStateError) {
isLoadingProsesCheckDistance.value = false;
SanckbarWidget(
context, "Error : " + next.toString(), snackbarType.warning);
} else if (next is PresensiClockInStateDone) {
isLoadingProsesCheckDistance.value = false;
if (next.model == "OK") {
SanckbarWidget(context, "Berhasil Absen Masuk", snackbarType.success);
requestLocationPermission();
}
// else{
// if(next.model == "WARNING"){
// SanckbarWidget(context, "Berhasil Absen Masuk", snackbarType.success);
// }
// }
}
});
// proses presensi clock in
ref.listen(presensiClockOutProvider, (prev, next) {
if (next is PresensiClockOutStateLoading) {
isLoadingProsesCheckDistance.value = true;
} else if (next is PresensiClockOutStateError) {
isLoadingProsesCheckDistance.value = false;
SanckbarWidget(
context, "Error : " + next.toString(), snackbarType.warning);
} else if (next is PresensiClockOutStateDone) {
isLoadingProsesCheckDistance.value = false;
if (next.model == "OK") {
SanckbarWidget(
context, "Berhasil Absen Pulang", snackbarType.success);
requestLocationPermission();
}
// else{
// if(next.model == "WARNING"){
// SanckbarWidget(context, "Berhasil Absen Masuk", snackbarType.success);
// }
// }
}
});
useEffect(() {
WidgetsBinding.instance.addPostFrameCallback((timeStamp) async {
final staffID = ref.read(currentUserProvider)?.model.staffId ?? "0";
@@ -150,18 +218,6 @@ class PresensiScreen extends HookConsumerWidget {
useEffect(() {
WidgetsBinding.instance.addPostFrameCallback((timeStamp) async {
requestLocationPermission();
// // jika sudah dapat latitude dan logitude baru panggil check distance provider
// if (positionLatitude.value.isNotEmpty &&
// positionLongitude.value.isNotEmpty) {
// // panggil check distance provider
// ref.read(checkDistanceProvider.notifier).checkDistance(
// selectedUser?.model.staffId ?? "",
// selectedUser?.model.companyId ?? "",
// positionLatitude.value,
// positionLongitude.value,
// );
// }
});
return () {};
}, []);
@@ -176,13 +232,14 @@ class PresensiScreen extends HookConsumerWidget {
String T_TransactionCurrentDistance,
String T_TransactionSelfiePhoto,
String token,
String tipeAbsen,
) async {
return showDialog(
context: context,
builder: (BuildContext context) {
return AlertDialog(
title: Text('Konfirmasi'),
content: Text('Apakah anda yakin untuk melakukan Clock In?'),
content: Text('Apakah anda yakin untuk melakukan $tipeAbsen?'),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(8.0),
),
@@ -191,7 +248,7 @@ class PresensiScreen extends HookConsumerWidget {
onPressed: () {
T_TransactionSelfiePhoto = "";
var param = {
Map<String, dynamic> param = {
"T_TransactionM_StaffID": T_TransactionM_StaffID,
"T_TransactionM_CompanyID": T_TransactionM_CompanyID,
"T_TransactionCurrentLatitude":
@@ -201,10 +258,42 @@ class PresensiScreen extends HookConsumerWidget {
"T_TransactionCurrentDistance":
T_TransactionCurrentDistance,
"T_TransactionSelfiePhoto": T_TransactionSelfiePhoto,
"token":token,
"token": token,
"isSelfie": "FALSE"
};
print(param);
Navigator.of(context).pop();
// print(param);
if (tipeAbsen == "Clock In") {
ref.read(presensiClockInProvider.notifier).presensiClockIn(
T_TransactionM_StaffID,
T_TransactionM_CompanyID,
T_TransactionCurrentLatitude,
T_TransactionCurrentLongitude,
T_TransactionCurrentDistance,
T_TransactionSelfiePhoto,
token,
"FALSE",
param,
);
Navigator.of(context).pop();
} else {
if (tipeAbsen == "Clock Out") {
ref
.read(presensiClockOutProvider.notifier)
.presensiClockOut(
T_TransactionM_StaffID,
T_TransactionM_CompanyID,
T_TransactionCurrentLatitude,
T_TransactionCurrentLongitude,
T_TransactionCurrentDistance,
T_TransactionSelfiePhoto,
token,
"FALSE",
param,
);
Navigator.of(context).pop();
}
}
},
child: Text(
'Yakin',
@@ -280,6 +369,7 @@ class PresensiScreen extends HookConsumerWidget {
// elevation: 1.0,
elevation: 0.5,
),
drawer: CustomDrawer(),
body: SafeArea(
child: Padding(
padding: EdgeInsets.only(
@@ -415,74 +505,137 @@ class PresensiScreen extends HookConsumerWidget {
height: Constant.getActualYPhone(context: context, y: 50),
),
// gambar icon presensi
Container(
width: Constant.getActualXPhone(context: context, x: 130),
height: Constant.getActualYPhone(context: context, y: 130),
child: FittedBox(
child: FloatingActionButton(
onPressed: () async {
final T_TransactionM_StaffID =
selectedUser?.model.staffId ?? "";
final T_TransactionM_CompanyID =
selectedUser?.model.companyId ?? "";
final T_TransactionCurrentLatitude =
positionLatitude.value;
final T_TransactionCurrentLongitude =
positionLongitude.value;
final T_TransactionCurrentDistance =
varCurrentDistanceProvider?.currentDistance ?? "";
final T_TransactionSelfiePhoto = "";
final token = selectedUser?.token ?? "";
// tombol aksi absen masuk & pulang
if (varCurrentCheckJamProvider?.isAbsenClockIn == "TRUE" &&
varCurrentCheckJamProvider?.isAbsenClockIn == "TRUE") ...[
SizedBox.shrink()
] else ...[
if (varCurrentCheckJamProvider?.isAbsenClockIn == "FALSE" &&
varCurrentCheckJamProvider?.jamClockIn == "") ...[
// gambar icon presensi clock in
(isLoadingAddressUserLocation.value)
? Center(
child: CircularProgressIndicator(),
)
: Container(
width: Constant.getActualXPhone(
context: context, x: 130),
height: Constant.getActualYPhone(
context: context, y: 130),
child: FittedBox(
child: FloatingActionButton(
onPressed: () async {
final T_TransactionM_StaffID =
selectedUser?.model.staffId ?? "";
final T_TransactionM_CompanyID =
selectedUser?.model.companyId ?? "";
final T_TransactionCurrentLatitude =
positionLatitude.value;
final T_TransactionCurrentLongitude =
positionLongitude.value;
final T_TransactionCurrentDistance =
varCurrentDistanceProvider
?.currentDistance ??
"";
final T_TransactionSelfiePhoto = "";
final token = selectedUser?.token ?? "";
showConfirmationDialog(
context,
T_TransactionM_StaffID,
T_TransactionM_CompanyID,
T_TransactionCurrentLatitude,
T_TransactionCurrentLongitude,
T_TransactionCurrentDistance,
T_TransactionSelfiePhoto,
token,
);
},
backgroundColor: Color(0xFFFFFFFF),
shape: CircleBorder(),
child: Container(
width: Constant.getActualXPhone(
context: context, x: 130),
height: Constant.getActualYPhone(
context: context, y: 130),
decoration: BoxDecoration(
image: DecorationImage(
// fit: BoxFit.cover,
image: AssetImage(
'images/presensi_finger2.png'), // Ganti dengan path gambar Anda
showConfirmationDialog(
context,
T_TransactionM_StaffID,
T_TransactionM_CompanyID,
T_TransactionCurrentLatitude,
T_TransactionCurrentLongitude,
T_TransactionCurrentDistance,
T_TransactionSelfiePhoto,
token,
"Clock In");
},
backgroundColor: Color(0xFFFFFFFF),
shape: CircleBorder(),
child: Container(
width: Constant.getActualXPhone(
context: context, x: 130),
height: Constant.getActualYPhone(
context: context, y: 130),
decoration: BoxDecoration(
image: DecorationImage(
// fit: BoxFit.cover,
image: AssetImage(
'images/presensi_finger2.png'), // Ganti dengan path gambar Anda
),
),
),
),
),
),
),
),
),
),
),
] else ...[
// gambar icon presensi clock out
if (varCurrentCheckJamProvider?.isAbsenClockIn ==
"TRUE" &&
varCurrentCheckJamProvider?.jamClockIn != "") ...[
(isLoadingAddressUserLocation.value)
? Center(
child: CircularProgressIndicator(),
)
: Container(
width: Constant.getActualXPhone(
context: context, x: 130),
height: Constant.getActualYPhone(
context: context, y: 130),
child: FittedBox(
child: FloatingActionButton(
onPressed: () async {
final T_TransactionM_StaffID =
selectedUser?.model.staffId ?? "";
final T_TransactionM_CompanyID =
selectedUser?.model.companyId ?? "";
final T_TransactionCurrentLatitude =
positionLatitude.value;
final T_TransactionCurrentLongitude =
positionLongitude.value;
final T_TransactionCurrentDistance =
varCurrentDistanceProvider
?.currentDistance ??
"";
final T_TransactionSelfiePhoto = "";
final token = selectedUser?.token ?? "";
// Container(
// width: Constant.getActualXPhone(context: context, x: 100),
// height: Constant.getActualYPhone(context: context, y: 200),
// decoration: BoxDecoration(
// image: DecorationImage(
// fit: BoxFit.cover,
// image: AssetImage(
// 'images/presensi_finger1.png'), // Ganti dengan path gambar Anda
// ),
// ),
// ),
showConfirmationDialog(
context,
T_TransactionM_StaffID,
T_TransactionM_CompanyID,
T_TransactionCurrentLatitude,
T_TransactionCurrentLongitude,
T_TransactionCurrentDistance,
T_TransactionSelfiePhoto,
token,
"Clock Out");
},
backgroundColor: Color(0xFFFFFFFF),
shape: CircleBorder(),
child: Container(
width: Constant.getActualXPhone(
context: context, x: 130),
height: Constant.getActualYPhone(
context: context, y: 130),
decoration: BoxDecoration(
image: DecorationImage(
// fit: BoxFit.cover,
image: AssetImage(
'images/presensi_finger_clok_out.png'), // Ganti dengan path gambar Anda
),
),
),
),
),
),
]
],
],
Spacer(),
// Expanded(
// child: SizedBox(),
// ),
// clock in & clock out
Padding(
padding: EdgeInsets.only(
@@ -510,19 +663,44 @@ class PresensiScreen extends HookConsumerWidget {
height: Constant.getActualYPhone(
context: context, y: 8),
),
Text(
'--:--',
style: Constant.titlePresensiH2_700(
context: context)
.copyWith(
color: Constant.textTrueBlack,
),
(isLoadingAddressUserLocation.value)
? Center(
child: CircularProgressIndicator(),
)
: (varCurrentCheckJamProvider
?.isAbsenClockIn ==
"TRUE" &&
varCurrentCheckJamProvider
?.jamClockIn !=
"")
? Text(
// '--:--',
varCurrentCheckJamProvider
?.jamClockIn ??
"NULL",
style: Constant.titlePresensiH2_700(
context: context)
.copyWith(
color: Constant.textTrueBlack,
),
)
: Text(
'--:--',
style: Constant.titlePresensiH2_700(
context: context)
.copyWith(
color: Constant.textTrueBlack,
),
),
SizedBox(
height: Constant.getActualYPhone(
context: context, y: 4),
),
Text(
'Clock In',
style: Constant.titleH2_700(context: context)
.copyWith(
color: Constant.textTrueBlack,
color: Constant.textLightGrey,
),
),
],
@@ -541,19 +719,44 @@ class PresensiScreen extends HookConsumerWidget {
height: Constant.getActualYPhone(
context: context, y: 8),
),
Text(
'--:--',
style: Constant.titlePresensiH2_700(
context: context)
.copyWith(
color: Constant.textTrueBlack,
),
(isLoadingAddressUserLocation.value)
? Center(
child: CircularProgressIndicator(),
)
: (varCurrentCheckJamProvider
?.isAbsenClockOut ==
"TRUE" &&
varCurrentCheckJamProvider
?.jamClockOut !=
"")
? Text(
// '--:--',
varCurrentCheckJamProvider
?.jamClockOut ??
"NULL",
style: Constant.titlePresensiH2_700(
context: context)
.copyWith(
color: Constant.textTrueBlack,
),
)
: Text(
'--:--',
style: Constant.titlePresensiH2_700(
context: context)
.copyWith(
color: Constant.textTrueBlack,
),
),
SizedBox(
height: Constant.getActualYPhone(
context: context, y: 4),
),
Text(
'Clock Out',
style: Constant.titleH2_700(context: context)
.copyWith(
color: Constant.textTrueBlack,
color: Constant.textLightGrey,
),
),
],
@@ -567,81 +770,6 @@ class PresensiScreen extends HookConsumerWidget {
),
),
),
// bottomNavigationBar: Container(
// width: Constant.getActualXPhone(context: context, x: 390),
// height: Constant.getActualYPhone(context: context, y: 84),
// decoration: BoxDecoration(
// color: Color(0xFFFFFFFF),
// boxShadow: [
// BoxShadow(
// offset: Offset(0, -1),
// blurRadius: 8,
// spreadRadius: -8,
// color: Color.fromRGBO(0, 0, 0, 0.10),
// ),
// ],
// ),
// child: Row(
// children: <Widget>[
// Expanded(
// child: Container(
// child: Column(
// children: [
// Image.asset(
// 'images/clockin_presensi.png', // Path gambar untuk "Clock In"
// width: Constant.getActualXPhone(context: context, x: 22),
// height: Constant.getActualYPhone(context: context, y: 22),
// ),
// SizedBox(
// height: Constant.getActualYPhone(context: context, y: 8),
// ),
// Text(
// '--:--',
// style: Constant.titlePresensiH2_700(context: context)
// .copyWith(
// color: Constant.textTrueBlack,
// ),
// ),
// Text(
// 'Clock In',
// style: Constant.titleH2_700(context: context).copyWith(
// color: Constant.textTrueBlack,
// ),
// ),
// ],
// ),
// )),
// Expanded(
// child: Container(
// child: Column(
// children: [
// Image.asset(
// 'images/clockout_presensi.png', // Path gambar untuk "Check In"
// width: Constant.getActualXPhone(context: context, x: 22),
// height: Constant.getActualYPhone(context: context, y: 22),
// ),
// SizedBox(
// height: Constant.getActualYPhone(context: context, y: 8),
// ),
// Text(
// '--:--',
// style: Constant.titlePresensiH2_700(context: context)
// .copyWith(
// color: Constant.textTrueBlack,
// ),
// ),
// Text(
// 'Clock Out',
// style: Constant.titleH2_700(context: context).copyWith(
// color: Constant.textTrueBlack,
// ),
// ),
// ],
// ),
// )),
// ],
// ),
// ),
),
);
}

View File

@@ -0,0 +1,183 @@
import 'dart:async';
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:flutter_hooks/flutter_hooks.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:shared_preferences/shared_preferences.dart';
import '../app/constant.dart';
import '../app/route.dart';
import '../provider/current_menu_provider.dart';
import '../provider/current_user_provider.dart';
import '../screen/login/logout_provider.dart';
class CustomDrawer extends HookConsumerWidget {
// final String userCompany;
const CustomDrawer({
Key? key,
// required this.userCompany,
}) : super(key: key);
@override
Widget build(BuildContext context, WidgetRef ref) {
final selectedUser = ref.read(currentUserProvider);
final isLoading = useState(false);
final errorMessage = useState("");
final successMessage = useState("");
final M_CompanyName = useState("-");
// useEffect(() {
// WidgetsBinding.instance.addPostFrameCallback((timeStamp) async {
// final staffID = ref.read(currentUserProvider)?.model.staffId ?? "0";
// if (staffID == "0") {
// //not login
// Navigator.of(context)
// .pushNamedAndRemoveUntil(loginRoute, (route) => true);
// // Navigator.popAndPushNamed(context, loginRoute);
// return;
// }
// });
// return () {};
// }, []);
ref.listen(logoutProvider, (prev, next) async {
if (next is LogoutStateLoading) {
isLoading.value = true;
} else if (next is LogoutStateError) {
isLoading.value = false;
errorMessage.value = next.message;
Timer(const Duration(seconds: 3), () {
errorMessage.value = "";
});
} else if (next is LogoutStateDone) {
isLoading.value = false;
final shared = await SharedPreferences.getInstance();
final bearerString = shared.get(Constant.bearerName).toString();
// print(bearerString);
if (bearerString.isNotEmpty) {
shared.remove(bearerString);
shared.clear();
// Navigator.popAndPushNamed(context, loginRoute);
Navigator.of(context)
.pushNamedAndRemoveUntil(loginRoute, (route) => false);
}
Timer(const Duration(seconds: 3), () async {
successMessage.value = "";
});
}
});
final currentMenu = ref.read(currentPageProvider);
return Container(
width: Constant.getActualXPhone(context: context, x: 300),
height: Constant.getActualYPhone(context: context, y: 844),
child: Drawer(
elevation: 0,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.all(Radius.circular(0))),
child: Column(
children: [
Expanded(
child: ListView(
children: [
// Container(
// child: Image(
// image:
// AssetImage('images/logo_sismedika_landscape.png')),
// ),
SizedBox(
height: Constant.getActualYPhone(context: context, y: 8),
),
Padding(
padding: EdgeInsets.only(
top: Constant.getActualYPhone(context: context, y: 10),
bottom: Constant.getActualYPhone(context: context, y: 10),
right: Constant.getActualXPhone(context: context, x: 24),
left: Constant.getActualXPhone(context: context, x: 24),
),
child: Container(
width: Constant.getActualXPhone(context: context, x: 300),
),
),
Chip(
backgroundColor: Constant.textLightGrey.withOpacity(0.16),
label: Text(
M_CompanyName.value,
overflow: TextOverflow.ellipsis,
style: TextStyle(
color: Constant.textLightGrey,
),
),
),
ListTile(
leading: Icon(
Icons.home,
color: (currentMenu == 0)
? Constant.textOrange
: Constant.textLightGrey,
),
title: Text(
'Home',
style: TextStyle(
color: (currentMenu == 0)
? Constant.textOrange
: Constant.textLightGrey,
),
),
onTap: () {
// Handle navigation to Home screen
Navigator.pop(context);
ref.read(currentPageProvider.state).update((state) => 0);
Navigator.pushNamed(context, homeRoute);
},
),
ListTile(
leading: Icon(
Icons.logout,
color: Constant.textLightGrey,
),
title: Text(
'Logout',
style: TextStyle(color: Constant.textLightGrey),
),
onTap: () {
// di set ke 0 lagi
ref.read(currentPageProvider.state).update((state) => 0);
// ref.read(logoutProvider.notifier).logout(
// M_UserID: selectedUser?.model.M_UserID ?? "",
// M_UserUsername:
// selectedUser?.model.M_UserUsername ?? "",
// );
},
),
],
),
),
// Versi Aplikasi
Padding(
padding: EdgeInsets.only(
right: Constant.getActualXPhone(context: context, x: 20),
bottom: Constant.getActualYPhone(context: context, y: 10),
),
child: Align(
alignment: Alignment.bottomRight,
child: Text(
'Versi ${Constant.version}',
style: Constant.titleH1_700(context: context)
.copyWith(color: Constant.textLightGrey),
),
),
),
],
),
),
);
}
}

View File

@@ -16,7 +16,7 @@ publish_to: 'none' # Remove this line if you wish to publish to pub.dev
# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
# In Windows, build-name is used as the major, minor, and patch parts
# of the product and file versions while build-number is used as the build suffix.
version: 1.0.0+1
version: 1.0.1
environment:
sdk: '>=3.0.6 <4.0.0'