From 79c072997936d8971dbf4cefd5447c193fdedd79 Mon Sep 17 00:00:00 2001 From: sindhu Date: Sat, 27 Jan 2024 11:12:03 +0700 Subject: [PATCH] step 16 : add drawer di home screen, sukses msg custom dialog untuk presensi selfie --- images/presensi_selfie_sukses.png | Bin 0 -> 2365 bytes lib/app/constant.dart | 30 + lib/screen/home/home_screen.dart | 1328 +++++++++-------- lib/screen/home/home_screen_v1.dart | 953 ++++++++++-- lib/screen/presensi/presensi_screen.dart | 6 +- .../presensi/presensi_selfie_screen.dart | 48 +- .../custom_dialog_presensi_selfie_sukses.dart | 111 ++ lib/widget/custom_drawer.dart | 94 +- 8 files changed, 1757 insertions(+), 813 deletions(-) create mode 100644 images/presensi_selfie_sukses.png create mode 100644 lib/widget/custom_dialog_presensi_selfie_sukses.dart diff --git a/images/presensi_selfie_sukses.png b/images/presensi_selfie_sukses.png new file mode 100644 index 0000000000000000000000000000000000000000..9d2237b0d2ff133b2ebb79aac767e9f97bef0b95 GIT binary patch literal 2365 zcmV-D3BvY?P)T_oN{!oqd#j47gkD;eN-zL?0mTjgAp){%I}YqWI-Gko|sZl)AXYf;-ySttwO5v?rrz-*z2FK!XS(g zghZH@Ld?={a~$yt(2KHwSaCh??AU8pR**573Bsx1(RJ7D}5}T&4b$gtbV-3|obC z2JP(bcsSZ_z_j>WQ=|d!Cw! z!-Wkjh%d%Pq+em1Ml7NX6hm~8NAUty45p;x%I|(Mke7&TAzBQ9i@PYLjf<*xr#2I{ zX&FfnD@IQui_*6sI%cq&vSRe2N-^cWeq%~sF{BZ|tr%e_^0ne?*3X;z62xXxeWS|( zJ?a^f(1Kk5!{q;A#fZX`Gdg-E?7^X8h;9-Bi?Bq-Q+Q%*d9CL)>?w#1;;|7b$oF(v z+_kl0#6nSD%N}$Uq%wD8em8e*(}u5QuMTlXmt}iYiBa`#ZA^5UAJ)-AB#-o2F_NIz zE$eD)A-;87g(Wd4z)!Rb@NF%`w+>5!bPDi0EW}zzdQb!MzSaih4hyl?ks^h{eCv;z zEW}zz>g>q4nk_`ynj>Y37#V4*OA6bcNQlr)FcaAKz^wj~hwjnOy=!0M&im)}S6(2C z;2Hl5!Sja8(zgWE3qj+Nci)2pe|r|r_>s1+voJURJrDKum&gPDEj7eYH*b(dyoK6F?`k3RF=R2Lbc`4|h+M$;#`t{ivIKsC9I*ele`&a=+wZ)D z&2#^4e*KZh>6pj$F+&fX#MYb7!E|K(MkO6fw1xOnS4zkMg`fUPe|OhD*dYeP0@Ua= zX6WHZkrPV6P;cF3?Q?Q5<4_(x0x^1*e!TV0xsJyLL0yd8MXqfUxxjZ@S`bHxv4kz2k8~EYXbo0C_+PbxeQff2dEtSLfs!gqYU1 zgEOosc$EIK)p+Yyu=VyiW7A=(+Q)>c^+%B21{qacm|UX>h*>Jmg^})R_|H$rE(XJ& zd4N9KL|mmNND%YVUAB(GiffOcx zhNLMRP5vDHLa}^YDid8+3dI~3ndYI2WFf++NpM_U#}UlA>DUcEhk?yU7R0PsiE@1K zzg$jjzkTu%e0%!WU4@b3_rfrW#>Eh4KtWi5n@>}nam_CVyVM&d_PLA`WYB=V`SO3X z7!0@Jy9peJHO7r`f`~&uMpU-mc&^duEl^s^VWaE-Z)t z_>Z3N;d2=l*sC1WjS-|*D#|h81_f#k*4ta`{CM-_`d}4b;C^~wNwjAMpepq$o`&F* zx(lLi-Dm{sTNJqY`}QEt44?daUl&;(HYd|k3S}ugRfZurJuHM>3Mg2 zeGmKweVwypRvam~0_&zkb{XR01c90ZxaV676DEkaJ*Po|o!1za@E0650q1bIx*(WY z5)d|sw>_s>wMdz#0hM6@+%nldX5I@Hh2K+K`%sG!H8|_@lAuNmSShty!2bO!xV?p} ziQ+nj9(q)N4SeoHKZ0w5Ae)=3a%^dpv#c^QCd>3wnlM;Jp@V0^>v--d^&Tvl;wfC_ z?|yFX9NrOC2h|an^kLPKYVF?GPxJu3R^Ok5^9!cJr%`VX29l?LV$!>YX_*MLj&AhrnV$d~; zvZvu-+vWimt);Z$i}C8G>1~@AU`1(VFfsHeU_k7)7CwFe&vffmM#mISXA))XT~^}| zgNb#6`^wzpA}M?ddk8N2u(7ewX@i!2iB%A$a^l|8QaERJe_Ww>!R?Tc6?o`RMFMbK z;r%goYnPb2w%jO;!$q}{h#&zZ%sd5rUQfP+T|qKd(R2nRj9wsEhy^L|7;;S9v7!@+ z3lfl5VUl!D?MO|KfP4s}UDH|AYD-Z!s*ikTWQ4!g`LszfMo~SXpf2Fn=3>&WsS}wA zvK_t^f~;m<)^}(qAw@`pGP$G+d>2`8OF)(wA;@;PKL*d65>gzeUoQ4t8(07VzClK; zQitI}TCpK4#tG7j-W+~-c#2%xG0Jo%=ohXpYb#I^dcDZj0#sC0eT5@^yEpyyuao6n jrT4B=mb8+UD+[ - Expanded( - child: Container( - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Image( - image: AssetImage('images/home_orange.png'), - ), - Text( - 'Beranda', - style: Constant.subtitle_500_12(context: context).copyWith( - color: Constant.textOrange, - ), - ) - ], - ), - )), - Expanded( - child: Container( - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Image( - image: AssetImage('images/person_grey.png'), - ), - Text( - 'Profile', - style: Constant.subtitle_500_12(context: context).copyWith( - color: Constant.textLightGrey, - ), - ) - ], - ), - )), - ], - ), - ), - body: SafeArea( - child: SingleChildScrollView( + drawer: CustomDrawer(), + floatingActionButtonLocation: FloatingActionButtonLocation.centerDocked, + floatingActionButton: Padding( + padding: EdgeInsets.only( + bottom: Constant.getActualYPhone(context: context, y: 30), + ), child: Container( - width: Constant.getActualXPhone(context: context, x: 390), - // height: Constant.getActualYPhone(context: context, y: 844), - child: RefreshIndicator( - onRefresh: () async {}, - child: Column( - children: [ - 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( - child: (googleSignIn.currentUser == null) - ? Center( - child: CircularProgressIndicator(), - ) - : ListTile( - // leading: Container( - // width: Constant.getActualXPhone( - // context: context, x: 36), - // height: Constant.getActualYPhone( - // context: context, y: 36), - // child: Image( - // image: AssetImage('images/avatar_c.png'), - // ), - // ), - leading: GoogleUserCircleAvatar( - identity: googleSignIn.currentUser!, - ), - title: Text( - // "Stephen Kusumo", - // selectedUser?.model.name ?? "", - // currentUserGoogle.displayName ?? "", - googleSignIn.currentUser?.displayName ?? "", - overflow: TextOverflow.ellipsis, - style: Constant.titleH1_700(context: context) - ..copyWith( - color: Constant.textBlack, - ), - ), - subtitle: Text( - // "Step@example.com", - // currentUserGoogle?.email ?? "", - // selectedUser?.model.email ?? "", - googleSignIn.currentUser?.email ?? "", - style: - Constant.subtitle_500_12(context: context) - .copyWith( - color: Constant.textLightGrey, - ), - ), - trailing: Container( - width: Constant.getActualXPhone( - context: context, x: 36), - height: Constant.getActualYPhone( - context: context, y: 36), - decoration: BoxDecoration( - borderRadius: BorderRadius.circular(12.0), - color: Colors.white, - shape: BoxShape.rectangle, - boxShadow: [ - BoxShadow( - offset: Offset(0, 12), - blurRadius: 24, - color: - Color.fromRGBO(145, 158, 171, 0.12), - ), - ], - ), - child: IconButton( - onPressed: () {}, - icon: Container( - width: Constant.getActualXPhone( - context: context, x: 20), - height: Constant.getActualYPhone( - context: context, y: 20), - child: Image( - image: - AssetImage('images/alert_badge.png'), - ), - ), - ), - ), - ), - ), - ), - - SizedBox( - height: Constant.getActualYPhone(context: context, y: 44), - ), - - //Card Time - Padding( - padding: EdgeInsets.only( - left: Constant.getActualXPhone(context: context, x: 33), - right: Constant.getActualXPhone(context: context, x: 27), - ), - child: Container( - width: Constant.getActualXPhone(context: context, x: 330), - height: - Constant.getActualYPhone(context: context, y: 200), - decoration: BoxDecoration( - borderRadius: BorderRadius.circular(40), - image: DecorationImage( - image: AssetImage( - 'images/card_bg_1.png'), // Ganti dengan path gambar Anda - fit: BoxFit.fill, // Sesuaikan cara gambar ditampilkan + width: Constant.getActualXPhone(context: context, x: 100), + height: Constant.getActualYPhone(context: context, y: 100), + child: FittedBox( + child: (isLoadingProsesCheckDistance.value) + ? SizedBox( + width: Constant.getActualXPhone(context: context, x: 50), + height: Constant.getActualYPhone(context: context, y: 50), + child: Center( + child: CircularProgressIndicator( + color: Constant.textOrange, ), ), - child: Padding( - padding: EdgeInsets.only( - top: - Constant.getActualYPhone(context: context, y: 16), - left: - Constant.getActualXPhone(context: context, x: 25), - right: - Constant.getActualXPhone(context: context, x: 25), - ), - child: Container( - width: Constant.getActualXPhone( - context: context, x: 280), - height: Constant.getActualYPhone( - context: context, y: 150), - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - // Date - RealTimeFormattedDate(), - SizedBox( - height: Constant.getActualYPhone( - context: context, y: 8), - ), - - //Time - RealTimeClock(), // Menampilkan waktu real-time menggunakan RealTimeClock - SizedBox( - height: Constant.getActualYPhone( - context: context, y: 20), - ), - Row( - mainAxisAlignment: MainAxisAlignment - .center, // Menengahkan secara horizontal - children: [ - Spacer(), // Spasi di sebelah kiri "Check In" - Column( - children: [ - Image.asset( - 'images/finger_tap.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), - ), - (varCurrentCheckJamProvider - ?.isAbsenClockIn == - "TRUE") - ? Text( - // '--:--', - varCurrentCheckJamProvider - ?.jamClockIn ?? - "NULL", - ) - : Text( - '--:--', - style: TextStyle( - // Atur gaya teks '--:--' sesuai kebutuhan - ), - ), - Text( - 'Clock In', - style: Constant.titleH2_700( - context: context) - .copyWith( - color: Constant.textLightGrey, - ), - ), - ], - ), - - SizedBox( - width: Constant.getActualXPhone( - context: context, x: 96), - ), // Jarak antara "Check In" dan "Check Out" - Column( - children: [ - Image.asset( - 'images/finger_tap.png', // Path gambar untuk "Check Out" - width: Constant.getActualXPhone( - context: context, x: 22), - height: Constant.getActualYPhone( - context: context, y: 22), - ), - SizedBox( - height: Constant.getActualYPhone( - context: context, y: 8), - ), - (varCurrentCheckJamProvider - ?.isAbsenClockOut == - "TRUE") - ? Text( - // '--:--', - varCurrentCheckJamProvider - ?.jamClockOut ?? - "NULL", - ) - : Text( - '--:--', - style: TextStyle( - // Atur gaya teks '--:--' sesuai kebutuhan - ), - ), - Text( - 'Clock Out', - style: Constant.titleH2_700( - context: context) - .copyWith( - color: Constant.textLightGrey, - ), - ), - ], - ), - Spacer(), // Spasi di sebelah kanan "Check Out" - ], - ), - - SizedBox( - height: Constant.getActualYPhone( - context: context, y: 16), - ), - ], + ) + : FloatingActionButton( + onPressed: () async { + await requestLocationPermission(); + }, + backgroundColor: Color(0xFFFFFFFF), + shape: CircleBorder(), + child: Container( + width: + Constant.getActualXPhone(context: context, x: 50), + height: + Constant.getActualYPhone(context: context, y: 50), + decoration: BoxDecoration( + image: DecorationImage( + image: AssetImage( + 'images/finger_tap_orange_botnav.png'), // Ganti dengan path gambar Anda ), ), ), ), - ), + ), + ), + ), - SizedBox( - height: Constant.getActualYPhone(context: context, y: 56), - ), + // // 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: [ + // Expanded( + // child: Container( + // child: Column( + // mainAxisAlignment: MainAxisAlignment.center, + // children: [ + // Image( + // image: AssetImage('images/home_orange.png'), + // ), + // Text( + // 'Beranda', + // style: Constant.subtitle_500_12(context: context).copyWith( + // color: Constant.textOrange, + // ), + // ) + // ], + // ), + // )), + // Expanded( + // child: Container( + // child: Column( + // mainAxisAlignment: MainAxisAlignment.center, + // children: [ + // Image( + // image: AssetImage('images/person_grey.png'), + // ), + // Text( + // 'Profile', + // style: Constant.subtitle_500_12(context: context).copyWith( + // color: Constant.textLightGrey, + // ), + // ) + // ], + // ), + // )), + // ], + // ), + // ), + body: SafeArea( + child: RefreshIndicator( + onRefresh: () async { + // print('refresh'); - //Menu Cuti Lembur - Padding( - padding: EdgeInsets.only( - left: Constant.getActualXPhone(context: context, x: 33), - right: Constant.getActualXPhone(context: context, x: 27), + 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; + } + + if (staffID != "0") { + // panggil check jam presensi provider + Map inpVariablesCheckPresensiJam = { + "M_StaffID": selectedUser?.model.staffId ?? "", + "M_CompanyID": selectedUser?.model.companyId ?? "", + "token": selectedUser?.token ?? "", + }; + + ref.read(checkPresensiJamProvider.notifier).checkPresensiJam( + selectedUser?.model.staffId ?? "", + selectedUser?.model.companyId ?? "", + selectedUser?.token ?? "", + inpVariablesCheckPresensiJam, + ); + } + }, + child: SingleChildScrollView( + physics: AlwaysScrollableScrollPhysics(), + child: Container( + width: Constant.getActualXPhone(context: context, x: 390), + // height: Constant.getActualYPhone(context: context, y: 844), + child: Column( + children: [ + SizedBox( + height: Constant.getActualYPhone(context: context, y: 44), ), - child: Container( - width: Constant.getActualXPhone(context: context, x: 330), - child: Row( - children: [ - //Menu Cuti - Container( - width: Constant.getActualXPhone( - context: context, x: 98), - // color: Colors.amber, - decoration: BoxDecoration( - color: Colors.white, - borderRadius: BorderRadius.circular(16), - boxShadow: [ - BoxShadow( - color: Color.fromRGBO(145, 158, 171, 0.20), - ), - ], - ), - 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: 8), - bottom: Constant.getActualYPhone( - context: context, y: 8), - ), - child: InkWell( - onTap: () {}, - child: Column( - children: [ - Container( - child: Image( - width: Constant.getActualXPhone( - context: context, x: 50), - height: Constant.getActualYPhone( - context: context, y: 50), - image: AssetImage('images/person.png'), - ), - ), - SizedBox( - height: Constant.getActualYPhone( - context: context, y: 8), - ), - Text( - 'Cuti', - style: Constant.titleH2_600_14( - context: context) - .copyWith( - color: Constant.textDarkGrey, - ), - ), - ], - ), - ), - ), - ), - SizedBox( - width: Constant.getActualXPhone( - context: context, x: 18), - ), - - //Menu Lembur - Container( - width: Constant.getActualXPhone( - context: context, x: 98), - // color: Colors.amber, - decoration: BoxDecoration( - color: Colors.white, - borderRadius: BorderRadius.circular(16), - boxShadow: [ - BoxShadow( - color: Color.fromRGBO(145, 158, 171, 0.20), - ), - ], - ), - 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: 8), - bottom: Constant.getActualYPhone( - context: context, y: 8), - ), - child: InkWell( - onTap: () {}, - child: Column( - children: [ - Container( - child: Image( - width: Constant.getActualXPhone( - context: context, x: 50), - height: Constant.getActualYPhone( - context: context, y: 50), - image: AssetImage('images/task.png'), - ), - ), - SizedBox( - height: Constant.getActualYPhone( - context: context, y: 8), - ), - Text( - 'Lembur', - style: Constant.titleH2_600_14( - context: context) - .copyWith( - color: Constant.textDarkGrey, - ), - ), - ], - ), - ), - ), - ), - ], - ), - ), - ), - - SizedBox( - height: Constant.getActualYPhone(context: context, y: 56), - ), - - //Menu Rekap Presensi - Padding( - padding: EdgeInsets.only( + //Card Time + Padding( + padding: EdgeInsets.only( + left: Constant.getActualXPhone(context: context, x: 33), right: Constant.getActualXPhone(context: context, x: 27), - left: Constant.getActualXPhone(context: context, x: 33), - bottom: - Constant.getActualYPhone(context: context, y: 40)), - child: Container( - width: Constant.getActualXPhone(context: context, x: 330), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - 'Rekap Presensi Bulan Ini', - style: Constant.titleH1_500_18(context: context) - .copyWith( - color: Constant.textTrueBlack, - ), + ), + child: Container( + width: + Constant.getActualXPhone(context: context, x: 330), + height: + Constant.getActualYPhone(context: context, y: 200), + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(40), + image: DecorationImage( + image: AssetImage( + 'images/card_bg_1.png'), // Ganti dengan path gambar Anda + fit: BoxFit + .fill, // Sesuaikan cara gambar ditampilkan ), - SizedBox( + ), + child: Padding( + padding: EdgeInsets.only( + top: Constant.getActualYPhone( + context: context, y: 16), + left: Constant.getActualXPhone( + context: context, x: 25), + right: Constant.getActualXPhone( + context: context, x: 25), + ), + child: Container( + width: Constant.getActualXPhone( + context: context, x: 280), height: Constant.getActualYPhone( - context: context, y: 20), - ), - Container( - decoration: BoxDecoration( - shape: BoxShape.rectangle, - borderRadius: BorderRadius.circular(16), - color: - Colors.white, // Set background color to #FFF - boxShadow: [ - BoxShadow( - color: Color.fromRGBO(145, 158, 171, 0.20), - blurRadius: 2, + context: context, y: 150), + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + // Date + RealTimeFormattedDate(), + SizedBox( + height: Constant.getActualYPhone( + context: context, y: 8), + ), + + //Time + RealTimeClock(), // Menampilkan waktu real-time menggunakan RealTimeClock + SizedBox( + height: Constant.getActualYPhone( + context: context, y: 20), + ), + Row( + mainAxisAlignment: MainAxisAlignment + .center, // Menengahkan secara horizontal + children: [ + Spacer(), // Spasi di sebelah kiri "Check In" + Column( + children: [ + Image.asset( + 'images/finger_tap.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), + ), + (varCurrentCheckJamProvider + ?.isAbsenClockIn == + "TRUE") + ? Text( + // '--:--', + varCurrentCheckJamProvider + ?.jamClockIn ?? + "NULL", + ) + : Text( + '--:--', + style: TextStyle( + // Atur gaya teks '--:--' sesuai kebutuhan + ), + ), + Text( + 'Clock In', + style: Constant.titleH2_700( + context: context) + .copyWith( + color: Constant.textLightGrey, + ), + ), + ], + ), + + SizedBox( + width: Constant.getActualXPhone( + context: context, x: 96), + ), // Jarak antara "Check In" dan "Check Out" + Column( + children: [ + Image.asset( + 'images/finger_tap.png', // Path gambar untuk "Check Out" + width: Constant.getActualXPhone( + context: context, x: 22), + height: Constant.getActualYPhone( + context: context, y: 22), + ), + SizedBox( + height: Constant.getActualYPhone( + context: context, y: 8), + ), + (varCurrentCheckJamProvider + ?.isAbsenClockOut == + "TRUE") + ? Text( + // '--:--', + varCurrentCheckJamProvider + ?.jamClockOut ?? + "NULL", + ) + : Text( + '--:--', + style: TextStyle( + // Atur gaya teks '--:--' sesuai kebutuhan + ), + ), + Text( + 'Clock Out', + style: Constant.titleH2_700( + context: context) + .copyWith( + color: Constant.textLightGrey, + ), + ), + ], + ), + Spacer(), // Spasi di sebelah kanan "Check Out" + ], + ), + + SizedBox( + height: Constant.getActualYPhone( + context: context, y: 16), ), ], ), - child: Padding( - padding: EdgeInsets.only( - top: Constant.getActualYPhone( - context: context, y: 12), - bottom: Constant.getActualYPhone( - context: context, y: 12), - left: Constant.getActualXPhone( - context: context, x: 24), - right: Constant.getActualXPhone( - context: context, x: 24), - ), - child: Row( - mainAxisAlignment: - MainAxisAlignment.spaceBetween, - children: [ - Container( - child: Column( - crossAxisAlignment: - CrossAxisAlignment.start, - children: [ - Text( - '24 hari', - style: Constant.subtitle_600_14( - context: context) - .copyWith( - color: Constant.textOrange, - ), - ), - SizedBox( - height: Constant.getActualYPhone( - context: context, y: 4), - ), - SizedBox( - child: Row( - children: [ - Image( - image: AssetImage( - 'images/person_available_grey.png'), - ), - SizedBox( - width: Constant.getActualXPhone( - context: context, x: 4), - ), - Text( - 'Kehadiran', - style: Constant.subtitle_500_12( - context: context) - .copyWith( - color: Constant.textDarkGrey, - ), - ), - ], - ), - ) - ], - ), - ), + ), + ), + ), + ), - Image( - image: AssetImage('images/divider.png'), - ), + SizedBox( + height: Constant.getActualYPhone(context: context, y: 56), + ), - //Tidak Hadir - Container( - child: Column( - crossAxisAlignment: - CrossAxisAlignment.start, - children: [ - Text( - '2 hari', - style: Constant.subtitle_600_14( - context: context) - .copyWith( - color: Constant.textOrange, - ), - ), - SizedBox( - height: Constant.getActualYPhone( - context: context, y: 4), - ), - SizedBox( - child: Row( - children: [ - Image( - image: AssetImage( - 'images/person_delete_grey.png'), - ), - SizedBox( - width: Constant.getActualXPhone( - context: context, x: 4), - ), - Text( - 'Tidak Hadir', - style: Constant.subtitle_500_12( - context: context) - .copyWith( - color: Constant.textDarkGrey, - ), - ), - ], - ), - ) - ], - ), - ), - - Image( - image: AssetImage('images/divider.png'), - ), - - //Tidak Hadir - Container( - child: Column( - crossAxisAlignment: - CrossAxisAlignment.start, - children: [ - Text( - '5 hari', - style: Constant.subtitle_600_14( - context: context) - .copyWith( - color: Constant.textOrange, - ), - ), - SizedBox( - height: Constant.getActualYPhone( - context: context, y: 4), - ), - SizedBox( - child: Row( - children: [ - Image( - image: AssetImage( - 'images/task_pending_grey.png'), - ), - SizedBox( - width: Constant.getActualXPhone( - context: context, x: 4), - ), - Text( - 'Lembur', - style: Constant.subtitle_500_12( - context: context) - .copyWith( - color: Constant.textDarkGrey, - ), - ), - ], - ), - ), - ], - ), + //Menu Cuti Lembur + Padding( + padding: EdgeInsets.only( + left: Constant.getActualXPhone(context: context, x: 33), + right: + Constant.getActualXPhone(context: context, x: 27), + ), + child: Container( + width: + Constant.getActualXPhone(context: context, x: 330), + child: Row( + children: [ + //Menu Cuti + Container( + width: Constant.getActualXPhone( + context: context, x: 98), + // color: Colors.amber, + decoration: BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.circular(16), + boxShadow: [ + BoxShadow( + color: Color.fromRGBO(145, 158, 171, 0.20), ), ], ), + 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: 8), + bottom: Constant.getActualYPhone( + context: context, y: 8), + ), + child: InkWell( + onTap: () {}, + child: Column( + children: [ + Container( + child: Image( + width: Constant.getActualXPhone( + context: context, x: 50), + height: Constant.getActualYPhone( + context: context, y: 50), + image: + AssetImage('images/person.png'), + ), + ), + SizedBox( + height: Constant.getActualYPhone( + context: context, y: 8), + ), + Text( + 'Cuti', + style: Constant.titleH2_600_14( + context: context) + .copyWith( + color: Constant.textDarkGrey, + ), + ), + ], + ), + ), + ), ), - ), - ], + + SizedBox( + width: Constant.getActualXPhone( + context: context, x: 18), + ), + + //Menu Lembur + Container( + width: Constant.getActualXPhone( + context: context, x: 98), + // color: Colors.amber, + decoration: BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.circular(16), + boxShadow: [ + BoxShadow( + color: Color.fromRGBO(145, 158, 171, 0.20), + ), + ], + ), + 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: 8), + bottom: Constant.getActualYPhone( + context: context, y: 8), + ), + child: InkWell( + onTap: () {}, + child: Column( + children: [ + Container( + child: Image( + width: Constant.getActualXPhone( + context: context, x: 50), + height: Constant.getActualYPhone( + context: context, y: 50), + image: AssetImage('images/task.png'), + ), + ), + SizedBox( + height: Constant.getActualYPhone( + context: context, y: 8), + ), + Text( + 'Lembur', + style: Constant.titleH2_600_14( + context: context) + .copyWith( + color: Constant.textDarkGrey, + ), + ), + ], + ), + ), + ), + ), + ], + ), ), ), - ), - ], + + SizedBox( + height: Constant.getActualYPhone(context: context, y: 56), + ), + + //Menu Rekap Presensi + Padding( + padding: EdgeInsets.only( + right: + Constant.getActualXPhone(context: context, x: 27), + left: + Constant.getActualXPhone(context: context, x: 33), + bottom: Constant.getActualYPhone( + context: context, y: 40)), + child: Container( + width: + Constant.getActualXPhone(context: context, x: 330), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + 'Rekap Presensi Bulan Ini', + style: Constant.titleH1_500_18(context: context) + .copyWith( + color: Constant.textTrueBlack, + ), + ), + SizedBox( + height: Constant.getActualYPhone( + context: context, y: 20), + ), + Container( + decoration: BoxDecoration( + shape: BoxShape.rectangle, + borderRadius: BorderRadius.circular(16), + color: Colors + .white, // Set background color to #FFF + boxShadow: [ + BoxShadow( + color: Color.fromRGBO(145, 158, 171, 0.20), + blurRadius: 2, + ), + ], + ), + child: Padding( + padding: EdgeInsets.only( + top: Constant.getActualYPhone( + context: context, y: 12), + bottom: Constant.getActualYPhone( + context: context, y: 12), + left: Constant.getActualXPhone( + context: context, x: 24), + right: Constant.getActualXPhone( + context: context, x: 24), + ), + child: Row( + mainAxisAlignment: + MainAxisAlignment.spaceBetween, + children: [ + Container( + child: Column( + crossAxisAlignment: + CrossAxisAlignment.start, + children: [ + Text( + '24 hari', + style: Constant.subtitle_600_14( + context: context) + .copyWith( + color: Constant.textOrange, + ), + ), + SizedBox( + height: Constant.getActualYPhone( + context: context, y: 4), + ), + SizedBox( + child: Row( + children: [ + Image( + image: AssetImage( + 'images/person_available_grey.png'), + ), + SizedBox( + width: + Constant.getActualXPhone( + context: context, + x: 4), + ), + Text( + 'Kehadiran', + style: + Constant.subtitle_500_12( + context: context) + .copyWith( + color: + Constant.textDarkGrey, + ), + ), + ], + ), + ) + ], + ), + ), + + Image( + image: AssetImage('images/divider.png'), + ), + + //Tidak Hadir + Container( + child: Column( + crossAxisAlignment: + CrossAxisAlignment.start, + children: [ + Text( + '2 hari', + style: Constant.subtitle_600_14( + context: context) + .copyWith( + color: Constant.textOrange, + ), + ), + SizedBox( + height: Constant.getActualYPhone( + context: context, y: 4), + ), + SizedBox( + child: Row( + children: [ + Image( + image: AssetImage( + 'images/person_delete_grey.png'), + ), + SizedBox( + width: + Constant.getActualXPhone( + context: context, + x: 4), + ), + Text( + 'Tidak Hadir', + style: + Constant.subtitle_500_12( + context: context) + .copyWith( + color: + Constant.textDarkGrey, + ), + ), + ], + ), + ) + ], + ), + ), + + Image( + image: AssetImage('images/divider.png'), + ), + + //Tidak Hadir + Container( + child: Column( + crossAxisAlignment: + CrossAxisAlignment.start, + children: [ + Text( + '5 hari', + style: Constant.subtitle_600_14( + context: context) + .copyWith( + color: Constant.textOrange, + ), + ), + SizedBox( + height: Constant.getActualYPhone( + context: context, y: 4), + ), + SizedBox( + child: Row( + children: [ + Image( + image: AssetImage( + 'images/task_pending_grey.png'), + ), + SizedBox( + width: + Constant.getActualXPhone( + context: context, + x: 4), + ), + Text( + 'Lembur', + style: + Constant.subtitle_500_12( + context: context) + .copyWith( + color: + Constant.textDarkGrey, + ), + ), + ], + ), + ), + ], + ), + ), + ], + ), + ), + ), + ], + ), + ), + ), + ], + ), ), ), ), diff --git a/lib/screen/home/home_screen_v1.dart b/lib/screen/home/home_screen_v1.dart index 142ebe0..73718fd 100644 --- a/lib/screen/home/home_screen_v1.dart +++ b/lib/screen/home/home_screen_v1.dart @@ -1,180 +1,859 @@ -import 'dart:async'; - -import 'package:absensi_sas_flutter/screen/login/logout_provider.dart'; +import 'package:absensi_sas_flutter/app/constant.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:google_sign_in/google_sign_in.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; -import 'package:shared_preferences/shared_preferences.dart'; +import 'package:permission_handler/permission_handler.dart'; -import '../../app/constant.dart'; import '../../app/route.dart'; +import '../../provider/current_check_distance_provider.dart'; +import '../../provider/current_check_jam_presensi_provider.dart'; +import '../../provider/current_menu_provider.dart'; import '../../provider/current_user_provider.dart'; import '../../provider/google_login_provider.dart'; +import '../../widget/custom_drawer.dart'; +import '../../widget/real_date.dart'; +import '../../widget/real_time.dart'; import '../../widget/sankbar_widget.dart'; +import '../presensi/check_distance_provider.dart'; +import '../presensi/check_presensi_jam_provider.dart'; class HomeScreenV1 extends HookConsumerWidget { const HomeScreenV1({super.key}); @override Widget build(BuildContext context, WidgetRef ref) { - final isLoading = useState(false); - // final errorMessage = useState(""); - final successMessage = useState(""); + final selectedUser = ref.read(currentUserProvider); + final isLoadingProsesCheckDistance = useState(false); + final varCurrentDistanceProvider = ref.watch(currentCheckDistanceProvider); + final varCurrentCheckJamProvider = + ref.watch(currentCheckJamPresensiProvider); + final positionLatitude = useState(""); + final positionLongitude = useState(""); + // GoogleSignInAccount? currentUserGoogle = + // ref.watch(currentUserGoogleProvider); + final googleSignIn = ref.watch(googleSignInProvider); - // final currentUserGoogleAccount = ref.watch(currentUserGoogleProvider); + 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); - GoogleSignInAccount? currentUserGoogle = - ref.watch(currentUserGoogleProvider); + // Navigator.popAndPushNamed(context, loginRoute); + return; + } + }); + return () {}; + }, []); - final selectedUser = ref.read(currentUserProvider); + useEffect(() { + WidgetsBinding.instance.addPostFrameCallback((timeStamp) async { + final staffID = ref.read(currentUserProvider)?.model.staffId ?? "0"; - // GoogleSignInAccount? accountX; - // final accountX = useState(null); + if (staffID != "0") { + // panggil check jam presensi provider + Map inpVariablesCheckPresensiJam = { + "M_StaffID": selectedUser?.model.staffId ?? "", + "M_CompanyID": selectedUser?.model.companyId ?? "", + "token": selectedUser?.token ?? "", + }; - // useEffect(() { - // WidgetsBinding.instance.addPostFrameCallback((timeStamp) async { - // final staffID = ref.read(currentUserProvider)?.model.staffId ?? "0"; - // if (staffID == "0" && currentUserGoogle == null) { - // //not login - // Navigator.of(context) - // .pushNamedAndRemoveUntil(loginRoute, (route) => true); + ref.read(checkPresensiJamProvider.notifier).checkPresensiJam( + selectedUser?.model.staffId ?? "", + selectedUser?.model.companyId ?? "", + selectedUser?.token ?? "", + inpVariablesCheckPresensiJam, + ); + } + }); + return () {}; + }, []); - // // Navigator.popAndPushNamed(context, loginRoute); - // return; - // } - // }); - // return () {}; - // }, []); + Future getAddressFromLocation() async { + try { + isLoadingProsesCheckDistance.value = true; + // Mendapatkan posisi pengguna + LocationPermission permission = await Geolocator.requestPermission(); - // useEffect(() { - // WidgetsBinding.instance.addPostFrameCallback((timeStamp) async { - // final staffID = ref.read(currentUserProvider)?.model.staffId ?? "0"; - // final accountGoogle = ref.read(currentUserGoogleProvider)?.id ?? "0"; + if (permission == LocationPermission.denied) { + isLoadingProsesCheckDistance.value = false; + SanckbarWidget(context, 'Izin lokasi ditolak', snackbarType.error); + // Handle jika pengguna menolak izin lokasi + print("Izin lokasi ditolak"); + return; + } - // if (staffID == "0" && accountGoogle == "0") { - // //not login - // Navigator.of(context) - // .pushNamedAndRemoveUntil(loginRoute, (route) => true); + Position position = await Geolocator.getCurrentPosition( + desiredAccuracy: LocationAccuracy.high); - // // Navigator.popAndPushNamed(context, loginRoute); - // return; - // } - // }); - // return () {}; - // }, []); + // Mendapatkan alamat dari posisi + List placemarks = await placemarkFromCoordinates( + position.latitude, position.longitude); - // LISTEN PROVIDER - 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 = ""; - // }); - SanckbarWidget(context, next.message, snackbarType.warning); - } else if (next is LogoutStateDone) { - isLoading.value = false; + if (placemarks.isNotEmpty) { + isLoadingProsesCheckDistance.value = false; + Placemark placemark = placemarks.first; + // String address = + // "${placemark.thoroughfare}, ${placemark.locality}, ${placemark.administrativeArea}, ${placemark.country},"; - if (next.model.status == "OK") { - 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 = ""; - }); + String address = + "${placemark.street}, ${placemark.subLocality}, ${placemark.subAdministrativeArea}, ${placemark.postalCode}"; + print("Alamat: $address"); + + positionLatitude.value = position.latitude.toString(); + positionLongitude.value = position.longitude.toString(); + + // panggil check distance provider + ref.read(checkDistanceProvider.notifier).checkDistance( + selectedUser?.model.staffId ?? "", + selectedUser?.model.companyId ?? "", + positionLatitude.value, + positionLongitude.value, + ); } else { + isLoadingProsesCheckDistance.value = false; SanckbarWidget( - context, - next.model.message.toString(), - snackbarType.warning, - ); + context, 'Tidak dapat menemukan alamat.', snackbarType.error); + print("Tidak dapat menemukan alamat."); + } + } catch (e) { + print("Error: $e"); + isLoadingProsesCheckDistance.value = false; + SanckbarWidget(context, 'Error : $e', snackbarType.error); + } + } + + Future requestLocationPermission() async { + var status = await Permission.location.request(); + isLoadingProsesCheckDistance.value = true; + if (status.isGranted) { + // Izin diberikan, lanjutkan dengan mendapatkan lokasi + getAddressFromLocation(); + } else { + isLoadingProsesCheckDistance.value = false; + // Izin ditolak, berikan pemberitahuan atau instruksi + // print('Izin lokasi ditolak'); + SanckbarWidget(context, 'Izin Ditolak', snackbarType.error); + } + } + + // check distance provider + ref.listen(checkDistanceProvider, (prev, next) { + if (next is CheckDistanceStateLoading) { + isLoadingProsesCheckDistance.value = true; + } else if (next is CheckDistanceStateError) { + isLoadingProsesCheckDistance.value = false; + SanckbarWidget(context, next.message, snackbarType.warning); + } else if (next is CheckDistanceStateDone) { + isLoadingProsesCheckDistance.value = false; + + if (next.model.selfie == "TRUE") { + ref.read(currentPageProvider.notifier).update((state) => 99); + // Navigator.of(context).pop(); + Navigator.of(context).restorablePushNamed(presensiSelfieRoute); + } else { + if (next.model.selfie == "FALSE") { + ref.read(currentPageProvider.notifier).update((state) => 99); + Navigator.of(context).restorablePushNamed(presensiRoute); + } } } }); - Future handleLogout() async { - final googleSignIn = GoogleSignIn(); - - // googleSignIn.signOut(); - await googleSignIn.disconnect(); - await googleSignIn.signOut(); - - // ref.read(currentUserGoogleProvider.notifier).update((state) => null); - // final shared = await SharedPreferences.getInstance(); - // final bearerString = shared.get(Constant.bearerName).toString(); - // if (bearerString.isNotEmpty) { - // shared.remove(bearerString); - // shared.clear(); - // } - - // if (googleSignIn.currentUser != null) { - // GoogleSignIn().signOut(); - // } - - // await GoogleSignIn().disconnect(); - - // Clear state dan kembali ke halaman login - // ref.read(currentUserGoogleProvider.notifier).update((state) => null); - // final shared = await SharedPreferences.getInstance(); - // final bearerString = shared.get(Constant.bearerName).toString(); - // if (bearerString.isNotEmpty) { - // shared.remove(bearerString); - // shared.clear(); - // } - Navigator.of(context) - .pushNamedAndRemoveUntil(loginRoute, (route) => false); - } + // check jam presensi + ref.listen(checkPresensiJamProvider, (prev, next) { + if (next is CheckPresensiJamStateLoading) { + isLoadingProsesCheckDistance.value = true; + } else if (next is CheckPresensiJamStateError) { + isLoadingProsesCheckDistance.value = false; + print("Error : " + next.toString()); + SanckbarWidget( + context, "Error : " + next.toString(), snackbarType.warning); + } else if (next is CheckPresensiJamStateDone) { + isLoadingProsesCheckDistance.value = false; + } + }); return Scaffold( - body: Padding( - padding: const EdgeInsets.all(20), - child: Column( - children: [ - (currentUserGoogle == null) - ? Center( - child: CircularProgressIndicator(), - ) - : Container( - child: ListTile( - leading: GoogleUserCircleAvatar( - // identity: accountX.value!, - // identity: selectedUser?.googleSignInAccount, - identity: currentUserGoogle, - ), - title: Text( - // accountX.value!.displayName ?? "" - // selectedUser?.model.name ?? "", - currentUserGoogle.displayName ?? "", - ), - // currentUserGoogle?.displayName ?? ""), - subtitle: Text( - // currentUserGoogle?.email ?? "", - selectedUser?.model.email ?? "", - // accountX.value!.email - ), - trailing: IconButton( - icon: Icon(Icons.logout_outlined), - onPressed: () async { - handleLogout(); - }, + floatingActionButtonLocation: FloatingActionButtonLocation.centerDocked, + floatingActionButton: Container( + width: Constant.getActualXPhone(context: context, x: 100), + height: Constant.getActualYPhone(context: context, y: 100), + child: FittedBox( + child: (isLoadingProsesCheckDistance.value) + ? SizedBox( + width: Constant.getActualXPhone(context: context, x: 50), + height: Constant.getActualYPhone(context: context, y: 50), + child: Center( + child: CircularProgressIndicator( + color: Constant.textOrange, + ), + ), + ) + : FloatingActionButton( + onPressed: () async { + await requestLocationPermission(); + }, + backgroundColor: Color(0xFFFFFFFF), + shape: CircleBorder(), + child: Container( + width: Constant.getActualXPhone(context: context, x: 50), + height: Constant.getActualYPhone(context: context, y: 50), + decoration: BoxDecoration( + image: DecorationImage( + image: AssetImage( + 'images/finger_tap_orange_botnav.png'), // Ganti dengan path gambar Anda ), ), ), + ), + ), + ), + 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: [ + Expanded( + child: Container( + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Image( + image: AssetImage('images/home_orange.png'), + ), + Text( + 'Beranda', + style: Constant.subtitle_500_12(context: context).copyWith( + color: Constant.textOrange, + ), + ) + ], + ), + )), + Expanded( + child: Container( + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Image( + image: AssetImage('images/person_grey.png'), + ), + Text( + 'Profile', + style: Constant.subtitle_500_12(context: context).copyWith( + color: Constant.textLightGrey, + ), + ) + ], + ), + )), + ], + ), + ), + body: SafeArea( + child: SingleChildScrollView( + child: Container( + width: Constant.getActualXPhone(context: context, x: 390), + // height: Constant.getActualYPhone(context: context, y: 844), + child: RefreshIndicator( + onRefresh: () async {}, + child: Column( + children: [ + 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( + child: (googleSignIn.currentUser == null) + ? Center( + child: CircularProgressIndicator(), + ) + : ListTile( + // leading: Container( + // width: Constant.getActualXPhone( + // context: context, x: 36), + // height: Constant.getActualYPhone( + // context: context, y: 36), + // child: Image( + // image: AssetImage('images/avatar_c.png'), + // ), + // ), + leading: GoogleUserCircleAvatar( + identity: googleSignIn.currentUser!, + ), + title: Text( + // "Stephen Kusumo", + // selectedUser?.model.name ?? "", + // currentUserGoogle.displayName ?? "", + googleSignIn.currentUser?.displayName ?? "", + overflow: TextOverflow.ellipsis, + style: Constant.titleH1_700(context: context) + ..copyWith( + color: Constant.textBlack, + ), + ), + subtitle: Text( + // "Step@example.com", + // currentUserGoogle?.email ?? "", + // selectedUser?.model.email ?? "", + googleSignIn.currentUser?.email ?? "", + style: + Constant.subtitle_500_12(context: context) + .copyWith( + color: Constant.textLightGrey, + ), + ), + trailing: Container( + width: Constant.getActualXPhone( + context: context, x: 36), + height: Constant.getActualYPhone( + context: context, y: 36), + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(12.0), + color: Colors.white, + shape: BoxShape.rectangle, + boxShadow: [ + BoxShadow( + offset: Offset(0, 12), + blurRadius: 24, + color: + Color.fromRGBO(145, 158, 171, 0.12), + ), + ], + ), + child: IconButton( + onPressed: () {}, + icon: Container( + width: Constant.getActualXPhone( + context: context, x: 20), + height: Constant.getActualYPhone( + context: context, y: 20), + child: Image( + image: + AssetImage('images/alert_badge.png'), + ), + ), + ), + ), + ), + ), + ), + + SizedBox( + height: Constant.getActualYPhone(context: context, y: 44), + ), + + //Card Time + Padding( + padding: EdgeInsets.only( + left: Constant.getActualXPhone(context: context, x: 33), + right: Constant.getActualXPhone(context: context, x: 27), + ), + child: Container( + width: Constant.getActualXPhone(context: context, x: 330), + height: + Constant.getActualYPhone(context: context, y: 200), + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(40), + image: DecorationImage( + image: AssetImage( + 'images/card_bg_1.png'), // Ganti dengan path gambar Anda + fit: BoxFit.fill, // Sesuaikan cara gambar ditampilkan + ), + ), + child: Padding( + padding: EdgeInsets.only( + top: + Constant.getActualYPhone(context: context, y: 16), + left: + Constant.getActualXPhone(context: context, x: 25), + right: + Constant.getActualXPhone(context: context, x: 25), + ), + child: Container( + width: Constant.getActualXPhone( + context: context, x: 280), + height: Constant.getActualYPhone( + context: context, y: 150), + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + // Date + RealTimeFormattedDate(), + SizedBox( + height: Constant.getActualYPhone( + context: context, y: 8), + ), + + //Time + RealTimeClock(), // Menampilkan waktu real-time menggunakan RealTimeClock + SizedBox( + height: Constant.getActualYPhone( + context: context, y: 20), + ), + Row( + mainAxisAlignment: MainAxisAlignment + .center, // Menengahkan secara horizontal + children: [ + Spacer(), // Spasi di sebelah kiri "Check In" + Column( + children: [ + Image.asset( + 'images/finger_tap.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), + ), + (varCurrentCheckJamProvider + ?.isAbsenClockIn == + "TRUE") + ? Text( + // '--:--', + varCurrentCheckJamProvider + ?.jamClockIn ?? + "NULL", + ) + : Text( + '--:--', + style: TextStyle( + // Atur gaya teks '--:--' sesuai kebutuhan + ), + ), + Text( + 'Clock In', + style: Constant.titleH2_700( + context: context) + .copyWith( + color: Constant.textLightGrey, + ), + ), + ], + ), + + SizedBox( + width: Constant.getActualXPhone( + context: context, x: 96), + ), // Jarak antara "Check In" dan "Check Out" + Column( + children: [ + Image.asset( + 'images/finger_tap.png', // Path gambar untuk "Check Out" + width: Constant.getActualXPhone( + context: context, x: 22), + height: Constant.getActualYPhone( + context: context, y: 22), + ), + SizedBox( + height: Constant.getActualYPhone( + context: context, y: 8), + ), + (varCurrentCheckJamProvider + ?.isAbsenClockOut == + "TRUE") + ? Text( + // '--:--', + varCurrentCheckJamProvider + ?.jamClockOut ?? + "NULL", + ) + : Text( + '--:--', + style: TextStyle( + // Atur gaya teks '--:--' sesuai kebutuhan + ), + ), + Text( + 'Clock Out', + style: Constant.titleH2_700( + context: context) + .copyWith( + color: Constant.textLightGrey, + ), + ), + ], + ), + Spacer(), // Spasi di sebelah kanan "Check Out" + ], + ), + + SizedBox( + height: Constant.getActualYPhone( + context: context, y: 16), + ), + ], + ), + ), + ), + ), + ), + + SizedBox( + height: Constant.getActualYPhone(context: context, y: 56), + ), + + //Menu Cuti Lembur + Padding( + padding: EdgeInsets.only( + left: Constant.getActualXPhone(context: context, x: 33), + right: Constant.getActualXPhone(context: context, x: 27), + ), + child: Container( + width: Constant.getActualXPhone(context: context, x: 330), + child: Row( + children: [ + //Menu Cuti + Container( + width: Constant.getActualXPhone( + context: context, x: 98), + // color: Colors.amber, + decoration: BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.circular(16), + boxShadow: [ + BoxShadow( + color: Color.fromRGBO(145, 158, 171, 0.20), + ), + ], + ), + 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: 8), + bottom: Constant.getActualYPhone( + context: context, y: 8), + ), + child: InkWell( + onTap: () {}, + child: Column( + children: [ + Container( + child: Image( + width: Constant.getActualXPhone( + context: context, x: 50), + height: Constant.getActualYPhone( + context: context, y: 50), + image: AssetImage('images/person.png'), + ), + ), + SizedBox( + height: Constant.getActualYPhone( + context: context, y: 8), + ), + Text( + 'Cuti', + style: Constant.titleH2_600_14( + context: context) + .copyWith( + color: Constant.textDarkGrey, + ), + ), + ], + ), + ), + ), + ), + + SizedBox( + width: Constant.getActualXPhone( + context: context, x: 18), + ), + + //Menu Lembur + Container( + width: Constant.getActualXPhone( + context: context, x: 98), + // color: Colors.amber, + decoration: BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.circular(16), + boxShadow: [ + BoxShadow( + color: Color.fromRGBO(145, 158, 171, 0.20), + ), + ], + ), + 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: 8), + bottom: Constant.getActualYPhone( + context: context, y: 8), + ), + child: InkWell( + onTap: () {}, + child: Column( + children: [ + Container( + child: Image( + width: Constant.getActualXPhone( + context: context, x: 50), + height: Constant.getActualYPhone( + context: context, y: 50), + image: AssetImage('images/task.png'), + ), + ), + SizedBox( + height: Constant.getActualYPhone( + context: context, y: 8), + ), + Text( + 'Lembur', + style: Constant.titleH2_600_14( + context: context) + .copyWith( + color: Constant.textDarkGrey, + ), + ), + ], + ), + ), + ), + ), + ], + ), + ), + ), + + SizedBox( + height: Constant.getActualYPhone(context: context, y: 56), + ), + + //Menu Rekap Presensi + Padding( + padding: EdgeInsets.only( + right: + Constant.getActualXPhone(context: context, x: 27), + left: Constant.getActualXPhone(context: context, x: 33), + bottom: + Constant.getActualYPhone(context: context, y: 40)), + child: Container( + width: Constant.getActualXPhone(context: context, x: 330), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + 'Rekap Presensi Bulan Ini', + style: Constant.titleH1_500_18(context: context) + .copyWith( + color: Constant.textTrueBlack, + ), + ), + SizedBox( + height: Constant.getActualYPhone( + context: context, y: 20), + ), + Container( + decoration: BoxDecoration( + shape: BoxShape.rectangle, + borderRadius: BorderRadius.circular(16), + color: + Colors.white, // Set background color to #FFF + boxShadow: [ + BoxShadow( + color: Color.fromRGBO(145, 158, 171, 0.20), + blurRadius: 2, + ), + ], + ), + child: Padding( + padding: EdgeInsets.only( + top: Constant.getActualYPhone( + context: context, y: 12), + bottom: Constant.getActualYPhone( + context: context, y: 12), + left: Constant.getActualXPhone( + context: context, x: 24), + right: Constant.getActualXPhone( + context: context, x: 24), + ), + child: Row( + mainAxisAlignment: + MainAxisAlignment.spaceBetween, + children: [ + Container( + child: Column( + crossAxisAlignment: + CrossAxisAlignment.start, + children: [ + Text( + '24 hari', + style: Constant.subtitle_600_14( + context: context) + .copyWith( + color: Constant.textOrange, + ), + ), + SizedBox( + height: Constant.getActualYPhone( + context: context, y: 4), + ), + SizedBox( + child: Row( + children: [ + Image( + image: AssetImage( + 'images/person_available_grey.png'), + ), + SizedBox( + width: Constant.getActualXPhone( + context: context, x: 4), + ), + Text( + 'Kehadiran', + style: Constant.subtitle_500_12( + context: context) + .copyWith( + color: Constant.textDarkGrey, + ), + ), + ], + ), + ) + ], + ), + ), + + Image( + image: AssetImage('images/divider.png'), + ), + + //Tidak Hadir + Container( + child: Column( + crossAxisAlignment: + CrossAxisAlignment.start, + children: [ + Text( + '2 hari', + style: Constant.subtitle_600_14( + context: context) + .copyWith( + color: Constant.textOrange, + ), + ), + SizedBox( + height: Constant.getActualYPhone( + context: context, y: 4), + ), + SizedBox( + child: Row( + children: [ + Image( + image: AssetImage( + 'images/person_delete_grey.png'), + ), + SizedBox( + width: Constant.getActualXPhone( + context: context, x: 4), + ), + Text( + 'Tidak Hadir', + style: Constant.subtitle_500_12( + context: context) + .copyWith( + color: Constant.textDarkGrey, + ), + ), + ], + ), + ) + ], + ), + ), + + Image( + image: AssetImage('images/divider.png'), + ), + + //Tidak Hadir + Container( + child: Column( + crossAxisAlignment: + CrossAxisAlignment.start, + children: [ + Text( + '5 hari', + style: Constant.subtitle_600_14( + context: context) + .copyWith( + color: Constant.textOrange, + ), + ), + SizedBox( + height: Constant.getActualYPhone( + context: context, y: 4), + ), + SizedBox( + child: Row( + children: [ + Image( + image: AssetImage( + 'images/task_pending_grey.png'), + ), + SizedBox( + width: Constant.getActualXPhone( + context: context, x: 4), + ), + Text( + 'Lembur', + style: Constant.subtitle_500_12( + context: context) + .copyWith( + color: Constant.textDarkGrey, + ), + ), + ], + ), + ), + ], + ), + ), + ], + ), + ), + ), + ], + ), + ), + ), + ], + ), + ), + ), + ), ), ); } diff --git a/lib/screen/presensi/presensi_screen.dart b/lib/screen/presensi/presensi_screen.dart index b4d4089..88c50d6 100644 --- a/lib/screen/presensi/presensi_screen.dart +++ b/lib/screen/presensi/presensi_screen.dart @@ -353,6 +353,7 @@ class PresensiScreen extends HookConsumerWidget { top: Constant.getActualYPhone(context: context, y: 30), ), child: Scaffold( + backgroundColor: Constant.textWhite, appBar: AppBar( title: Text( // 'Home Screen', @@ -369,7 +370,7 @@ class PresensiScreen extends HookConsumerWidget { // elevation: 1.0, elevation: 0.5, ), - drawer: CustomDrawer(), + drawer: CustomDrawer(), body: SafeArea( child: Padding( padding: EdgeInsets.only( @@ -507,7 +508,8 @@ class PresensiScreen extends HookConsumerWidget { // tombol aksi absen masuk & pulang if (varCurrentCheckJamProvider?.isAbsenClockIn == "TRUE" && - varCurrentCheckJamProvider?.isAbsenClockOut == "TRUE") ...[ + varCurrentCheckJamProvider?.isAbsenClockOut == + "TRUE") ...[ SizedBox.shrink() ] else ...[ if (varCurrentCheckJamProvider?.isAbsenClockIn == "FALSE" && diff --git a/lib/screen/presensi/presensi_selfie_screen.dart b/lib/screen/presensi/presensi_selfie_screen.dart index 152b3e9..b1af355 100644 --- a/lib/screen/presensi/presensi_selfie_screen.dart +++ b/lib/screen/presensi/presensi_selfie_screen.dart @@ -19,6 +19,7 @@ import '../../app/route.dart'; import '../../provider/current_check_distance_provider.dart'; import '../../provider/current_check_jam_presensi_provider.dart'; import '../../provider/current_user_provider.dart'; +import '../../widget/custom_dialog_presensi_selfie_sukses.dart'; import '../../widget/real_date.dart'; import '../../widget/real_time.dart'; import '../../widget/sankbar_widget.dart'; @@ -284,7 +285,17 @@ class PresensiSelfieScreen extends HookConsumerWidget { } else if (next is PresensiClockInStateDone) { isLoadingProsesCheckDistance.value = false; if (next.model == "OK") { - SanckbarWidget(context, "Berhasil Absen Masuk", snackbarType.success); + // SanckbarWidget(context, "Berhasil Absen Masuk", snackbarType.success); + showDialog( + context: context, + builder: (BuildContext context) { + return CustomDialogPresensiSukses( + isiPesan: + 'Pengajuan presensi telah diajukan, mohon menunggu approval team leader! ', + messageStatus: 'Clock In Berhasil', + ); + }, + ); requestLocationPermission(); } // else{ @@ -295,7 +306,7 @@ class PresensiSelfieScreen extends HookConsumerWidget { } }); - // proses presensi clock in + // proses presensi clock out ref.listen(presensiClockOutProvider, (prev, next) { if (next is PresensiClockOutStateLoading) { isLoadingProsesCheckDistance.value = true; @@ -306,8 +317,18 @@ class PresensiSelfieScreen extends HookConsumerWidget { } else if (next is PresensiClockOutStateDone) { isLoadingProsesCheckDistance.value = false; if (next.model == "OK") { - SanckbarWidget( - context, "Berhasil Absen Pulang", snackbarType.success); + // SanckbarWidget( + // context, "Berhasil Absen Pulang", snackbarType.success); + showDialog( + context: context, + builder: (BuildContext context) { + return CustomDialogPresensiSukses( + isiPesan: + 'Pengajuan presensi telah diajukan, mohon menunggu approval team leader! ', + messageStatus: 'Clock Out Berhasil', + ); + }, + ); requestLocationPermission(); } // else{ @@ -481,6 +502,7 @@ class PresensiSelfieScreen extends HookConsumerWidget { top: Constant.getActualYPhone(context: context, y: 30), ), child: Scaffold( + backgroundColor: Constant.textWhite, appBar: AppBar( title: Text( // 'Home Screen', @@ -512,6 +534,20 @@ class PresensiSelfieScreen extends HookConsumerWidget { child: Column( children: [ // Text(ref.watch(currentCheckDistanceProvider)?.currentDistance ?? "NULL"), + + // ElevatedButton( + // onPressed: () { + // showDialog( + // context: context, + // builder: (BuildContext context) { + // return CustomDialogPresensiSukses( + // isiPesan: 'sasasa', + // messageStatus: 'Clock In Berhasil', + // ); + // }, + // ); + // }, + // child: Text('ok')), // Spacer(), // tanggal sekarang RealTimeFormattedDate(), @@ -869,8 +905,8 @@ class PresensiSelfieScreen extends HookConsumerWidget { context: context, x: 20), top: Constant.getActualYPhone( context: context, y: 24), - // bottom: Constant.getActualYPhone( - // context: context, y: 24), + bottom: Constant.getActualYPhone( + context: context, y: 24), ), child: SizedBox( width: Constant.getActualXPhone( diff --git a/lib/widget/custom_dialog_presensi_selfie_sukses.dart b/lib/widget/custom_dialog_presensi_selfie_sukses.dart new file mode 100644 index 0000000..ec82125 --- /dev/null +++ b/lib/widget/custom_dialog_presensi_selfie_sukses.dart @@ -0,0 +1,111 @@ +import 'package:flutter/material.dart'; +import 'package:hooks_riverpod/hooks_riverpod.dart'; + +import '../app/constant.dart'; + +class CustomDialogPresensiSukses extends HookConsumerWidget { + final String messageStatus; + final String isiPesan; + + CustomDialogPresensiSukses({ + required this.messageStatus, + required this.isiPesan, + }); + + @override + Widget build(BuildContext context, WidgetRef ref) { + return Dialog( + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(8.0), + ), + elevation: 0, + backgroundColor: Colors.white, + child: contentBox(context), + ); + } + + Widget contentBox(BuildContext context) { + return Stack( + alignment: Alignment.center, + children: [ + Container( + padding: EdgeInsets.all(16), + decoration: BoxDecoration( + shape: BoxShape.rectangle, + color: Colors.white, + borderRadius: BorderRadius.circular(8), + ), + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + Padding( + padding: EdgeInsets.only( + top: Constant.getActualYPhone(context: context, y: 24), + ), + child: Container( + width: Constant.getActualXPhone(context: context, x: 100), + height: Constant.getActualYPhone(context: context, y: 100), + decoration: BoxDecoration( + image: DecorationImage( + image: AssetImage( + 'images/presensi_selfie_sukses.png'), // Ganti dengan path gambar Anda + ), + ), + ), + ), + SizedBox( + height: Constant.getActualYPhone(context: context, y: 36), + ), + Text( + messageStatus, + style: Constant.titleH1_700_18(context: context).copyWith( + color: Constant.textOrange, + ), + textAlign: TextAlign.center, + ), + SizedBox( + height: Constant.getActualYPhone(context: context, y: 12), + ), + Text( + // 'Pengajuan presensi telah berhasil diajukan, mohon menunggu approval team leader!', + isiPesan, + style: Constant.titleH2_400_14(context: context).copyWith( + color: Constant.textTrueBlack, + ), + textAlign: TextAlign.center, + ), + SizedBox( + height: Constant.getActualYPhone(context: context, y: 36), + ), + ElevatedButton( + onPressed: () { + Navigator.of(context).pop(); // Close the dialog + }, + style: ButtonStyle( + backgroundColor: MaterialStateColor.resolveWith( + (st) => Constant.textOrange), + shape: MaterialStateProperty.all( + RoundedRectangleBorder( + borderRadius: BorderRadius.circular(8), + side: BorderSide( + color: Constant.textOrange, + ), + ), + ), + shadowColor: MaterialStateProperty.all(Color(0xffff48423d)), + elevation: MaterialStateProperty.all(4.0), + ), + child: Text( + 'OK', + style: Constant.titleH2_400_14(context: context).copyWith( + color: Constant.textWhite, + ), + ), + ), + ], + ), + ), + ], + ); + } +} diff --git a/lib/widget/custom_drawer.dart b/lib/widget/custom_drawer.dart index d8a69e7..84823f0 100644 --- a/lib/widget/custom_drawer.dart +++ b/lib/widget/custom_drawer.dart @@ -77,22 +77,34 @@ class CustomDrawer extends HookConsumerWidget { child: Drawer( elevation: 0, shape: RoundedRectangleBorder( - borderRadius: BorderRadius.all(Radius.circular(0))), + borderRadius: BorderRadius.all( + Radius.circular(0), + ), + ), child: Column( children: [ Expanded( child: ListView( children: [ - // Container( - // child: Image( - // image: - // AssetImage('images/logo_sismedika_landscape.png')), - // ), - + Padding( + padding: EdgeInsets.only( + top: Constant.getActualYPhone(context: context, y: 50), + bottom: Constant.getActualYPhone(context: context, y: 10), + right: Constant.getActualXPhone(context: context, x: 24), + left: Constant.getActualXPhone(context: context, x: 24), + ), + child: Container( + child: Image( + fit: BoxFit.cover, + 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), @@ -104,17 +116,16 @@ class CustomDrawer extends HookConsumerWidget { 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, - ), - ), - ), - + // 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, @@ -137,26 +148,47 @@ class CustomDrawer extends HookConsumerWidget { Navigator.of(context).popAndPushNamed(homeRoute); }, ), - ListTile( leading: Icon( - Icons.logout, - color: Constant.textLightGrey, + Icons.person, + color: (currentMenu == 5) + ? Constant.textOrange + : Constant.textLightGrey, ), title: Text( - 'Logout', - style: TextStyle(color: Constant.textLightGrey), + 'Profil', + style: TextStyle( + color: (currentMenu == 5) + ? Constant.textOrange + : 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 ?? "", - // ); + // Handle navigation to Home screen + Navigator.pop(context); + ref.read(currentPageProvider.state).update((state) => 5); + // Navigator.of(context).popAndPushNamed(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 ?? "", + // // ); + // }, + // ), ], ), ),