step 3 : copy login screen app dokter
This commit is contained in:
103
app_petty_cash/lib/app/app_extension.dart
Normal file
103
app_petty_cash/lib/app/app_extension.dart
Normal file
@@ -0,0 +1,103 @@
|
|||||||
|
import 'package:intl/intl.dart';
|
||||||
|
|
||||||
|
extension AppStringExtension on String {
|
||||||
|
String currencyFormat() {
|
||||||
|
final numberFormat = NumberFormat.currency(
|
||||||
|
locale: 'id_ID',
|
||||||
|
decimalDigits: 0,
|
||||||
|
symbol: 'Rp ',
|
||||||
|
);
|
||||||
|
return numberFormat.format(double.parse(this));
|
||||||
|
}
|
||||||
|
|
||||||
|
String dateFormat() {
|
||||||
|
final dateFormatFromApi = DateFormat('yyyy-M-dd hh:mm:ss');
|
||||||
|
// final dateFormat = DateFormat('dd MMM yyyy');
|
||||||
|
final dateFormat = DateFormat('dd/M/yy');
|
||||||
|
return dateFormat.format(dateFormatFromApi.parse(this));
|
||||||
|
}
|
||||||
|
|
||||||
|
String dateFormatdmy() {
|
||||||
|
final dateFormatFromApi = DateFormat('yyyy-M-dd hh:mm:ss');
|
||||||
|
// final dateFormat = DateFormat('dd MMM yyyy');
|
||||||
|
final dateFormat = DateFormat('dd-MM-yyyy hh:mm:ss');
|
||||||
|
return dateFormat.format(dateFormatFromApi.parse(this));
|
||||||
|
}
|
||||||
|
|
||||||
|
String dateFormatdmyHistorical() {
|
||||||
|
final dateFormatFromApi = DateFormat('yyyy-MM-dd');
|
||||||
|
// final dateFormat = DateFormat('dd MMM yyyy');
|
||||||
|
final dateFormat = DateFormat('dd-MM-yyyy');
|
||||||
|
return dateFormat.format(dateFormatFromApi.parse(this));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
String formatBulanIndo(String tanggal) {
|
||||||
|
DateTime dateTime = DateFormat("yyyy-MM-dd").parse(tanggal);
|
||||||
|
|
||||||
|
var m = DateFormat('MM').format(dateTime);
|
||||||
|
var month = "";
|
||||||
|
switch (m) {
|
||||||
|
case '01':
|
||||||
|
{
|
||||||
|
month = "Januari";
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case '02':
|
||||||
|
{
|
||||||
|
month = "Februari";
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case '03':
|
||||||
|
{
|
||||||
|
month = "Maret";
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case '04':
|
||||||
|
{
|
||||||
|
month = "April";
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case '05':
|
||||||
|
{
|
||||||
|
month = "Mei";
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case '06':
|
||||||
|
{
|
||||||
|
month = "Juni";
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case '07':
|
||||||
|
{
|
||||||
|
month = "Juli";
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case '08':
|
||||||
|
{
|
||||||
|
month = "Agustus";
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case '09':
|
||||||
|
{
|
||||||
|
month = "September";
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case '10':
|
||||||
|
{
|
||||||
|
month = "Oktober";
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case '11':
|
||||||
|
{
|
||||||
|
month = "November";
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case '12':
|
||||||
|
{
|
||||||
|
month = "Desember";
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return month;
|
||||||
|
}
|
||||||
556
app_petty_cash/lib/app/constant.dart
Normal file
556
app_petty_cash/lib/app/constant.dart
Normal file
@@ -0,0 +1,556 @@
|
|||||||
|
// ignore_for_file: prefer_const_constructors, non_constant_identifier_names
|
||||||
|
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
class Constant {
|
||||||
|
static double designHeight = 1024;
|
||||||
|
static double designWidth = 1440;
|
||||||
|
|
||||||
|
static double designHeightPhone = 844;
|
||||||
|
static double designWidthPhone = 390;
|
||||||
|
|
||||||
|
static String bearerName = "petty-cash";
|
||||||
|
static String version = "2.00";
|
||||||
|
|
||||||
|
// static String baseUrl = "https://devregonline.pramita.co.id/one-api/xdoc/";
|
||||||
|
|
||||||
|
// tester devbandungraya
|
||||||
|
static String baseUrl =
|
||||||
|
"http://devbandungraya.aplikasi.web.id/one-api-doctor/doctor_mitra/";
|
||||||
|
|
||||||
|
static String baseUrl_appdoctor =
|
||||||
|
"http://devbandungraya.aplikasi.web.id/one-api/app_doctor/";
|
||||||
|
|
||||||
|
// * surabaya
|
||||||
|
// static String baseUrl =
|
||||||
|
// "http://surabaya.bisone.pramitalab.id/one-api-doctor/doctor_mitra/";
|
||||||
|
|
||||||
|
// static String baseUrl_appdoctor =
|
||||||
|
// "http://surabaya.bisone.pramitalab.id/one-api/app_doctor/";
|
||||||
|
|
||||||
|
// * jakarta
|
||||||
|
// static String baseUrl =
|
||||||
|
// "http://jakarta.bisone2.pramitalab.id/one-api-doctor/doctor_mitra/";
|
||||||
|
|
||||||
|
// static String baseUrl_appdoctor =
|
||||||
|
// "http://jakarta.bisone2.pramitalab.id/one-api/app_doctor/";
|
||||||
|
|
||||||
|
// * bandung
|
||||||
|
// static String baseUrl =
|
||||||
|
// "http://bandung.bisone3.pramitalab.id/one-api-doctor/doctor_mitra/";
|
||||||
|
|
||||||
|
// static String baseUrl_appdoctor =
|
||||||
|
// "http://bandung.bisone3.pramitalab.id/one-api/app_doctor/";
|
||||||
|
|
||||||
|
// * salatiga
|
||||||
|
// static String baseUrl =
|
||||||
|
// "http://salatigaraya.bisone7.pramitalab.id/one-api-doctor/doctor_mitra/";
|
||||||
|
|
||||||
|
// static String baseUrl_appdoctor =
|
||||||
|
// "http://salatigaraya.bisone7.pramitalab.id/one-api/app_doctor/";
|
||||||
|
|
||||||
|
// * semarang
|
||||||
|
// static String baseUrl =
|
||||||
|
// "http://semarang.bisone7.pramitalab.id/one-api-doctor/doctor_mitra/";
|
||||||
|
|
||||||
|
// static String baseUrl_appdoctor =
|
||||||
|
// "http://semarang.bisone7.pramitalab.id/one-api/app_doctor/";
|
||||||
|
|
||||||
|
// * magelang
|
||||||
|
// static String baseUrl =
|
||||||
|
// "http://magelang.bisone7.pramitalab.id/one-api-doctor/doctor_mitra/";
|
||||||
|
|
||||||
|
// static String baseUrl_appdoctor =
|
||||||
|
// "http://magelang.bisone7.pramitalab.id/one-api/app_doctor/";
|
||||||
|
|
||||||
|
// // * tegal
|
||||||
|
// static String baseUrl =
|
||||||
|
// "http://tegal.bisone7.pramitalab.id/one-api-doctor/doctor_mitra/";
|
||||||
|
|
||||||
|
// static String baseUrl_appdoctor =
|
||||||
|
// "http://tegal.bisone7.pramitalab.id/one-api/app_doctor/";
|
||||||
|
|
||||||
|
// // * cirebon
|
||||||
|
// static String baseUrl =
|
||||||
|
// "http://cirebon.bisone4.pramitalab.id/one-api-doctor/doctor_mitra/";
|
||||||
|
|
||||||
|
// static String baseUrl_appdoctor =
|
||||||
|
// "http://cirebon.bisone4.pramitalab.id/one-api/app_doctor/";
|
||||||
|
|
||||||
|
// // * tasik
|
||||||
|
// static String baseUrl =
|
||||||
|
// "http://tasikmalaya.bisone2.pramitalab.id/one-api-doctor/doctor_mitra/";
|
||||||
|
|
||||||
|
// static String baseUrl_appdoctor =
|
||||||
|
// "http://tasikmalaya.bisone2.pramitalab.id/one-api/app_doctor/";
|
||||||
|
|
||||||
|
// // * jogja
|
||||||
|
// static String baseUrl =
|
||||||
|
// "http://jogja.bisone.pramitalab.id/one-api-doctor/doctor_mitra/";
|
||||||
|
|
||||||
|
// static String baseUrl_appdoctor =
|
||||||
|
// "http://jogja.bisone.pramitalab.id/one-api/app_doctor/";
|
||||||
|
|
||||||
|
// // * bali
|
||||||
|
// static String baseUrl =
|
||||||
|
// "http://bali.bisone.pramitalab.id/one-api-doctor/doctor_mitra/";
|
||||||
|
|
||||||
|
// static String baseUrl_appdoctor =
|
||||||
|
// "http://bali.bisone.pramitalab.id/one-api/app_doctor/";
|
||||||
|
|
||||||
|
// // * medan
|
||||||
|
// static String baseUrl =
|
||||||
|
// "http://medan.bisone4.pramitalab.id/one-api-doctor/doctor_mitra/";
|
||||||
|
|
||||||
|
// static String baseUrl_appdoctor =
|
||||||
|
// "http://medan.bisone4.pramitalab.id/one-api/app_doctor/";
|
||||||
|
|
||||||
|
// // * palembang
|
||||||
|
// static String baseUrl =
|
||||||
|
// "http://palembang.bisone5.pramitalab.id/one-api-doctor/doctor_mitra/";
|
||||||
|
|
||||||
|
// static String baseUrl_appdoctor =
|
||||||
|
// "http://palembang.bisone5.pramitalab.id/one-api/app_doctor/";
|
||||||
|
|
||||||
|
// // * pontianak
|
||||||
|
// static String baseUrl =
|
||||||
|
// "http://pontianakraya.bisone2.pramitalab.id/one-api-doctor/doctor_mitra/";
|
||||||
|
|
||||||
|
// static String baseUrl_appdoctor =
|
||||||
|
// "http://pontianakraya.bisone2.pramitalab.id/one-api/app_doctor/";
|
||||||
|
|
||||||
|
// // * balikpapan
|
||||||
|
// static String baseUrl =
|
||||||
|
// "http://balikpapan.bisone2.pramitalab.id/one-api-doctor/doctor_mitra/";
|
||||||
|
|
||||||
|
// static String baseUrl_appdoctor =
|
||||||
|
// "http://balikpapan.bisone2.pramitalab.id/one-api/app_doctor/";
|
||||||
|
|
||||||
|
// // * padang
|
||||||
|
// static String baseUrl =
|
||||||
|
// "http://padang.bisone4.pramitalab.id/one-api-doctor/doctor_mitra/";
|
||||||
|
|
||||||
|
// static String baseUrl_appdoctor =
|
||||||
|
// "http://padang.bisone4.pramitalab.id/one-api/app_doctor/";
|
||||||
|
|
||||||
|
// // * pekanbaru
|
||||||
|
// static String baseUrl =
|
||||||
|
// "http://pekanbaru.bisone4.pramitalab.id/one-api-doctor/doctor_mitra/";
|
||||||
|
|
||||||
|
// static String baseUrl_appdoctor =
|
||||||
|
// "http://pekanbaru.bisone4.pramitalab.id/one-api/app_doctor/";
|
||||||
|
|
||||||
|
// // * makassar
|
||||||
|
// static String baseUrl =
|
||||||
|
// "http://makassar.bisone2.pramitalab.id/one-api-doctor/doctor_mitra/";
|
||||||
|
|
||||||
|
// static String baseUrl_appdoctor =
|
||||||
|
// "http://makassar.bisone2.pramitalab.id/one-api/app_doctor/";
|
||||||
|
|
||||||
|
// // * manado
|
||||||
|
// static String baseUrl =
|
||||||
|
// "http://manado.bisone2.pramitalab.id/one-api-doctor/doctor_mitra/";
|
||||||
|
|
||||||
|
// static String baseUrl_appdoctor =
|
||||||
|
// "http://manado.bisone2.pramitalab.id/one-api/app_doctor/";
|
||||||
|
|
||||||
|
// * bekasi
|
||||||
|
// static String baseUrl =
|
||||||
|
// "http://bekasiraya.bisone2.pramitalab.id/one-api-doctor/doctor_mitra/";
|
||||||
|
|
||||||
|
// static String baseUrl_appdoctor =
|
||||||
|
// "http://bekasiraya.bisone2.pramitalab.id/one-api/app_doctor/";
|
||||||
|
|
||||||
|
//color Theme
|
||||||
|
// login marketing
|
||||||
|
static Color subTitleBlack = const Color(0xff000000);
|
||||||
|
static Color backgroundColor = const Color(0xffFFFFFF);
|
||||||
|
static Color buttonLoginBackgroundColor = const Color(0xffE61301);
|
||||||
|
|
||||||
|
static Color buttonRedBackgroundColor = const Color(0xffd90504);
|
||||||
|
static Color textLoginColor = const Color(0xffFFFFFF);
|
||||||
|
static Color shadowLoginMarketing = Colors.grey.withOpacity(0.3);
|
||||||
|
static Color boxDecorationShadowLoginMaketing = Colors.blueGrey;
|
||||||
|
static Color textRedProblemMaketing = const Color(0xffE61301);
|
||||||
|
|
||||||
|
// home
|
||||||
|
static Color backgroundColorWelcome = const Color(0xffE61301);
|
||||||
|
static Color textMonthToDate = const Color(0xff80848E);
|
||||||
|
static Color textListStatusOrder = const Color(0xff070708);
|
||||||
|
static Color confirmed = const Color(0xff0BAF48);
|
||||||
|
static Color backgroundTotalOrderRight = const Color(0xffF6F5F5);
|
||||||
|
static Color dividerHorizontal = const Color(0xffF4F6F8);
|
||||||
|
static Color backgroundTopHome = const Color(0xffFEF0EB);
|
||||||
|
|
||||||
|
// order detail
|
||||||
|
static Color textOrderDetail = const Color(0xff7E7F81);
|
||||||
|
static Color cardConfirmed = const Color(0xffEBF9F0);
|
||||||
|
static Color cardUnconfirmed = const Color(0xffFEF0EB);
|
||||||
|
static Color textDropdown = const Color(0xff282828);
|
||||||
|
|
||||||
|
// pendaftaran Pasien
|
||||||
|
static Color textCardPendaftaranPasien = const Color(0xff2E2D2D);
|
||||||
|
// static Color cardColorPendaftaranPasien = const Color(0xffFDFDFD);
|
||||||
|
static Color cardColorPendaftaranPasien = const Color(0xffF4F6F8);
|
||||||
|
static Color floatingbg = const Color(0xffDC2626);
|
||||||
|
|
||||||
|
// pendaftaran pasien - demografi
|
||||||
|
static Color backgroundCardNetral1_100 = const Color(0xffD1D2D6);
|
||||||
|
static Color backgroundCardGreen_600 = const Color(0xff0BAF48);
|
||||||
|
|
||||||
|
// divider
|
||||||
|
static Color dividerColor = Color(0xffD1D2D6);
|
||||||
|
|
||||||
|
// grey
|
||||||
|
static Color greyColor = Color(0xff80848E);
|
||||||
|
static Color chipText = Color(0xff637381);
|
||||||
|
|
||||||
|
// chip bg color
|
||||||
|
static Color chipBg = Color(0xffEDEFF2);
|
||||||
|
|
||||||
|
// checkbox color
|
||||||
|
static Color checkboxActive = Colors.red;
|
||||||
|
static Color checkboxCheck = Colors.white;
|
||||||
|
static Color checkboxSelected = Colors.red.shade100;
|
||||||
|
|
||||||
|
// icon file
|
||||||
|
static Color fileColor = Color(0xFF087D33);
|
||||||
|
|
||||||
|
// fixing color
|
||||||
|
static Color red_100 = Color(0xffFFB9B3);
|
||||||
|
static Color red_200 = Color(0xffFE8A80);
|
||||||
|
static Color red_300 = Color(0xffFE5B4D);
|
||||||
|
static Color red_400 = Color(0xffFE2C1A);
|
||||||
|
static Color red_500 = Color(0xffE61301);
|
||||||
|
static Color red_600 = Color(0xffB20F01);
|
||||||
|
static Color red_700 = Color(0xff7F0A01);
|
||||||
|
static Color red_800 = Color(0xff4C0600);
|
||||||
|
static Color red_900 = Color(0xff190200);
|
||||||
|
|
||||||
|
static Color green_100 = Color(0xffBCFBD3);
|
||||||
|
static Color green_200 = Color(0xff8CF8B4);
|
||||||
|
static Color green_300 = Color(0xff5CF595);
|
||||||
|
static Color green_400 = Color(0xff2CF275);
|
||||||
|
static Color green_500 = Color(0xff0EDD5B);
|
||||||
|
static Color green_600 = Color(0xff0BAF48);
|
||||||
|
static Color green_700 = Color(0xff087D33);
|
||||||
|
static Color green_800 = Color(0xff054D20);
|
||||||
|
static Color green_900 = Color(0xff021D0C);
|
||||||
|
|
||||||
|
static Color netral_100 = Color(0xffD1D2D6);
|
||||||
|
static Color netral_200 = Color(0xffB6B8BE);
|
||||||
|
static Color netral_300 = Color(0xff9B9EA6);
|
||||||
|
static Color netral_400 = Color(0xff80848E);
|
||||||
|
static Color netral_500 = Color(0xff676A74);
|
||||||
|
static Color netral_600 = Color(0xff4F5259);
|
||||||
|
static Color netral_700 = Color(0xff37393E);
|
||||||
|
static Color netral_800 = Color(0xff1F2023);
|
||||||
|
static Color netral_900 = Color(0xff070708);
|
||||||
|
|
||||||
|
static Color white = Color(0xffFDFDFD);
|
||||||
|
|
||||||
|
static Color textBlack = Color(0xff070708);
|
||||||
|
static Color textRed = Color(0xffE61301);
|
||||||
|
static Color textGrey = Color(0xff80848E);
|
||||||
|
static Color textWhite = Color(0xffFDFDFD);
|
||||||
|
static Color textGreen = Color(0xff0BAF48);
|
||||||
|
|
||||||
|
//typoGraphy
|
||||||
|
static TextStyle titleH1Login({required BuildContext context}) {
|
||||||
|
return TextStyle(
|
||||||
|
fontSize: Constant.getActualYPhone(context: context, y: 24),
|
||||||
|
fontWeight: FontWeight.w700,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
static TextStyle titleH3_700({required BuildContext context}) {
|
||||||
|
return TextStyle(
|
||||||
|
fontSize: Constant.getActualYPhone(context: context, y: 24),
|
||||||
|
fontWeight: FontWeight.w700,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
static TextStyle titleH3_700V2({required BuildContext context}) {
|
||||||
|
return TextStyle(
|
||||||
|
fontSize: Constant.getActualYPhone(context: context, y: 32),
|
||||||
|
fontWeight: FontWeight.w700,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
static TextStyle titleH3_700GantiPassword({required BuildContext context}) {
|
||||||
|
return TextStyle(
|
||||||
|
fontSize: Constant.getActualYPhone(context: context, y: 14),
|
||||||
|
fontWeight: FontWeight.w500,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
static TextStyle titleH3_700SignOut({required BuildContext context}) {
|
||||||
|
return TextStyle(
|
||||||
|
fontSize: Constant.getActualYPhone(context: context, y: 30),
|
||||||
|
fontWeight: FontWeight.w600,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
static TextStyle titleH4Login({required BuildContext context}) {
|
||||||
|
return TextStyle(
|
||||||
|
fontSize: Constant.getActualYPhone(context: context, y: 16),
|
||||||
|
fontWeight: FontWeight.w400,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// homescreen
|
||||||
|
static TextStyle titleLast30Days({required BuildContext context}) {
|
||||||
|
return TextStyle(
|
||||||
|
fontSize: Constant.getActualYPhone(context: context, y: 16),
|
||||||
|
fontWeight: FontWeight.w700,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
static TextStyle titleH4_500({required BuildContext context}) {
|
||||||
|
return TextStyle(
|
||||||
|
fontSize: Constant.getActualYPhone(context: context, y: 20),
|
||||||
|
fontWeight: FontWeight.w500,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
static TextStyle H4_500({required BuildContext context}) {
|
||||||
|
return TextStyle(
|
||||||
|
fontSize: Constant.getActualYPhone(context: context, y: 20),
|
||||||
|
fontWeight: FontWeight.w500,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
static TextStyle H4_600({required BuildContext context}) {
|
||||||
|
return TextStyle(
|
||||||
|
fontSize: Constant.getActualYPhone(context: context, y: 20),
|
||||||
|
fontWeight: FontWeight.w600,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
static TextStyle H4_700V2({required BuildContext context}) {
|
||||||
|
return TextStyle(
|
||||||
|
fontSize: Constant.getActualYPhone(context: context, y: 28),
|
||||||
|
fontWeight: FontWeight.w700,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
static TextStyle titleH5({required BuildContext context}) {
|
||||||
|
return TextStyle(
|
||||||
|
fontSize: Constant.getActualYPhone(context: context, y: 18),
|
||||||
|
fontWeight: FontWeight.w500,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
static TextStyle caption1_400({required BuildContext context}) {
|
||||||
|
return TextStyle(
|
||||||
|
fontSize: Constant.getActualYPhone(context: context, y: 11),
|
||||||
|
fontWeight: FontWeight.w400,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
static TextStyle caption3_500({required BuildContext context}) {
|
||||||
|
return TextStyle(
|
||||||
|
fontSize: Constant.getActualYPhone(context: context, y: 9),
|
||||||
|
fontWeight: FontWeight.w500,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
static TextStyle titleH2({required BuildContext context}) {
|
||||||
|
return TextStyle(
|
||||||
|
fontSize: Constant.getActualYPhone(context: context, y: 32),
|
||||||
|
fontWeight: FontWeight.w500,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
static TextStyle titleH1_600({required BuildContext context}) {
|
||||||
|
return TextStyle(
|
||||||
|
fontSize: Constant.getActualYPhone(context: context, y: 36),
|
||||||
|
fontWeight: FontWeight.w600,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
static TextStyle body3({required BuildContext context}) {
|
||||||
|
return TextStyle(
|
||||||
|
fontSize: Constant.getActualYPhone(context: context, y: 12),
|
||||||
|
fontWeight: FontWeight.w400,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
static TextStyle body1({required BuildContext context}) {
|
||||||
|
return TextStyle(
|
||||||
|
fontSize: Constant.getActualYPhone(context: context, y: 16),
|
||||||
|
fontWeight: FontWeight.w500,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
static TextStyle body1_400({required BuildContext context}) {
|
||||||
|
return TextStyle(
|
||||||
|
fontSize: Constant.getActualYPhone(context: context, y: 16),
|
||||||
|
fontWeight: FontWeight.w400,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
static TextStyle body1_400_dibulan({required BuildContext context}) {
|
||||||
|
return TextStyle(
|
||||||
|
fontSize: Constant.getActualYPhone(context: context, y: 14),
|
||||||
|
fontWeight: FontWeight.w400,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
static TextStyle body1_600({required BuildContext context}) {
|
||||||
|
return TextStyle(
|
||||||
|
fontSize: Constant.getActualYPhone(context: context, y: 16),
|
||||||
|
fontWeight: FontWeight.w600,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
static TextStyle body1_500({required BuildContext context}) {
|
||||||
|
return TextStyle(
|
||||||
|
fontSize: Constant.getActualYPhone(context: context, y: 16),
|
||||||
|
fontWeight: FontWeight.w500,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
static TextStyle body2_400({required BuildContext context}) {
|
||||||
|
return TextStyle(
|
||||||
|
fontSize: Constant.getActualYPhone(context: context, y: 14),
|
||||||
|
fontWeight: FontWeight.w400,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
static TextStyle titleH3({required BuildContext context}) {
|
||||||
|
return TextStyle(
|
||||||
|
fontSize: Constant.getActualYPhone(context: context, y: 24),
|
||||||
|
fontWeight: FontWeight.w500,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
static TextStyle titleH3_600({required BuildContext context}) {
|
||||||
|
return TextStyle(
|
||||||
|
fontSize: Constant.getActualYPhone(context: context, y: 24),
|
||||||
|
fontWeight: FontWeight.w600,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
static TextStyle H3_600({required BuildContext context}) {
|
||||||
|
return TextStyle(
|
||||||
|
fontSize: Constant.getActualYPhone(context: context, y: 24),
|
||||||
|
fontWeight: FontWeight.w600,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
static TextStyle H3_500({required BuildContext context}) {
|
||||||
|
return TextStyle(
|
||||||
|
fontSize: Constant.getActualYPhone(context: context, y: 24),
|
||||||
|
fontWeight: FontWeight.w500,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
static TextStyle H5_500({required BuildContext context}) {
|
||||||
|
return TextStyle(
|
||||||
|
fontSize: Constant.getActualYPhone(context: context, y: 18),
|
||||||
|
fontWeight: FontWeight.w500,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
static TextStyle body2({required BuildContext context}) {
|
||||||
|
return TextStyle(
|
||||||
|
fontSize: Constant.getActualYPhone(context: context, y: 14),
|
||||||
|
fontWeight: FontWeight.w400,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
static TextStyle body2_500({required BuildContext context}) {
|
||||||
|
return TextStyle(
|
||||||
|
fontSize: Constant.getActualYPhone(context: context, y: 14),
|
||||||
|
fontWeight: FontWeight.w400,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
static TextStyle body2_500_italic({required BuildContext context}) {
|
||||||
|
return TextStyle(
|
||||||
|
fontSize: Constant.getActualYPhone(context: context, y: 14),
|
||||||
|
fontWeight: FontWeight.w400,
|
||||||
|
fontStyle: FontStyle.italic);
|
||||||
|
}
|
||||||
|
|
||||||
|
static TextStyle body1_700({required BuildContext context}) {
|
||||||
|
return TextStyle(
|
||||||
|
fontSize: Constant.getActualYPhone(context: context, y: 16),
|
||||||
|
fontWeight: FontWeight.w700,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
static TextStyle H3_700({required BuildContext context}) {
|
||||||
|
return TextStyle(
|
||||||
|
fontSize: Constant.getActualYPhone(context: context, y: 24),
|
||||||
|
fontWeight: FontWeight.w700,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
static TextStyle body3_400({required BuildContext context}) {
|
||||||
|
return TextStyle(
|
||||||
|
fontSize: Constant.getActualYPhone(context: context, y: 12),
|
||||||
|
fontWeight: FontWeight.w400,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
static TextStyle body3_500({required BuildContext context}) {
|
||||||
|
return TextStyle(
|
||||||
|
fontSize: Constant.getActualYPhone(context: context, y: 12),
|
||||||
|
fontWeight: FontWeight.w500,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
static TextStyle titleH7_700({required BuildContext context}) {
|
||||||
|
return TextStyle(
|
||||||
|
fontSize: Constant.getActualYPhone(context: context, y: 12),
|
||||||
|
fontWeight: FontWeight.w700,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// pendaftaran pasien
|
||||||
|
static TextStyle titleH5_600({required BuildContext context}) {
|
||||||
|
return TextStyle(
|
||||||
|
fontSize: Constant.getActualYPhone(context: context, y: 18),
|
||||||
|
fontWeight: FontWeight.w600,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// demografi
|
||||||
|
static TextStyle body2_600({required BuildContext context}) {
|
||||||
|
return TextStyle(
|
||||||
|
fontSize: Constant.getActualYPhone(context: context, y: 14),
|
||||||
|
fontWeight: FontWeight.w600,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
//size convertion
|
||||||
|
static double getActualX({
|
||||||
|
required BuildContext context,
|
||||||
|
required double x,
|
||||||
|
}) {
|
||||||
|
return x / designWidth * MediaQuery.of(context).size.width;
|
||||||
|
}
|
||||||
|
|
||||||
|
static double getActualY({
|
||||||
|
required BuildContext context,
|
||||||
|
required double y,
|
||||||
|
}) {
|
||||||
|
return y / designHeight * MediaQuery.of(context).size.height;
|
||||||
|
}
|
||||||
|
|
||||||
|
static double getActualXPhone({
|
||||||
|
required BuildContext context,
|
||||||
|
required double x,
|
||||||
|
}) {
|
||||||
|
return x / designWidthPhone * MediaQuery.of(context).size.width;
|
||||||
|
}
|
||||||
|
|
||||||
|
static double getActualYPhone({
|
||||||
|
required BuildContext context,
|
||||||
|
required double y,
|
||||||
|
}) {
|
||||||
|
return y / designHeightPhone * MediaQuery.of(context).size.height;
|
||||||
|
}
|
||||||
|
}
|
||||||
19
app_petty_cash/lib/app/route.dart
Normal file
19
app_petty_cash/lib/app/route.dart
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
import '../screen/login/login_screen.dart';
|
||||||
|
|
||||||
|
const loginRoute = "/loginRoute";
|
||||||
|
const menuRoute = "/menuRoute";
|
||||||
|
|
||||||
|
class AppRoute {
|
||||||
|
static Route<dynamic> generateRoute(RouteSettings settings) {
|
||||||
|
// default
|
||||||
|
return MaterialPageRoute(builder: (context) {
|
||||||
|
return MediaQuery(
|
||||||
|
data: MediaQuery.of(context)
|
||||||
|
.copyWith(textScaleFactor: 1.0, padding: const EdgeInsets.all(0)),
|
||||||
|
child: const LoginScreen(),
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
72
app_petty_cash/lib/model/auth_model.dart
Normal file
72
app_petty_cash/lib/model/auth_model.dart
Normal file
@@ -0,0 +1,72 @@
|
|||||||
|
class AuthModel {
|
||||||
|
final String token;
|
||||||
|
final AuthDoctorModel model;
|
||||||
|
|
||||||
|
AuthModel({
|
||||||
|
required this.token,
|
||||||
|
required this.model,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
class AuthDoctorModel {
|
||||||
|
|
||||||
|
// "M_UserID": "1",
|
||||||
|
// "M_UserUsername": "alhadad",
|
||||||
|
// "M_UserM_DoctorCode": "3101210841",
|
||||||
|
// "M_UserM_DoctorID": "9562",
|
||||||
|
// "M_UserM_StaffID": "376",
|
||||||
|
// "ip": "139.194.156.91",
|
||||||
|
// "agent": "PostmanRuntime/7.29.2"
|
||||||
|
|
||||||
|
late String doctorID;
|
||||||
|
late String doctorName;
|
||||||
|
|
||||||
|
// new
|
||||||
|
late String M_UserID;
|
||||||
|
late String M_UserUsername;
|
||||||
|
late String M_UserM_DoctorCode;
|
||||||
|
late String M_UserM_DoctorID;
|
||||||
|
late String M_UserM_StaffID;
|
||||||
|
late String M_UserM_MouID;
|
||||||
|
late String ip;
|
||||||
|
late String agent;
|
||||||
|
|
||||||
|
AuthDoctorModel({
|
||||||
|
// required this.doctorID,
|
||||||
|
// required this.doctorName,
|
||||||
|
|
||||||
|
required this.M_UserID,
|
||||||
|
required this.M_UserUsername,
|
||||||
|
required this.M_UserM_DoctorCode,
|
||||||
|
required this.M_UserM_DoctorID,
|
||||||
|
this.M_UserM_StaffID = "",
|
||||||
|
this.M_UserM_MouID = "",
|
||||||
|
this.ip = "",
|
||||||
|
this.agent = ""
|
||||||
|
});
|
||||||
|
|
||||||
|
AuthDoctorModel.fromJson(Map<String, dynamic> json) {
|
||||||
|
M_UserID = json['M_UserID'].toString();
|
||||||
|
M_UserUsername = json['M_UserUsername'].toString();
|
||||||
|
M_UserM_DoctorCode = json['M_UserM_DoctorCode'].toString();
|
||||||
|
M_UserM_DoctorID = json['M_UserM_DoctorID'].toString();
|
||||||
|
M_UserM_StaffID = json['M_UserM_StaffID'].toString();
|
||||||
|
M_UserM_MouID = json['M_UserM_MouID'].toString();
|
||||||
|
ip = json['ip'].toString();
|
||||||
|
agent = json['agent'].toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
Map<String, dynamic> toJson() {
|
||||||
|
final Map<String, dynamic> data = <String, dynamic>{};
|
||||||
|
data['M_UserID'] = M_UserID;
|
||||||
|
data['M_UserUsername'] = M_UserUsername;
|
||||||
|
data['M_UserM_DoctorCode'] = M_UserM_DoctorCode;
|
||||||
|
data['M_UserM_DoctorID'] = M_UserM_DoctorID;
|
||||||
|
data['M_UserM_StaffID'] = M_UserM_StaffID;
|
||||||
|
data['M_UserM_MouID'] = M_UserM_MouID;
|
||||||
|
data['ip'] = ip;
|
||||||
|
data['agent'] = agent;
|
||||||
|
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
}
|
||||||
3
app_petty_cash/lib/provider/current_menu_provider.dart
Normal file
3
app_petty_cash/lib/provider/current_menu_provider.dart
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||||
|
|
||||||
|
final currentPageProvider = StateProvider<int?>((ref) => null);
|
||||||
4
app_petty_cash/lib/provider/current_user_provider.dart
Normal file
4
app_petty_cash/lib/provider/current_user_provider.dart
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||||
|
import '../model/auth_model.dart';
|
||||||
|
|
||||||
|
final currentUserProvider = StateProvider<AuthModel?>((ref) => null);
|
||||||
4
app_petty_cash/lib/provider/dio_provider.dart
Normal file
4
app_petty_cash/lib/provider/dio_provider.dart
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
import 'package:dio/dio.dart';
|
||||||
|
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||||
|
|
||||||
|
final dioProvider = Provider<Dio>((ref) => Dio());
|
||||||
90
app_petty_cash/lib/repository/auth_repository.dart
Normal file
90
app_petty_cash/lib/repository/auth_repository.dart
Normal file
@@ -0,0 +1,90 @@
|
|||||||
|
import '../app/constant.dart';
|
||||||
|
import '../model/auth_model.dart';
|
||||||
|
import 'base_repository.dart';
|
||||||
|
|
||||||
|
class AuthRepository extends BaseRepository {
|
||||||
|
AuthRepository({required super.dio});
|
||||||
|
|
||||||
|
Future<AuthModel> login({
|
||||||
|
required String username,
|
||||||
|
required String dokterId,
|
||||||
|
required String password,
|
||||||
|
}) async {
|
||||||
|
final param = {
|
||||||
|
"username": username,
|
||||||
|
"doctor_id": dokterId,
|
||||||
|
"password": password
|
||||||
|
|
||||||
|
// "username": "alhadad1",
|
||||||
|
// "doctor_id": "2891",
|
||||||
|
// "password": "3"
|
||||||
|
};
|
||||||
|
// final service = "${Constant.baseUrl}xauth/login";
|
||||||
|
final service = "${Constant.baseUrl}auth/login";
|
||||||
|
final resp = await post(param: param, service: service);
|
||||||
|
final result = AuthModel(
|
||||||
|
token: resp["data"]["token"],
|
||||||
|
model: AuthDoctorModel.fromJson(resp["data"]["user"]),
|
||||||
|
);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<String> logout({
|
||||||
|
required String M_UserID,
|
||||||
|
required String M_UserUsername,
|
||||||
|
}) async {
|
||||||
|
final param = {
|
||||||
|
"M_UserID": M_UserID,
|
||||||
|
"M_UserUsername": M_UserUsername
|
||||||
|
// "username": "alhadad",
|
||||||
|
// "doctor_id": "3101210841",
|
||||||
|
// "password": "riau123"
|
||||||
|
};
|
||||||
|
|
||||||
|
final service = "${Constant.baseUrl}auth/logout";
|
||||||
|
final resp = await post(param: param, service: service);
|
||||||
|
|
||||||
|
if (resp["status"] == "OK") {
|
||||||
|
return resp['status'];
|
||||||
|
} else {
|
||||||
|
return resp['message'];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<String> change_password({
|
||||||
|
required String token,
|
||||||
|
required String M_UserID,
|
||||||
|
required String username,
|
||||||
|
required String doctor_id,
|
||||||
|
required String new_password,
|
||||||
|
required String confirm_password,
|
||||||
|
}) async {
|
||||||
|
final param = {
|
||||||
|
"token": token,
|
||||||
|
"M_UserID": M_UserID,
|
||||||
|
"username": username,
|
||||||
|
"doctor_id": doctor_id,
|
||||||
|
"new_password": new_password,
|
||||||
|
"confirm_password": confirm_password
|
||||||
|
|
||||||
|
// "username": "alhadad",
|
||||||
|
// "doctor_id": "3101210841",
|
||||||
|
// "password": "riau123"
|
||||||
|
};
|
||||||
|
|
||||||
|
final service = "${Constant.baseUrl}auth/change_password";
|
||||||
|
final resp = await post(param: param, service: service);
|
||||||
|
|
||||||
|
// final result = AuthModel(
|
||||||
|
// token: resp["data"]["token"],
|
||||||
|
// model: AuthDoctorModel.fromJson(resp["data"]["user"]),
|
||||||
|
// );
|
||||||
|
// return result;
|
||||||
|
|
||||||
|
if (resp["status"] == "OK") {
|
||||||
|
return resp['message'];
|
||||||
|
} else {
|
||||||
|
return resp['message'];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
104
app_petty_cash/lib/repository/base_repository.dart
Normal file
104
app_petty_cash/lib/repository/base_repository.dart
Normal file
@@ -0,0 +1,104 @@
|
|||||||
|
import 'dart:convert';
|
||||||
|
import 'dart:io';
|
||||||
|
|
||||||
|
import 'package:dio/dio.dart';
|
||||||
|
|
||||||
|
abstract class BaseRepository {
|
||||||
|
final Dio dio;
|
||||||
|
BaseRepository({required this.dio});
|
||||||
|
|
||||||
|
Future<Map<String, dynamic>> post({
|
||||||
|
required Map<String, dynamic> param,
|
||||||
|
required String service,
|
||||||
|
String? token,
|
||||||
|
}) async {
|
||||||
|
try {
|
||||||
|
final response = await dio.post(
|
||||||
|
// Constant.baseUrl + service,
|
||||||
|
service,
|
||||||
|
data: jsonEncode(param),
|
||||||
|
options: Options(
|
||||||
|
headers: token != null
|
||||||
|
? {
|
||||||
|
HttpHeaders.contentTypeHeader: "application/json",
|
||||||
|
HttpHeaders.authorizationHeader: "Bearer $token",
|
||||||
|
}
|
||||||
|
: {
|
||||||
|
HttpHeaders.contentTypeHeader: "application/json",
|
||||||
|
},
|
||||||
|
contentType: "application/json",
|
||||||
|
),
|
||||||
|
);
|
||||||
|
if (response.statusCode != 200) {
|
||||||
|
throw BaseRepositoryException(
|
||||||
|
message: "Invalid Http Response ${response.statusCode}",
|
||||||
|
);
|
||||||
|
}
|
||||||
|
Map<String, dynamic> jsonData = jsonDecode(response.data);
|
||||||
|
if (jsonData["status"] != "OK") {
|
||||||
|
throw BaseRepositoryException(
|
||||||
|
message: jsonData["message"],
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
return jsonData;
|
||||||
|
}
|
||||||
|
} on DioError catch (e) {
|
||||||
|
throw BaseRepositoryException(message: e.message);
|
||||||
|
} on SocketException catch (e) {
|
||||||
|
throw BaseRepositoryException(message: e.message);
|
||||||
|
} on BaseRepositoryException catch (e) {
|
||||||
|
throw BaseRepositoryException(message: e.message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<Map<String, dynamic>> get({
|
||||||
|
// required Map<String, dynamic> param,
|
||||||
|
required String service,
|
||||||
|
String? token,
|
||||||
|
}) async {
|
||||||
|
try {
|
||||||
|
final response = await dio.post(
|
||||||
|
// Constant.baseUrl + service,
|
||||||
|
service,
|
||||||
|
// data: jsonEncode(param),
|
||||||
|
options: Options(
|
||||||
|
headers: token != null
|
||||||
|
? {
|
||||||
|
HttpHeaders.contentTypeHeader: "application/json",
|
||||||
|
HttpHeaders.authorizationHeader: "Bearer $token",
|
||||||
|
}
|
||||||
|
: {
|
||||||
|
HttpHeaders.contentTypeHeader: "application/json",
|
||||||
|
},
|
||||||
|
contentType: "application/json",
|
||||||
|
),
|
||||||
|
);
|
||||||
|
if (response.statusCode != 200) {
|
||||||
|
throw BaseRepositoryException(
|
||||||
|
message: "Invalid Http Response ${response.statusCode}",
|
||||||
|
);
|
||||||
|
}
|
||||||
|
Map<String, dynamic> jsonData = jsonDecode(response.data);
|
||||||
|
if (jsonData["status"] != "OK") {
|
||||||
|
throw BaseRepositoryException(
|
||||||
|
message: jsonData["message"],
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
return jsonData;
|
||||||
|
}
|
||||||
|
} on DioError catch (e) {
|
||||||
|
throw BaseRepositoryException(message: e.message);
|
||||||
|
} on SocketException catch (e) {
|
||||||
|
throw BaseRepositoryException(message: e.message);
|
||||||
|
} on BaseRepositoryException catch (e) {
|
||||||
|
throw BaseRepositoryException(message: e.message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class BaseRepositoryException implements Exception {
|
||||||
|
final String message;
|
||||||
|
BaseRepositoryException({
|
||||||
|
required this.message,
|
||||||
|
});
|
||||||
|
}
|
||||||
278
app_petty_cash/lib/screen/login/block_body.dart
Normal file
278
app_petty_cash/lib/screen/login/block_body.dart
Normal file
@@ -0,0 +1,278 @@
|
|||||||
|
// ignore_for_file: prefer_const_constructors, use_full_hex_values_for_flutter_colors
|
||||||
|
|
||||||
|
import 'dart:async';
|
||||||
|
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_hooks/flutter_hooks.dart';
|
||||||
|
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||||
|
|
||||||
|
import '../../app/constant.dart';
|
||||||
|
import '../../app/route.dart';
|
||||||
|
import '../../provider/current_menu_provider.dart';
|
||||||
|
import '../../provider/current_user_provider.dart';
|
||||||
|
import 'custom_text_field.dart';
|
||||||
|
import 'login_provider.dart';
|
||||||
|
|
||||||
|
class BlockBody extends HookConsumerWidget {
|
||||||
|
const BlockBody({
|
||||||
|
Key? key,
|
||||||
|
}) : super(key: key);
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context, WidgetRef ref) {
|
||||||
|
final isPasswordObscured = useState<bool>(true);
|
||||||
|
final ctrlUsername = useTextEditingController(text: "");
|
||||||
|
final ctrlDokterId = useTextEditingController(text: "");
|
||||||
|
final ctrlPassword = useTextEditingController(text: "");
|
||||||
|
final isLoading = useState(false);
|
||||||
|
final errorMessage = useState("");
|
||||||
|
final isSuccess = useState(false);
|
||||||
|
|
||||||
|
ref.listen(loginProvider, (prev, next) {
|
||||||
|
if (next is LoginStateLoading) {
|
||||||
|
isLoading.value = true;
|
||||||
|
} else if (next is LoginStateError) {
|
||||||
|
isLoading.value = false;
|
||||||
|
errorMessage.value = next.message;
|
||||||
|
Timer(const Duration(seconds: 3), () {
|
||||||
|
errorMessage.value = "";
|
||||||
|
});
|
||||||
|
} else if (next is LoginStateDone) {
|
||||||
|
isLoading.value = false;
|
||||||
|
isSuccess.value = true;
|
||||||
|
ref.read(currentPageProvider.state).update((state) => 0);
|
||||||
|
ref.read(currentUserProvider.notifier).state = next.model;
|
||||||
|
|
||||||
|
// print(next.model.model.doctorName);
|
||||||
|
|
||||||
|
// Navigator.of(context).pop();
|
||||||
|
// Navigator.of(context).pushNamedAndRemoveUntil(menuRoute,(route) => true,);
|
||||||
|
// Navigator.popAndPushNamed(context,menuRoute);
|
||||||
|
|
||||||
|
Navigator.of(context)
|
||||||
|
.pushNamedAndRemoveUntil(menuRoute, (route) => false);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return ListView(
|
||||||
|
children: [
|
||||||
|
Container(
|
||||||
|
width: Constant.getActualXPhone(context: context, x: 390),
|
||||||
|
height: Constant.getActualYPhone(context: context, y: 343),
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
image: DecorationImage(
|
||||||
|
image: AssetImage('images/header_tanpa_logo.png'),
|
||||||
|
fit: BoxFit.cover,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
child: Column(
|
||||||
|
children: [
|
||||||
|
SizedBox(
|
||||||
|
height: Constant.getActualYPhone(context: context, y: 136),
|
||||||
|
),
|
||||||
|
Container(
|
||||||
|
width: Constant.getActualXPhone(context: context, x: 148),
|
||||||
|
height: Constant.getActualYPhone(context: context, y: 78),
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
image: DecorationImage(
|
||||||
|
fit: BoxFit.fitHeight,
|
||||||
|
image: AssetImage('images/logo_pramita.png'),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
SizedBox(
|
||||||
|
height: Constant.getActualYPhone(context: context, y: 43),
|
||||||
|
),
|
||||||
|
Container(
|
||||||
|
width: Constant.getActualXPhone(context: context, x: 391),
|
||||||
|
height: Constant.getActualYPhone(context: context, y: 454),
|
||||||
|
padding: EdgeInsets.only(
|
||||||
|
left: Constant.getActualXPhone(context: context, x: 32),
|
||||||
|
right: Constant.getActualXPhone(context: context, x: 32),
|
||||||
|
top: Constant.getActualYPhone(context: context, y: 20),
|
||||||
|
bottom: Constant.getActualYPhone(context: context, y: 20),
|
||||||
|
),
|
||||||
|
child: Column(
|
||||||
|
children: [
|
||||||
|
// form
|
||||||
|
SizedBox(
|
||||||
|
width: Constant.getActualXPhone(context: context, x: 180),
|
||||||
|
height: Constant.getActualYPhone(context: context, y: 29),
|
||||||
|
child: Align(
|
||||||
|
alignment: Alignment.center,
|
||||||
|
child: Text("LOGIN DOKTER",
|
||||||
|
style: Constant.titleH3_700(context: context)
|
||||||
|
.copyWith(color: Constant.subTitleBlack)),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
|
||||||
|
SizedBox(
|
||||||
|
height: Constant.getActualYPhone(context: context, y: 4),
|
||||||
|
),
|
||||||
|
|
||||||
|
// notify error dari backend start
|
||||||
|
|
||||||
|
if (isLoading.value)
|
||||||
|
SizedBox(
|
||||||
|
width: Constant.getActualXPhone(context: context, x: 20),
|
||||||
|
height: Constant.getActualYPhone(context: context, y: 20),
|
||||||
|
child: CircularProgressIndicator(),
|
||||||
|
),
|
||||||
|
|
||||||
|
if (errorMessage.value != "")
|
||||||
|
Text(
|
||||||
|
"Peringatan : ${errorMessage.value}",
|
||||||
|
style: Constant.titleH7_700(context: context)
|
||||||
|
.copyWith(color: Constant.textRedProblemMaketing),
|
||||||
|
),
|
||||||
|
|
||||||
|
// notify error dari backend end
|
||||||
|
|
||||||
|
SizedBox(
|
||||||
|
height: Constant.getActualYPhone(context: context, y: 24),
|
||||||
|
),
|
||||||
|
// textfield marketing ID
|
||||||
|
SizedBox(
|
||||||
|
width: Constant.getActualXPhone(context: context, x: 320),
|
||||||
|
height: Constant.getActualYPhone(context: context, y: 50),
|
||||||
|
child: CustomTextField(
|
||||||
|
ctrl: ctrlDokterId,
|
||||||
|
isPassword: false,
|
||||||
|
hintText: "Doctor ID",
|
||||||
|
labelText: "Doctor ID",
|
||||||
|
isError: (errorMessage.value != "") ? true : false,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
|
||||||
|
SizedBox(
|
||||||
|
height: Constant.getActualYPhone(context: context, y: 20),
|
||||||
|
),
|
||||||
|
// textfield username
|
||||||
|
SizedBox(
|
||||||
|
width: Constant.getActualXPhone(context: context, x: 320),
|
||||||
|
height: Constant.getActualYPhone(context: context, y: 50),
|
||||||
|
child: CustomTextField(
|
||||||
|
ctrl: ctrlUsername,
|
||||||
|
isPassword: false,
|
||||||
|
hintText: "Username",
|
||||||
|
labelText: "Username",
|
||||||
|
isError: (errorMessage.value != "") ? true : false,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
|
||||||
|
SizedBox(
|
||||||
|
height: Constant.getActualYPhone(context: context, y: 20),
|
||||||
|
),
|
||||||
|
// textfield password
|
||||||
|
SizedBox(
|
||||||
|
width: Constant.getActualXPhone(context: context, x: 320),
|
||||||
|
height: Constant.getActualYPhone(context: context, y: 50),
|
||||||
|
child: CustomTextField(
|
||||||
|
ctrl: ctrlPassword,
|
||||||
|
isPassword: false,
|
||||||
|
obscureText: isPasswordObscured.value,
|
||||||
|
hintText: "Password",
|
||||||
|
labelText: "Password",
|
||||||
|
onToggle: () {
|
||||||
|
isPasswordObscured.value = !isPasswordObscured.value;
|
||||||
|
},
|
||||||
|
isError: (errorMessage.value != "") ? true : false,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
|
||||||
|
SizedBox(
|
||||||
|
height: Constant.getActualYPhone(context: context, y: 40),
|
||||||
|
),
|
||||||
|
// button login
|
||||||
|
SizedBox(
|
||||||
|
width: Constant.getActualXPhone(context: context, x: 320),
|
||||||
|
height: Constant.getActualYPhone(context: context, y: 50),
|
||||||
|
child: ElevatedButton(
|
||||||
|
onPressed: (isSuccess.value == true)
|
||||||
|
? () {}
|
||||||
|
: () {
|
||||||
|
if (ctrlUsername.text.isEmpty ||
|
||||||
|
ctrlDokterId.text.isEmpty ||
|
||||||
|
ctrlPassword.text.isEmpty) {
|
||||||
|
isLoading.value = true;
|
||||||
|
errorMessage.value = 'Inputan harus diisi';
|
||||||
|
Timer(const Duration(seconds: 3), () {
|
||||||
|
isLoading.value = false;
|
||||||
|
errorMessage.value = "";
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
ref.read(loginProvider.notifier).login(
|
||||||
|
username: ctrlUsername.text,
|
||||||
|
dokterId: ctrlDokterId.text,
|
||||||
|
password: ctrlPassword.text);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
style: ButtonStyle(
|
||||||
|
backgroundColor: MaterialStateColor.resolveWith((st) =>
|
||||||
|
(isSuccess.value == true)
|
||||||
|
? Constant.textGrey
|
||||||
|
: Constant.buttonLoginBackgroundColor),
|
||||||
|
shape: MaterialStateProperty.all<RoundedRectangleBorder>(
|
||||||
|
RoundedRectangleBorder(
|
||||||
|
borderRadius: BorderRadius.circular(8.0),
|
||||||
|
side: BorderSide(color: Colors.red),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
shadowColor: MaterialStateProperty.all(Color(0xffff48423d)),
|
||||||
|
elevation: MaterialStateProperty.all(4.0),
|
||||||
|
),
|
||||||
|
child: Align(
|
||||||
|
alignment: Alignment.center,
|
||||||
|
child: Text(
|
||||||
|
'LOGIN',
|
||||||
|
style: Constant.titleH3_700(context: context)
|
||||||
|
.copyWith(color: Constant.textLoginColor),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
|
||||||
|
SizedBox(
|
||||||
|
height: Constant.getActualYPhone(context: context, y: 22),
|
||||||
|
),
|
||||||
|
|
||||||
|
// versi
|
||||||
|
Align(
|
||||||
|
alignment: Alignment.center,
|
||||||
|
child: Text(
|
||||||
|
'Versi ${Constant.version}',
|
||||||
|
style: Constant.titleH4Login(context: context)
|
||||||
|
.copyWith(color: Constant.textGrey),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
|
||||||
|
// text problem login
|
||||||
|
|
||||||
|
// SizedBox(
|
||||||
|
// width: Constant.getActualXPhone(context: context, x: 121),
|
||||||
|
// height: Constant.getActualYPhone(context: context, y: 20),
|
||||||
|
// // color: Colors.brown,
|
||||||
|
// child: Align(
|
||||||
|
// alignment: Alignment.center,
|
||||||
|
// child: InkWell(
|
||||||
|
// onTap: () {
|
||||||
|
// Navigator.of(context).pushNamed(problemLoginRoute);
|
||||||
|
// },
|
||||||
|
// child: Text(
|
||||||
|
// 'Problem Login ? ',
|
||||||
|
// style: Constant.body1_400(context: context)
|
||||||
|
// .copyWith(color: Constant.textRedProblemMaketing),
|
||||||
|
// ),
|
||||||
|
// ),
|
||||||
|
// ),
|
||||||
|
// ),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
375
app_petty_cash/lib/screen/login/block_bodyv2.dart
Normal file
375
app_petty_cash/lib/screen/login/block_bodyv2.dart
Normal file
@@ -0,0 +1,375 @@
|
|||||||
|
// ignore_for_file: prefer_const_constructors, use_full_hex_values_for_flutter_colors
|
||||||
|
|
||||||
|
import 'dart:async';
|
||||||
|
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter/services.dart';
|
||||||
|
import 'package:flutter_hooks/flutter_hooks.dart';
|
||||||
|
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||||
|
|
||||||
|
import '../../app/constant.dart';
|
||||||
|
import '../../app/route.dart';
|
||||||
|
import '../../provider/current_menu_provider.dart';
|
||||||
|
import '../../provider/current_user_provider.dart';
|
||||||
|
import 'custom_text_field.dart';
|
||||||
|
import 'login_provider.dart';
|
||||||
|
|
||||||
|
class BlockBodyV2 extends HookConsumerWidget {
|
||||||
|
const BlockBodyV2({
|
||||||
|
Key? key,
|
||||||
|
}) : super(key: key);
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context, WidgetRef ref) {
|
||||||
|
final isPasswordObscured = useState<bool>(true);
|
||||||
|
final ctrlUsername = useTextEditingController(text: "");
|
||||||
|
final ctrlDokterId = useTextEditingController(text: "");
|
||||||
|
final ctrlPassword = useTextEditingController(text: "");
|
||||||
|
final isLoading = useState(false);
|
||||||
|
final errorMessage = useState("");
|
||||||
|
final isSuccess = useState(false);
|
||||||
|
final focusNodeDokterID = useFocusNode();
|
||||||
|
final focusNodeDokterUsername = useFocusNode();
|
||||||
|
final focusNodeDokterPassword = useFocusNode();
|
||||||
|
|
||||||
|
final dokterIDhasFocus = useState(false);
|
||||||
|
final usernamehasFocus = useState(false);
|
||||||
|
final passwordhasFocus = useState(false);
|
||||||
|
|
||||||
|
focusNodeDokterID.addListener(() {
|
||||||
|
if (focusNodeDokterID.hasPrimaryFocus) {
|
||||||
|
dokterIDhasFocus.value = true;
|
||||||
|
usernamehasFocus.value = false;
|
||||||
|
passwordhasFocus.value = false;
|
||||||
|
} else {
|
||||||
|
dokterIDhasFocus.value = false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
focusNodeDokterUsername.addListener(() {
|
||||||
|
if (focusNodeDokterUsername.hasFocus) {
|
||||||
|
dokterIDhasFocus.value = false;
|
||||||
|
usernamehasFocus.value = true;
|
||||||
|
passwordhasFocus.value = false;
|
||||||
|
} else {
|
||||||
|
usernamehasFocus.value = false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
focusNodeDokterPassword.addListener(() {
|
||||||
|
if (focusNodeDokterPassword.hasFocus) {
|
||||||
|
dokterIDhasFocus.value = false;
|
||||||
|
usernamehasFocus.value = false;
|
||||||
|
passwordhasFocus.value = true;
|
||||||
|
} else {
|
||||||
|
passwordhasFocus.value = false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
ref.listen(loginProvider, (prev, next) {
|
||||||
|
if (next is LoginStateLoading) {
|
||||||
|
isLoading.value = true;
|
||||||
|
} else if (next is LoginStateError) {
|
||||||
|
isLoading.value = false;
|
||||||
|
errorMessage.value = next.message;
|
||||||
|
Timer(const Duration(seconds: 3), () {
|
||||||
|
errorMessage.value = "";
|
||||||
|
});
|
||||||
|
} else if (next is LoginStateDone) {
|
||||||
|
isLoading.value = false;
|
||||||
|
isSuccess.value = true;
|
||||||
|
ref.read(currentPageProvider.state).update((state) => 0);
|
||||||
|
ref.read(currentUserProvider.notifier).state = next.model;
|
||||||
|
|
||||||
|
// print(next.model.model.doctorName);
|
||||||
|
|
||||||
|
// Navigator.of(context).pop();
|
||||||
|
// Navigator.of(context).pushNamedAndRemoveUntil(menuRoute,(route) => true,);
|
||||||
|
// Navigator.popAndPushNamed(context,menuRoute);
|
||||||
|
|
||||||
|
Navigator.of(context)
|
||||||
|
.pushNamedAndRemoveUntil(menuRoute, (route) => false);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return ListView(
|
||||||
|
children: [
|
||||||
|
SizedBox(
|
||||||
|
height: Constant.getActualYPhone(context: context, y: 30),
|
||||||
|
),
|
||||||
|
Padding(
|
||||||
|
padding: EdgeInsets.only(
|
||||||
|
left: Constant.getActualXPhone(context: context, x: 40),
|
||||||
|
right: Constant.getActualXPhone(context: context, x: 40),
|
||||||
|
),
|
||||||
|
child: Container(
|
||||||
|
width: Constant.getActualXPhone(context: context, x: 283),
|
||||||
|
height: Constant.getActualYPhone(context: context, y: 100),
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
// color: Colors.green,
|
||||||
|
image: DecorationImage(
|
||||||
|
fit: BoxFit.fitWidth,
|
||||||
|
// image: AssetImage('images/logo_pramita.png'),
|
||||||
|
image: AssetImage('images/logo_gabung_bg_png.png'),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
SizedBox(
|
||||||
|
height: Constant.getActualYPhone(context: context, y: 60),
|
||||||
|
),
|
||||||
|
// form
|
||||||
|
Container(
|
||||||
|
width: Constant.getActualXPhone(context: context, x: 180),
|
||||||
|
height: Constant.getActualYPhone(context: context, y: 40),
|
||||||
|
// color: Colors.amber,
|
||||||
|
child: Align(
|
||||||
|
alignment: Alignment.center,
|
||||||
|
child: Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
|
mainAxisSize: MainAxisSize.max,
|
||||||
|
children: [
|
||||||
|
Text(
|
||||||
|
"LOGIN",
|
||||||
|
style: Constant.titleH3_700V2(context: context)
|
||||||
|
.copyWith(color: Constant.subTitleBlack),
|
||||||
|
),
|
||||||
|
Text(
|
||||||
|
" DOKTER",
|
||||||
|
style: Constant.titleH3_700V2(context: context).copyWith(
|
||||||
|
color: Color(0xffd70302),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
|
||||||
|
SizedBox(
|
||||||
|
height: Constant.getActualYPhone(context: context, y: 20),
|
||||||
|
),
|
||||||
|
|
||||||
|
// notify error dari backend start
|
||||||
|
|
||||||
|
if (isLoading.value)
|
||||||
|
SizedBox(
|
||||||
|
width: Constant.getActualXPhone(context: context, x: 20),
|
||||||
|
height: Constant.getActualYPhone(context: context, y: 20),
|
||||||
|
child: Center(child: CircularProgressIndicator()),
|
||||||
|
),
|
||||||
|
|
||||||
|
if (errorMessage.value != "")
|
||||||
|
Center(
|
||||||
|
child: Text(
|
||||||
|
"Peringatan : ${errorMessage.value}",
|
||||||
|
style: Constant.titleH7_700(context: context)
|
||||||
|
.copyWith(color: Constant.textRedProblemMaketing),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
|
||||||
|
// notify error dari backend end
|
||||||
|
|
||||||
|
SizedBox(
|
||||||
|
height: Constant.getActualYPhone(context: context, y: 50),
|
||||||
|
),
|
||||||
|
// textfield marketing ID
|
||||||
|
Padding(
|
||||||
|
padding: EdgeInsets.only(
|
||||||
|
left: Constant.getActualXPhone(context: context, x: 100),
|
||||||
|
right: Constant.getActualXPhone(context: context, x: 100),
|
||||||
|
),
|
||||||
|
child: Container(
|
||||||
|
width: Constant.getActualXPhone(context: context, x: 320),
|
||||||
|
height: Constant.getActualYPhone(context: context, y: 50),
|
||||||
|
// color: Colors.blue,
|
||||||
|
// decoration: BoxDecoration(
|
||||||
|
// // border: Border.all(color: Colors.black),
|
||||||
|
// color: Color(0xffee0606),
|
||||||
|
// borderRadius: BorderRadius.circular(30),
|
||||||
|
// ),
|
||||||
|
child: CustomTextFieldLogin(
|
||||||
|
// onTap: () {
|
||||||
|
// dokterIDhasFocus.value = true;
|
||||||
|
// },
|
||||||
|
// onEditingComplete: () {
|
||||||
|
// dokterIDhasFocus.value = false;
|
||||||
|
// },
|
||||||
|
onChange: (String x) {
|
||||||
|
// print(x);
|
||||||
|
if (x.isNotEmpty || ctrlDokterId.text.isNotEmpty) {
|
||||||
|
print('onchange');
|
||||||
|
focusNodeDokterID.requestFocus();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
ctrl: ctrlDokterId,
|
||||||
|
focusNode: focusNodeDokterID,
|
||||||
|
hasFocus: dokterIDhasFocus.value,
|
||||||
|
isPassword: false,
|
||||||
|
hintText: "DOKTER ID",
|
||||||
|
labelText: "DOKTER ID",
|
||||||
|
isError: (errorMessage.value != "") ? true : false,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
|
||||||
|
SizedBox(
|
||||||
|
height: Constant.getActualYPhone(context: context, y: 40),
|
||||||
|
),
|
||||||
|
// textfield username
|
||||||
|
Padding(
|
||||||
|
padding: EdgeInsets.only(
|
||||||
|
left: Constant.getActualXPhone(context: context, x: 100),
|
||||||
|
right: Constant.getActualXPhone(context: context, x: 100),
|
||||||
|
),
|
||||||
|
child: Container(
|
||||||
|
width: Constant.getActualXPhone(context: context, x: 320),
|
||||||
|
height: Constant.getActualYPhone(context: context, y: 50),
|
||||||
|
// color: Colors.blue,
|
||||||
|
// decoration: BoxDecoration(
|
||||||
|
// // border: Border.all(color: Colors.black),
|
||||||
|
// color: Color(0xffee0606),
|
||||||
|
// borderRadius: BorderRadius.circular(30),
|
||||||
|
// ),
|
||||||
|
child: CustomTextFieldLogin(
|
||||||
|
// onTap: () {
|
||||||
|
// if (ctrlUsername.text.isNotEmpty) {
|
||||||
|
// focusNodeDokterUsername.requestFocus();
|
||||||
|
// }
|
||||||
|
// },
|
||||||
|
onChange: (String x) {
|
||||||
|
// print(x);
|
||||||
|
if (x.isNotEmpty || ctrlUsername.text.isNotEmpty) {
|
||||||
|
focusNodeDokterUsername.requestFocus();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
ctrl: ctrlUsername,
|
||||||
|
focusNode: focusNodeDokterUsername,
|
||||||
|
hasFocus: usernamehasFocus.value,
|
||||||
|
isPassword: false,
|
||||||
|
hintText: "USERNAME",
|
||||||
|
labelText: "USERNAME",
|
||||||
|
isError: (errorMessage.value != "") ? true : false,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
|
||||||
|
SizedBox(
|
||||||
|
height: Constant.getActualYPhone(context: context, y: 40),
|
||||||
|
),
|
||||||
|
// textfield password
|
||||||
|
Padding(
|
||||||
|
padding: EdgeInsets.only(
|
||||||
|
left: Constant.getActualXPhone(context: context, x: 100),
|
||||||
|
right: Constant.getActualXPhone(context: context, x: 100),
|
||||||
|
),
|
||||||
|
child: Container(
|
||||||
|
width: Constant.getActualXPhone(context: context, x: 320),
|
||||||
|
height: Constant.getActualYPhone(context: context, y: 50),
|
||||||
|
// color: Colors.blue,
|
||||||
|
// decoration: BoxDecoration(
|
||||||
|
// // border: Border.all(color: Colors.black),
|
||||||
|
// color: Color(0xffee0606),
|
||||||
|
// borderRadius: BorderRadius.circular(30),
|
||||||
|
// ),
|
||||||
|
child: CustomTextFieldLogin(
|
||||||
|
// onTap: () {
|
||||||
|
// if (ctrlPassword.text.isNotEmpty) {
|
||||||
|
// focusNodeDokterPassword.requestFocus();
|
||||||
|
// }
|
||||||
|
// },
|
||||||
|
onChange: (String x) {
|
||||||
|
// print(x);
|
||||||
|
if (x.isNotEmpty || ctrlPassword.text.isNotEmpty) {
|
||||||
|
focusNodeDokterPassword.requestFocus();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
ctrl: ctrlPassword,
|
||||||
|
focusNode: focusNodeDokterPassword,
|
||||||
|
hasFocus: passwordhasFocus.value,
|
||||||
|
isPassword: false,
|
||||||
|
obscureText: isPasswordObscured.value,
|
||||||
|
hintText: "PASSWORD",
|
||||||
|
labelText: "PASSWORD",
|
||||||
|
onToggle: () {
|
||||||
|
isPasswordObscured.value = !isPasswordObscured.value;
|
||||||
|
},
|
||||||
|
isError: (errorMessage.value != "") ? true : false,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
|
||||||
|
SizedBox(
|
||||||
|
height: Constant.getActualYPhone(context: context, y: 40),
|
||||||
|
),
|
||||||
|
// button login
|
||||||
|
Padding(
|
||||||
|
padding: EdgeInsets.only(
|
||||||
|
left: Constant.getActualXPhone(context: context, x: 100),
|
||||||
|
right: Constant.getActualXPhone(context: context, x: 100),
|
||||||
|
),
|
||||||
|
child: SizedBox(
|
||||||
|
width: Constant.getActualXPhone(context: context, x: 320),
|
||||||
|
height: Constant.getActualYPhone(context: context, y: 50),
|
||||||
|
child: ElevatedButton(
|
||||||
|
onPressed: (isSuccess.value == true)
|
||||||
|
? () {}
|
||||||
|
: () {
|
||||||
|
if (ctrlUsername.text.isEmpty ||
|
||||||
|
ctrlDokterId.text.isEmpty ||
|
||||||
|
ctrlPassword.text.isEmpty) {
|
||||||
|
isLoading.value = true;
|
||||||
|
errorMessage.value = 'Inputan harus diisi';
|
||||||
|
Timer(const Duration(seconds: 3), () {
|
||||||
|
isLoading.value = false;
|
||||||
|
errorMessage.value = "";
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
ref.read(loginProvider.notifier).login(
|
||||||
|
username: ctrlUsername.text,
|
||||||
|
dokterId: ctrlDokterId.text,
|
||||||
|
password: ctrlPassword.text);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
style: ButtonStyle(
|
||||||
|
backgroundColor: MaterialStateColor.resolveWith((st) =>
|
||||||
|
(isSuccess.value == true)
|
||||||
|
? Constant.textGrey
|
||||||
|
: Constant.buttonRedBackgroundColor),
|
||||||
|
shape: MaterialStateProperty.all<RoundedRectangleBorder>(
|
||||||
|
RoundedRectangleBorder(
|
||||||
|
borderRadius: BorderRadius.circular(30),
|
||||||
|
side: BorderSide(color: Colors.red),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
shadowColor: MaterialStateProperty.all(Color(0xffff48423d)),
|
||||||
|
elevation: MaterialStateProperty.all(4.0),
|
||||||
|
),
|
||||||
|
child: Align(
|
||||||
|
alignment: Alignment.center,
|
||||||
|
child: Text(
|
||||||
|
'SIGN IN',
|
||||||
|
style: Constant.titleH3_700(context: context)
|
||||||
|
.copyWith(color: Constant.textLoginColor),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
|
||||||
|
SizedBox(
|
||||||
|
height: Constant.getActualYPhone(context: context, y: 22),
|
||||||
|
),
|
||||||
|
|
||||||
|
// versi
|
||||||
|
Align(
|
||||||
|
alignment: Alignment.center,
|
||||||
|
child: Text(
|
||||||
|
'Versi ${Constant.version}',
|
||||||
|
style: Constant.titleH4Login(context: context)
|
||||||
|
.copyWith(color: Constant.textGrey),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
19
app_petty_cash/lib/screen/login/block_header.dart
Normal file
19
app_petty_cash/lib/screen/login/block_header.dart
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
import '../../app/constant.dart';
|
||||||
|
|
||||||
|
class BlokHeader extends StatelessWidget {
|
||||||
|
const BlokHeader({
|
||||||
|
Key? key,
|
||||||
|
}) : super(key: key);
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Image.asset(
|
||||||
|
'images/Background.png',
|
||||||
|
fit: BoxFit.fill,
|
||||||
|
width: Constant.getActualXPhone(context: context, x: 390),
|
||||||
|
height: double.infinity,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
290
app_petty_cash/lib/screen/login/custom_text_field.dart
Normal file
290
app_petty_cash/lib/screen/login/custom_text_field.dart
Normal file
@@ -0,0 +1,290 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
import '../../app/constant.dart';
|
||||||
|
|
||||||
|
// login
|
||||||
|
class CustomTextFieldLogin extends StatelessWidget {
|
||||||
|
final String hintText;
|
||||||
|
final String labelText;
|
||||||
|
final bool isPassword;
|
||||||
|
final bool obscureText;
|
||||||
|
final bool isMaxLine;
|
||||||
|
final void Function()? onToggle;
|
||||||
|
final TextEditingController? ctrl;
|
||||||
|
final void Function(String)? onChange;
|
||||||
|
final void Function(String)? onSubmitted;
|
||||||
|
final void Function()? onTap;
|
||||||
|
final void Function()? onEditingComplete;
|
||||||
|
final FocusNode? focusNode;
|
||||||
|
final bool isPrefix;
|
||||||
|
|
||||||
|
final bool isError;
|
||||||
|
final bool isTextArea;
|
||||||
|
final bool isReadOnly;
|
||||||
|
|
||||||
|
final bool hasFocus;
|
||||||
|
|
||||||
|
const CustomTextFieldLogin({
|
||||||
|
Key? key,
|
||||||
|
required this.hintText,
|
||||||
|
required this.labelText,
|
||||||
|
this.isPassword = false,
|
||||||
|
this.isMaxLine = false,
|
||||||
|
this.onToggle,
|
||||||
|
this.obscureText = false,
|
||||||
|
this.ctrl,
|
||||||
|
this.onChange,
|
||||||
|
this.onSubmitted,
|
||||||
|
this.focusNode,
|
||||||
|
this.isPrefix = false,
|
||||||
|
this.isTextArea = false,
|
||||||
|
this.isError = false,
|
||||||
|
this.isReadOnly = false,
|
||||||
|
this.hasFocus = false,
|
||||||
|
this.onTap,
|
||||||
|
this.onEditingComplete
|
||||||
|
}) : super(key: key);
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return TextField(
|
||||||
|
autofocus: true,
|
||||||
|
showCursor: (hasFocus) ? true : false,
|
||||||
|
readOnly: isReadOnly,
|
||||||
|
controller: ctrl,
|
||||||
|
enableInteractiveSelection: false,
|
||||||
|
style:
|
||||||
|
Constant.titleH4Login(context: context).copyWith(color: Colors.white),
|
||||||
|
obscureText: obscureText,
|
||||||
|
onChanged: onChange,
|
||||||
|
onSubmitted: onSubmitted,
|
||||||
|
onTap: onTap,
|
||||||
|
onEditingComplete: onEditingComplete,
|
||||||
|
focusNode: focusNode,
|
||||||
|
maxLines: (isTextArea) ? 4 : 1,
|
||||||
|
cursorColor: Colors.white,
|
||||||
|
decoration: InputDecoration(
|
||||||
|
fillColor: (hasFocus) ? Color(0xffff6868) : Color(0xffd90504),
|
||||||
|
filled: true,
|
||||||
|
focusedBorder: OutlineInputBorder(
|
||||||
|
borderSide:
|
||||||
|
BorderSide(color: Constant.buttonLoginBackgroundColor, width: 2),
|
||||||
|
borderRadius: BorderRadius.circular(30),
|
||||||
|
),
|
||||||
|
enabledBorder: (isError == true)
|
||||||
|
? OutlineInputBorder(
|
||||||
|
// ignore: prefer_const_constructors
|
||||||
|
borderRadius: BorderRadius.all(Radius.circular(30)),
|
||||||
|
borderSide: BorderSide(
|
||||||
|
color: Constant.textRedProblemMaketing,
|
||||||
|
width: 1,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
: OutlineInputBorder(
|
||||||
|
// ignore: prefer_const_constructors
|
||||||
|
borderRadius: BorderRadius.all(Radius.circular(30)),
|
||||||
|
borderSide: BorderSide(
|
||||||
|
color: Constant.buttonLoginBackgroundColor,
|
||||||
|
width: 2,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
// hintStyle: Constant.body1_400(context: context)
|
||||||
|
// .copyWith(color: Constant.textBlack),
|
||||||
|
// labelStyle: Constant.body3_400(context: context),
|
||||||
|
hintStyle:
|
||||||
|
Constant.body3_400(context: context).copyWith(color: Colors.white),
|
||||||
|
labelStyle: Constant.body3_400(context: context),
|
||||||
|
// labelText: labelText,
|
||||||
|
hintText: hintText,
|
||||||
|
alignLabelWithHint: true,
|
||||||
|
border: OutlineInputBorder(
|
||||||
|
borderRadius: BorderRadius.circular(30),
|
||||||
|
),
|
||||||
|
prefixIcon: isPrefix ? const Icon(Icons.search) : null,
|
||||||
|
prefixStyle: isPrefix ? Constant.titleH4Login(context: context) : null,
|
||||||
|
// suffixIcon: isPassword
|
||||||
|
// ? IconButton(
|
||||||
|
// alignment: Alignment.centerRight,
|
||||||
|
// onPressed: onToggle,
|
||||||
|
// icon: const Icon(Icons.remove_red_eye),
|
||||||
|
// iconSize: Constant.getActualYPhone(context: context, y: 24),
|
||||||
|
// )
|
||||||
|
// : null,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// selain login
|
||||||
|
class CustomTextField extends StatelessWidget {
|
||||||
|
final String hintText;
|
||||||
|
final String labelText;
|
||||||
|
final bool isPassword;
|
||||||
|
final bool obscureText;
|
||||||
|
final bool isMaxLine;
|
||||||
|
final void Function()? onToggle;
|
||||||
|
final TextEditingController? ctrl;
|
||||||
|
final void Function(String)? onChange;
|
||||||
|
final void Function(String)? onSubmitted;
|
||||||
|
final FocusNode? focusNode;
|
||||||
|
final bool isPrefix;
|
||||||
|
|
||||||
|
final bool isError;
|
||||||
|
final bool isTextArea;
|
||||||
|
final bool isReadOnly;
|
||||||
|
|
||||||
|
const CustomTextField(
|
||||||
|
{Key? key,
|
||||||
|
required this.hintText,
|
||||||
|
required this.labelText,
|
||||||
|
this.isPassword = false,
|
||||||
|
this.isMaxLine = false,
|
||||||
|
this.onToggle,
|
||||||
|
this.obscureText = false,
|
||||||
|
this.ctrl,
|
||||||
|
this.onChange,
|
||||||
|
this.onSubmitted,
|
||||||
|
this.focusNode,
|
||||||
|
this.isPrefix = false,
|
||||||
|
this.isTextArea = false,
|
||||||
|
this.isError = false,
|
||||||
|
this.isReadOnly = false})
|
||||||
|
: super(key: key);
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return TextField(
|
||||||
|
readOnly: isReadOnly,
|
||||||
|
controller: ctrl,
|
||||||
|
style: Constant.titleH4Login(context: context),
|
||||||
|
obscureText: obscureText,
|
||||||
|
onChanged: onChange,
|
||||||
|
onSubmitted: onSubmitted,
|
||||||
|
focusNode: focusNode,
|
||||||
|
maxLines: (isTextArea) ? 4 : 1,
|
||||||
|
decoration: InputDecoration(
|
||||||
|
// focusedBorder: OutlineInputBorder(
|
||||||
|
// borderSide: BorderSide(color: Constant.textGrey, width: 1),
|
||||||
|
// borderRadius: BorderRadius.circular(8.0),
|
||||||
|
// ),
|
||||||
|
enabledBorder: (isError == true)
|
||||||
|
? OutlineInputBorder(
|
||||||
|
// ignore: prefer_const_constructors
|
||||||
|
borderRadius: BorderRadius.all(Radius.circular(8)),
|
||||||
|
borderSide: BorderSide(
|
||||||
|
color: Constant.textRedProblemMaketing,
|
||||||
|
width: 1,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
: null,
|
||||||
|
// hintStyle: Constant.body1_400(context: context)
|
||||||
|
// .copyWith(color: Constant.textBlack),
|
||||||
|
// labelStyle: Constant.body3_400(context: context),
|
||||||
|
hintStyle: Constant.body3_400(context: context),
|
||||||
|
labelStyle: Constant.body3_400(context: context),
|
||||||
|
labelText: labelText,
|
||||||
|
hintText: hintText,
|
||||||
|
alignLabelWithHint: true,
|
||||||
|
border: OutlineInputBorder(
|
||||||
|
borderRadius: BorderRadius.circular(8),
|
||||||
|
),
|
||||||
|
prefixIcon: isPrefix ? const Icon(Icons.search) : null,
|
||||||
|
prefixStyle: isPrefix ? Constant.titleH4Login(context: context) : null,
|
||||||
|
// suffixIcon: isPassword
|
||||||
|
// ? IconButton(
|
||||||
|
// alignment: Alignment.centerRight,
|
||||||
|
// onPressed: onToggle,
|
||||||
|
// icon: const Icon(Icons.remove_red_eye),
|
||||||
|
// iconSize: Constant.getActualYPhone(context: context, y: 24),
|
||||||
|
// )
|
||||||
|
// : null,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// untuk inputan selain login
|
||||||
|
class CustomTextFieldV2 extends StatelessWidget {
|
||||||
|
final String hintText;
|
||||||
|
final String labelText;
|
||||||
|
final bool isPassword;
|
||||||
|
final bool obscureText;
|
||||||
|
final bool isMaxLine;
|
||||||
|
final void Function()? onToggle;
|
||||||
|
final TextEditingController? ctrl;
|
||||||
|
final void Function(String)? onChange;
|
||||||
|
final void Function(String)? onSubmitted;
|
||||||
|
final FocusNode? focusNode;
|
||||||
|
final bool isPrefix;
|
||||||
|
final InkWell? suffixIcon;
|
||||||
|
|
||||||
|
final bool isError;
|
||||||
|
final bool isTextArea;
|
||||||
|
|
||||||
|
const CustomTextFieldV2(
|
||||||
|
{Key? key,
|
||||||
|
required this.hintText,
|
||||||
|
required this.labelText,
|
||||||
|
this.isPassword = false,
|
||||||
|
this.isMaxLine = false,
|
||||||
|
this.onToggle,
|
||||||
|
this.obscureText = false,
|
||||||
|
this.ctrl,
|
||||||
|
this.onChange,
|
||||||
|
this.onSubmitted,
|
||||||
|
this.focusNode,
|
||||||
|
this.isPrefix = false,
|
||||||
|
this.isTextArea = false,
|
||||||
|
this.isError = false,
|
||||||
|
this.suffixIcon})
|
||||||
|
: super(key: key);
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return TextField(
|
||||||
|
controller: ctrl,
|
||||||
|
style: Constant.titleH4Login(context: context),
|
||||||
|
obscureText: obscureText,
|
||||||
|
onChanged: onChange,
|
||||||
|
onSubmitted: onSubmitted,
|
||||||
|
focusNode: focusNode,
|
||||||
|
maxLines: (isTextArea) ? 4 : 1,
|
||||||
|
decoration: InputDecoration(
|
||||||
|
// focusedBorder: OutlineInputBorder(
|
||||||
|
// borderSide: BorderSide(color: Constant.textGrey, width: 1),
|
||||||
|
// borderRadius: BorderRadius.circular(8.0),
|
||||||
|
// ),
|
||||||
|
enabledBorder: (isError == true)
|
||||||
|
? OutlineInputBorder(
|
||||||
|
// ignore: prefer_const_constructors
|
||||||
|
borderRadius: BorderRadius.all(Radius.circular(8)),
|
||||||
|
borderSide: BorderSide(
|
||||||
|
color: Constant.textRedProblemMaketing,
|
||||||
|
width: 1,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
: null,
|
||||||
|
hintStyle: Constant.body3_400(context: context),
|
||||||
|
labelStyle: Constant.body3_400(context: context),
|
||||||
|
labelText: labelText,
|
||||||
|
hintText: hintText,
|
||||||
|
alignLabelWithHint: true,
|
||||||
|
border: OutlineInputBorder(
|
||||||
|
borderRadius: BorderRadius.circular(8),
|
||||||
|
),
|
||||||
|
prefixIcon: isPrefix ? const Icon(Icons.search) : null,
|
||||||
|
prefixStyle:
|
||||||
|
isPrefix ? Constant.titleH4Login(context: context) : null,
|
||||||
|
suffixIcon: suffixIcon
|
||||||
|
// suffixIcon: isPassword
|
||||||
|
// ? IconButton(
|
||||||
|
// alignment: Alignment.centerRight,
|
||||||
|
// onPressed: onToggle,
|
||||||
|
// icon: const Icon(Icons.remove_red_eye),
|
||||||
|
// iconSize: Constant.getActualYPhone(context: context, y: 24),
|
||||||
|
// )
|
||||||
|
// : null,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
83
app_petty_cash/lib/screen/login/login_provider.dart
Normal file
83
app_petty_cash/lib/screen/login/login_provider.dart
Normal file
@@ -0,0 +1,83 @@
|
|||||||
|
import 'dart:convert';
|
||||||
|
|
||||||
|
import 'package:equatable/equatable.dart';
|
||||||
|
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||||
|
import 'package:shared_preferences/shared_preferences.dart';
|
||||||
|
|
||||||
|
import '../../app/constant.dart';
|
||||||
|
import '../../model/auth_model.dart';
|
||||||
|
import '../../provider/current_user_provider.dart';
|
||||||
|
import '../../provider/dio_provider.dart';
|
||||||
|
import '../../repository/auth_repository.dart';
|
||||||
|
import '../../repository/base_repository.dart';
|
||||||
|
|
||||||
|
// 3. state provider
|
||||||
|
final loginProvider = StateNotifierProvider<LoginNotifier, LoginState>(
|
||||||
|
(ref) => LoginNotifier(ref: ref));
|
||||||
|
|
||||||
|
// 2. notifier
|
||||||
|
class LoginNotifier extends StateNotifier<LoginState> {
|
||||||
|
final Ref ref;
|
||||||
|
LoginNotifier({required this.ref}) : super(LoginStateInit());
|
||||||
|
void login({
|
||||||
|
required String username,
|
||||||
|
required String dokterId,
|
||||||
|
required String password,
|
||||||
|
}) async {
|
||||||
|
try {
|
||||||
|
state = LoginStateLoading();
|
||||||
|
final resp = await AuthRepository(dio: ref.read(dioProvider))
|
||||||
|
.login(username: username, dokterId: dokterId, password: password);
|
||||||
|
|
||||||
|
// print(resp);
|
||||||
|
state = LoginStateDone(model: resp);
|
||||||
|
//Simpan ke token
|
||||||
|
final shared = await SharedPreferences.getInstance();
|
||||||
|
final token = jsonEncode({
|
||||||
|
"date": DateTime.now().toString(),
|
||||||
|
"model": resp.model,
|
||||||
|
"token": resp.token
|
||||||
|
});
|
||||||
|
await shared.setString(Constant.bearerName, token);
|
||||||
|
ref.read(currentUserProvider.notifier).state = resp;
|
||||||
|
|
||||||
|
// print(shared.getString(Constant.bearerName));
|
||||||
|
} catch (e) {
|
||||||
|
if (e is BaseRepositoryException) {
|
||||||
|
state = LoginStateError(message: e.message);
|
||||||
|
} else {
|
||||||
|
state = LoginStateError(message: e.toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 1. state
|
||||||
|
abstract class LoginState extends Equatable {
|
||||||
|
final DateTime date;
|
||||||
|
const LoginState(this.date);
|
||||||
|
@override
|
||||||
|
List<Object?> get props => [date];
|
||||||
|
}
|
||||||
|
|
||||||
|
class LoginStateInit extends LoginState {
|
||||||
|
LoginStateInit() : super(DateTime.now());
|
||||||
|
}
|
||||||
|
|
||||||
|
class LoginStateLoading extends LoginState {
|
||||||
|
LoginStateLoading() : super(DateTime.now());
|
||||||
|
}
|
||||||
|
|
||||||
|
class LoginStateError extends LoginState {
|
||||||
|
final String message;
|
||||||
|
LoginStateError({
|
||||||
|
required this.message,
|
||||||
|
}) : super(DateTime.now());
|
||||||
|
}
|
||||||
|
|
||||||
|
class LoginStateDone extends LoginState {
|
||||||
|
final AuthModel model;
|
||||||
|
LoginStateDone({
|
||||||
|
required this.model,
|
||||||
|
}) : super(DateTime.now());
|
||||||
|
}
|
||||||
79
app_petty_cash/lib/screen/login/login_screen.dart
Normal file
79
app_petty_cash/lib/screen/login/login_screen.dart
Normal file
@@ -0,0 +1,79 @@
|
|||||||
|
// ignore_for_file: use_build_context_synchronously, prefer_const_constructors
|
||||||
|
|
||||||
|
import 'dart:convert';
|
||||||
|
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_hooks/flutter_hooks.dart';
|
||||||
|
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||||
|
import 'package:shared_preferences/shared_preferences.dart';
|
||||||
|
|
||||||
|
import '../../app/constant.dart';
|
||||||
|
import '../../app/route.dart';
|
||||||
|
import '../../model/auth_model.dart';
|
||||||
|
import '../../provider/current_menu_provider.dart';
|
||||||
|
import '../../provider/current_user_provider.dart';
|
||||||
|
import 'block_body.dart';
|
||||||
|
import 'block_bodyv2.dart';
|
||||||
|
|
||||||
|
class LoginScreen extends HookConsumerWidget {
|
||||||
|
const LoginScreen({Key? key}) : super(key: key);
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context, WidgetRef ref) {
|
||||||
|
useEffect(() {
|
||||||
|
WidgetsBinding.instance.addPostFrameCallback((timeStamp) async {
|
||||||
|
final shared = await SharedPreferences.getInstance();
|
||||||
|
final bearerString = shared.get(Constant.bearerName).toString();
|
||||||
|
final xmodel = jsonDecode(bearerString);
|
||||||
|
if (xmodel == null) return;
|
||||||
|
final authModel = AuthModel(
|
||||||
|
token: xmodel["token"],
|
||||||
|
model: AuthDoctorModel(
|
||||||
|
M_UserM_DoctorID: xmodel["model"]["M_UserM_DoctorID"],
|
||||||
|
M_UserUsername: xmodel["model"]["M_UserUsername"],
|
||||||
|
M_UserM_DoctorCode: xmodel["model"]["M_UserM_DoctorCode"],
|
||||||
|
M_UserM_MouID: xmodel["model"]["M_UserM_MouID"] ?? "",
|
||||||
|
M_UserID: xmodel["model"]["M_UserID"]),
|
||||||
|
);
|
||||||
|
ref.read(currentUserProvider.notifier).state = authModel;
|
||||||
|
|
||||||
|
ref.read(currentPageProvider.state).update((state) => 0);
|
||||||
|
|
||||||
|
Navigator.of(context).pushNamedAndRemoveUntil(
|
||||||
|
menuRoute,
|
||||||
|
(route) => false,
|
||||||
|
);
|
||||||
|
});
|
||||||
|
return () {};
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
return GestureDetector(
|
||||||
|
// buat dismiss keyboard
|
||||||
|
onTap: () => FocusManager.instance.primaryFocus?.unfocus(),
|
||||||
|
child: Scaffold(
|
||||||
|
resizeToAvoidBottomInset: true,
|
||||||
|
backgroundColor: Constant.backgroundColor,
|
||||||
|
body: SafeArea(
|
||||||
|
child: Center(
|
||||||
|
child: Container(
|
||||||
|
width: Constant.getActualXPhone(context: context, x: 390),
|
||||||
|
height: Constant.getActualYPhone(context: context, y: 844),
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
gradient: LinearGradient(
|
||||||
|
colors: [
|
||||||
|
Color(0xffdadae6),
|
||||||
|
Color(0xfff6f7fb),
|
||||||
|
],
|
||||||
|
begin: Alignment.centerLeft,
|
||||||
|
end: Alignment.centerRight,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
// child: BlockBody(),
|
||||||
|
child: BlockBodyV2(),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
64
app_petty_cash/lib/screen/splash/splash_screen.dart
Normal file
64
app_petty_cash/lib/screen/splash/splash_screen.dart
Normal file
@@ -0,0 +1,64 @@
|
|||||||
|
import 'dart:async';
|
||||||
|
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_hooks/flutter_hooks.dart';
|
||||||
|
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||||
|
|
||||||
|
import '../../app/constant.dart';
|
||||||
|
import '../../app/route.dart';
|
||||||
|
import '../../provider/current_user_provider.dart';
|
||||||
|
|
||||||
|
class SplashScreen extends HookConsumerWidget {
|
||||||
|
const SplashScreen({super.key});
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context, WidgetRef ref) {
|
||||||
|
// useEffect(() {
|
||||||
|
// WidgetsBinding.instance.addPostFrameCallback((timeStamp) async {
|
||||||
|
// final doctorID =
|
||||||
|
// ref.read(currentUserProvider)?.model.M_UserM_DoctorCode ?? "0";
|
||||||
|
// // print(doctorID);
|
||||||
|
|
||||||
|
// if (doctorID == "0") {
|
||||||
|
// //not login
|
||||||
|
|
||||||
|
// Navigator.of(context)
|
||||||
|
// .pushNamedAndRemoveUntil(loginRoute, (route) => false);
|
||||||
|
// return;
|
||||||
|
|
||||||
|
// } else {
|
||||||
|
// Navigator.of(context)
|
||||||
|
// .pushNamedAndRemoveUntil(menuRoute, (route) => false);
|
||||||
|
// }
|
||||||
|
// });
|
||||||
|
// return () {};
|
||||||
|
// }, []);
|
||||||
|
|
||||||
|
// setelah 3 detik redirect ke login route
|
||||||
|
Timer(const Duration(seconds: 3), () {
|
||||||
|
Navigator.of(context).pushNamedAndRemoveUntil(
|
||||||
|
loginRoute,
|
||||||
|
(route) => false,
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
return Scaffold(
|
||||||
|
// appBar: AppBar(
|
||||||
|
// backgroundColor: Constant.backgroundColor,
|
||||||
|
// elevation: 0,
|
||||||
|
// ),
|
||||||
|
backgroundColor: Constant.backgroundColor,
|
||||||
|
body: SafeArea(
|
||||||
|
child: Container(
|
||||||
|
width: Constant.getActualXPhone(context: context, x: 390),
|
||||||
|
height: Constant.getActualYPhone(context: context, y: 844),
|
||||||
|
child: Image.asset(
|
||||||
|
"images/splashscreen.png",
|
||||||
|
fit: BoxFit.cover,
|
||||||
|
// scale: 1,
|
||||||
|
),
|
||||||
|
// color: Colors.green,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user