439 lines
18 KiB
Dart
439 lines
18 KiB
Dart
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,
|
|
// ),
|
|
// ),
|
|
// ],
|
|
// ),
|
|
// )),
|
|
// ],
|
|
// ),
|
|
// ),
|
|
),
|
|
);
|
|
}
|
|
}
|