step 9 : add fungsi permission handler, get current latitude, longitude
This commit is contained in:
BIN
images/clockin_presensi.png
Normal file
BIN
images/clockin_presensi.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 485 B |
BIN
images/clockout_presensi.png
Normal file
BIN
images/clockout_presensi.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 488 B |
BIN
images/finger_presensi.png
Normal file
BIN
images/finger_presensi.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 702 B |
BIN
images/presensi_finger1.png
Normal file
BIN
images/presensi_finger1.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 46 KiB |
BIN
images/presensi_finger2.png
Normal file
BIN
images/presensi_finger2.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 3.7 KiB |
BIN
images/sync_white.png
Normal file
BIN
images/sync_white.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 356 B |
@@ -19,6 +19,8 @@ class Constant {
|
|||||||
static Color textLightGrey = const Color(0xff919EAB);
|
static Color textLightGrey = const Color(0xff919EAB);
|
||||||
static Color textOrange = const Color(0xffF15A29);
|
static Color textOrange = const Color(0xffF15A29);
|
||||||
static Color textDarkGrey = const Color(0xff637381);
|
static Color textDarkGrey = const Color(0xff637381);
|
||||||
|
static Color bgAddressPresensi = const Color.fromRGBO(241, 90, 41, 0.08);
|
||||||
|
static Color textWhite = Color(0xffFDFDFD);
|
||||||
|
|
||||||
// size convertion
|
// size convertion
|
||||||
static double getActualXPhone({
|
static double getActualXPhone({
|
||||||
@@ -57,6 +59,13 @@ class Constant {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static TextStyle titleH2_400_12({required BuildContext context}) {
|
||||||
|
return TextStyle(
|
||||||
|
fontSize: Constant.getActualYPhone(context: context, y: 12),
|
||||||
|
fontWeight: FontWeight.w400,
|
||||||
|
fontFamily: 'Public Sans');
|
||||||
|
}
|
||||||
|
|
||||||
static TextStyle titleH2_600_14({required BuildContext context}) {
|
static TextStyle titleH2_600_14({required BuildContext context}) {
|
||||||
return TextStyle(
|
return TextStyle(
|
||||||
fontSize: Constant.getActualYPhone(context: context, y: 14),
|
fontSize: Constant.getActualYPhone(context: context, y: 14),
|
||||||
@@ -79,6 +88,14 @@ class Constant {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static TextStyle titlePresensiH2_700({required BuildContext context}) {
|
||||||
|
return TextStyle(
|
||||||
|
fontFamily: 'Quicksand',
|
||||||
|
fontSize: Constant.getActualYPhone(context: context, y: 24),
|
||||||
|
fontWeight: FontWeight.w700,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
static TextStyle time_700({required BuildContext context}) {
|
static TextStyle time_700({required BuildContext context}) {
|
||||||
return TextStyle(
|
return TextStyle(
|
||||||
fontSize: Constant.getActualYPhone(context: context, y: 28),
|
fontSize: Constant.getActualYPhone(context: context, y: 28),
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import 'package:absensi_sas_flutter/screen/home/home_screen_v1.dart';
|
import 'package:absensi_sas_flutter/screen/home/home_screen_v1.dart';
|
||||||
|
import 'package:absensi_sas_flutter/screen/presensi/presensi_screen.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import '../screen/home/home_screen.dart';
|
import '../screen/home/home_screen.dart';
|
||||||
import '../test_flutter_map.dart';
|
import '../test_flutter_map.dart';
|
||||||
@@ -9,6 +10,7 @@ const loginRoute = "/loginRoute";
|
|||||||
const splashRoute = "/splashRoute";
|
const splashRoute = "/splashRoute";
|
||||||
const testFlutterMapRoute = "/testFlutterMapRoute";
|
const testFlutterMapRoute = "/testFlutterMapRoute";
|
||||||
const homeRoute = "/homeRoute";
|
const homeRoute = "/homeRoute";
|
||||||
|
const presensiRoute = "/presensiRoute";
|
||||||
|
|
||||||
class AppRoute {
|
class AppRoute {
|
||||||
static Route<dynamic> generateRoute(RouteSettings settings) {
|
static Route<dynamic> generateRoute(RouteSettings settings) {
|
||||||
@@ -35,6 +37,17 @@ class AppRoute {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// presensi route
|
||||||
|
if (settings.name == presensiRoute) {
|
||||||
|
return MaterialPageRoute(builder: (context) {
|
||||||
|
return MediaQuery(
|
||||||
|
data: MediaQuery.of(context)
|
||||||
|
.copyWith(textScaleFactor: 1.0, padding: EdgeInsets.all(0)),
|
||||||
|
child: PresensiScreen(),
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
// splash screen
|
// splash screen
|
||||||
if (settings.name == splashRoute) {
|
if (settings.name == splashRoute) {
|
||||||
return MaterialPageRoute(builder: (context) {
|
return MaterialPageRoute(builder: (context) {
|
||||||
|
|||||||
@@ -46,7 +46,7 @@ class MyApp extends StatelessWidget {
|
|||||||
),
|
),
|
||||||
// home: TestMap(),
|
// home: TestMap(),
|
||||||
// initialRoute: loginRoute,
|
// initialRoute: loginRoute,
|
||||||
initialRoute: homeRoute,
|
initialRoute: presensiRoute,
|
||||||
// initialRoute: testFlutterMapRoute,
|
// initialRoute: testFlutterMapRoute,
|
||||||
onGenerateRoute: AppRoute.generateRoute,
|
onGenerateRoute: AppRoute.generateRoute,
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -163,27 +163,27 @@ class LoginScreen extends HookConsumerWidget {
|
|||||||
SizedBox(
|
SizedBox(
|
||||||
height: Constant.getActualYPhone(context: context, y: 100),
|
height: Constant.getActualYPhone(context: context, y: 100),
|
||||||
),
|
),
|
||||||
// (currentUserGoogle != null)
|
(currentUserGoogle != null)
|
||||||
// ? Container(
|
? Container(
|
||||||
// child: ListTile(
|
child: ListTile(
|
||||||
// leading: GoogleUserCircleAvatar(
|
leading: GoogleUserCircleAvatar(
|
||||||
// identity: currentUserGoogle,
|
identity: currentUserGoogle,
|
||||||
// ),
|
),
|
||||||
// title: Text(
|
title: Text(
|
||||||
// currentUserGoogle.displayName ?? "",
|
currentUserGoogle.displayName ?? "",
|
||||||
// ),
|
),
|
||||||
// subtitle: Text(
|
subtitle: Text(
|
||||||
// currentUserGoogle.email,
|
currentUserGoogle.email,
|
||||||
// ),
|
),
|
||||||
// trailing: IconButton(
|
trailing: IconButton(
|
||||||
// icon: Icon(Icons.logout_outlined),
|
icon: Icon(Icons.logout_outlined),
|
||||||
// onPressed: () async {
|
onPressed: () async {
|
||||||
// await googleSignIn.disconnect();
|
await googleSignIn.disconnect();
|
||||||
// },
|
},
|
||||||
// ),
|
),
|
||||||
// ),
|
),
|
||||||
// )
|
)
|
||||||
// :
|
:
|
||||||
// Logo Landscape
|
// Logo Landscape
|
||||||
Padding(
|
Padding(
|
||||||
padding: EdgeInsets.only(
|
padding: EdgeInsets.only(
|
||||||
|
|||||||
438
lib/screen/presensi/presensi_screen.dart
Normal file
438
lib/screen/presensi/presensi_screen.dart
Normal file
@@ -0,0 +1,438 @@
|
|||||||
|
import 'package:absensi_sas_flutter/widget/real_date.dart';
|
||||||
|
import 'package:absensi_sas_flutter/widget/sankbar_widget.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_hooks/flutter_hooks.dart';
|
||||||
|
import 'package:geocoding/geocoding.dart';
|
||||||
|
import 'package:geolocator/geolocator.dart';
|
||||||
|
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||||
|
import 'package:permission_handler/permission_handler.dart';
|
||||||
|
|
||||||
|
|
||||||
|
import '../../app/constant.dart';
|
||||||
|
import '../../widget/real_time.dart';
|
||||||
|
|
||||||
|
class PresensiScreen extends HookConsumerWidget {
|
||||||
|
const PresensiScreen({super.key});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context, WidgetRef ref) {
|
||||||
|
final currentAddressUserLocation = useState<String>("");
|
||||||
|
final isLoadingAddressUserLocation = useState<bool>(false);
|
||||||
|
|
||||||
|
Future<void> getAddressFromLocation() async {
|
||||||
|
try {
|
||||||
|
isLoadingAddressUserLocation.value = true;
|
||||||
|
// Mendapatkan posisi pengguna
|
||||||
|
LocationPermission permission = await Geolocator.requestPermission();
|
||||||
|
|
||||||
|
if (permission == LocationPermission.denied) {
|
||||||
|
isLoadingAddressUserLocation.value = false;
|
||||||
|
SanckbarWidget(context, 'Izin lokasi ditolak', snackbarType.error);
|
||||||
|
// Handle jika pengguna menolak izin lokasi
|
||||||
|
print("Izin lokasi ditolak");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Position position = await Geolocator.getCurrentPosition(
|
||||||
|
desiredAccuracy: LocationAccuracy.high);
|
||||||
|
|
||||||
|
// Mendapatkan alamat dari posisi
|
||||||
|
List<Placemark> placemarks = await placemarkFromCoordinates(
|
||||||
|
position.latitude, position.longitude);
|
||||||
|
|
||||||
|
if (placemarks.isNotEmpty) {
|
||||||
|
isLoadingAddressUserLocation.value = false;
|
||||||
|
Placemark placemark = placemarks.first;
|
||||||
|
// String address =
|
||||||
|
// "${placemark.thoroughfare}, ${placemark.locality}, ${placemark.administrativeArea}, ${placemark.country},";
|
||||||
|
|
||||||
|
String address =
|
||||||
|
"${placemark.street}, ${placemark.subLocality}, ${placemark.subAdministrativeArea}, ${placemark.postalCode}";
|
||||||
|
print("Alamat: $address");
|
||||||
|
|
||||||
|
if (address != "") {
|
||||||
|
currentAddressUserLocation.value = address;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
isLoadingAddressUserLocation.value = false;
|
||||||
|
SanckbarWidget(
|
||||||
|
context, 'Tidak dapat menemukan alamat.', snackbarType.error);
|
||||||
|
print("Tidak dapat menemukan alamat.");
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
print("Error: $e");
|
||||||
|
isLoadingAddressUserLocation.value = false;
|
||||||
|
SanckbarWidget(context, 'Error : $e', snackbarType.error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> _requestLocationPermission() async {
|
||||||
|
var status = await Permission.location.request();
|
||||||
|
isLoadingAddressUserLocation.value = true;
|
||||||
|
if (status.isGranted) {
|
||||||
|
// Izin diberikan, lanjutkan dengan mendapatkan lokasi
|
||||||
|
getAddressFromLocation();
|
||||||
|
} else {
|
||||||
|
isLoadingAddressUserLocation.value = false;
|
||||||
|
// Izin ditolak, berikan pemberitahuan atau instruksi
|
||||||
|
// print('Izin lokasi ditolak');
|
||||||
|
SanckbarWidget(context, 'Izin Ditolak', snackbarType.error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
useEffect(() {
|
||||||
|
WidgetsBinding.instance.addPostFrameCallback((timeStamp) async {
|
||||||
|
getAddressFromLocation();
|
||||||
|
});
|
||||||
|
return () {};
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
return Padding(
|
||||||
|
padding: EdgeInsets.only(
|
||||||
|
top: Constant.getActualYPhone(context: context, y: 30),
|
||||||
|
),
|
||||||
|
child: Scaffold(
|
||||||
|
appBar: AppBar(
|
||||||
|
title: Text(
|
||||||
|
// 'Home Screen',
|
||||||
|
'Presensi',
|
||||||
|
overflow: TextOverflow.ellipsis,
|
||||||
|
style: TextStyle(
|
||||||
|
color: Constant.textBlack,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
backgroundColor: Constant.textWhite,
|
||||||
|
iconTheme: IconThemeData(
|
||||||
|
color: Constant.textBlack,
|
||||||
|
),
|
||||||
|
// elevation: 1.0,
|
||||||
|
elevation: 0.5,
|
||||||
|
),
|
||||||
|
body: SafeArea(
|
||||||
|
child: Padding(
|
||||||
|
padding: EdgeInsets.only(
|
||||||
|
top: Constant.getActualYPhone(context: context, y: 58),
|
||||||
|
left: Constant.getActualXPhone(context: context, x: 33),
|
||||||
|
right: Constant.getActualXPhone(context: context, x: 27),
|
||||||
|
),
|
||||||
|
child: Container(
|
||||||
|
width: Constant.getActualXPhone(context: context, x: 390),
|
||||||
|
// height: Constant.getActualYPhone(context: context, y: 844),
|
||||||
|
height: MediaQuery.of(context).size.height,
|
||||||
|
child: Column(
|
||||||
|
children: [
|
||||||
|
// Spacer(),
|
||||||
|
// tanggal sekarang
|
||||||
|
RealTimeFormattedDate(),
|
||||||
|
SizedBox(
|
||||||
|
height: Constant.getActualYPhone(context: context, y: 8),
|
||||||
|
),
|
||||||
|
// jam sekarang
|
||||||
|
RealTimeClock(),
|
||||||
|
SizedBox(
|
||||||
|
height: Constant.getActualYPhone(context: context, y: 24),
|
||||||
|
),
|
||||||
|
|
||||||
|
// address dan refresh
|
||||||
|
Container(
|
||||||
|
width: Constant.getActualXPhone(context: context, x: 350),
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
borderRadius: BorderRadius.circular(16),
|
||||||
|
color: Constant.bgAddressPresensi,
|
||||||
|
),
|
||||||
|
child: Padding(
|
||||||
|
padding: EdgeInsets.only(
|
||||||
|
left: Constant.getActualXPhone(context: context, x: 12),
|
||||||
|
right:
|
||||||
|
Constant.getActualXPhone(context: context, x: 12),
|
||||||
|
top: Constant.getActualYPhone(context: context, y: 12),
|
||||||
|
bottom:
|
||||||
|
Constant.getActualYPhone(context: context, y: 12),
|
||||||
|
),
|
||||||
|
child: Row(
|
||||||
|
children: [
|
||||||
|
// Bagian kiri
|
||||||
|
Padding(
|
||||||
|
padding: EdgeInsets.only(left: 12, right: 8),
|
||||||
|
child: Column(
|
||||||
|
children: [
|
||||||
|
Icon(
|
||||||
|
Icons.location_on_outlined,
|
||||||
|
color: Constant.textDarkGrey,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
|
||||||
|
// Bagian tengah
|
||||||
|
Expanded(
|
||||||
|
child: Padding(
|
||||||
|
padding: EdgeInsets.symmetric(horizontal: 8),
|
||||||
|
child: Column(
|
||||||
|
children: [
|
||||||
|
(isLoadingAddressUserLocation.value)
|
||||||
|
? Center(
|
||||||
|
child: CircularProgressIndicator(),
|
||||||
|
)
|
||||||
|
: Text(
|
||||||
|
// 'Perumahan Grand House of Klodran No. 5, Klodran, Kec. Colomadu, Kabupaten Karanganyar, Jawa Tengah 57172',
|
||||||
|
currentAddressUserLocation.value,
|
||||||
|
overflow: TextOverflow.ellipsis,
|
||||||
|
maxLines: 10,
|
||||||
|
style: Constant.titleH2_400_12(
|
||||||
|
context: context)
|
||||||
|
.copyWith(
|
||||||
|
color: Constant.textDarkGrey,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
|
||||||
|
// Bagian kanan
|
||||||
|
Padding(
|
||||||
|
padding: EdgeInsets.only(right: 12),
|
||||||
|
child: Column(
|
||||||
|
children: [
|
||||||
|
InkWell(
|
||||||
|
onTap: () async {
|
||||||
|
getAddressFromLocation();
|
||||||
|
},
|
||||||
|
child: Container(
|
||||||
|
width: Constant.getActualXPhone(
|
||||||
|
context: context, x: 36),
|
||||||
|
height: Constant.getActualYPhone(
|
||||||
|
context: context, y: 36),
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
borderRadius: BorderRadius.circular(12),
|
||||||
|
color: Constant.textOrange,
|
||||||
|
),
|
||||||
|
child: Image.asset(
|
||||||
|
'images/sync_white.png', // Path gambar untuk "Refresh"
|
||||||
|
width: Constant.getActualXPhone(
|
||||||
|
context: context, x: 20),
|
||||||
|
height: Constant.getActualYPhone(
|
||||||
|
context: context, y: 20),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
|
||||||
|
SizedBox(
|
||||||
|
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: () {},
|
||||||
|
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
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
|
||||||
|
// 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
|
||||||
|
// ),
|
||||||
|
// ),
|
||||||
|
// ),
|
||||||
|
|
||||||
|
Spacer(),
|
||||||
|
|
||||||
|
// Expanded(
|
||||||
|
// child: SizedBox(),
|
||||||
|
// ),
|
||||||
|
|
||||||
|
// clock in & clock out
|
||||||
|
Padding(
|
||||||
|
padding: EdgeInsets.only(
|
||||||
|
left: Constant.getActualXPhone(context: context, x: 70),
|
||||||
|
right: Constant.getActualXPhone(context: context, x: 70),
|
||||||
|
// top:
|
||||||
|
// Constant.getActualYPhone(context: context, y: 12),
|
||||||
|
bottom: Constant.getActualYPhone(context: context, y: 55),
|
||||||
|
),
|
||||||
|
child: Container(
|
||||||
|
width: Constant.getActualXPhone(context: context, x: 390),
|
||||||
|
// color: Colors.amber,
|
||||||
|
child: Row(
|
||||||
|
children: [
|
||||||
|
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,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
Spacer(),
|
||||||
|
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,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
// 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,
|
||||||
|
// ),
|
||||||
|
// ),
|
||||||
|
// ],
|
||||||
|
// ),
|
||||||
|
// )),
|
||||||
|
// ],
|
||||||
|
// ),
|
||||||
|
// ),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
40
pubspec.lock
40
pubspec.lock
@@ -576,6 +576,46 @@ packages:
|
|||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.2.1"
|
version: "2.2.1"
|
||||||
|
permission_handler:
|
||||||
|
dependency: "direct main"
|
||||||
|
description:
|
||||||
|
name: permission_handler
|
||||||
|
sha256: "284a66179cabdf942f838543e10413246f06424d960c92ba95c84439154fcac8"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "11.0.1"
|
||||||
|
permission_handler_android:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: permission_handler_android
|
||||||
|
sha256: f9fddd3b46109bd69ff3f9efa5006d2d309b7aec0f3c1c5637a60a2d5659e76e
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "11.1.0"
|
||||||
|
permission_handler_apple:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: permission_handler_apple
|
||||||
|
sha256: "99e220bce3f8877c78e4ace901082fb29fa1b4ebde529ad0932d8d664b34f3f5"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "9.1.4"
|
||||||
|
permission_handler_platform_interface:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: permission_handler_platform_interface
|
||||||
|
sha256: "6760eb5ef34589224771010805bea6054ad28453906936f843a8cc4d3a55c4a4"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "3.12.0"
|
||||||
|
permission_handler_windows:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: permission_handler_windows
|
||||||
|
sha256: cc074aace208760f1eee6aa4fae766b45d947df85bc831cde77009cdb4720098
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "0.1.3"
|
||||||
pigeon:
|
pigeon:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
|||||||
@@ -51,6 +51,7 @@ dependencies:
|
|||||||
intl: ^0.17.0
|
intl: ^0.17.0
|
||||||
graphql: ^5.1.3
|
graphql: ^5.1.3
|
||||||
top_snackbar_flutter: ^3.1.0
|
top_snackbar_flutter: ^3.1.0
|
||||||
|
permission_handler: ^11.0.0
|
||||||
|
|
||||||
dev_dependencies:
|
dev_dependencies:
|
||||||
flutter_test:
|
flutter_test:
|
||||||
|
|||||||
@@ -7,8 +7,11 @@
|
|||||||
#include "generated_plugin_registrant.h"
|
#include "generated_plugin_registrant.h"
|
||||||
|
|
||||||
#include <geolocator_windows/geolocator_windows.h>
|
#include <geolocator_windows/geolocator_windows.h>
|
||||||
|
#include <permission_handler_windows/permission_handler_windows_plugin.h>
|
||||||
|
|
||||||
void RegisterPlugins(flutter::PluginRegistry* registry) {
|
void RegisterPlugins(flutter::PluginRegistry* registry) {
|
||||||
GeolocatorWindowsRegisterWithRegistrar(
|
GeolocatorWindowsRegisterWithRegistrar(
|
||||||
registry->GetRegistrarForPlugin("GeolocatorWindows"));
|
registry->GetRegistrarForPlugin("GeolocatorWindows"));
|
||||||
|
PermissionHandlerWindowsPluginRegisterWithRegistrar(
|
||||||
|
registry->GetRegistrarForPlugin("PermissionHandlerWindowsPlugin"));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
|
|
||||||
list(APPEND FLUTTER_PLUGIN_LIST
|
list(APPEND FLUTTER_PLUGIN_LIST
|
||||||
geolocator_windows
|
geolocator_windows
|
||||||
|
permission_handler_windows
|
||||||
)
|
)
|
||||||
|
|
||||||
list(APPEND FLUTTER_FFI_PLUGIN_LIST
|
list(APPEND FLUTTER_FFI_PLUGIN_LIST
|
||||||
|
|||||||
Reference in New Issue
Block a user