step 3 : hapus ai_barcode_scanner, ai barcode, update permission_handler, flutter_map,latlong2
@@ -8,7 +8,7 @@ plugins {
|
|||||||
android {
|
android {
|
||||||
namespace = "com.example.kdr_kurir_app_v2"
|
namespace = "com.example.kdr_kurir_app_v2"
|
||||||
compileSdk = flutter.compileSdkVersion
|
compileSdk = flutter.compileSdkVersion
|
||||||
ndkVersion = flutter.ndkVersion
|
ndkVersion = "27.0.12077973"
|
||||||
|
|
||||||
compileOptions {
|
compileOptions {
|
||||||
sourceCompatibility = JavaVersion.VERSION_11
|
sourceCompatibility = JavaVersion.VERSION_11
|
||||||
|
|||||||
7
android/app/src/main/res/xml/network_security_config.xml
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
<network-security-config>
|
||||||
|
<base-config cleartextTrafficPermitted="true">
|
||||||
|
<trust-anchors>
|
||||||
|
<certificates src="system" />
|
||||||
|
</trust-anchors>
|
||||||
|
</base-config>
|
||||||
|
</network-security-config>
|
||||||
122
lib/app/constant.dart
Normal file
@@ -0,0 +1,122 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
class Constant {
|
||||||
|
static String tokenName = "kdr-kurir";
|
||||||
|
// static String baseUrl = "http://devkedungdororaya.aplikasi.web.id/one-api/";
|
||||||
|
|
||||||
|
static String baseUrl = "http://kd-kurir.aplikasi.web.id/one-api/";
|
||||||
|
static String baseBirtUrl = "http://kd-kurir.aplikasi.web.id/";
|
||||||
|
|
||||||
|
static double designHeight = 844;
|
||||||
|
static double designWidth = 390;
|
||||||
|
|
||||||
|
static String version = "1.01";
|
||||||
|
|
||||||
|
//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;
|
||||||
|
}
|
||||||
|
|
||||||
|
//color identity
|
||||||
|
static Color backgroundWhite = const Color(0xffFFFFFF);
|
||||||
|
static Color textBlack = const Color(0xFF070708);
|
||||||
|
static Color textGrey = const Color(0xFF919EAB);
|
||||||
|
static Color primaryBlue = const Color(0xFF005AA9);
|
||||||
|
static Color backgroundBlue = const Color(0xFF1890FF).withOpacity(0.25);
|
||||||
|
static Color iconBlue = const Color(0xFF3366FF);
|
||||||
|
static Color primaryGreen = const Color(0xFF229A16);
|
||||||
|
static Color backgroundGreen = const Color(0xFF54D62C).withOpacity(0.25);
|
||||||
|
static Color primaryOrange = const Color(0xFFB78103);
|
||||||
|
static Color backgroundOrange = const Color(0xFFFFC107).withOpacity(0.25);
|
||||||
|
static Color primaryRed = const Color(0xFFB72136);
|
||||||
|
static Color primaryYellow = const Color(0xFFFFC107);
|
||||||
|
static Color primaryPurple = const Color(0xFFBF07FF);
|
||||||
|
static Color backgroundPurple = const Color(0xFFBF07FF).withOpacity(0.25);
|
||||||
|
static Color textSecondary = const Color(0xFF637381);
|
||||||
|
|
||||||
|
// sindhu
|
||||||
|
static Color textPrimary = const Color(0xff212B36);
|
||||||
|
static Color primaryMain = const Color(0xff3366FF);
|
||||||
|
static Color errorDark = const Color(0xffB72136);
|
||||||
|
// static Color dropdownTextColor = const Color(0xff005AA9);
|
||||||
|
static Color blueButton = const Color(0xff005AA9);
|
||||||
|
static Color primaryDark = const Color(0xff005AA9);
|
||||||
|
static Color buttonIsNotActive = const Color(0xffDFE3E8);
|
||||||
|
static Color historyCardColor = const Color(0xff54D62C).withOpacity(0.08);
|
||||||
|
static Color historyCardColorPending =
|
||||||
|
const Color(0xffFF0D05).withOpacity(0.08);
|
||||||
|
|
||||||
|
// typography
|
||||||
|
static TextStyle heading2({required BuildContext context}) {
|
||||||
|
return TextStyle(
|
||||||
|
fontSize: Constant.getActualY(context: context, y: 28),
|
||||||
|
height: 1.5,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
static TextStyle body1({required BuildContext context}) {
|
||||||
|
return TextStyle(
|
||||||
|
fontSize: Constant.getActualY(context: context, y: 16),
|
||||||
|
height: 1.5,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
static TextStyle caption1({required BuildContext context}) {
|
||||||
|
return TextStyle(
|
||||||
|
fontSize: Constant.getActualY(context: context, y: 12),
|
||||||
|
height: 1.5,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
static TextStyle buttonLarge({required BuildContext context}) {
|
||||||
|
return TextStyle(
|
||||||
|
fontSize: Constant.getActualY(context: context, y: 15),
|
||||||
|
height: 1.5,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
static TextStyle heading4({required BuildContext context}) {
|
||||||
|
return TextStyle(
|
||||||
|
fontSize: Constant.getActualY(context: context, y: 18),
|
||||||
|
height: 1.5,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
static TextStyle body3({required BuildContext context}) {
|
||||||
|
return TextStyle(
|
||||||
|
fontSize: Constant.getActualY(context: context, y: 14),
|
||||||
|
height: 1.5,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
static TextStyle caption2({required BuildContext context}) {
|
||||||
|
return TextStyle(
|
||||||
|
fontSize: Constant.getActualY(context: context, y: 10),
|
||||||
|
height: 1.5,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
static TextStyle heading3({required BuildContext context}) {
|
||||||
|
return TextStyle(
|
||||||
|
fontSize: Constant.getActualY(context: context, y: 20),
|
||||||
|
height: 1.5,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
static TextStyle body2({required BuildContext context}) {
|
||||||
|
return TextStyle(
|
||||||
|
fontSize: Constant.getActualY(context: context, y: 14),
|
||||||
|
height: 1.5,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
285
lib/app/route.dart
Normal file
@@ -0,0 +1,285 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import '../screen/change_password_screen/change_password_screen.dart';
|
||||||
|
import '../screen/input_pekerjaan/input_pekerjaan_lain_lain.dart';
|
||||||
|
import '../screen/input_pekerjaan/input_pekerjaan_pengambilan_bahan.dart';
|
||||||
|
import '../screen/personal_information_screen/personal_information_screen.dart';
|
||||||
|
import '../screen/test/test_home_screen.dart';
|
||||||
|
import '../screen/work_process_screen/work_process_screen.dart';
|
||||||
|
|
||||||
|
import '../screen/input_pekerjaan/input_lain_lain_screen.dart';
|
||||||
|
import '../screen/input_pekerjaan/input_pekerjaan_pengantaran_hasil.dart';
|
||||||
|
import '../screen/input_pekerjaan/input_pekerjaan_screen.dart';
|
||||||
|
import '../screen/input_pekerjaan/input_pengambilan_bahan_screen.dart';
|
||||||
|
import '../screen/input_pekerjaan/input_pengantaran_hasil_dokter_screen.dart';
|
||||||
|
import '../screen/input_pekerjaan/input_pengantaran_hasil_instansi_screen.dart';
|
||||||
|
import '../screen/input_pekerjaan/input_pengantaran_hasil_pasien_screen.dart';
|
||||||
|
import '../screen/input_pekerjaan/input_scan_screen.dart';
|
||||||
|
import '../screen/konfirmasi/konfirmasi_screen.dart';
|
||||||
|
import '../screen/login/login_screen.dart';
|
||||||
|
import '../screen/problemlogin/problem_login_screen.dart';
|
||||||
|
import '../screen/splash_screen/splash_screen.dart';
|
||||||
|
import '../screen/menu_screen/menu_screen.dart';
|
||||||
|
// import '../screen/splash_screen.dart';
|
||||||
|
|
||||||
|
const splashRoute = "/splashRoute";
|
||||||
|
const loginRoute = "/loginRoute";
|
||||||
|
const problemLoginRoute = "/problemLoginRoute";
|
||||||
|
const testHomeRoute = "/testHomeRoute";
|
||||||
|
const inputPekerjaan = "/inputPekerjaan";
|
||||||
|
const inputScanRoute = "/inputScanRoute";
|
||||||
|
const konfirmasiRoute = "/konfirmasiRoute";
|
||||||
|
const inputPengantaranHasilPasien = "/inputPengantaranHasilPasien";
|
||||||
|
const inputPengantaranHasilInstansi = "/inputPengantaranHasilInstansi";
|
||||||
|
const inputPengantaranHasilDokter = "/inputPengantaranHasilDokter";
|
||||||
|
const inputPengambilanBahan = "/inputPengambilanBahan";
|
||||||
|
const inputLainLain = "/inputLainLain";
|
||||||
|
const personalInformationRoute = "/personalInformation";
|
||||||
|
const changePasswordRoute = "/changPassword";
|
||||||
|
const workProcessRoute = "/workProcessRoute";
|
||||||
|
|
||||||
|
const menuRoute = "/menuRoute";
|
||||||
|
const inputPekerjaanPengantaranHasil = "/inputPekerjaanPengantaranHasil";
|
||||||
|
const inputPekerjaanPengambilanBahan = "/inputPekerjaanPengambilanBahan";
|
||||||
|
const inputPekerjaanLainLain = "/inputPekerjaanLainLain";
|
||||||
|
|
||||||
|
class inputPekerjaanProp {
|
||||||
|
final int input;
|
||||||
|
final int tipe;
|
||||||
|
|
||||||
|
inputPekerjaanProp(this.input, this.tipe);
|
||||||
|
}
|
||||||
|
|
||||||
|
class InputScanPekerjaanProp {
|
||||||
|
final int input;
|
||||||
|
final int tipe;
|
||||||
|
|
||||||
|
InputScanPekerjaanProp(this.input, this.tipe);
|
||||||
|
}
|
||||||
|
|
||||||
|
class AppRoute {
|
||||||
|
static Route<dynamic> generateRoute(RouteSettings settings) {
|
||||||
|
// splash screen
|
||||||
|
if (settings.name == splashRoute) {
|
||||||
|
return MaterialPageRoute(builder: (context) {
|
||||||
|
return MediaQuery(
|
||||||
|
data: MediaQuery.of(context).copyWith(
|
||||||
|
textScaleFactor: 1.0, padding: const EdgeInsets.all(0)),
|
||||||
|
child: const SplashScreen());
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// login
|
||||||
|
if (settings.name == loginRoute) {
|
||||||
|
return MaterialPageRoute(builder: (context) {
|
||||||
|
return MediaQuery(
|
||||||
|
data: MediaQuery.of(context).copyWith(
|
||||||
|
textScaleFactor: 1.0, padding: const EdgeInsets.all(0)),
|
||||||
|
child: const LoginScreen());
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// problem login
|
||||||
|
if (settings.name == problemLoginRoute) {
|
||||||
|
return MaterialPageRoute(builder: (context) {
|
||||||
|
return MediaQuery(
|
||||||
|
data: MediaQuery.of(context).copyWith(
|
||||||
|
textScaleFactor: 1.0, padding: const EdgeInsets.all(0)),
|
||||||
|
child: const ProblemLoginScreen());
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// test home screen
|
||||||
|
if (settings.name == testHomeRoute) {
|
||||||
|
return MaterialPageRoute(builder: (context) {
|
||||||
|
return MediaQuery(
|
||||||
|
data: MediaQuery.of(context).copyWith(
|
||||||
|
textScaleFactor: 1.0, padding: const EdgeInsets.all(0)),
|
||||||
|
child: const TestHomeScreen());
|
||||||
|
});
|
||||||
|
}
|
||||||
|
// test Menu screen
|
||||||
|
if (settings.name == menuRoute) {
|
||||||
|
return MaterialPageRoute(builder: (context) {
|
||||||
|
return MediaQuery(
|
||||||
|
data: MediaQuery.of(context).copyWith(
|
||||||
|
textScaleFactor: 1.0, padding: const EdgeInsets.all(0)),
|
||||||
|
child: const MenuScreen());
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// input pekerjaan
|
||||||
|
if (settings.name == inputPekerjaan) {
|
||||||
|
final inputPekerjaanProp args = settings.arguments as inputPekerjaanProp;
|
||||||
|
return MaterialPageRoute(builder: (context) {
|
||||||
|
return MediaQuery(
|
||||||
|
data: MediaQuery.of(context).copyWith(
|
||||||
|
textScaleFactor: 1.0, padding: const EdgeInsets.all(0)),
|
||||||
|
child: InputPekerjaan(
|
||||||
|
input: args.input,
|
||||||
|
tipe: args.tipe,
|
||||||
|
));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// input pekerjaan pengantaran hasil
|
||||||
|
if (settings.name == inputPekerjaanPengantaranHasil) {
|
||||||
|
return MaterialPageRoute(builder: (context) {
|
||||||
|
return MediaQuery(
|
||||||
|
data: MediaQuery.of(context).copyWith(
|
||||||
|
textScaleFactor: 1.0, padding: const EdgeInsets.all(0)),
|
||||||
|
child: const InputPekerjaanPengantaranHasil());
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// input pekerjaan pengambilan bahan
|
||||||
|
if (settings.name == inputPekerjaanPengambilanBahan) {
|
||||||
|
return MaterialPageRoute(builder: (context) {
|
||||||
|
return MediaQuery(
|
||||||
|
data: MediaQuery.of(context).copyWith(
|
||||||
|
textScaleFactor: 1.0, padding: const EdgeInsets.all(0)),
|
||||||
|
child: const InputPekerjaanPengambilanBahan());
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// input pekerjaan lain lain
|
||||||
|
if (settings.name == inputPekerjaanLainLain) {
|
||||||
|
return MaterialPageRoute(builder: (context) {
|
||||||
|
return MediaQuery(
|
||||||
|
data: MediaQuery.of(context).copyWith(
|
||||||
|
textScaleFactor: 1.0, padding: const EdgeInsets.all(0)),
|
||||||
|
child: const InputPekerjaanPekerjaanLainLain());
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// input pengantaran hasil pasien
|
||||||
|
if (settings.name == inputPengantaranHasilPasien) {
|
||||||
|
final args = settings.arguments as Map<String, dynamic>;
|
||||||
|
return MaterialPageRoute(builder: (context) {
|
||||||
|
return MediaQuery(
|
||||||
|
data: MediaQuery.of(context).copyWith(
|
||||||
|
textScaleFactor: 1.0, padding: const EdgeInsets.all(0)),
|
||||||
|
child: InputPengantaranHasilPasienScreen(
|
||||||
|
data: args,
|
||||||
|
));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// input pengantaran hasil instansi
|
||||||
|
if (settings.name == inputPengantaranHasilInstansi) {
|
||||||
|
final args = settings.arguments as Map<String, dynamic>;
|
||||||
|
return MaterialPageRoute(builder: (context) {
|
||||||
|
return MediaQuery(
|
||||||
|
data: MediaQuery.of(context)
|
||||||
|
.copyWith(textScaleFactor: 1.0, padding: const EdgeInsets.all(0)),
|
||||||
|
child: InputPengantaranHasilInstansiScreen(
|
||||||
|
data: args,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// input pengantaran hasil dokter
|
||||||
|
if (settings.name == inputPengantaranHasilDokter) {
|
||||||
|
final args = settings.arguments as Map<String, dynamic>;
|
||||||
|
return MaterialPageRoute(builder: (context) {
|
||||||
|
return MediaQuery(
|
||||||
|
data: MediaQuery.of(context)
|
||||||
|
.copyWith(textScaleFactor: 1.0, padding: const EdgeInsets.all(0)),
|
||||||
|
child: InputPengantaranHasilDokterScreen(
|
||||||
|
data: args,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// input pengambilan bahan
|
||||||
|
if (settings.name == inputPengambilanBahan) {
|
||||||
|
final args = settings.arguments as Map<String, dynamic>;
|
||||||
|
return MaterialPageRoute(builder: (context) {
|
||||||
|
return MediaQuery(
|
||||||
|
data: MediaQuery.of(context)
|
||||||
|
.copyWith(textScaleFactor: 1.0, padding: const EdgeInsets.all(0)),
|
||||||
|
child: InputPengambilanBahanScreen(
|
||||||
|
data: args,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// input lain lain
|
||||||
|
if (settings.name == inputLainLain) {
|
||||||
|
final args = settings.arguments as Map<String, dynamic>;
|
||||||
|
return MaterialPageRoute(builder: (context) {
|
||||||
|
return MediaQuery(
|
||||||
|
data: MediaQuery.of(context)
|
||||||
|
.copyWith(textScaleFactor: 1.0, padding: const EdgeInsets.all(0)),
|
||||||
|
child: InputLainLain(
|
||||||
|
data: args,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// input scan
|
||||||
|
if (settings.name == inputScanRoute) {
|
||||||
|
// final args = settings.arguments as Map<String, dynamic>;
|
||||||
|
final InputScanPekerjaanProp args =
|
||||||
|
settings.arguments as InputScanPekerjaanProp;
|
||||||
|
return MaterialPageRoute(builder: (context) {
|
||||||
|
return MediaQuery(
|
||||||
|
data: MediaQuery.of(context)
|
||||||
|
.copyWith(textScaleFactor: 1.0, padding: const EdgeInsets.all(0)),
|
||||||
|
child: InputScanScreen(
|
||||||
|
data: args,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// konfirmasi
|
||||||
|
if (settings.name == konfirmasiRoute) {
|
||||||
|
return MaterialPageRoute(builder: (context) {
|
||||||
|
return MediaQuery(
|
||||||
|
data: MediaQuery.of(context).copyWith(
|
||||||
|
textScaleFactor: 1.0, padding: const EdgeInsets.all(0)),
|
||||||
|
child: const KonfirmasiScreen());
|
||||||
|
});
|
||||||
|
}
|
||||||
|
// Informasi Pribadi
|
||||||
|
if (settings.name == personalInformationRoute) {
|
||||||
|
return MaterialPageRoute(builder: (context) {
|
||||||
|
return MediaQuery(
|
||||||
|
data: MediaQuery.of(context).copyWith(
|
||||||
|
textScaleFactor: 1.0, padding: const EdgeInsets.all(0)),
|
||||||
|
child: const PersonalInformationScreen());
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (settings.name == changePasswordRoute) {
|
||||||
|
return MaterialPageRoute(builder: (context) {
|
||||||
|
return MediaQuery(
|
||||||
|
data: MediaQuery.of(context).copyWith(
|
||||||
|
textScaleFactor: 1.0, padding: const EdgeInsets.all(0)),
|
||||||
|
child: const ChangePasswordScreen());
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (settings.name == workProcessRoute) {
|
||||||
|
final args = settings.arguments as DetailWorkProp;
|
||||||
|
|
||||||
|
return MaterialPageRoute(builder: (context) {
|
||||||
|
return MediaQuery(
|
||||||
|
data: MediaQuery.of(context).copyWith(
|
||||||
|
textScaleFactor: 1.0, padding: const EdgeInsets.all(0)),
|
||||||
|
child: WorkProcessScreen(
|
||||||
|
data: args,
|
||||||
|
));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return MaterialPageRoute(builder: (context) {
|
||||||
|
return MediaQuery(
|
||||||
|
data: MediaQuery.of(context)
|
||||||
|
.copyWith(textScaleFactor: 1.0, padding: const EdgeInsets.all(0)),
|
||||||
|
child: const SplashScreen());
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
BIN
lib/images/bg_login.png
Normal file
|
After Width: | Height: | Size: 10 KiB |
BIN
lib/images/bg_problem_login.png
Normal file
|
After Width: | Height: | Size: 13 KiB |
BIN
lib/images/icon_eye_password_active.png
Normal file
|
After Width: | Height: | Size: 551 B |
BIN
lib/images/icon_eye_password_not_active.png
Normal file
|
After Width: | Height: | Size: 597 B |
BIN
lib/images/icon_home.png
Normal file
|
After Width: | Height: | Size: 282 B |
BIN
lib/images/icon_home_bell.png
Normal file
|
After Width: | Height: | Size: 426 B |
BIN
lib/images/icon_home_diterima.png
Normal file
|
After Width: | Height: | Size: 432 B |
BIN
lib/images/icon_home_hasil.png
Normal file
|
After Width: | Height: | Size: 326 B |
BIN
lib/images/icon_home_lainnya.png
Normal file
|
After Width: | Height: | Size: 330 B |
BIN
lib/images/icon_home_sample.png
Normal file
|
After Width: | Height: | Size: 535 B |
BIN
lib/images/icon_home_selesai.png
Normal file
|
After Width: | Height: | Size: 445 B |
BIN
lib/images/icon_home_total.png
Normal file
|
After Width: | Height: | Size: 390 B |
BIN
lib/images/logo_kdr.png
Normal file
|
After Width: | Height: | Size: 21 KiB |
BIN
lib/images/logo_kurir_konfirmasi.png
Normal file
|
After Width: | Height: | Size: 9.6 KiB |
133
lib/main.dart
@@ -1,7 +1,18 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||||
|
import 'package:flutter/services.dart';
|
||||||
|
import 'package:intl/date_symbol_data_file.dart';
|
||||||
|
|
||||||
|
import 'app/constant.dart';
|
||||||
|
import 'app/route.dart';
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
runApp(const MyApp());
|
WidgetsFlutterBinding.ensureInitialized();
|
||||||
|
SystemChrome.setPreferredOrientations([
|
||||||
|
DeviceOrientation.portraitUp,
|
||||||
|
DeviceOrientation.portraitUp,
|
||||||
|
]).then((value) => runApp(const ProviderScope(child: MyApp())));
|
||||||
|
// runApp(const ProviderScope(child: MyApp()));
|
||||||
}
|
}
|
||||||
|
|
||||||
class MyApp extends StatelessWidget {
|
class MyApp extends StatelessWidget {
|
||||||
@@ -11,112 +22,34 @@ class MyApp extends StatelessWidget {
|
|||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return MaterialApp(
|
return MaterialApp(
|
||||||
title: 'Flutter Demo',
|
title: 'Aplikasi Kurir Kedungdoro',
|
||||||
theme: ThemeData(
|
theme: ThemeData(
|
||||||
// This is the theme of your application.
|
primarySwatch: createMaterialColor(const Color(0xFF005AA9)),
|
||||||
//
|
fontFamily: 'OpenSans'),
|
||||||
// TRY THIS: Try running your application with "flutter run". You'll see
|
debugShowCheckedModeBanner: false,
|
||||||
// the application has a purple toolbar. Then, without quitting the app,
|
// initialRoute: loginRoute,
|
||||||
// try changing the seedColor in the colorScheme below to Colors.green
|
initialRoute: splashRoute,
|
||||||
// and then invoke "hot reload" (save your changes or press the "hot
|
onGenerateRoute: AppRoute.generateRoute,
|
||||||
// reload" button in a Flutter-supported IDE, or press "r" if you used
|
|
||||||
// the command line to start the app).
|
|
||||||
//
|
|
||||||
// Notice that the counter didn't reset back to zero; the application
|
|
||||||
// state is not lost during the reload. To reset the state, use hot
|
|
||||||
// restart instead.
|
|
||||||
//
|
|
||||||
// This works for code too, not just values: Most code changes can be
|
|
||||||
// tested with just a hot reload.
|
|
||||||
colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
|
|
||||||
),
|
|
||||||
home: const MyHomePage(title: 'Flutter Demo Home Page'),
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class MyHomePage extends StatefulWidget {
|
MaterialColor createMaterialColor(Color color) {
|
||||||
const MyHomePage({super.key, required this.title});
|
List strengths = <double>[.05];
|
||||||
|
Map<int, Color> swatch = {};
|
||||||
|
final int r = color.red, g = color.green, b = color.blue;
|
||||||
|
|
||||||
// This widget is the home page of your application. It is stateful, meaning
|
for (int i = 1; i < 10; i++) {
|
||||||
// that it has a State object (defined below) that contains fields that affect
|
strengths.add(0.1 * i);
|
||||||
// how it looks.
|
|
||||||
|
|
||||||
// This class is the configuration for the state. It holds the values (in this
|
|
||||||
// case the title) provided by the parent (in this case the App widget) and
|
|
||||||
// used by the build method of the State. Fields in a Widget subclass are
|
|
||||||
// always marked "final".
|
|
||||||
|
|
||||||
final String title;
|
|
||||||
|
|
||||||
@override
|
|
||||||
State<MyHomePage> createState() => _MyHomePageState();
|
|
||||||
}
|
|
||||||
|
|
||||||
class _MyHomePageState extends State<MyHomePage> {
|
|
||||||
int _counter = 0;
|
|
||||||
|
|
||||||
void _incrementCounter() {
|
|
||||||
setState(() {
|
|
||||||
// This call to setState tells the Flutter framework that something has
|
|
||||||
// changed in this State, which causes it to rerun the build method below
|
|
||||||
// so that the display can reflect the updated values. If we changed
|
|
||||||
// _counter without calling setState(), then the build method would not be
|
|
||||||
// called again, and so nothing would appear to happen.
|
|
||||||
_counter++;
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
for (var strength in strengths) {
|
||||||
@override
|
final double ds = 0.5 - strength;
|
||||||
Widget build(BuildContext context) {
|
swatch[(strength * 1000).round()] = Color.fromRGBO(
|
||||||
// This method is rerun every time setState is called, for instance as done
|
r + ((ds < 0 ? r : (255 - r)) * ds).round(),
|
||||||
// by the _incrementCounter method above.
|
g + ((ds < 0 ? g : (255 - g)) * ds).round(),
|
||||||
//
|
b + ((ds < 0 ? b : (255 - b)) * ds).round(),
|
||||||
// The Flutter framework has been optimized to make rerunning build methods
|
1,
|
||||||
// fast, so that you can just rebuild anything that needs updating rather
|
|
||||||
// than having to individually change instances of widgets.
|
|
||||||
return Scaffold(
|
|
||||||
appBar: AppBar(
|
|
||||||
// TRY THIS: Try changing the color here to a specific color (to
|
|
||||||
// Colors.amber, perhaps?) and trigger a hot reload to see the AppBar
|
|
||||||
// change color while the other colors stay the same.
|
|
||||||
backgroundColor: Theme.of(context).colorScheme.inversePrimary,
|
|
||||||
// Here we take the value from the MyHomePage object that was created by
|
|
||||||
// the App.build method, and use it to set our appbar title.
|
|
||||||
title: Text(widget.title),
|
|
||||||
),
|
|
||||||
body: Center(
|
|
||||||
// Center is a layout widget. It takes a single child and positions it
|
|
||||||
// in the middle of the parent.
|
|
||||||
child: Column(
|
|
||||||
// Column is also a layout widget. It takes a list of children and
|
|
||||||
// arranges them vertically. By default, it sizes itself to fit its
|
|
||||||
// children horizontally, and tries to be as tall as its parent.
|
|
||||||
//
|
|
||||||
// Column has various properties to control how it sizes itself and
|
|
||||||
// how it positions its children. Here we use mainAxisAlignment to
|
|
||||||
// center the children vertically; the main axis here is the vertical
|
|
||||||
// axis because Columns are vertical (the cross axis would be
|
|
||||||
// horizontal).
|
|
||||||
//
|
|
||||||
// TRY THIS: Invoke "debug painting" (choose the "Toggle Debug Paint"
|
|
||||||
// action in the IDE, or press "p" in the console), to see the
|
|
||||||
// wireframe for each widget.
|
|
||||||
mainAxisAlignment: MainAxisAlignment.center,
|
|
||||||
children: <Widget>[
|
|
||||||
const Text('You have pushed the button this many times:'),
|
|
||||||
Text(
|
|
||||||
'$_counter',
|
|
||||||
style: Theme.of(context).textTheme.headlineMedium,
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
floatingActionButton: FloatingActionButton(
|
|
||||||
onPressed: _incrementCounter,
|
|
||||||
tooltip: 'Increment',
|
|
||||||
child: const Icon(Icons.add),
|
|
||||||
), // This trailing comma makes auto-formatting nicer for build methods.
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
return MaterialColor(color.value, swatch);
|
||||||
}
|
}
|
||||||
|
|||||||
71
lib/models/auth_model.dart
Normal file
@@ -0,0 +1,71 @@
|
|||||||
|
class AuthModel {
|
||||||
|
final String token;
|
||||||
|
final AuthKurirModel model;
|
||||||
|
|
||||||
|
AuthModel({
|
||||||
|
required this.token,
|
||||||
|
required this.model,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
class AuthKurirModel {
|
||||||
|
User? user;
|
||||||
|
String? token;
|
||||||
|
|
||||||
|
AuthKurirModel({this.user, this.token});
|
||||||
|
|
||||||
|
AuthKurirModel.fromJson(Map<String, dynamic> json) {
|
||||||
|
user = json['user'] != null ? User.fromJson(json['user']) : null;
|
||||||
|
token = json['token'];
|
||||||
|
}
|
||||||
|
|
||||||
|
Map<String, dynamic> toJson() {
|
||||||
|
final Map<String, dynamic> data = <String, dynamic>{};
|
||||||
|
if (user != null) {
|
||||||
|
data['user'] = user!.toJson();
|
||||||
|
}
|
||||||
|
data['token'] = token;
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class User {
|
||||||
|
String? mUserID;
|
||||||
|
String? mUserUsername;
|
||||||
|
String? mStaffName;
|
||||||
|
String? ip;
|
||||||
|
String? agent;
|
||||||
|
String? mUserPassword = "";
|
||||||
|
String? mCourierID;
|
||||||
|
|
||||||
|
User(
|
||||||
|
{this.mUserID,
|
||||||
|
this.mUserUsername,
|
||||||
|
this.mStaffName,
|
||||||
|
this.ip,
|
||||||
|
this.agent,
|
||||||
|
this.mUserPassword,
|
||||||
|
this.mCourierID});
|
||||||
|
|
||||||
|
User.fromJson(Map<String, dynamic> json) {
|
||||||
|
mUserID = json['M_UserID'];
|
||||||
|
mUserUsername = json['M_UserUsername'];
|
||||||
|
mStaffName = json['Nat_StaffName'];
|
||||||
|
ip = json['ip'];
|
||||||
|
agent = json['agent'];
|
||||||
|
mCourierID = json['M_CourierID'];
|
||||||
|
mUserPassword = "";
|
||||||
|
}
|
||||||
|
|
||||||
|
Map<String, dynamic> toJson() {
|
||||||
|
final Map<String, dynamic> data = <String, dynamic>{};
|
||||||
|
data['M_UserID'] = mUserID;
|
||||||
|
data['M_UserUsername'] = mUserUsername;
|
||||||
|
data['Nat_StaffName'] = mStaffName;
|
||||||
|
data['ip'] = ip;
|
||||||
|
data['agent'] = agent;
|
||||||
|
data['M_CourierID'] = mCourierID;
|
||||||
|
data['M_UserPassword'] = mUserPassword;
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
}
|
||||||
32
lib/models/company_model.dart
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
class CompanyModel {
|
||||||
|
String? mCompanyID;
|
||||||
|
String? mCompanyName;
|
||||||
|
String? mCompanyNumber;
|
||||||
|
String? detail;
|
||||||
|
String? mCompanyAddress;
|
||||||
|
|
||||||
|
CompanyModel(
|
||||||
|
{this.mCompanyID,
|
||||||
|
this.mCompanyName,
|
||||||
|
this.mCompanyNumber,
|
||||||
|
this.detail,
|
||||||
|
this.mCompanyAddress});
|
||||||
|
|
||||||
|
CompanyModel.fromJson(Map<String, dynamic> json) {
|
||||||
|
mCompanyID = json['M_CompanyID'];
|
||||||
|
mCompanyName = json['M_CompanyName'];
|
||||||
|
mCompanyNumber = json['M_CompanyNumber'];
|
||||||
|
detail = json['detail'];
|
||||||
|
mCompanyAddress = json['M_CompanyAddress'];
|
||||||
|
}
|
||||||
|
|
||||||
|
Map<String, dynamic> toJson() {
|
||||||
|
final Map<String, dynamic> data = new Map<String, dynamic>();
|
||||||
|
data['M_CompanyID'] = this.mCompanyID;
|
||||||
|
data['M_CompanyName'] = this.mCompanyName;
|
||||||
|
data['M_CompanyNumber'] = this.mCompanyNumber;
|
||||||
|
data['detail'] = this.detail;
|
||||||
|
data['M_CompanyAddress'] = this.mCompanyAddress;
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
}
|
||||||
149
lib/models/detail_history_model.dart
Normal file
@@ -0,0 +1,149 @@
|
|||||||
|
import 'dart:convert';
|
||||||
|
|
||||||
|
import '../models/patient_model.dart';
|
||||||
|
|
||||||
|
// "note_penyerahan": "lengkap",
|
||||||
|
// "alamat_pengantaran": "Jl Sampangan no 231 ABA Barusari, Semarang Selatan, Semarang",
|
||||||
|
// "penerima": "Nicolas Saputra",
|
||||||
|
// "note_penerima": "oke lengkap",
|
||||||
|
class DetailHistoryModel {
|
||||||
|
String? id;
|
||||||
|
String? tipeid;
|
||||||
|
String? tipe;
|
||||||
|
String? noSuratJalan;
|
||||||
|
String? nama;
|
||||||
|
String? distance;
|
||||||
|
String? cdate;
|
||||||
|
String? alamatPengambilan;
|
||||||
|
String? petugasPenyerahan;
|
||||||
|
String? alamatPengantaran;
|
||||||
|
String? penerima;
|
||||||
|
String? lokasiPengambilanAwal;
|
||||||
|
String? latPengambilanAwal;
|
||||||
|
String? lngPengambilanAwal;
|
||||||
|
String? lokasiPengambilanAkhir;
|
||||||
|
String? latPengambilanAkhir;
|
||||||
|
String? lngPengambilanAkhir;
|
||||||
|
String? lokasiPengantaranAwal;
|
||||||
|
String? latPengantaranAwal;
|
||||||
|
String? lngPengantaranAwal;
|
||||||
|
String? lokasiPengantaranAkhir;
|
||||||
|
String? latPengantaranAkhir;
|
||||||
|
String? lngPengantaranAkhir;
|
||||||
|
String? notePenyerahan;
|
||||||
|
String? notePenerimaan;
|
||||||
|
List<PatientModel>? patients;
|
||||||
|
String? foNote;
|
||||||
|
String? adminNote;
|
||||||
|
|
||||||
|
DetailHistoryModel(
|
||||||
|
{this.id,
|
||||||
|
this.tipeid,
|
||||||
|
this.tipe,
|
||||||
|
this.noSuratJalan,
|
||||||
|
this.nama,
|
||||||
|
this.distance,
|
||||||
|
this.cdate,
|
||||||
|
this.alamatPengambilan,
|
||||||
|
this.petugasPenyerahan,
|
||||||
|
this.alamatPengantaran,
|
||||||
|
this.penerima,
|
||||||
|
this.lokasiPengambilanAwal,
|
||||||
|
this.latPengambilanAwal,
|
||||||
|
this.lngPengambilanAwal,
|
||||||
|
this.lokasiPengambilanAkhir,
|
||||||
|
this.latPengambilanAkhir,
|
||||||
|
this.lngPengambilanAkhir,
|
||||||
|
this.lokasiPengantaranAwal,
|
||||||
|
this.latPengantaranAwal,
|
||||||
|
this.lngPengantaranAwal,
|
||||||
|
this.lokasiPengantaranAkhir,
|
||||||
|
this.latPengantaranAkhir,
|
||||||
|
this.lngPengantaranAkhir,
|
||||||
|
this.notePenerimaan,
|
||||||
|
this.notePenyerahan,
|
||||||
|
this.foNote,
|
||||||
|
this.adminNote,
|
||||||
|
this.patients});
|
||||||
|
|
||||||
|
DetailHistoryModel.fromJson(Map<String, dynamic> json) {
|
||||||
|
id = json['id'];
|
||||||
|
tipeid = json['tipeid'];
|
||||||
|
tipe = json['tipe'];
|
||||||
|
noSuratJalan = json['no_surat_jalan'];
|
||||||
|
nama = json['nama'];
|
||||||
|
distance = json['distance'];
|
||||||
|
cdate = json['cdate'];
|
||||||
|
alamatPengambilan = json['alamat_pengambilan'];
|
||||||
|
petugasPenyerahan = json['petugas_penyerahan'];
|
||||||
|
alamatPengantaran = json['alamat_pengantaran'];
|
||||||
|
penerima = json['penerima'];
|
||||||
|
lokasiPengambilanAwal = json['lokasi_pengambilan_awal'];
|
||||||
|
latPengambilanAwal = json['lat_pengambilan_awal'];
|
||||||
|
lngPengambilanAwal = json['lng_pengambilan_awal'];
|
||||||
|
lokasiPengambilanAkhir = json['lokasi_pengambilan_akhir'];
|
||||||
|
latPengambilanAkhir = json['lat_pengambilan_akhir'];
|
||||||
|
lngPengambilanAkhir = json['lng_pengambilan_akhir'];
|
||||||
|
lokasiPengantaranAwal = json['lokasi_pengantaran_awal'];
|
||||||
|
latPengantaranAwal = json['lat_pengantaran_awal'];
|
||||||
|
lngPengantaranAwal = json['lng_pengantaran_awal'];
|
||||||
|
lokasiPengantaranAkhir = json['lokasi_pengantaran_akhir'];
|
||||||
|
latPengantaranAkhir = json['lat_pengantaran_akhir'];
|
||||||
|
lngPengantaranAkhir = json['lng_pengantaran_akhir'];
|
||||||
|
notePenerimaan = json['note_penerima'];
|
||||||
|
notePenyerahan = json['note_penyerahan'];
|
||||||
|
foNote = json['fo_note'];
|
||||||
|
adminNote = json['admin_note'];
|
||||||
|
// patients = json['patients'];
|
||||||
|
if (json['patients'].toString().isNotEmpty) {
|
||||||
|
var data = <PatientModel>[];
|
||||||
|
// print("hasil json decode");
|
||||||
|
// print(jsonDecode(json['patients']));
|
||||||
|
// print("end");
|
||||||
|
try {
|
||||||
|
jsonDecode(json['patients']).forEach((v) {
|
||||||
|
data.add(PatientModel.fromJson(v));
|
||||||
|
});
|
||||||
|
} catch (e) {
|
||||||
|
print(e);
|
||||||
|
}
|
||||||
|
patients = data;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Map<String, dynamic> toJson() {
|
||||||
|
final Map<String, dynamic> data = new Map<String, dynamic>();
|
||||||
|
data['id'] = this.id;
|
||||||
|
data['tipeid'] = this.tipeid;
|
||||||
|
data['tipe'] = this.tipe;
|
||||||
|
data['no_surat_jalan'] = this.noSuratJalan;
|
||||||
|
data['nama'] = this.nama;
|
||||||
|
data['distance'] = this.distance;
|
||||||
|
data['cdate'] = this.cdate;
|
||||||
|
data['alamat_pengambilan'] = this.alamatPengambilan;
|
||||||
|
data['petugas_penyerahan'] = this.petugasPenyerahan;
|
||||||
|
data['alamat_pengantaran'] = this.alamatPengantaran;
|
||||||
|
data['penerima'] = this.penerima;
|
||||||
|
data['lokasi_pengambilan_awal'] = this.lokasiPengambilanAwal;
|
||||||
|
data['lat_pengambilan_awal'] = this.latPengambilanAwal;
|
||||||
|
data['lng_pengambilan_awal'] = this.lngPengambilanAwal;
|
||||||
|
data['lokasi_pengambilan_akhir'] = this.lokasiPengambilanAkhir;
|
||||||
|
data['lat_pengambilan_akhir'] = this.latPengambilanAkhir;
|
||||||
|
data['lng_pengambilan_akhir'] = this.lngPengambilanAkhir;
|
||||||
|
data['lokasi_pengantaran_awal'] = this.lokasiPengantaranAwal;
|
||||||
|
data['lat_pengantaran_awal'] = this.latPengantaranAwal;
|
||||||
|
data['lng_pengantaran_awal'] = this.lngPengantaranAwal;
|
||||||
|
data['lokasi_pengantaran_akhir'] = this.lokasiPengantaranAkhir;
|
||||||
|
data['lat_pengantaran_akhir'] = this.latPengantaranAkhir;
|
||||||
|
data['lng_pengantaran_akhir'] = this.lngPengantaranAkhir;
|
||||||
|
data['note_penyerahan'] = this.notePenyerahan;
|
||||||
|
data['note_penerima'] = this.notePenerimaan;
|
||||||
|
data['fo_note'] = this.foNote;
|
||||||
|
data['admin_note'] = this.adminNote;
|
||||||
|
// data['patients'] = this.patients;
|
||||||
|
if (this.patients != null || this.patients != "") {
|
||||||
|
data['patients'] = this.patients!.map((v) => v.toJson()).toList();
|
||||||
|
}
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
}
|
||||||
195
lib/models/detail_work_model.dart
Normal file
@@ -0,0 +1,195 @@
|
|||||||
|
import 'dart:convert';
|
||||||
|
|
||||||
|
import '../models/patient_model.dart';
|
||||||
|
|
||||||
|
class DetailWorkModel {
|
||||||
|
String? id;
|
||||||
|
String? tipeid;
|
||||||
|
String? tipe;
|
||||||
|
String? noSuratJalan;
|
||||||
|
String? nama;
|
||||||
|
String? distance;
|
||||||
|
String? cdate;
|
||||||
|
String? alamatPengambilan;
|
||||||
|
String? petugasPenyerahan;
|
||||||
|
String? alamatPengantaran;
|
||||||
|
String? penerima;
|
||||||
|
String? lokasiPengambilanAwal;
|
||||||
|
String? latPengambilanAwal;
|
||||||
|
String? lngPengambilanAwal;
|
||||||
|
String? lokasiPengambilanAkhir;
|
||||||
|
String? latPengambilanAkhir;
|
||||||
|
String? lngPengambilanAkhir;
|
||||||
|
String? lokasiPengantaranAwal;
|
||||||
|
String? latPengantaranAwal;
|
||||||
|
String? lngPengantaranAwal;
|
||||||
|
String? lokasiPengantaranAkhir;
|
||||||
|
String? latPengantaranAkhir;
|
||||||
|
String? lngPengantaranAkhir;
|
||||||
|
String? notePenyerahan;
|
||||||
|
String? notePenerimaan;
|
||||||
|
List<PatientModel>? patients;
|
||||||
|
// TAMBAHAN INPUTAN INFO
|
||||||
|
String? suhuBox;
|
||||||
|
String? suhuSample;
|
||||||
|
String? totalPasien;
|
||||||
|
String? totalEdta;
|
||||||
|
String? totalCitras;
|
||||||
|
String? totalSerum;
|
||||||
|
String? totalUrine;
|
||||||
|
String? totalPleura;
|
||||||
|
String? otherSample;
|
||||||
|
String? totalOther;
|
||||||
|
String? foNote;
|
||||||
|
String? adminNote;
|
||||||
|
String? branchID;
|
||||||
|
|
||||||
|
DetailWorkModel(
|
||||||
|
{this.id,
|
||||||
|
this.tipeid,
|
||||||
|
this.tipe,
|
||||||
|
this.noSuratJalan,
|
||||||
|
this.nama,
|
||||||
|
this.distance,
|
||||||
|
this.cdate,
|
||||||
|
this.alamatPengambilan,
|
||||||
|
this.petugasPenyerahan,
|
||||||
|
this.alamatPengantaran,
|
||||||
|
this.penerima,
|
||||||
|
this.lokasiPengambilanAwal,
|
||||||
|
this.latPengambilanAwal,
|
||||||
|
this.lngPengambilanAwal,
|
||||||
|
this.lokasiPengambilanAkhir,
|
||||||
|
this.latPengambilanAkhir,
|
||||||
|
this.lngPengambilanAkhir,
|
||||||
|
this.lokasiPengantaranAwal,
|
||||||
|
this.latPengantaranAwal,
|
||||||
|
this.lngPengantaranAwal,
|
||||||
|
this.lokasiPengantaranAkhir,
|
||||||
|
this.latPengantaranAkhir,
|
||||||
|
this.lngPengantaranAkhir,
|
||||||
|
this.notePenerimaan,
|
||||||
|
this.notePenyerahan,
|
||||||
|
this.patients,
|
||||||
|
// TAMBAHAN INPUTAN INFO
|
||||||
|
this.suhuBox,
|
||||||
|
this.suhuSample,
|
||||||
|
this.totalPasien,
|
||||||
|
this.totalEdta,
|
||||||
|
this.totalCitras,
|
||||||
|
this.totalSerum,
|
||||||
|
this.totalUrine,
|
||||||
|
this.totalPleura,
|
||||||
|
this.otherSample,
|
||||||
|
this.totalOther,
|
||||||
|
this.foNote,
|
||||||
|
this.adminNote,
|
||||||
|
this.branchID});
|
||||||
|
|
||||||
|
DetailWorkModel.fromJson(Map<String, dynamic> json) {
|
||||||
|
id = json['id'];
|
||||||
|
tipeid = json['tipeid'];
|
||||||
|
tipe = json['tipe'];
|
||||||
|
noSuratJalan = json['no_surat_jalan'];
|
||||||
|
nama = json['nama'];
|
||||||
|
distance = json['distance'];
|
||||||
|
cdate = json['cdate'];
|
||||||
|
alamatPengambilan = json['alamat_pengambilan'];
|
||||||
|
petugasPenyerahan = json['petugas_penyerahan'];
|
||||||
|
alamatPengantaran = json['alamat_pengantaran'];
|
||||||
|
penerima = json['penerima'];
|
||||||
|
lokasiPengambilanAwal = json['lokasi_pengambilan_awal'];
|
||||||
|
latPengambilanAwal = json['lat_pengambilan_awal'];
|
||||||
|
lngPengambilanAwal = json['lng_pengambilan_awal'];
|
||||||
|
lokasiPengambilanAkhir = json['lokasi_pengambilan_akhir'];
|
||||||
|
latPengambilanAkhir = json['lat_pengambilan_akhir'];
|
||||||
|
lngPengambilanAkhir = json['lng_pengambilan_akhir'];
|
||||||
|
lokasiPengantaranAwal = json['lokasi_pengantaran_awal'];
|
||||||
|
latPengantaranAwal = json['lat_pengantaran_awal'];
|
||||||
|
lngPengantaranAwal = json['lng_pengantaran_awal'];
|
||||||
|
lokasiPengantaranAkhir = json['lokasi_pengantaran_akhir'];
|
||||||
|
latPengantaranAkhir = json['lat_pengantaran_akhir'];
|
||||||
|
lngPengantaranAkhir = json['lng_pengantaran_akhir'];
|
||||||
|
notePenerimaan = json['note_penerima'];
|
||||||
|
notePenyerahan = json['note_penyerahan'];
|
||||||
|
// patients = json['patients'];
|
||||||
|
if (json['patients'].toString().isNotEmpty) {
|
||||||
|
var data = <PatientModel>[];
|
||||||
|
// print("hasil json decode");
|
||||||
|
// print(jsonDecode(json['patients']));
|
||||||
|
// print("end");
|
||||||
|
try {
|
||||||
|
jsonDecode(json['patients']).forEach((v) {
|
||||||
|
data.add(PatientModel.fromJson(v));
|
||||||
|
});
|
||||||
|
} catch (e) {
|
||||||
|
print(e);
|
||||||
|
}
|
||||||
|
patients = data;
|
||||||
|
}
|
||||||
|
|
||||||
|
// TAMBAHAN INPUTAN INFO
|
||||||
|
suhuBox = json['suhu_box'];
|
||||||
|
suhuSample = json['suhu_sample'];
|
||||||
|
totalPasien = json['total_pasien'];
|
||||||
|
totalEdta = json['total_edta'];
|
||||||
|
totalCitras = json['total_citras'];
|
||||||
|
totalSerum = json['total_serum'];
|
||||||
|
totalUrine = json['total_urine'];
|
||||||
|
totalPleura = json['total_pleura'];
|
||||||
|
otherSample = json['other_sample'];
|
||||||
|
totalOther = json['total_other'];
|
||||||
|
foNote = json['fo_note'];
|
||||||
|
adminNote = json['admin_note'];
|
||||||
|
branchID = json['branchid'];
|
||||||
|
}
|
||||||
|
|
||||||
|
Map<String, dynamic> toJson() {
|
||||||
|
final Map<String, dynamic> data = new Map<String, dynamic>();
|
||||||
|
data['id'] = this.id;
|
||||||
|
data['tipeid'] = this.tipeid;
|
||||||
|
data['tipe'] = this.tipe;
|
||||||
|
data['no_surat_jalan'] = this.noSuratJalan;
|
||||||
|
data['nama'] = this.nama;
|
||||||
|
data['distance'] = this.distance;
|
||||||
|
data['cdate'] = this.cdate;
|
||||||
|
data['alamat_pengambilan'] = this.alamatPengambilan;
|
||||||
|
data['petugas_penyerahan'] = this.petugasPenyerahan;
|
||||||
|
data['alamat_pengantaran'] = this.alamatPengantaran;
|
||||||
|
data['penerima'] = this.penerima;
|
||||||
|
data['lokasi_pengambilan_awal'] = this.lokasiPengambilanAwal;
|
||||||
|
data['lat_pengambilan_awal'] = this.latPengambilanAwal;
|
||||||
|
data['lng_pengambilan_awal'] = this.lngPengambilanAwal;
|
||||||
|
data['lokasi_pengambilan_akhir'] = this.lokasiPengambilanAkhir;
|
||||||
|
data['lat_pengambilan_akhir'] = this.latPengambilanAkhir;
|
||||||
|
data['lng_pengambilan_akhir'] = this.lngPengambilanAkhir;
|
||||||
|
data['lokasi_pengantaran_awal'] = this.lokasiPengantaranAwal;
|
||||||
|
data['lat_pengantaran_awal'] = this.latPengantaranAwal;
|
||||||
|
data['lng_pengantaran_awal'] = this.lngPengantaranAwal;
|
||||||
|
data['lokasi_pengantaran_akhir'] = this.lokasiPengantaranAkhir;
|
||||||
|
data['lat_pengantaran_akhir'] = this.latPengantaranAkhir;
|
||||||
|
data['lng_pengantaran_akhir'] = this.lngPengantaranAkhir;
|
||||||
|
data['note_penyerahan'] = this.notePenyerahan;
|
||||||
|
data['note_penerima'] = this.notePenerimaan;
|
||||||
|
// data['patients'] = this.patients;
|
||||||
|
if (this.patients != null || this.patients != "") {
|
||||||
|
data['patients'] = this.patients!.map((v) => v.toJson()).toList();
|
||||||
|
}
|
||||||
|
|
||||||
|
// TAMBAHAN INPUTAN INFO
|
||||||
|
data['suhu_box'] = this.suhuBox;
|
||||||
|
data['suhu_sample'] = this.suhuSample;
|
||||||
|
data['total_pasien'] = this.totalPasien;
|
||||||
|
data['total_edta'] = this.totalEdta;
|
||||||
|
data['total_citras'] = this.totalCitras;
|
||||||
|
data['total_serum'] = this.totalSerum;
|
||||||
|
data['total_urine'] = this.totalUrine;
|
||||||
|
data['total_pleura'] = this.totalPleura;
|
||||||
|
data['other_sample'] = this.otherSample;
|
||||||
|
data['total_other'] = this.totalOther;
|
||||||
|
data['fo_note'] = this.foNote;
|
||||||
|
data['admin_note'] = this.adminNote;
|
||||||
|
data['branchid'] = this.branchID;
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
}
|
||||||
44
lib/models/history_model.dart
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
class HistoryModel {
|
||||||
|
String? id;
|
||||||
|
int? tipeid;
|
||||||
|
String? tipe;
|
||||||
|
String? noSuratJalan;
|
||||||
|
String? nama;
|
||||||
|
String? distance;
|
||||||
|
String? cdate;
|
||||||
|
String? ispending;
|
||||||
|
|
||||||
|
HistoryModel(
|
||||||
|
{this.id,
|
||||||
|
this.tipeid,
|
||||||
|
this.tipe,
|
||||||
|
this.noSuratJalan,
|
||||||
|
this.nama,
|
||||||
|
this.distance,
|
||||||
|
this.cdate,
|
||||||
|
this.ispending});
|
||||||
|
|
||||||
|
HistoryModel.fromJson(Map<String, dynamic> json) {
|
||||||
|
id = json['id'];
|
||||||
|
tipeid = int.parse(json['tipeid']);
|
||||||
|
tipe = json['tipe'];
|
||||||
|
noSuratJalan = json['no_surat_jalan'];
|
||||||
|
nama = json['nama'];
|
||||||
|
distance = json['distance'];
|
||||||
|
cdate = json['cdate'];
|
||||||
|
ispending = json['ispending'];
|
||||||
|
}
|
||||||
|
|
||||||
|
Map<String, dynamic> toJson() {
|
||||||
|
final Map<String, dynamic> data = new Map<String, dynamic>();
|
||||||
|
data['id'] = this.id;
|
||||||
|
data['tipeid'] = this.tipeid;
|
||||||
|
data['tipe'] = this.tipe;
|
||||||
|
data['no_surat_jalan'] = this.noSuratJalan;
|
||||||
|
data['nama'] = this.nama;
|
||||||
|
data['distance'] = this.distance;
|
||||||
|
data['cdate'] = this.cdate;
|
||||||
|
data['ispending'] = this.ispending;
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
}
|
||||||
23
lib/models/history_type_model.dart
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
import 'package:equatable/equatable.dart';
|
||||||
|
|
||||||
|
class HistoryTypeModel extends Equatable {
|
||||||
|
String? tipeid;
|
||||||
|
String? tipename;
|
||||||
|
|
||||||
|
HistoryTypeModel({this.tipeid, this.tipename});
|
||||||
|
|
||||||
|
HistoryTypeModel.fromJson(Map<String, dynamic> json) {
|
||||||
|
tipeid = json['tipeid'];
|
||||||
|
tipename = json['tipename'];
|
||||||
|
}
|
||||||
|
|
||||||
|
Map<String, dynamic> toJson() {
|
||||||
|
final Map<String, dynamic> data = new Map<String, dynamic>();
|
||||||
|
data['tipeid'] = this.tipeid;
|
||||||
|
data['tipename'] = this.tipename;
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
List<Object?> get props => [tipeid];
|
||||||
|
}
|
||||||
32
lib/models/patient_model.dart
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
class PatientModel {
|
||||||
|
String? tOrderDeliveryID;
|
||||||
|
String? tOrderHeaderID;
|
||||||
|
String? tOrderHeaderLabNumber;
|
||||||
|
String? pasien;
|
||||||
|
String? courierConfirmNote;
|
||||||
|
|
||||||
|
PatientModel(
|
||||||
|
{this.tOrderDeliveryID,
|
||||||
|
this.tOrderHeaderID,
|
||||||
|
this.tOrderHeaderLabNumber,
|
||||||
|
this.pasien,
|
||||||
|
this.courierConfirmNote});
|
||||||
|
|
||||||
|
PatientModel.fromJson(Map<String, dynamic> json) {
|
||||||
|
tOrderDeliveryID = json['T_OrderDeliveryID'];
|
||||||
|
tOrderHeaderID = json['T_OrderHeaderID'];
|
||||||
|
tOrderHeaderLabNumber = json['T_OrderHeaderLabNumber'];
|
||||||
|
pasien = json['pasien'];
|
||||||
|
courierConfirmNote = json['courier_confirmNote'];
|
||||||
|
}
|
||||||
|
|
||||||
|
Map<String, dynamic> toJson() {
|
||||||
|
final Map<String, dynamic> data = new Map<String, dynamic>();
|
||||||
|
data['T_OrderDeliveryID'] = this.tOrderDeliveryID;
|
||||||
|
data['T_OrderHeaderID'] = this.tOrderHeaderID;
|
||||||
|
data['T_OrderHeaderLabNumber'] = this.tOrderHeaderLabNumber;
|
||||||
|
data['pasien'] = this.pasien;
|
||||||
|
data['courier_confirmNote'] = this.courierConfirmNote;
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
}
|
||||||
92
lib/models/pending_work_model.dart
Normal file
@@ -0,0 +1,92 @@
|
|||||||
|
import 'dart:convert';
|
||||||
|
|
||||||
|
import '../models/patient_model.dart';
|
||||||
|
|
||||||
|
class PendingWorkModel {
|
||||||
|
int? id;
|
||||||
|
int? tipeid;
|
||||||
|
String? tipe;
|
||||||
|
String? noSuratJalan;
|
||||||
|
String? nama;
|
||||||
|
String? noLab;
|
||||||
|
String? alamat;
|
||||||
|
String? statusTransaksi;
|
||||||
|
String? branchid;
|
||||||
|
String? branchcode;
|
||||||
|
String? branchname;
|
||||||
|
String? branchaddress;
|
||||||
|
String? supervisor;
|
||||||
|
List<PatientModel>? patients;
|
||||||
|
String? note;
|
||||||
|
|
||||||
|
PendingWorkModel(
|
||||||
|
{this.id,
|
||||||
|
this.tipeid,
|
||||||
|
this.tipe,
|
||||||
|
this.noSuratJalan,
|
||||||
|
this.nama,
|
||||||
|
this.noLab,
|
||||||
|
this.alamat,
|
||||||
|
this.statusTransaksi,
|
||||||
|
this.branchid,
|
||||||
|
this.branchcode,
|
||||||
|
this.branchname,
|
||||||
|
this.branchaddress,
|
||||||
|
this.patients,
|
||||||
|
this.note});
|
||||||
|
|
||||||
|
PendingWorkModel.fromJson(Map<String, dynamic> json) {
|
||||||
|
id = int.parse(json['id']);
|
||||||
|
tipeid = int.parse(json['tipeid']);
|
||||||
|
tipe = json['tipe'];
|
||||||
|
noSuratJalan = json['no_surat_jalan'];
|
||||||
|
nama = json['nama'];
|
||||||
|
noLab = json['no_lab'];
|
||||||
|
alamat = json['alamat'];
|
||||||
|
statusTransaksi = json['status_transaksi'];
|
||||||
|
branchid = json['branchid'];
|
||||||
|
branchcode = json['branchcode'];
|
||||||
|
branchname = json['branchname'];
|
||||||
|
branchaddress = json['branchaddress'];
|
||||||
|
note = json['note'];
|
||||||
|
supervisor = json['supervisor'];
|
||||||
|
// print("patient :" + json['patients']);
|
||||||
|
if (json['patients'].toString().isNotEmpty) {
|
||||||
|
var data = <PatientModel>[];
|
||||||
|
// print("hasil json decode");
|
||||||
|
// print(jsonDecode(json['patients']));
|
||||||
|
// print("end");
|
||||||
|
try {
|
||||||
|
jsonDecode(json['patients']).forEach((v) {
|
||||||
|
data.add(PatientModel.fromJson(v));
|
||||||
|
});
|
||||||
|
} catch (e) {
|
||||||
|
print(e);
|
||||||
|
}
|
||||||
|
patients = data;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Map<String, dynamic> toJson() {
|
||||||
|
final Map<String, dynamic> data = new Map<String, dynamic>();
|
||||||
|
data['id'] = this.id;
|
||||||
|
data['tipeid'] = this.tipeid;
|
||||||
|
data['tipe'] = this.tipe;
|
||||||
|
data['no_surat_jalan'] = this.noSuratJalan;
|
||||||
|
data['nama'] = this.nama;
|
||||||
|
data['no_lab'] = this.noLab;
|
||||||
|
data['alamat'] = this.alamat;
|
||||||
|
data['status_transaksi'] = this.statusTransaksi;
|
||||||
|
data['branchid'] = this.branchid;
|
||||||
|
data['branchcode'] = this.branchcode;
|
||||||
|
data['branchname'] = this.branchname;
|
||||||
|
data['branchaddress'] = this.branchaddress;
|
||||||
|
data['patients'] = this.patients;
|
||||||
|
if (this.patients != null || this.patients != "") {
|
||||||
|
data['patients'] = this.patients!.map((v) => v.toJson()).toList();
|
||||||
|
}
|
||||||
|
data['note'] = this.note;
|
||||||
|
data['supervisor'] = this.supervisor;
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
}
|
||||||
36
lib/models/personal_information_model.dart
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
class PersonalInformationModel {
|
||||||
|
String? mUserID;
|
||||||
|
String? mUserUsername;
|
||||||
|
String? mUserPassword;
|
||||||
|
String? natStaffName;
|
||||||
|
String? natStaffNIK;
|
||||||
|
String? mCourierID;
|
||||||
|
|
||||||
|
PersonalInformationModel(
|
||||||
|
{this.mUserID,
|
||||||
|
this.mUserUsername,
|
||||||
|
this.mUserPassword,
|
||||||
|
this.natStaffName,
|
||||||
|
this.natStaffNIK,
|
||||||
|
this.mCourierID});
|
||||||
|
|
||||||
|
PersonalInformationModel.fromJson(Map<String, dynamic> json) {
|
||||||
|
mUserID = json['M_UserID'];
|
||||||
|
mUserUsername = json['M_UserUsername'];
|
||||||
|
mUserPassword = json['M_UserPassword'];
|
||||||
|
natStaffName = json['Nat_StaffName'];
|
||||||
|
natStaffNIK = json['Nat_StaffNIK'];
|
||||||
|
mCourierID = json['M_CourierID'];
|
||||||
|
}
|
||||||
|
|
||||||
|
Map<String, dynamic> toJson() {
|
||||||
|
final Map<String, dynamic> data = new Map<String, dynamic>();
|
||||||
|
data['M_UserID'] = this.mUserID;
|
||||||
|
data['M_UserUsername'] = this.mUserUsername;
|
||||||
|
data['M_UserPassword'] = this.mUserPassword;
|
||||||
|
data['Nat_StaffName'] = this.natStaffName;
|
||||||
|
data['Nat_StaffNIK'] = this.natStaffNIK;
|
||||||
|
data['M_CourierID'] = this.mCourierID;
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
}
|
||||||
25
lib/models/response_list_branch_model.dart
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
class ResponseListBranchModel {
|
||||||
|
String? branchid;
|
||||||
|
String? branchcode;
|
||||||
|
String? branchname;
|
||||||
|
String? branchaddress;
|
||||||
|
|
||||||
|
ResponseListBranchModel(
|
||||||
|
{this.branchid, this.branchcode, this.branchname, this.branchaddress});
|
||||||
|
|
||||||
|
ResponseListBranchModel.fromJson(Map<String, dynamic> json) {
|
||||||
|
branchid = json['branchid'];
|
||||||
|
branchcode = json['branchcode'];
|
||||||
|
branchname = json['branchname'];
|
||||||
|
branchaddress = json['branchaddress'];
|
||||||
|
}
|
||||||
|
|
||||||
|
Map<String, dynamic> toJson() {
|
||||||
|
final Map<String, dynamic> data = <String, dynamic>{};
|
||||||
|
data['branchid'] = branchid;
|
||||||
|
data['branchcode'] = branchcode;
|
||||||
|
data['branchname'] = branchname;
|
||||||
|
data['branchaddress'] = branchaddress;
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
}
|
||||||
21
lib/models/response_save_change_password_model.dart
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
class ResponseSaveChangePasswordModel {
|
||||||
|
String? status;
|
||||||
|
String? message;
|
||||||
|
|
||||||
|
ResponseSaveChangePasswordModel({
|
||||||
|
this.status,
|
||||||
|
this.message,
|
||||||
|
});
|
||||||
|
|
||||||
|
ResponseSaveChangePasswordModel.fromJson(Map<String, dynamic> json) {
|
||||||
|
status = json['status'];
|
||||||
|
message = json['message'];
|
||||||
|
}
|
||||||
|
|
||||||
|
Map<String, dynamic> toJson() {
|
||||||
|
final Map<String, dynamic> data = <String, dynamic>{};
|
||||||
|
data['status'] = status;
|
||||||
|
data['message'] = message;
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
}
|
||||||
21
lib/models/response_save_pengantaran_hasil_model.dart
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
class ResponseSavePengantaranHasilModel {
|
||||||
|
String? status;
|
||||||
|
String? message;
|
||||||
|
|
||||||
|
ResponseSavePengantaranHasilModel({
|
||||||
|
this.status,
|
||||||
|
this.message,
|
||||||
|
});
|
||||||
|
|
||||||
|
ResponseSavePengantaranHasilModel.fromJson(Map<String, dynamic> json) {
|
||||||
|
status = json['status'];
|
||||||
|
message = json['message'];
|
||||||
|
}
|
||||||
|
|
||||||
|
Map<String, dynamic> toJson() {
|
||||||
|
final Map<String, dynamic> data = <String, dynamic>{};
|
||||||
|
data['status'] = status;
|
||||||
|
data['message'] = message;
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
}
|
||||||
21
lib/models/response_save_work_suhu_model.dart
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
class ResponseSaveWorkSuhuModel {
|
||||||
|
String? status;
|
||||||
|
String? message;
|
||||||
|
|
||||||
|
ResponseSaveWorkSuhuModel({
|
||||||
|
this.status,
|
||||||
|
this.message,
|
||||||
|
});
|
||||||
|
|
||||||
|
ResponseSaveWorkSuhuModel.fromJson(Map<String, dynamic> json) {
|
||||||
|
status = json['status'];
|
||||||
|
message = json['message'];
|
||||||
|
}
|
||||||
|
|
||||||
|
Map<String, dynamic> toJson() {
|
||||||
|
final Map<String, dynamic> data = <String, dynamic>{};
|
||||||
|
data['status'] = status;
|
||||||
|
data['message'] = message;
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
}
|
||||||
21
lib/models/response_save_work_tunda_model.dart
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
class ResponseSaveWorkTundaModel {
|
||||||
|
String? status;
|
||||||
|
String? message;
|
||||||
|
|
||||||
|
ResponseSaveWorkTundaModel({
|
||||||
|
this.status,
|
||||||
|
this.message,
|
||||||
|
});
|
||||||
|
|
||||||
|
ResponseSaveWorkTundaModel.fromJson(Map<String, dynamic> json) {
|
||||||
|
status = json['status'];
|
||||||
|
message = json['message'];
|
||||||
|
}
|
||||||
|
|
||||||
|
Map<String, dynamic> toJson() {
|
||||||
|
final Map<String, dynamic> data = <String, dynamic>{};
|
||||||
|
data['status'] = status;
|
||||||
|
data['message'] = message;
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
}
|
||||||
86
lib/models/response_search_pengantaran_hasil_model.dart
Normal file
@@ -0,0 +1,86 @@
|
|||||||
|
import 'dart:convert';
|
||||||
|
|
||||||
|
import 'patient_model.dart';
|
||||||
|
|
||||||
|
class ResponseSearchPengantaranHasilModel {
|
||||||
|
String? deliveryid;
|
||||||
|
String? tipeid;
|
||||||
|
String? tipe;
|
||||||
|
String? sourceId;
|
||||||
|
String? nama;
|
||||||
|
String? nomor;
|
||||||
|
String? detail;
|
||||||
|
String? alamat;
|
||||||
|
String? branchid;
|
||||||
|
String? branchcode;
|
||||||
|
String? branchname;
|
||||||
|
String? branchaddress;
|
||||||
|
List<PatientModel>? patients;
|
||||||
|
|
||||||
|
ResponseSearchPengantaranHasilModel(
|
||||||
|
{this.deliveryid,
|
||||||
|
this.tipeid,
|
||||||
|
this.tipe,
|
||||||
|
this.sourceId,
|
||||||
|
this.nama,
|
||||||
|
this.nomor,
|
||||||
|
this.detail,
|
||||||
|
this.alamat,
|
||||||
|
this.branchid,
|
||||||
|
this.branchcode,
|
||||||
|
this.branchname,
|
||||||
|
this.branchaddress,
|
||||||
|
this.patients});
|
||||||
|
|
||||||
|
ResponseSearchPengantaranHasilModel.fromJson(Map<String, dynamic> json) {
|
||||||
|
deliveryid = json['id'];
|
||||||
|
tipeid = json['tipeid'];
|
||||||
|
tipe = json['tipe'];
|
||||||
|
sourceId = json['source_id'];
|
||||||
|
nama = json['nama'];
|
||||||
|
nomor = json['nomor'];
|
||||||
|
detail = json['detail'];
|
||||||
|
alamat = json['alamat'];
|
||||||
|
branchid = json['branchid'];
|
||||||
|
branchcode = json['branchcode'];
|
||||||
|
branchname = json['branchname'];
|
||||||
|
branchaddress = json['branchaddress'];
|
||||||
|
// patients = json['patients'];
|
||||||
|
|
||||||
|
if (json['patients'].toString().isNotEmpty) {
|
||||||
|
var data = <PatientModel>[];
|
||||||
|
// print("hasil json decode");
|
||||||
|
// print(jsonDecode(json['patients']));
|
||||||
|
// print("end");
|
||||||
|
try {
|
||||||
|
jsonDecode(json['patients']).forEach((v) {
|
||||||
|
data.add(PatientModel.fromJson(v));
|
||||||
|
});
|
||||||
|
} catch (e) {
|
||||||
|
print(e);
|
||||||
|
}
|
||||||
|
patients = data;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Map<String, dynamic> toJson() {
|
||||||
|
final Map<String, dynamic> data = <String, dynamic>{};
|
||||||
|
data['id'] = deliveryid;
|
||||||
|
data['tipeid'] = tipeid;
|
||||||
|
data['tipe'] = tipe;
|
||||||
|
data['source_id'] = sourceId;
|
||||||
|
data['nama'] = nama;
|
||||||
|
data['nomor'] = nomor;
|
||||||
|
data['detail'] = detail;
|
||||||
|
data['alamat'] = alamat;
|
||||||
|
data['branchid'] = branchid;
|
||||||
|
data['branchcode'] = branchcode;
|
||||||
|
data['branchname'] = branchname;
|
||||||
|
data['branchaddress'] = branchaddress;
|
||||||
|
// data['patients'] = patients;
|
||||||
|
if (patients != null || patients != "") {
|
||||||
|
data['patients'] = patients!.map((v) => v.toJson()).toList();
|
||||||
|
}
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
}
|
||||||
92
lib/models/work_list_model.dart
Normal file
@@ -0,0 +1,92 @@
|
|||||||
|
import 'dart:convert';
|
||||||
|
|
||||||
|
import '../models/patient_model.dart';
|
||||||
|
|
||||||
|
class WorkListModel {
|
||||||
|
int? id;
|
||||||
|
int? tipeid;
|
||||||
|
String? tipe;
|
||||||
|
String? noSuratJalan;
|
||||||
|
String? nama;
|
||||||
|
String? noLab;
|
||||||
|
String? alamat;
|
||||||
|
String? statusTransaksi;
|
||||||
|
String? branchid;
|
||||||
|
String? branchcode;
|
||||||
|
String? branchname;
|
||||||
|
String? branchaddress;
|
||||||
|
String? supervisor;
|
||||||
|
List<PatientModel>? patients;
|
||||||
|
String? note;
|
||||||
|
|
||||||
|
WorkListModel(
|
||||||
|
{this.id,
|
||||||
|
this.tipeid,
|
||||||
|
this.tipe,
|
||||||
|
this.noSuratJalan,
|
||||||
|
this.nama,
|
||||||
|
this.noLab,
|
||||||
|
this.alamat,
|
||||||
|
this.statusTransaksi,
|
||||||
|
this.branchid,
|
||||||
|
this.branchcode,
|
||||||
|
this.branchname,
|
||||||
|
this.branchaddress,
|
||||||
|
this.patients,
|
||||||
|
this.note});
|
||||||
|
|
||||||
|
WorkListModel.fromJson(Map<String, dynamic> json) {
|
||||||
|
id = int.parse(json['id']);
|
||||||
|
tipeid = int.parse(json['tipeid']);
|
||||||
|
tipe = json['tipe'];
|
||||||
|
noSuratJalan = json['no_surat_jalan'];
|
||||||
|
nama = json['nama'];
|
||||||
|
noLab = json['no_lab'];
|
||||||
|
alamat = json['alamat'];
|
||||||
|
statusTransaksi = json['status_transaksi'];
|
||||||
|
branchid = json['branchid'];
|
||||||
|
branchcode = json['branchcode'];
|
||||||
|
branchname = json['branchname'];
|
||||||
|
branchaddress = json['branchaddress'];
|
||||||
|
note = json['note'];
|
||||||
|
supervisor = json['supervisor'];
|
||||||
|
// print("patient :" + json['patients']);
|
||||||
|
if (json['patients'].toString().isNotEmpty) {
|
||||||
|
var data = <PatientModel>[];
|
||||||
|
// print("hasil json decode");
|
||||||
|
// print(jsonDecode(json['patients']));
|
||||||
|
// print("end");
|
||||||
|
try {
|
||||||
|
jsonDecode(json['patients']).forEach((v) {
|
||||||
|
data.add(PatientModel.fromJson(v));
|
||||||
|
});
|
||||||
|
} catch (e) {
|
||||||
|
print(e);
|
||||||
|
}
|
||||||
|
patients = data;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Map<String, dynamic> toJson() {
|
||||||
|
final Map<String, dynamic> data = new Map<String, dynamic>();
|
||||||
|
data['id'] = this.id;
|
||||||
|
data['tipeid'] = this.tipeid;
|
||||||
|
data['tipe'] = this.tipe;
|
||||||
|
data['no_surat_jalan'] = this.noSuratJalan;
|
||||||
|
data['nama'] = this.nama;
|
||||||
|
data['no_lab'] = this.noLab;
|
||||||
|
data['alamat'] = this.alamat;
|
||||||
|
data['status_transaksi'] = this.statusTransaksi;
|
||||||
|
data['branchid'] = this.branchid;
|
||||||
|
data['branchcode'] = this.branchcode;
|
||||||
|
data['branchname'] = this.branchname;
|
||||||
|
data['branchaddress'] = this.branchaddress;
|
||||||
|
data['patients'] = this.patients;
|
||||||
|
if (this.patients != null || this.patients != "") {
|
||||||
|
data['patients'] = this.patients!.map((v) => v.toJson()).toList();
|
||||||
|
}
|
||||||
|
data['note'] = this.note;
|
||||||
|
data['supervisor'] = this.supervisor;
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
}
|
||||||
18
lib/models/work_status_model.dart
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
class WorkStatusModel {
|
||||||
|
String? statusid;
|
||||||
|
String? statusname;
|
||||||
|
|
||||||
|
WorkStatusModel({this.statusid, this.statusname});
|
||||||
|
|
||||||
|
WorkStatusModel.fromJson(Map<String, dynamic> json) {
|
||||||
|
statusid = json['statusid'];
|
||||||
|
statusname = json['statusname'];
|
||||||
|
}
|
||||||
|
|
||||||
|
Map<String, dynamic> toJson() {
|
||||||
|
final Map<String, dynamic> data = new Map<String, dynamic>();
|
||||||
|
data['statusid'] = this.statusid;
|
||||||
|
data['statusname'] = this.statusname;
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
}
|
||||||
18
lib/models/work_supervisor_model.dart
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
class WorkSupervisorModel {
|
||||||
|
String? supervisorid;
|
||||||
|
String? supervisorname;
|
||||||
|
|
||||||
|
WorkSupervisorModel({this.supervisorid, this.supervisorname});
|
||||||
|
|
||||||
|
WorkSupervisorModel.fromJson(Map<String, dynamic> json) {
|
||||||
|
supervisorid = json['supervisorid'];
|
||||||
|
supervisorname = json['supervisorname'];
|
||||||
|
}
|
||||||
|
|
||||||
|
Map<String, dynamic> toJson() {
|
||||||
|
final Map<String, dynamic> data = new Map<String, dynamic>();
|
||||||
|
data['supervisorid'] = this.supervisorid;
|
||||||
|
data['supervisorname'] = this.supervisorname;
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
}
|
||||||
21
lib/models/work_total_model.dart
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
class WorkTotalModel {
|
||||||
|
String? totalAll;
|
||||||
|
String? receive;
|
||||||
|
String? done;
|
||||||
|
|
||||||
|
WorkTotalModel({this.totalAll, this.receive, this.done});
|
||||||
|
|
||||||
|
WorkTotalModel.fromJson(Map<String, dynamic> json) {
|
||||||
|
totalAll = json['total_all'];
|
||||||
|
receive = json['receive'];
|
||||||
|
done = json['done'];
|
||||||
|
}
|
||||||
|
|
||||||
|
Map<String, dynamic> toJson() {
|
||||||
|
final Map<String, dynamic> data = new Map<String, dynamic>();
|
||||||
|
data['total_all'] = this.totalAll;
|
||||||
|
data['receive'] = this.receive;
|
||||||
|
data['done'] = this.done;
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
}
|
||||||
32
lib/models/work_type_model.dart
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
class WorkTypeModel {
|
||||||
|
int? id;
|
||||||
|
String? name;
|
||||||
|
|
||||||
|
WorkTypeModel({this.id, this.name});
|
||||||
|
|
||||||
|
WorkTypeModel.fromJson(Map<String, dynamic> json) {
|
||||||
|
id = int.parse(json['tipeid']);
|
||||||
|
name = json['tipename'];
|
||||||
|
}
|
||||||
|
|
||||||
|
Map<String, dynamic> toJson() {
|
||||||
|
final Map<String, dynamic> data = new Map<String, dynamic>();
|
||||||
|
data['tipeid'] = this.id;
|
||||||
|
data['tipename'] = this.name;
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 1 Pengantaran Hasil Pasien
|
||||||
|
// 2 Pengantaran Hasil Instansi
|
||||||
|
// 3 Pengantaran Hasil Dokter
|
||||||
|
// 4 Lain-lain
|
||||||
|
// 5 Pengambilan Sampel
|
||||||
|
|
||||||
|
// List<WorkTypeModel> WorkTypeData = [
|
||||||
|
// WorkTypeModel(id: 1, name: "Pengantaran Hasil Pasien"),
|
||||||
|
// WorkTypeModel(id: 2, name: "Pengantaran Hasil Instansi"),
|
||||||
|
// WorkTypeModel(id: 3, name: "Pengantaran Hasil Dokter"),
|
||||||
|
// WorkTypeModel(id: 4, name: "Lain-lain"),
|
||||||
|
// WorkTypeModel(id: 5, name: "Pengambilan Sampel"),
|
||||||
|
// ];
|
||||||
4
lib/provider/current_scan_provider.dart
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||||
|
|
||||||
|
final barcodeScanResult = StateProvider<String>((ref) => "");
|
||||||
|
final isFromScanScreen = StateProvider<bool?>((ref) => false);
|
||||||
5
lib/provider/current_user_provider.dart
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||||
|
|
||||||
|
import '../models/auth_model.dart';
|
||||||
|
|
||||||
|
final currentUserProvider = StateProvider<AuthModel?>((ref) => null);
|
||||||
8
lib/provider/dio_provider.dart
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
import 'package:dio/dio.dart';
|
||||||
|
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||||
|
|
||||||
|
final dioProvider = Provider<Dio>((ref) => Dio());
|
||||||
|
|
||||||
|
// final pageProvider = StateProvider(
|
||||||
|
// (ref) => 0,
|
||||||
|
// );
|
||||||
8
lib/provider/history_filter_provider.dart
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||||
|
import 'package:intl/intl.dart';
|
||||||
|
|
||||||
|
import '../models/history_type_model.dart';
|
||||||
|
|
||||||
|
final selectedTypeProvider = StateProvider<HistoryTypeModel>(
|
||||||
|
(ref) => HistoryTypeModel(tipeid: "0", tipename: "Semua"));
|
||||||
|
final dateFilterProvider = StateProvider<DateTime>((ref) => DateTime.now());
|
||||||
51
lib/repository/auth_repository.dart
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
import '../app/constant.dart';
|
||||||
|
import '../models/auth_model.dart';
|
||||||
|
import 'base_repository.dart';
|
||||||
|
|
||||||
|
class AuthRepository extends BaseRepository {
|
||||||
|
AuthRepository({required super.dio});
|
||||||
|
|
||||||
|
Future<AuthModel> login({
|
||||||
|
required String username,
|
||||||
|
required String password,
|
||||||
|
}) async {
|
||||||
|
final param = {
|
||||||
|
"username": username,
|
||||||
|
"password": password
|
||||||
|
|
||||||
|
// "username": "alhadad1",
|
||||||
|
// "doctor_id": "2891",
|
||||||
|
// "password": "3"
|
||||||
|
};
|
||||||
|
final service =
|
||||||
|
"${Constant.baseUrl}v1/courier/login/login/?username=$username&password=$password";
|
||||||
|
final resp = await post(param: param, service: service);
|
||||||
|
final result = AuthModel(
|
||||||
|
token: resp['data']["token"],
|
||||||
|
model: AuthKurirModel.fromJson(resp["data"]),
|
||||||
|
);
|
||||||
|
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}v1/courier/login/logout";
|
||||||
|
final resp = await post(param: param, service: service);
|
||||||
|
|
||||||
|
if (resp["status"] == "OK") {
|
||||||
|
return resp['status'];
|
||||||
|
} else {
|
||||||
|
return resp['message'];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
100
lib/repository/base_repository.dart
Normal file
@@ -0,0 +1,100 @@
|
|||||||
|
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(
|
||||||
|
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 String service,
|
||||||
|
String? token,
|
||||||
|
}) async {
|
||||||
|
try {
|
||||||
|
final response = await dio.get(
|
||||||
|
service,
|
||||||
|
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,
|
||||||
|
});
|
||||||
|
}
|
||||||
29
lib/repository/change_password_repository.dart
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
import 'dart:convert';
|
||||||
|
|
||||||
|
import '../models/personal_information_model.dart';
|
||||||
|
|
||||||
|
import '../app/constant.dart';
|
||||||
|
import '../models/response_save_change_password_model.dart';
|
||||||
|
import 'base_repository.dart';
|
||||||
|
|
||||||
|
class ChangePasswordRepository extends BaseRepository {
|
||||||
|
ChangePasswordRepository({required super.dio});
|
||||||
|
|
||||||
|
Future<ResponseSaveChangePasswordModel> ubahPassword(
|
||||||
|
{required String userID,
|
||||||
|
required String oldPassword,
|
||||||
|
required String newPassword}) async {
|
||||||
|
final param = {
|
||||||
|
"userid": userID,
|
||||||
|
"old": oldPassword,
|
||||||
|
"new": newPassword,
|
||||||
|
};
|
||||||
|
|
||||||
|
print(param);
|
||||||
|
|
||||||
|
final url =
|
||||||
|
"${Constant.baseUrl}/v1/courier/login/change_password/?userid=$userID&old=$oldPassword&new=$newPassword";
|
||||||
|
final resp = await post(param: param, service: url);
|
||||||
|
return ResponseSaveChangePasswordModel.fromJson(resp);
|
||||||
|
}
|
||||||
|
}
|
||||||
35
lib/repository/company_repository.dart
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
import '../models/company_model.dart';
|
||||||
|
import '../models/work_status_model.dart';
|
||||||
|
import '../models/work_supervisor_model.dart';
|
||||||
|
|
||||||
|
import '../app/constant.dart';
|
||||||
|
import '../models/work_type_model.dart';
|
||||||
|
import 'base_repository.dart';
|
||||||
|
|
||||||
|
class CompanyRepository extends BaseRepository {
|
||||||
|
CompanyRepository({required super.dio});
|
||||||
|
|
||||||
|
Future<List<CompanyModel>> search({required String keyword}) async {
|
||||||
|
// http: //10.9.9.3/one-api/v1/courier/mobile/inputcourier/search_company_all/?search=sas
|
||||||
|
final url = Constant.baseUrl +
|
||||||
|
"/v1/courier/mobile/inputcourier/search_company_all/?search=$keyword";
|
||||||
|
final resp = await get(service: url);
|
||||||
|
List<CompanyModel> data;
|
||||||
|
// print(resp['data']);
|
||||||
|
if (resp['status'] == 'OK') {
|
||||||
|
data = [];
|
||||||
|
if (resp['data'] != null) {
|
||||||
|
resp['data']['records'].forEach((e) {
|
||||||
|
final model = CompanyModel.fromJson(e);
|
||||||
|
data.add(model);
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
data = [];
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
data = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
}
|
||||||
65
lib/repository/filter_repository.dart
Normal file
@@ -0,0 +1,65 @@
|
|||||||
|
import '../models/work_status_model.dart';
|
||||||
|
import '../models/work_supervisor_model.dart';
|
||||||
|
|
||||||
|
import '../app/constant.dart';
|
||||||
|
import '../models/work_type_model.dart';
|
||||||
|
import 'base_repository.dart';
|
||||||
|
|
||||||
|
class FilterRepository extends BaseRepository {
|
||||||
|
FilterRepository({required super.dio});
|
||||||
|
|
||||||
|
Future<List<WorkTypeModel>> getType() async {
|
||||||
|
final url = Constant.baseUrl + "/v1/courier/mobile/homescreen/list_tipe";
|
||||||
|
final resp = await get(service: url);
|
||||||
|
List<WorkTypeModel> data;
|
||||||
|
// print(resp['data']);
|
||||||
|
if (resp['status'] == 'OK') {
|
||||||
|
data = [];
|
||||||
|
resp['data'].forEach((e) {
|
||||||
|
final model = WorkTypeModel.fromJson(e);
|
||||||
|
data.add(model);
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
data = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<List<WorkStatusModel>> getStatus() async {
|
||||||
|
final url = Constant.baseUrl + "v1/courier/mobile/homescreen/list_status";
|
||||||
|
final resp = await get(service: url);
|
||||||
|
List<WorkStatusModel> data;
|
||||||
|
// print(resp['data']);
|
||||||
|
if (resp['status'] == 'OK') {
|
||||||
|
data = [];
|
||||||
|
resp['data'].forEach((e) {
|
||||||
|
final model = WorkStatusModel.fromJson(e);
|
||||||
|
data.add(model);
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
data = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<List<WorkSupervisorModel>> getSupervisor() async {
|
||||||
|
final url =
|
||||||
|
Constant.baseUrl + "v1/courier/mobile/homescreen/list_supervisor";
|
||||||
|
final resp = await get(service: url);
|
||||||
|
List<WorkSupervisorModel> data;
|
||||||
|
// print(resp['data']);
|
||||||
|
if (resp['status'] == 'OK') {
|
||||||
|
data = [];
|
||||||
|
resp['data'].forEach((e) {
|
||||||
|
final model = WorkSupervisorModel.fromJson(e);
|
||||||
|
data.add(model);
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
data = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
}
|
||||||
59
lib/repository/get_other_repository.dart
Normal file
@@ -0,0 +1,59 @@
|
|||||||
|
import '../app/constant.dart';
|
||||||
|
import 'base_repository.dart';
|
||||||
|
|
||||||
|
class GetOtherRepository extends BaseRepository {
|
||||||
|
GetOtherRepository({required super.dio});
|
||||||
|
|
||||||
|
Future<bool> setLocation(
|
||||||
|
{required String id,
|
||||||
|
required String step,
|
||||||
|
required String lat,
|
||||||
|
required String long,
|
||||||
|
required String address,
|
||||||
|
required String branchID}) async {
|
||||||
|
final url =
|
||||||
|
"${Constant.baseUrl}/v1/courier/mobile/process/add_other/?id=$id&locid=$step&lat=$lat&long=$long&address=$address&branchid=$branchID";
|
||||||
|
final resp = await get(service: url);
|
||||||
|
bool data = false;
|
||||||
|
|
||||||
|
if (resp['status'] == "OK") {
|
||||||
|
data = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<bool> setDeliveryPerson({
|
||||||
|
required String id,
|
||||||
|
required String name,
|
||||||
|
required String note,
|
||||||
|
}) async {
|
||||||
|
final url =
|
||||||
|
"${Constant.baseUrl}/v1/courier/mobile/process/update_deliver_other/?id=$id&name=$name¬e=$note";
|
||||||
|
final resp = await get(service: url);
|
||||||
|
bool data = false;
|
||||||
|
|
||||||
|
if (resp['status'] == "OK") {
|
||||||
|
data = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<bool> setReceivePerson({
|
||||||
|
required String id,
|
||||||
|
required String name,
|
||||||
|
required String note,
|
||||||
|
}) async {
|
||||||
|
final url =
|
||||||
|
"${Constant.baseUrl}/v1/courier/mobile/process/update_receive_other/?id=$id&name=$name¬e=$note";
|
||||||
|
final resp = await get(service: url);
|
||||||
|
bool data = false;
|
||||||
|
|
||||||
|
if (resp['status'] == "OK") {
|
||||||
|
data = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
}
|
||||||
72
lib/repository/get_sample_repository.dart
Normal file
@@ -0,0 +1,72 @@
|
|||||||
|
import '../app/constant.dart';
|
||||||
|
import 'base_repository.dart';
|
||||||
|
|
||||||
|
class GetSampleRepository extends BaseRepository {
|
||||||
|
GetSampleRepository({required super.dio});
|
||||||
|
|
||||||
|
Future<bool> setLocation(
|
||||||
|
{required String id,
|
||||||
|
required String step,
|
||||||
|
required String lat,
|
||||||
|
required String long,
|
||||||
|
required String address,
|
||||||
|
required String branchID}) async {
|
||||||
|
final url =
|
||||||
|
"${Constant.baseUrl}/v1/courier/mobile/process/add_sample/?id=$id&locid=$step&lat=$lat&long=$long&address=$address&branchid=$branchID";
|
||||||
|
final resp = await get(service: url);
|
||||||
|
bool data = false;
|
||||||
|
|
||||||
|
if (resp['status'] == "OK") {
|
||||||
|
data = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<bool> setDeliveryPerson({
|
||||||
|
required String id,
|
||||||
|
required String name,
|
||||||
|
required String note,
|
||||||
|
// Inputan INFO
|
||||||
|
required String jumlahPasien,
|
||||||
|
required String edtaRutin,
|
||||||
|
required String darahCitras,
|
||||||
|
required String serum,
|
||||||
|
required String urine,
|
||||||
|
required String pleura,
|
||||||
|
required String otherTextBahan,
|
||||||
|
required String totalOther,
|
||||||
|
}) async {
|
||||||
|
// final url =
|
||||||
|
// "${Constant.baseUrl}/v1/courier/mobile/process/update_deliver_sample/?id=$id&name=$name¬e=$note";
|
||||||
|
|
||||||
|
final url =
|
||||||
|
"${Constant.baseUrl}/v1/courier/mobile/process/update_deliver_sample/?id=$id&name=$name¬e=$note&t_patient=$jumlahPasien&t_edta=$edtaRutin&t_citras=$darahCitras&t_serum=$serum&t_urine=$urine&t_pleura=$pleura&t_other=$totalOther&other=$otherTextBahan";
|
||||||
|
final resp = await get(service: url);
|
||||||
|
bool data = false;
|
||||||
|
|
||||||
|
if (resp['status'] == "OK") {
|
||||||
|
data = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<bool> setReceivePerson({
|
||||||
|
required String id,
|
||||||
|
required String name,
|
||||||
|
required String note,
|
||||||
|
required String suhuSample,
|
||||||
|
}) async {
|
||||||
|
final url =
|
||||||
|
"${Constant.baseUrl}/v1/courier/mobile/process/update_receive_sample/?id=$id&name=$name¬e=$note&suhu=$suhuSample";
|
||||||
|
final resp = await get(service: url);
|
||||||
|
bool data = false;
|
||||||
|
|
||||||
|
if (resp['status'] == "OK") {
|
||||||
|
data = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
}
|
||||||
78
lib/repository/history_screen_repository.dart
Normal file
@@ -0,0 +1,78 @@
|
|||||||
|
import 'dart:convert';
|
||||||
|
|
||||||
|
import '../models/detail_history_model.dart';
|
||||||
|
import '../models/history_model.dart';
|
||||||
|
import '../models/history_type_model.dart';
|
||||||
|
import '../models/work_status_model.dart';
|
||||||
|
import '../models/work_supervisor_model.dart';
|
||||||
|
|
||||||
|
import '../app/constant.dart';
|
||||||
|
import '../models/work_type_model.dart';
|
||||||
|
import 'base_repository.dart';
|
||||||
|
|
||||||
|
class HistoryRepository extends BaseRepository {
|
||||||
|
HistoryRepository({required super.dio});
|
||||||
|
|
||||||
|
Future<List<HistoryModel>> getData(
|
||||||
|
{required String id, required String date, required String type}) async {
|
||||||
|
// http: //10.9.9.3/one-api/v1/courier/mobile/history/list_all/?id=40&startdate=11-09-2023&tipeid=3
|
||||||
|
final url = Constant.baseUrl +
|
||||||
|
"/v1/courier/mobile/history/list_all/?id=$id&startdate=$date&tipeid=$type";
|
||||||
|
final resp = await get(service: url);
|
||||||
|
List<HistoryModel> data = [];
|
||||||
|
print(resp['data']);
|
||||||
|
if (resp['status'] == 'OK') {
|
||||||
|
data = [];
|
||||||
|
resp['data'].forEach((e) {
|
||||||
|
final model = HistoryModel.fromJson(e);
|
||||||
|
data.add(model);
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
data = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<DetailHistoryModel> getDetail(
|
||||||
|
{required String id,
|
||||||
|
required String tipeId,
|
||||||
|
required String deliveryId}) async {
|
||||||
|
final url =
|
||||||
|
"${Constant.baseUrl}/v1/courier/mobile/history/list_by_id/?id=$id&tipeid=$tipeId&deliveryid=$deliveryId";
|
||||||
|
final resp = await get(service: url);
|
||||||
|
// DetailHistoryModel data;
|
||||||
|
// print(resp['data']);
|
||||||
|
|
||||||
|
DetailHistoryModel data = DetailHistoryModel.fromJson(resp['data'][0]);
|
||||||
|
|
||||||
|
// resp['data'].forEach((e) {
|
||||||
|
// final model = HistoryModel.fromJson(e);
|
||||||
|
// data.add(model);
|
||||||
|
// });
|
||||||
|
// }
|
||||||
|
// print(data.alamatPengambilan);
|
||||||
|
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<List<HistoryTypeModel>> getHistoryType() async {
|
||||||
|
// http: //10.9.9.3/one-api/v1/courier/mobile/homescreen/list_tipe_history
|
||||||
|
final url =
|
||||||
|
"${Constant.baseUrl}/v1/courier/mobile/homescreen/list_tipe_history";
|
||||||
|
final resp = await get(service: url);
|
||||||
|
// DetailHistoryModel data;
|
||||||
|
// print(resp['data']);
|
||||||
|
|
||||||
|
List<HistoryTypeModel> data = List.empty(growable: true);
|
||||||
|
|
||||||
|
resp['data'].forEach((e) {
|
||||||
|
final model = HistoryTypeModel.fromJson(e);
|
||||||
|
data.add(model);
|
||||||
|
});
|
||||||
|
|
||||||
|
// print(data.alamatPengambilan);
|
||||||
|
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
}
|
||||||
42
lib/repository/home_screen_repository.dart
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
import 'dart:convert';
|
||||||
|
|
||||||
|
import '../app/constant.dart';
|
||||||
|
import '../models/pending_work_model.dart';
|
||||||
|
import '../models/work_total_model.dart';
|
||||||
|
import 'base_repository.dart';
|
||||||
|
|
||||||
|
class HomeScreenRepository extends BaseRepository {
|
||||||
|
HomeScreenRepository({required super.dio});
|
||||||
|
Future<WorkTotalModel> getTotalWork({required String id}) async {
|
||||||
|
final url =
|
||||||
|
Constant.baseUrl + "v1/courier/mobile/homescreen/list_total/?id=$id";
|
||||||
|
final resp = await get(service: url);
|
||||||
|
WorkTotalModel data;
|
||||||
|
// print(resp['data']);
|
||||||
|
if (resp['status'] == 'OK') {
|
||||||
|
data = WorkTotalModel.fromJson(resp['data']);
|
||||||
|
} else {
|
||||||
|
data = {} as WorkTotalModel;
|
||||||
|
}
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<List<PendingWorkModel>> getPendingWork({required String id}) async {
|
||||||
|
final url =
|
||||||
|
Constant.baseUrl + "/v1/courier/mobile/homescreen/list_order/?id=$id";
|
||||||
|
final resp = await get(service: url);
|
||||||
|
List<PendingWorkModel> data;
|
||||||
|
// print(resp['data']);
|
||||||
|
if (resp['status'] == 'OK') {
|
||||||
|
data = [];
|
||||||
|
resp['data'].forEach((e) {
|
||||||
|
final model = PendingWorkModel.fromJson(e);
|
||||||
|
data.add(model);
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
data = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
}
|
||||||
76
lib/repository/input_lain_lain_repository.dart
Normal file
@@ -0,0 +1,76 @@
|
|||||||
|
import '../app/constant.dart';
|
||||||
|
import '../models/auth_model.dart';
|
||||||
|
import '../models/response_list_branch_model.dart';
|
||||||
|
import '../models/response_save_pengantaran_hasil_model.dart';
|
||||||
|
import '../models/response_search_pengantaran_hasil_model.dart';
|
||||||
|
import 'base_repository.dart';
|
||||||
|
|
||||||
|
class DummyNoLabDokter {
|
||||||
|
final String noLab;
|
||||||
|
final int idLab;
|
||||||
|
final String nama;
|
||||||
|
final String alamatPengantaran;
|
||||||
|
|
||||||
|
DummyNoLabDokter(
|
||||||
|
this.noLab,
|
||||||
|
this.idLab,
|
||||||
|
this.nama,
|
||||||
|
this.alamatPengantaran
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
class InputLainLainRepository extends BaseRepository {
|
||||||
|
InputLainLainRepository({required super.dio});
|
||||||
|
|
||||||
|
List<DummyNoLabDokter> result = [
|
||||||
|
DummyNoLabDokter("110378", 1, "Agas", "Jl wora wari"),
|
||||||
|
DummyNoLabDokter("110390", 2, "Indy Ratna", "Jl moestopo"),
|
||||||
|
DummyNoLabDokter("140390", 3, "Jarot", "Jl pahlawan no 1"),
|
||||||
|
DummyNoLabDokter("190390", 4, "Deny", "Jl Ir Soekarno"),
|
||||||
|
DummyNoLabDokter("119090", 5, "Said Hasan", "Jl mawar no 04"),
|
||||||
|
DummyNoLabDokter("110391", 1, "Jarot P", "Jl nawangsih no 07"),
|
||||||
|
DummyNoLabDokter("110399", 2, "Joko S", "Jl Pegangsaan no 04"),
|
||||||
|
];
|
||||||
|
|
||||||
|
Future<List<ResponseListBranchModel>> loadListCabangInputLainLain() async {
|
||||||
|
final service =
|
||||||
|
"${Constant.baseUrl}v1/courier/mobile/homescreen/list_branch";
|
||||||
|
final resp = await get(service: service);
|
||||||
|
|
||||||
|
final result = List<ResponseListBranchModel>.empty(growable: true);
|
||||||
|
if (resp['data'] != null) {
|
||||||
|
resp['data'].forEach((e) {
|
||||||
|
final model = ResponseListBranchModel.fromJson(e);
|
||||||
|
result.add(model);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<ResponseSavePengantaranHasilModel> inputLainLainSave({
|
||||||
|
required String courierID,
|
||||||
|
required String tipeID,
|
||||||
|
required String branchID,
|
||||||
|
required String branchCode,
|
||||||
|
required String pickup,
|
||||||
|
required String destination,
|
||||||
|
required String note
|
||||||
|
}) async {
|
||||||
|
final param = {
|
||||||
|
"id": courierID,
|
||||||
|
"tipeid": tipeID,
|
||||||
|
"branchid": branchID,
|
||||||
|
"branchcode": branchCode,
|
||||||
|
"pickup": pickup,
|
||||||
|
"destination":destination,
|
||||||
|
"note": note
|
||||||
|
};
|
||||||
|
|
||||||
|
print("param : $param");
|
||||||
|
|
||||||
|
final service = "${Constant.baseUrl}v1/courier/mobile/inputcourier/add/?id=$courierID&tipeid=$tipeID&branchid=$branchID&branchcode=$branchCode&pickup=$pickup&destination=$destination¬e=$note";
|
||||||
|
final resp = await post(param: param, service: service);
|
||||||
|
return ResponseSavePengantaranHasilModel.fromJson(resp);
|
||||||
|
}
|
||||||
|
}
|
||||||
28
lib/repository/kurir_tolak_repository.dart
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
import 'dart:convert';
|
||||||
|
|
||||||
|
import '../app/constant.dart';
|
||||||
|
|
||||||
|
import '../app/constant.dart';
|
||||||
|
import 'base_repository.dart';
|
||||||
|
|
||||||
|
class KurirTolakRepository extends BaseRepository {
|
||||||
|
KurirTolakRepository({required super.dio});
|
||||||
|
|
||||||
|
Future<bool> getKurirTolak(
|
||||||
|
{required String id,
|
||||||
|
required String tipeId,
|
||||||
|
required String deliveryId,
|
||||||
|
required String note}) async {
|
||||||
|
final url =
|
||||||
|
"${Constant.baseUrl}/v1/courier/mobile/worklist/cancel/?id=$id&tipeid=$tipeId&deliveryid=$deliveryId¬e=$note";
|
||||||
|
final resp = await get(service: url);
|
||||||
|
bool data = false;
|
||||||
|
// print(resp['data']);
|
||||||
|
|
||||||
|
if (resp["status"] == "OK") {
|
||||||
|
data = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
}
|
||||||
74
lib/repository/pengambilan_bahan_repository.dart
Normal file
@@ -0,0 +1,74 @@
|
|||||||
|
import '../app/constant.dart';
|
||||||
|
import '../models/auth_model.dart';
|
||||||
|
import '../models/response_list_branch_model.dart';
|
||||||
|
import '../models/response_save_pengantaran_hasil_model.dart';
|
||||||
|
import '../models/response_search_pengantaran_hasil_model.dart';
|
||||||
|
import 'base_repository.dart';
|
||||||
|
|
||||||
|
class DummyNoLabDokter {
|
||||||
|
final String noLab;
|
||||||
|
final int idLab;
|
||||||
|
final String nama;
|
||||||
|
final String alamatPengantaran;
|
||||||
|
|
||||||
|
DummyNoLabDokter(
|
||||||
|
this.noLab,
|
||||||
|
this.idLab,
|
||||||
|
this.nama,
|
||||||
|
this.alamatPengantaran
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
class PengambilanBahanRepository extends BaseRepository {
|
||||||
|
PengambilanBahanRepository({required super.dio});
|
||||||
|
|
||||||
|
List<DummyNoLabDokter> result = [
|
||||||
|
DummyNoLabDokter("110378", 1, "Agas", "Jl wora wari"),
|
||||||
|
DummyNoLabDokter("110390", 2, "Indy Ratna", "Jl moestopo"),
|
||||||
|
DummyNoLabDokter("140390", 3, "Jarot", "Jl pahlawan no 1"),
|
||||||
|
DummyNoLabDokter("190390", 4, "Deny", "Jl Ir Soekarno"),
|
||||||
|
DummyNoLabDokter("119090", 5, "Said Hasan", "Jl mawar no 04"),
|
||||||
|
DummyNoLabDokter("110391", 1, "Jarot P", "Jl nawangsih no 07"),
|
||||||
|
DummyNoLabDokter("110399", 2, "Joko S", "Jl Pegangsaan no 04"),
|
||||||
|
];
|
||||||
|
|
||||||
|
Future<List<ResponseListBranchModel>> loadListCabangPengambilanBahan() async {
|
||||||
|
final service =
|
||||||
|
"${Constant.baseUrl}v1/courier/mobile/homescreen/list_branch";
|
||||||
|
final resp = await get(service: service);
|
||||||
|
|
||||||
|
final result = List<ResponseListBranchModel>.empty(growable: true);
|
||||||
|
if (resp['data'] != null) {
|
||||||
|
resp['data'].forEach((e) {
|
||||||
|
final model = ResponseListBranchModel.fromJson(e);
|
||||||
|
result.add(model);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<ResponseSavePengantaranHasilModel> pengambilanBahanSave({
|
||||||
|
required String courierID,
|
||||||
|
required String tipeID,
|
||||||
|
required String branchID,
|
||||||
|
required String branchCode,
|
||||||
|
required String name,
|
||||||
|
required String destination
|
||||||
|
}) async {
|
||||||
|
final param = {
|
||||||
|
"id": courierID,
|
||||||
|
"tipeid": tipeID,
|
||||||
|
"branchid": branchID,
|
||||||
|
"branchcode": branchCode,
|
||||||
|
"name": name,
|
||||||
|
"destination":destination
|
||||||
|
};
|
||||||
|
|
||||||
|
print("param : $param");
|
||||||
|
|
||||||
|
final service = "${Constant.baseUrl}v1/courier/mobile/inputcourier/add/?id=$courierID&tipeid=$tipeID&branchid=$branchID&branchcode=$branchCode&name=$name&destination=$destination";
|
||||||
|
final resp = await post(param: param, service: service);
|
||||||
|
return ResponseSavePengantaranHasilModel.fromJson(resp);
|
||||||
|
}
|
||||||
|
}
|
||||||
72
lib/repository/pengantaran_hasil_dokter_repository.dart
Normal file
@@ -0,0 +1,72 @@
|
|||||||
|
import '../app/constant.dart';
|
||||||
|
import '../models/auth_model.dart';
|
||||||
|
import '../models/response_save_pengantaran_hasil_model.dart';
|
||||||
|
import '../models/response_search_pengantaran_hasil_model.dart';
|
||||||
|
import 'base_repository.dart';
|
||||||
|
|
||||||
|
class DummyNoLabDokter {
|
||||||
|
final String noLab;
|
||||||
|
final int idLab;
|
||||||
|
final String nama;
|
||||||
|
final String alamatPengantaran;
|
||||||
|
|
||||||
|
DummyNoLabDokter(
|
||||||
|
this.noLab,
|
||||||
|
this.idLab,
|
||||||
|
this.nama,
|
||||||
|
this.alamatPengantaran
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
class PengantaranHasilDokterRepository extends BaseRepository {
|
||||||
|
PengantaranHasilDokterRepository({required super.dio});
|
||||||
|
|
||||||
|
List<DummyNoLabDokter> result = [
|
||||||
|
DummyNoLabDokter("110378", 1, "Agas", "Jl wora wari"),
|
||||||
|
DummyNoLabDokter("110390", 2, "Indy Ratna", "Jl moestopo"),
|
||||||
|
DummyNoLabDokter("140390", 3, "Jarot", "Jl pahlawan no 1"),
|
||||||
|
DummyNoLabDokter("190390", 4, "Deny", "Jl Ir Soekarno"),
|
||||||
|
DummyNoLabDokter("119090", 5, "Said Hasan", "Jl mawar no 04"),
|
||||||
|
DummyNoLabDokter("110391", 1, "Jarot P", "Jl nawangsih no 07"),
|
||||||
|
DummyNoLabDokter("110399", 2, "Joko S", "Jl Pegangsaan no 04"),
|
||||||
|
];
|
||||||
|
|
||||||
|
Future<List<ResponseSearchPengantaranHasilModel>> loadListNoDokterPengantaranHasilDokter({
|
||||||
|
required String search,
|
||||||
|
}) async {
|
||||||
|
final param = {
|
||||||
|
"search": search,
|
||||||
|
};
|
||||||
|
final service =
|
||||||
|
"${Constant.baseUrl}v1/courier/mobile/inputcourier/search_doctor/?search=$search";
|
||||||
|
final resp = await post(param: param, service: service);
|
||||||
|
|
||||||
|
final result = List<ResponseSearchPengantaranHasilModel>.empty(growable: true);
|
||||||
|
if (resp['data'] != null) {
|
||||||
|
resp['data']['records'].forEach((e) {
|
||||||
|
final model = ResponseSearchPengantaranHasilModel.fromJson(e);
|
||||||
|
result.add(model);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<ResponseSavePengantaranHasilModel> pengantaranHasilDokterSave({
|
||||||
|
required String courierID,
|
||||||
|
required String tipeID,
|
||||||
|
required String deliveryID,
|
||||||
|
}) async {
|
||||||
|
final param = {
|
||||||
|
"id": courierID,
|
||||||
|
"tipeid": tipeID,
|
||||||
|
"deliveryid": deliveryID
|
||||||
|
};
|
||||||
|
|
||||||
|
print("param : $param");
|
||||||
|
|
||||||
|
final service = "${Constant.baseUrl}v1/courier/mobile/inputcourier/add/?id=$courierID&tipeid=$tipeID&deliveryid=$deliveryID";
|
||||||
|
final resp = await post(param: param, service: service);
|
||||||
|
return ResponseSavePengantaranHasilModel.fromJson(resp);
|
||||||
|
}
|
||||||
|
}
|
||||||
71
lib/repository/pengantaran_hasil_instansi_repository.dart
Normal file
@@ -0,0 +1,71 @@
|
|||||||
|
import '../app/constant.dart';
|
||||||
|
import '../models/auth_model.dart';
|
||||||
|
import '../models/response_save_pengantaran_hasil_model.dart';
|
||||||
|
import '../models/response_search_pengantaran_hasil_model.dart';
|
||||||
|
import 'base_repository.dart';
|
||||||
|
|
||||||
|
class DummyNoSuratJalan {
|
||||||
|
final String noSuratJalan;
|
||||||
|
final int idSuratJalan;
|
||||||
|
final String nama;
|
||||||
|
final String alamatPengantaran;
|
||||||
|
|
||||||
|
DummyNoSuratJalan(
|
||||||
|
this.noSuratJalan,
|
||||||
|
this.idSuratJalan,
|
||||||
|
this.nama,
|
||||||
|
this.alamatPengantaran
|
||||||
|
);
|
||||||
|
}
|
||||||
|
class PengantaranHasilInstansiRepository extends BaseRepository {
|
||||||
|
PengantaranHasilInstansiRepository({required super.dio});
|
||||||
|
|
||||||
|
List<DummyNoSuratJalan> result = [
|
||||||
|
DummyNoSuratJalan("110378", 1, "Agas", "Jl wora wari"),
|
||||||
|
DummyNoSuratJalan("110390", 2, "Indy Ratna", "Jl moestopo"),
|
||||||
|
DummyNoSuratJalan("140390", 3, "Jarot", "Jl pahlawan no 1"),
|
||||||
|
DummyNoSuratJalan("190390", 4, "Deny", "Jl Ir Soekarno"),
|
||||||
|
DummyNoSuratJalan("119090", 5, "Said Hasan", "Jl mawar no 04"),
|
||||||
|
DummyNoSuratJalan("110391", 1, "Jarot P", "Jl nawangsih no 07"),
|
||||||
|
DummyNoSuratJalan("110399", 2, "Joko S", "Jl Pegangsaan no 04"),
|
||||||
|
];
|
||||||
|
|
||||||
|
Future<List<ResponseSearchPengantaranHasilModel>> loadListNoSuratJalanPengantaranHasilInstansi({
|
||||||
|
required String search,
|
||||||
|
}) async {
|
||||||
|
final param = {
|
||||||
|
"search": search,
|
||||||
|
};
|
||||||
|
final service =
|
||||||
|
"${Constant.baseUrl}v1/courier/mobile/inputcourier/search_company/?search=$search";
|
||||||
|
final resp = await post(param: param, service: service);
|
||||||
|
|
||||||
|
final result = List<ResponseSearchPengantaranHasilModel>.empty(growable: true);
|
||||||
|
if (resp['data'] != null) {
|
||||||
|
resp['data']['records'].forEach((e) {
|
||||||
|
final model = ResponseSearchPengantaranHasilModel.fromJson(e);
|
||||||
|
result.add(model);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<ResponseSavePengantaranHasilModel> pengantaranHasilInstansiSave({
|
||||||
|
required String courierID,
|
||||||
|
required String tipeID,
|
||||||
|
required String deliveryID,
|
||||||
|
}) async {
|
||||||
|
final param = {
|
||||||
|
"id": courierID,
|
||||||
|
"tipeid": tipeID,
|
||||||
|
"deliveryid": deliveryID
|
||||||
|
};
|
||||||
|
|
||||||
|
print("param : $param");
|
||||||
|
|
||||||
|
final service = "${Constant.baseUrl}v1/courier/mobile/inputcourier/add/?id=$courierID&tipeid=$tipeID&deliveryid=$deliveryID";
|
||||||
|
final resp = await post(param: param, service: service);
|
||||||
|
return ResponseSavePengantaranHasilModel.fromJson(resp);
|
||||||
|
}
|
||||||
|
}
|
||||||
48
lib/repository/pengantaran_hasil_pasien_repository.dart
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
import '../app/constant.dart';
|
||||||
|
import '../models/response_save_pengantaran_hasil_model.dart';
|
||||||
|
import '../models/response_search_pengantaran_hasil_model.dart';
|
||||||
|
import 'base_repository.dart';
|
||||||
|
|
||||||
|
class PengantaranHasilPasienRepository extends BaseRepository {
|
||||||
|
PengantaranHasilPasienRepository({required super.dio});
|
||||||
|
|
||||||
|
// search no lab pasien
|
||||||
|
Future<List<ResponseSearchPengantaranHasilModel>>
|
||||||
|
loadListNoLabPengantaranHasilPasien({
|
||||||
|
required String search,
|
||||||
|
}) async {
|
||||||
|
final param = {
|
||||||
|
"search": search,
|
||||||
|
};
|
||||||
|
final service =
|
||||||
|
"${Constant.baseUrl}v1/courier/mobile/inputcourier/search_patient/?search=$search";
|
||||||
|
final resp = await post(param: param, service: service);
|
||||||
|
|
||||||
|
final result = List<ResponseSearchPengantaranHasilModel>.empty(growable: true);
|
||||||
|
if (resp['data'] != null) {
|
||||||
|
resp['data']['records'].forEach((e) {
|
||||||
|
final model = ResponseSearchPengantaranHasilModel.fromJson(e);
|
||||||
|
result.add(model);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
// simpan input pengantaran hasil pasien
|
||||||
|
Future<ResponseSavePengantaranHasilModel> pengantaranHasilPasienSave({
|
||||||
|
required String courierID,
|
||||||
|
required String tipeID,
|
||||||
|
required String deliveryID,
|
||||||
|
}) async {
|
||||||
|
final param = {
|
||||||
|
"id": courierID,
|
||||||
|
"tipeid": tipeID,
|
||||||
|
"deliveryid": deliveryID
|
||||||
|
};
|
||||||
|
|
||||||
|
final service = "${Constant.baseUrl}v1/courier/mobile/inputcourier/add/?id=$courierID&tipeid=$tipeID&deliveryid=$deliveryID";
|
||||||
|
final resp = await post(param: param, service: service);
|
||||||
|
return ResponseSavePengantaranHasilModel.fromJson(resp);
|
||||||
|
}
|
||||||
|
}
|
||||||
34
lib/repository/personal_information_repository.dart
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
import 'dart:convert';
|
||||||
|
|
||||||
|
import '../models/personal_information_model.dart';
|
||||||
|
|
||||||
|
import '../app/constant.dart';
|
||||||
|
import 'base_repository.dart';
|
||||||
|
|
||||||
|
class PersonalInformationRepository extends BaseRepository {
|
||||||
|
PersonalInformationRepository({required super.dio});
|
||||||
|
|
||||||
|
Future<List<PersonalInformationModel>> getPersonalInformation(
|
||||||
|
{required String mCourierID}) async {
|
||||||
|
final param = {
|
||||||
|
"id": mCourierID
|
||||||
|
};
|
||||||
|
|
||||||
|
final url =
|
||||||
|
"${Constant.baseUrl}/v1/courier/mobile/profile/info/?id=$mCourierID";
|
||||||
|
final resp = await get(service: url);
|
||||||
|
// print("url :" + url);
|
||||||
|
List<PersonalInformationModel> data;
|
||||||
|
// print(resp['data']);
|
||||||
|
if (resp['status'] == 'OK' && resp['status'] != null) {
|
||||||
|
data = [];
|
||||||
|
resp['data'].forEach((e) {
|
||||||
|
final model = PersonalInformationModel.fromJson(e);
|
||||||
|
data.add(model);
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
data = [];
|
||||||
|
}
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
}
|
||||||
59
lib/repository/result_delivery_repository.dart
Normal file
@@ -0,0 +1,59 @@
|
|||||||
|
import '../app/constant.dart';
|
||||||
|
import 'base_repository.dart';
|
||||||
|
|
||||||
|
class ResultDeliveryRepository extends BaseRepository {
|
||||||
|
ResultDeliveryRepository({required super.dio});
|
||||||
|
|
||||||
|
Future<bool> setLocation(
|
||||||
|
{required String id,
|
||||||
|
required String step,
|
||||||
|
required String lat,
|
||||||
|
required String long,
|
||||||
|
required String address,
|
||||||
|
required String branchID}) async {
|
||||||
|
final url =
|
||||||
|
"${Constant.baseUrl}/v1/courier/mobile/process/add_delivery/?id=$id&locid=$step&lat=$lat&long=$long&address=$address&branchid=$branchID";
|
||||||
|
final resp = await get(service: url);
|
||||||
|
bool data = false;
|
||||||
|
|
||||||
|
if (resp['status'] == "OK") {
|
||||||
|
data = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<bool> setDeliveryPerson({
|
||||||
|
required String id,
|
||||||
|
required String name,
|
||||||
|
required String note,
|
||||||
|
}) async {
|
||||||
|
final url =
|
||||||
|
"${Constant.baseUrl}/v1/courier/mobile/process/update_deliver/?id=$id&name=$name¬e=$note";
|
||||||
|
final resp = await get(service: url);
|
||||||
|
bool data = false;
|
||||||
|
|
||||||
|
if (resp['status'] == "OK") {
|
||||||
|
data = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<bool> setReceivePerson({
|
||||||
|
required String id,
|
||||||
|
required String name,
|
||||||
|
required String note,
|
||||||
|
}) async {
|
||||||
|
final url =
|
||||||
|
"${Constant.baseUrl}/v1/courier/mobile/process/update_receive/?id=$id&name=$name¬e=$note";
|
||||||
|
final resp = await get(service: url);
|
||||||
|
bool data = false;
|
||||||
|
|
||||||
|
if (resp['status'] == "OK") {
|
||||||
|
data = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
}
|
||||||
28
lib/repository/work_input_suhu_repository.dart
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
import '../app/constant.dart';
|
||||||
|
import '../models/response_save_work_suhu_model.dart';
|
||||||
|
import 'base_repository.dart';
|
||||||
|
|
||||||
|
|
||||||
|
class WorkInputSuhuRepository extends BaseRepository {
|
||||||
|
WorkInputSuhuRepository({required super.dio});
|
||||||
|
|
||||||
|
Future<ResponseSaveWorkSuhuModel> inputWorkSuhu({
|
||||||
|
required String deliveryId,
|
||||||
|
required String suhu
|
||||||
|
}) async {
|
||||||
|
final param = {
|
||||||
|
"id": deliveryId,
|
||||||
|
"suhu": suhu
|
||||||
|
};
|
||||||
|
|
||||||
|
print("param : $param");
|
||||||
|
|
||||||
|
// Pengantaran Hasil => tipeID 1
|
||||||
|
// Lain-lain => tipeID 4
|
||||||
|
// Pengambilan Bahan => tipeID 5
|
||||||
|
|
||||||
|
final service = "${Constant.baseUrl}v1/courier/mobile/process/update_temperatur_box/?id=$deliveryId&suhu=$suhu";
|
||||||
|
final resp = await post(param: param, service: service);
|
||||||
|
return ResponseSaveWorkSuhuModel.fromJson(resp);
|
||||||
|
}
|
||||||
|
}
|
||||||
58
lib/repository/work_list_repository.dart
Normal file
@@ -0,0 +1,58 @@
|
|||||||
|
import 'dart:convert';
|
||||||
|
|
||||||
|
import '../models/work_list_model.dart';
|
||||||
|
|
||||||
|
import '../app/constant.dart';
|
||||||
|
import '../models/detail_work_model.dart';
|
||||||
|
import '../models/pending_work_model.dart';
|
||||||
|
import '../models/work_total_model.dart';
|
||||||
|
import 'base_repository.dart';
|
||||||
|
|
||||||
|
class WorkListRepository extends BaseRepository {
|
||||||
|
WorkListRepository({required super.dio});
|
||||||
|
|
||||||
|
Future<List<WorkListModel>> getListWork(
|
||||||
|
{required String id,
|
||||||
|
required String tipeId,
|
||||||
|
required String supervisor,
|
||||||
|
required String status}) async {
|
||||||
|
final url =
|
||||||
|
"${Constant.baseUrl}/v1/courier/mobile/worklist/listbycourierv2/?id=$id&tipeid=$tipeId&status='$status'&supervisor='$supervisor'";
|
||||||
|
final resp = await get(service: url);
|
||||||
|
// print("url :" + url);
|
||||||
|
List<WorkListModel> data;
|
||||||
|
// print(resp['data']);
|
||||||
|
if (resp['status'] == 'OK' && resp['status'] != null) {
|
||||||
|
data = [];
|
||||||
|
resp['data'].forEach((e) {
|
||||||
|
final model = WorkListModel.fromJson(e);
|
||||||
|
data.add(model);
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
data = [];
|
||||||
|
}
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<DetailWorkModel> getDetail(
|
||||||
|
{required String id,
|
||||||
|
required String tipeId,
|
||||||
|
required String deliveryId}) async {
|
||||||
|
final url =
|
||||||
|
"${Constant.baseUrl}/v1/courier/mobile/worklist/list_by_id/?id=$id&tipeid=$tipeId&deliveryid=$deliveryId";
|
||||||
|
final resp = await get(service: url);
|
||||||
|
// DetailWorkModel data;
|
||||||
|
// print(resp['data']);
|
||||||
|
|
||||||
|
DetailWorkModel data = DetailWorkModel.fromJson(resp['data'][0]);
|
||||||
|
|
||||||
|
// resp['data'].forEach((e) {
|
||||||
|
// final model = HistoryModel.fromJson(e);
|
||||||
|
// data.add(model);
|
||||||
|
// });
|
||||||
|
// }
|
||||||
|
// print(data.alamatPengambilan);
|
||||||
|
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
}
|
||||||
32
lib/repository/work_tunda_repository.dart
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
import '../app/constant.dart';
|
||||||
|
import '../models/response_save_work_tunda_model.dart';
|
||||||
|
import 'base_repository.dart';
|
||||||
|
|
||||||
|
|
||||||
|
class WorkTundaRepository extends BaseRepository {
|
||||||
|
WorkTundaRepository({required super.dio});
|
||||||
|
|
||||||
|
Future<ResponseSaveWorkTundaModel> inputWorkTunda({
|
||||||
|
required String courierID,
|
||||||
|
required String tipeID,
|
||||||
|
required String deliveryID,
|
||||||
|
required String note
|
||||||
|
}) async {
|
||||||
|
final param = {
|
||||||
|
"id": courierID,
|
||||||
|
"tipeid": tipeID,
|
||||||
|
"deliveryid": deliveryID,
|
||||||
|
"note": note
|
||||||
|
};
|
||||||
|
|
||||||
|
print("param : $param");
|
||||||
|
|
||||||
|
// Pengantaran Hasil => tipeID 1
|
||||||
|
// Lain-lain => tipeID 4
|
||||||
|
// Pengambilan Bahan => tipeID 5
|
||||||
|
|
||||||
|
final service = "${Constant.baseUrl}v1/courier/mobile/pending/add/?id=$courierID&tipeid=$tipeID&deliveryid=$deliveryID¬e=$note";
|
||||||
|
final resp = await post(param: param, service: service);
|
||||||
|
return ResponseSaveWorkTundaModel.fromJson(resp);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,78 @@
|
|||||||
|
import 'package:equatable/equatable.dart';
|
||||||
|
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||||
|
import '../../models/personal_information_model.dart';
|
||||||
|
import '../../repository/change_password_repository.dart';
|
||||||
|
import '../../repository/personal_information_repository.dart';
|
||||||
|
import '../../repository/work_list_repository.dart';
|
||||||
|
|
||||||
|
import '../../models/pending_work_model.dart';
|
||||||
|
import '../../models/response_save_change_password_model.dart';
|
||||||
|
import '../../provider/dio_provider.dart';
|
||||||
|
import '../../repository/base_repository.dart';
|
||||||
|
import '../../repository/home_screen_repository.dart';
|
||||||
|
|
||||||
|
abstract class ChangePasswordState extends Equatable {
|
||||||
|
final DateTime date;
|
||||||
|
const ChangePasswordState(this.date);
|
||||||
|
@override
|
||||||
|
List<Object?> get props => [date];
|
||||||
|
}
|
||||||
|
|
||||||
|
class ChangePasswordStateInit extends ChangePasswordState {
|
||||||
|
ChangePasswordStateInit() : super(DateTime.now());
|
||||||
|
}
|
||||||
|
|
||||||
|
class ChangePasswordStateLoading extends ChangePasswordState {
|
||||||
|
ChangePasswordStateLoading() : super(DateTime.now());
|
||||||
|
}
|
||||||
|
|
||||||
|
class ChangePasswordStateError extends ChangePasswordState {
|
||||||
|
final String message;
|
||||||
|
ChangePasswordStateError({
|
||||||
|
required this.message,
|
||||||
|
}) : super(DateTime.now());
|
||||||
|
}
|
||||||
|
|
||||||
|
class ChangePasswordStateDone extends ChangePasswordState {
|
||||||
|
final ResponseSaveChangePasswordModel model;
|
||||||
|
ChangePasswordStateDone({
|
||||||
|
required this.model,
|
||||||
|
}) : super(DateTime.now());
|
||||||
|
}
|
||||||
|
|
||||||
|
//notifier
|
||||||
|
class ChangePasswordNotifier extends StateNotifier<ChangePasswordState> {
|
||||||
|
final Ref ref;
|
||||||
|
ChangePasswordNotifier({
|
||||||
|
required this.ref,
|
||||||
|
}) : super(ChangePasswordStateInit());
|
||||||
|
|
||||||
|
void ubahPassword({
|
||||||
|
required String userID,
|
||||||
|
required String oldPassword,
|
||||||
|
required String newPassword,
|
||||||
|
}) async {
|
||||||
|
try {
|
||||||
|
state = ChangePasswordStateLoading();
|
||||||
|
final dio = ref.read(dioProvider);
|
||||||
|
final resp = await ChangePasswordRepository(dio: dio)
|
||||||
|
.ubahPassword(
|
||||||
|
userID: userID,
|
||||||
|
oldPassword: oldPassword,
|
||||||
|
newPassword: newPassword
|
||||||
|
);
|
||||||
|
state = ChangePasswordStateDone(model: resp);
|
||||||
|
} catch (e) {
|
||||||
|
if (e is BaseRepositoryException) {
|
||||||
|
state = ChangePasswordStateError(message: e.message.toString());
|
||||||
|
} else {
|
||||||
|
state = ChangePasswordStateError(message: e.toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//provider
|
||||||
|
final ChangePasswordProvider =
|
||||||
|
StateNotifierProvider<ChangePasswordNotifier, ChangePasswordState>(
|
||||||
|
(ref) => ChangePasswordNotifier(ref: ref));
|
||||||
268
lib/screen/change_password_screen/change_password_screen.dart
Normal file
@@ -0,0 +1,268 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter/src/widgets/framework.dart';
|
||||||
|
import 'package:flutter/src/widgets/placeholder.dart';
|
||||||
|
import 'package:flutter_hooks/flutter_hooks.dart';
|
||||||
|
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||||
|
import '../../app/route.dart';
|
||||||
|
import '../change_password_screen/change_password_provider.dart';
|
||||||
|
import '/widget/snackbar_widget.dart';
|
||||||
|
import 'package:shared_preferences/shared_preferences.dart';
|
||||||
|
|
||||||
|
import '../../app/constant.dart';
|
||||||
|
import '../../provider/current_user_provider.dart';
|
||||||
|
|
||||||
|
class ChangePasswordScreen extends HookConsumerWidget {
|
||||||
|
const ChangePasswordScreen({super.key});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context, WidgetRef ref) {
|
||||||
|
final currentPassword = useTextEditingController(text: "");
|
||||||
|
final passwordNow = useTextEditingController(text: "");
|
||||||
|
final confirmPassword = useTextEditingController(text: "");
|
||||||
|
|
||||||
|
final hideCurrentPassword = useState(true);
|
||||||
|
final hidePasswordNow = useState(true);
|
||||||
|
final hideConfirmPassword = useState(true);
|
||||||
|
|
||||||
|
final isLoading = useState<bool>(false);
|
||||||
|
final userID = ref.watch(currentUserProvider)?.model.user?.mUserID ?? "0";
|
||||||
|
|
||||||
|
ref.listen(ChangePasswordProvider, (previous, next) async {
|
||||||
|
if (next is ChangePasswordStateLoading) {
|
||||||
|
isLoading.value = true;
|
||||||
|
} else if (next is ChangePasswordStateError) {
|
||||||
|
isLoading.value = false;
|
||||||
|
// print(next.message);
|
||||||
|
SanckbarWidget(
|
||||||
|
context, next.message, snackbarType.error);
|
||||||
|
} else if (next is ChangePasswordStateDone) {
|
||||||
|
isLoading.value = false;
|
||||||
|
isLoading.value = false;
|
||||||
|
if (next.model.status != "OK") {
|
||||||
|
SanckbarWidget(context, "${next.model.message}", snackbarType.error);
|
||||||
|
} else {
|
||||||
|
final shared = await SharedPreferences.getInstance();
|
||||||
|
final passwordSharePref = shared.getString("passwordX");
|
||||||
|
if (passwordSharePref != null) {
|
||||||
|
await shared.setString("passwordX", confirmPassword.text);
|
||||||
|
}
|
||||||
|
SanckbarWidget(
|
||||||
|
context,
|
||||||
|
"Berhasil Mengubah Password",
|
||||||
|
snackbarType.success);
|
||||||
|
Navigator.of(context).pushNamedAndRemoveUntil(
|
||||||
|
menuRoute,
|
||||||
|
(route) => false,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
disabledBtn<bool>() {
|
||||||
|
if (currentPassword.text.isNotEmpty &&
|
||||||
|
passwordNow.text.isNotEmpty &&
|
||||||
|
confirmPassword.text.isNotEmpty &&
|
||||||
|
(passwordNow.text == confirmPassword.text)) {
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return Scaffold(
|
||||||
|
bottomNavigationBar: Container(
|
||||||
|
padding: EdgeInsets.symmetric(
|
||||||
|
horizontal: Constant.getActualX(context: context, x: 35),
|
||||||
|
vertical: Constant.getActualY(context: context, y: 40)),
|
||||||
|
child: ElevatedButton(
|
||||||
|
onPressed: () {
|
||||||
|
// showDialog(
|
||||||
|
// context: context,
|
||||||
|
// builder: (context) {
|
||||||
|
// return ErrorDialog(
|
||||||
|
// title: "Something Went Wrong",
|
||||||
|
// message: "404 Not Found",
|
||||||
|
// showImage: true,
|
||||||
|
// showButton: true,
|
||||||
|
// buttonText: "Close",
|
||||||
|
// buttonFunction: () {
|
||||||
|
// print("a");
|
||||||
|
// });
|
||||||
|
// },
|
||||||
|
// );
|
||||||
|
if (currentPassword.text.isNotEmpty &&
|
||||||
|
passwordNow.text.isNotEmpty &&
|
||||||
|
confirmPassword.text.isNotEmpty &&
|
||||||
|
(passwordNow.text == confirmPassword.text)) {
|
||||||
|
// print("a");
|
||||||
|
|
||||||
|
ref.read(ChangePasswordProvider.notifier).ubahPassword(
|
||||||
|
userID: userID,
|
||||||
|
oldPassword: currentPassword.text,
|
||||||
|
newPassword: passwordNow.text);
|
||||||
|
} else {
|
||||||
|
// null;
|
||||||
|
if (currentPassword.text.isEmpty) {
|
||||||
|
SanckbarWidget(
|
||||||
|
context,
|
||||||
|
"Password Saat ini tidak boleh kosong",
|
||||||
|
snackbarType.warning);
|
||||||
|
} else {
|
||||||
|
if ((passwordNow.text.isEmpty ||
|
||||||
|
confirmPassword.text.isEmpty)) {
|
||||||
|
SanckbarWidget(
|
||||||
|
context,
|
||||||
|
"Password Saat ini atau Konformasi Password tidak boleh kosong",
|
||||||
|
snackbarType.warning);
|
||||||
|
} else {
|
||||||
|
if ((passwordNow.text != confirmPassword.text)) {
|
||||||
|
SanckbarWidget(
|
||||||
|
context,
|
||||||
|
"Konfirmasi Password & Password Baru harus sama",
|
||||||
|
snackbarType.warning);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
style: ElevatedButton.styleFrom(
|
||||||
|
shape: RoundedRectangleBorder(
|
||||||
|
side: const BorderSide(width: 0.1, color: Colors.grey),
|
||||||
|
borderRadius: BorderRadius.circular(8),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
child: Container(
|
||||||
|
height: Constant.getActualY(context: context, y: 46),
|
||||||
|
child: Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
|
children: const [
|
||||||
|
Text(
|
||||||
|
"Simpan",
|
||||||
|
style: TextStyle(fontWeight: FontWeight.bold),
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
)),
|
||||||
|
),
|
||||||
|
body: ListView(
|
||||||
|
children: [
|
||||||
|
Container(
|
||||||
|
height: Constant.getActualY(context: context, y: 56),
|
||||||
|
),
|
||||||
|
Container(
|
||||||
|
padding: EdgeInsets.symmetric(
|
||||||
|
horizontal: Constant.getActualX(context: context, x: 10)),
|
||||||
|
height: Constant.getActualY(context: context, y: 48),
|
||||||
|
child: Row(
|
||||||
|
children: [
|
||||||
|
IconButton(
|
||||||
|
onPressed: () {
|
||||||
|
Navigator.of(context).pop();
|
||||||
|
},
|
||||||
|
icon: Icon(Icons.arrow_back_ios_rounded),
|
||||||
|
),
|
||||||
|
Text(
|
||||||
|
"Ubah Password",
|
||||||
|
style: Constant.body1(context: context).copyWith(
|
||||||
|
fontWeight: FontWeight.w600, color: Constant.textPrimary),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Container(
|
||||||
|
height: Constant.getActualY(context: context, y: 31),
|
||||||
|
),
|
||||||
|
Container(
|
||||||
|
margin: EdgeInsets.symmetric(
|
||||||
|
horizontal: Constant.getActualX(context: context, x: 34)),
|
||||||
|
child: TextFormField(
|
||||||
|
controller: currentPassword,
|
||||||
|
obscureText: hideCurrentPassword.value,
|
||||||
|
enableSuggestions: false,
|
||||||
|
autocorrect: false,
|
||||||
|
decoration: InputDecoration(
|
||||||
|
suffixIcon: InkWell(
|
||||||
|
onTap: () {
|
||||||
|
hideCurrentPassword.value = !hideCurrentPassword.value;
|
||||||
|
},
|
||||||
|
child: Icon(!hideCurrentPassword.value
|
||||||
|
? Icons.remove_red_eye
|
||||||
|
: Icons.remove_red_eye_outlined)),
|
||||||
|
labelText: "Password Saat Ini",
|
||||||
|
hintText: "Password Saat Ini",
|
||||||
|
border:
|
||||||
|
OutlineInputBorder(borderRadius: BorderRadius.circular(8)),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Container(
|
||||||
|
height: Constant.getActualY(context: context, y: 24),
|
||||||
|
),
|
||||||
|
Container(
|
||||||
|
margin: EdgeInsets.symmetric(
|
||||||
|
horizontal: Constant.getActualX(context: context, x: 34)),
|
||||||
|
child: TextFormField(
|
||||||
|
controller: passwordNow,
|
||||||
|
obscureText: hidePasswordNow.value,
|
||||||
|
enableSuggestions: false,
|
||||||
|
autocorrect: false,
|
||||||
|
decoration: InputDecoration(
|
||||||
|
suffixIcon: InkWell(
|
||||||
|
onTap: () {
|
||||||
|
hidePasswordNow.value = !hidePasswordNow.value;
|
||||||
|
},
|
||||||
|
child: Icon(!hidePasswordNow.value
|
||||||
|
? Icons.remove_red_eye
|
||||||
|
: Icons.remove_red_eye_outlined)),
|
||||||
|
labelText: "Password Baru",
|
||||||
|
hintText: "Password Baru",
|
||||||
|
border:
|
||||||
|
OutlineInputBorder(borderRadius: BorderRadius.circular(8)),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Container(
|
||||||
|
height: Constant.getActualY(context: context, y: 24),
|
||||||
|
),
|
||||||
|
Container(
|
||||||
|
margin: EdgeInsets.symmetric(
|
||||||
|
horizontal: Constant.getActualX(context: context, x: 34)),
|
||||||
|
child: TextFormField(
|
||||||
|
controller: confirmPassword,
|
||||||
|
obscureText: hideConfirmPassword.value,
|
||||||
|
enableSuggestions: false,
|
||||||
|
autocorrect: false,
|
||||||
|
autovalidateMode: AutovalidateMode.onUserInteraction,
|
||||||
|
validator: (value) {
|
||||||
|
if (value != passwordNow.text) {
|
||||||
|
return "Konfirmasi password berbeda";
|
||||||
|
}
|
||||||
|
},
|
||||||
|
onEditingComplete: () {
|
||||||
|
FocusScope.of(context).unfocus();
|
||||||
|
},
|
||||||
|
// onChanged: (e) {
|
||||||
|
// if (e != passwordNow.text) {
|
||||||
|
// print("diff");
|
||||||
|
// }
|
||||||
|
// },
|
||||||
|
decoration: InputDecoration(
|
||||||
|
suffixIcon: InkWell(
|
||||||
|
onTap: () {
|
||||||
|
hideConfirmPassword.value = !hideConfirmPassword.value;
|
||||||
|
},
|
||||||
|
child: Icon(!hideConfirmPassword.value
|
||||||
|
? Icons.remove_red_eye
|
||||||
|
: Icons.remove_red_eye_outlined)),
|
||||||
|
labelText: "konfirmasi Password Baru",
|
||||||
|
hintText: "konfirmasi Password Baru",
|
||||||
|
border:
|
||||||
|
OutlineInputBorder(borderRadius: BorderRadius.circular(8)),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,72 @@
|
|||||||
|
import 'package:equatable/equatable.dart';
|
||||||
|
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||||
|
import '/models/detail_history_model.dart';
|
||||||
|
import '/models/history_model.dart';
|
||||||
|
import '/../repository/history_screen_repository.dart';
|
||||||
|
import '/screen/history_screen/history_screen.dart';
|
||||||
|
|
||||||
|
import '../../models/pending_work_model.dart';
|
||||||
|
import '../../provider/dio_provider.dart';
|
||||||
|
import '../../repository/base_repository.dart';
|
||||||
|
import '../../repository/home_screen_repository.dart';
|
||||||
|
|
||||||
|
abstract class DetailHistoryState extends Equatable {
|
||||||
|
final DateTime date;
|
||||||
|
const DetailHistoryState(this.date);
|
||||||
|
@override
|
||||||
|
List<Object?> get props => [date];
|
||||||
|
}
|
||||||
|
|
||||||
|
class DetailHistoryStateInit extends DetailHistoryState {
|
||||||
|
DetailHistoryStateInit() : super(DateTime.now());
|
||||||
|
}
|
||||||
|
|
||||||
|
class DetailHistoryStateLoading extends DetailHistoryState {
|
||||||
|
DetailHistoryStateLoading() : super(DateTime.now());
|
||||||
|
}
|
||||||
|
|
||||||
|
class DetailHistoryStateError extends DetailHistoryState {
|
||||||
|
final String message;
|
||||||
|
DetailHistoryStateError({
|
||||||
|
required this.message,
|
||||||
|
}) : super(DateTime.now());
|
||||||
|
}
|
||||||
|
|
||||||
|
class DetailHistoryStateDone extends DetailHistoryState {
|
||||||
|
final DetailHistoryModel model;
|
||||||
|
DetailHistoryStateDone({
|
||||||
|
required this.model,
|
||||||
|
}) : super(DateTime.now());
|
||||||
|
}
|
||||||
|
|
||||||
|
//notifier
|
||||||
|
class DetailHistoryNotifier extends StateNotifier<DetailHistoryState> {
|
||||||
|
final Ref ref;
|
||||||
|
DetailHistoryNotifier({
|
||||||
|
required this.ref,
|
||||||
|
}) : super(DetailHistoryStateInit());
|
||||||
|
|
||||||
|
void getData(
|
||||||
|
{required String id,
|
||||||
|
required String tipeId,
|
||||||
|
required String deliveryId}) async {
|
||||||
|
try {
|
||||||
|
state = DetailHistoryStateLoading();
|
||||||
|
final dio = ref.read(dioProvider);
|
||||||
|
final resp = await HistoryRepository(dio: dio)
|
||||||
|
.getDetail(id: id, tipeId: tipeId, deliveryId: deliveryId);
|
||||||
|
state = DetailHistoryStateDone(model: resp);
|
||||||
|
} catch (e) {
|
||||||
|
if (e is BaseRepositoryException) {
|
||||||
|
state = DetailHistoryStateError(message: e.message.toString());
|
||||||
|
} else {
|
||||||
|
state = DetailHistoryStateError(message: e.toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//provider
|
||||||
|
final DetailHistoryProvider =
|
||||||
|
StateNotifierProvider<DetailHistoryNotifier, DetailHistoryState>(
|
||||||
|
(ref) => DetailHistoryNotifier(ref: ref));
|
||||||
792
lib/screen/detail_history_screen/detail_history_screen.dart
Normal file
@@ -0,0 +1,792 @@
|
|||||||
|
import 'dart:convert';
|
||||||
|
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter/src/widgets/framework.dart';
|
||||||
|
import 'package:flutter/src/widgets/placeholder.dart';
|
||||||
|
import 'package:flutter_hooks/flutter_hooks.dart';
|
||||||
|
import 'package:geolocator/geolocator.dart';
|
||||||
|
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||||
|
import 'package:intl/intl.dart';
|
||||||
|
import '/models/detail_history_model.dart';
|
||||||
|
import '/screen/detail_history_screen/detail_history_provider.dart';
|
||||||
|
import '/widget/chip_type.dart';
|
||||||
|
import '/widget/patient_card.dart';
|
||||||
|
import 'package:loading_animation_widget/loading_animation_widget.dart';
|
||||||
|
import 'package:maps_launcher/maps_launcher.dart';
|
||||||
|
|
||||||
|
import '../../app/constant.dart';
|
||||||
|
import '../../widget/snackbar_widget.dart';
|
||||||
|
|
||||||
|
class DetailHistoryProp {
|
||||||
|
final String tipeId;
|
||||||
|
final String kurirId;
|
||||||
|
final String deliveryId;
|
||||||
|
|
||||||
|
DetailHistoryProp(this.tipeId, this.kurirId, this.deliveryId);
|
||||||
|
}
|
||||||
|
|
||||||
|
class DetailHistoryScreen extends HookConsumerWidget {
|
||||||
|
const DetailHistoryScreen(
|
||||||
|
{super.key, required this.data, required this.prop});
|
||||||
|
final Map<String, dynamic> data;
|
||||||
|
final DetailHistoryProp prop;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context, WidgetRef ref) {
|
||||||
|
final detailLoading = useState(false);
|
||||||
|
final detailData = useState<DetailHistoryModel>(DetailHistoryModel());
|
||||||
|
var formattedDate = useState('');
|
||||||
|
|
||||||
|
final pengambilanAwalLoc = useState<Map<String, String>>(
|
||||||
|
{"long": "110.7104622", "lat": "-7.5031631"});
|
||||||
|
final pengambilanAkhirLoc = useState<Map<String, String>>(
|
||||||
|
{"long": "110.7104622", "lat": "-7.5031631"});
|
||||||
|
final pengantaranAwalLoc = useState<Map<String, String>>(
|
||||||
|
{"long": "110.7104622", "lat": "-7.5031631"});
|
||||||
|
final pengantaranAkhirLoc = useState<Map<String, String>>(
|
||||||
|
{"long": "110.7104622", "lat": "-7.5031631"});
|
||||||
|
final petugasPengambilan = useState("Liliana Ruby");
|
||||||
|
final petugasPengantaran = useState("Liliana Ruby");
|
||||||
|
final catatanPengambilan = useState("Lengkap");
|
||||||
|
final catatanPengantaran = useState("Lengkap");
|
||||||
|
|
||||||
|
List<Map<String, String>> listPasien = [
|
||||||
|
{"id": "1", "name": "Sabrina Dewi", "no_lab": "112035"},
|
||||||
|
{"id": "2", "name": "Lisa Andriani", "no_lab": "113040"},
|
||||||
|
{"id": "3", "name": "Leo Rolly", "no_lab": "112987"},
|
||||||
|
];
|
||||||
|
fetchData() {
|
||||||
|
ref.read(DetailHistoryProvider.notifier).getData(
|
||||||
|
id: prop.kurirId, tipeId: prop.tipeId, deliveryId: prop.deliveryId);
|
||||||
|
}
|
||||||
|
|
||||||
|
useEffect(() {
|
||||||
|
WidgetsBinding.instance.addPostFrameCallback((timeStamp) async {
|
||||||
|
fetchData();
|
||||||
|
});
|
||||||
|
return () {};
|
||||||
|
}, []);
|
||||||
|
ref.listen(
|
||||||
|
DetailHistoryProvider,
|
||||||
|
(previous, next) {
|
||||||
|
if (next is DetailHistoryStateLoading) {
|
||||||
|
detailLoading.value = true;
|
||||||
|
} else if (next is DetailHistoryStateError) {
|
||||||
|
// print(next.message);
|
||||||
|
detailLoading.value = false;
|
||||||
|
SanckbarWidget(
|
||||||
|
context, next.message.substring(0, 30), snackbarType.error);
|
||||||
|
} else if (next is DetailHistoryStateDone) {
|
||||||
|
// print(next.model);
|
||||||
|
detailData.value = next.model;
|
||||||
|
String originalDateString = next.model.cdate.toString();
|
||||||
|
DateTime originalDate =
|
||||||
|
DateFormat('dd-MM-yyyy HH:mm:ss').parse(originalDateString);
|
||||||
|
// String formattedDate = DateFormat.yMMMMd('id').format(originalDate);
|
||||||
|
formattedDate.value = DateFormat('d MMM HH:mm').format(originalDate);
|
||||||
|
// print("data from json");
|
||||||
|
// print(next.model.tipeid);
|
||||||
|
pengambilanAwalLoc.value = {
|
||||||
|
"long": next.model.lngPengambilanAwal ?? "0",
|
||||||
|
"lat": next.model.latPengambilanAwal ?? "0"
|
||||||
|
};
|
||||||
|
pengambilanAkhirLoc.value = {
|
||||||
|
"long": next.model.lngPengambilanAkhir ?? "0",
|
||||||
|
"lat": next.model.latPengambilanAkhir ?? "0"
|
||||||
|
};
|
||||||
|
|
||||||
|
pengantaranAwalLoc.value = {
|
||||||
|
"long": next.model.lngPengantaranAwal ?? "0",
|
||||||
|
"lat": next.model.latPengantaranAwal ?? "0"
|
||||||
|
};
|
||||||
|
pengantaranAkhirLoc.value = {
|
||||||
|
"long": next.model.lngPengantaranAkhir ?? "0",
|
||||||
|
"lat": next.model.latPengantaranAkhir ?? "0"
|
||||||
|
};
|
||||||
|
petugasPengambilan.value = next.model.petugasPenyerahan ?? " ";
|
||||||
|
petugasPengantaran.value = next.model.penerima ?? " ";
|
||||||
|
catatanPengantaran.value = next.model.notePenerimaan ?? " ";
|
||||||
|
catatanPengambilan.value = next.model.notePenyerahan ?? " ";
|
||||||
|
|
||||||
|
detailLoading.value = false;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
return detailLoading.value
|
||||||
|
? SizedBox(
|
||||||
|
height: Constant.designHeight * 0.9,
|
||||||
|
child: Center(
|
||||||
|
child: LoadingAnimationWidget.fourRotatingDots(
|
||||||
|
color: Constant.primaryBlue, size: 50),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
: SingleChildScrollView(
|
||||||
|
child: Column(children: [
|
||||||
|
SizedBox(
|
||||||
|
height: Constant.getActualY(context: context, y: 24),
|
||||||
|
),
|
||||||
|
Container(
|
||||||
|
padding: EdgeInsets.symmetric(
|
||||||
|
horizontal: Constant.getActualX(context: context, x: 20)),
|
||||||
|
height: Constant.getActualY(context: context, y: 40),
|
||||||
|
child: Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
|
children: [
|
||||||
|
Image.asset(
|
||||||
|
"assets/icon_detail_riwayat_motor.png",
|
||||||
|
width: Constant.getActualX(context: context, x: 64),
|
||||||
|
height: Constant.getActualX(context: context, x: 64),
|
||||||
|
),
|
||||||
|
Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.end,
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
|
children: [
|
||||||
|
Text(
|
||||||
|
formattedDate.value,
|
||||||
|
style: Constant.body1(context: context)
|
||||||
|
.copyWith(fontWeight: FontWeight.w500),
|
||||||
|
),
|
||||||
|
ChipType(
|
||||||
|
name: detailData.value.tipe.toString(),
|
||||||
|
tipe: int.parse(prop.tipeId),
|
||||||
|
isDetailHistory: true,
|
||||||
|
)
|
||||||
|
],
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Container(
|
||||||
|
padding: EdgeInsets.symmetric(
|
||||||
|
horizontal: Constant.getActualX(context: context, x: 35)),
|
||||||
|
// color: Colors.red,
|
||||||
|
height: Constant.getActualY(context: context, y: 737),
|
||||||
|
child: SingleChildScrollView(
|
||||||
|
// reverse: MediaQuery.of(context).viewInsets.bottom != 0
|
||||||
|
// ? true
|
||||||
|
// : false,
|
||||||
|
child: Padding(
|
||||||
|
padding: EdgeInsets.only(
|
||||||
|
bottom: MediaQuery.of(context).viewInsets.bottom),
|
||||||
|
child: Column(
|
||||||
|
// shrinkWrap: true,
|
||||||
|
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
SizedBox(
|
||||||
|
height: Constant.getActualY(context: context, y: 12),
|
||||||
|
),
|
||||||
|
displayDetailText(context, "No. Surat Jalan",
|
||||||
|
detailData.value.noSuratJalan.toString()),
|
||||||
|
SizedBox(
|
||||||
|
height: Constant.getActualY(context: context, y: 12),
|
||||||
|
),
|
||||||
|
displayDetailText(
|
||||||
|
context, "Nama", detailData.value.nama.toString()),
|
||||||
|
SizedBox(
|
||||||
|
height: Constant.getActualY(context: context, y: 12),
|
||||||
|
),
|
||||||
|
if (int.parse(prop.tipeId) == 1)
|
||||||
|
Container(
|
||||||
|
margin: EdgeInsets.only(
|
||||||
|
bottom:
|
||||||
|
Constant.getActualY(context: context, y: 12),
|
||||||
|
),
|
||||||
|
child: displayDetailText(context, "Catatan FO",
|
||||||
|
detailData.value.foNote ?? ""),
|
||||||
|
),
|
||||||
|
if (int.parse(prop.tipeId) == 1 ||
|
||||||
|
int.parse(prop.tipeId) == 2 ||
|
||||||
|
int.parse(prop.tipeId) == 3 ||
|
||||||
|
int.parse(prop.tipeId) == 4 ||
|
||||||
|
int.parse(prop.tipeId) == 5)
|
||||||
|
displayDetailText(context, "Catatan Admin",
|
||||||
|
detailData.value.adminNote ?? ""),
|
||||||
|
SizedBox(
|
||||||
|
height: Constant.getActualY(context: context, y: 12),
|
||||||
|
),
|
||||||
|
if (int.parse(prop.tipeId) == 1 ||
|
||||||
|
int.parse(prop.tipeId) == 2 ||
|
||||||
|
int.parse(prop.tipeId) == 3)
|
||||||
|
Text(
|
||||||
|
"Pengambilan Hasil",
|
||||||
|
// maxLines: 5,
|
||||||
|
overflow: TextOverflow.visible,
|
||||||
|
style: Constant.body1(context: context).copyWith(
|
||||||
|
fontWeight: FontWeight.w600,
|
||||||
|
color: Constant.textPrimary),
|
||||||
|
),
|
||||||
|
if (int.parse(prop.tipeId) == 5)
|
||||||
|
Text(
|
||||||
|
"Pengambilan Bahan",
|
||||||
|
// maxLines: 5,
|
||||||
|
overflow: TextOverflow.visible,
|
||||||
|
style: Constant.body1(context: context).copyWith(
|
||||||
|
fontWeight: FontWeight.w600,
|
||||||
|
color: Constant.textPrimary),
|
||||||
|
),
|
||||||
|
if (int.parse(prop.tipeId) == 4)
|
||||||
|
Text(
|
||||||
|
"Pengirim",
|
||||||
|
// maxLines: 5,
|
||||||
|
overflow: TextOverflow.visible,
|
||||||
|
style: Constant.body1(context: context).copyWith(
|
||||||
|
fontWeight: FontWeight.w600,
|
||||||
|
color: Constant.textPrimary),
|
||||||
|
),
|
||||||
|
SizedBox(
|
||||||
|
height: Constant.getActualY(context: context, y: 12),
|
||||||
|
),
|
||||||
|
Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.start,
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Expanded(
|
||||||
|
child: Text(
|
||||||
|
"Alamat Pengambilan",
|
||||||
|
style: Constant.body1(context: context)
|
||||||
|
.copyWith(
|
||||||
|
fontWeight: FontWeight.w400,
|
||||||
|
color: Constant.textPrimary),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Expanded(
|
||||||
|
child: Text(
|
||||||
|
": ${detailData.value.alamatPengambilan}",
|
||||||
|
maxLines: 2,
|
||||||
|
overflow: TextOverflow.ellipsis,
|
||||||
|
style: Constant.body1(context: context)
|
||||||
|
.copyWith(
|
||||||
|
fontWeight: FontWeight.w400,
|
||||||
|
color: Constant.textPrimary),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
SizedBox(
|
||||||
|
height: Constant.getActualY(context: context, y: 12),
|
||||||
|
),
|
||||||
|
Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
|
children: [
|
||||||
|
Row(
|
||||||
|
children: [
|
||||||
|
if (pengambilanAwalLoc.value["lat"] == "" ||
|
||||||
|
pengambilanAwalLoc.value['long'] == "")
|
||||||
|
Icon(Icons.location_on,
|
||||||
|
color: Constant.primaryBlue),
|
||||||
|
if (pengambilanAwalLoc.value["lat"] == "" ||
|
||||||
|
pengambilanAwalLoc.value['long'] == "")
|
||||||
|
SizedBox(
|
||||||
|
width: Constant.getActualX(
|
||||||
|
context: context, x: 4),
|
||||||
|
),
|
||||||
|
Text(
|
||||||
|
"Lokasi Awal",
|
||||||
|
style: Constant.body1(context: context)
|
||||||
|
.copyWith(
|
||||||
|
fontWeight: FontWeight.w400,
|
||||||
|
color: Constant.textPrimary),
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
if (pengambilanAwalLoc.value["lat"] != "" ||
|
||||||
|
pengambilanAwalLoc.value['long'] != "")
|
||||||
|
InkWell(
|
||||||
|
onTap: () {
|
||||||
|
MapsLauncher.launchCoordinates(
|
||||||
|
double.parse(
|
||||||
|
pengambilanAwalLoc.value["lat"]!),
|
||||||
|
double.parse(
|
||||||
|
pengambilanAwalLoc.value["long"]!));
|
||||||
|
},
|
||||||
|
child: Row(
|
||||||
|
children: [
|
||||||
|
Text(
|
||||||
|
"Sudah ditandai",
|
||||||
|
style: Constant.body1(context: context)
|
||||||
|
.copyWith(
|
||||||
|
fontWeight: FontWeight.w600,
|
||||||
|
color: Constant.primaryBlue),
|
||||||
|
),
|
||||||
|
SizedBox(
|
||||||
|
width: Constant.getActualX(
|
||||||
|
context: context, x: 4),
|
||||||
|
),
|
||||||
|
Icon(
|
||||||
|
Icons.map_outlined,
|
||||||
|
color: Constant.primaryBlue,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
SizedBox(
|
||||||
|
height: Constant.getActualY(context: context, y: 12),
|
||||||
|
),
|
||||||
|
Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
|
children: [
|
||||||
|
Row(
|
||||||
|
children: [
|
||||||
|
if (pengambilanAkhirLoc.value["lat"] == "" ||
|
||||||
|
pengambilanAkhirLoc.value['long'] == "")
|
||||||
|
Icon(
|
||||||
|
Icons.location_on,
|
||||||
|
color: Constant.primaryBlue,
|
||||||
|
),
|
||||||
|
if (pengambilanAkhirLoc.value["lat"] == "" ||
|
||||||
|
pengambilanAkhirLoc.value['long'] == "")
|
||||||
|
SizedBox(
|
||||||
|
width: Constant.getActualX(
|
||||||
|
context: context, x: 4),
|
||||||
|
),
|
||||||
|
Text(
|
||||||
|
"Lokasi Akhir",
|
||||||
|
style: Constant.body1(context: context)
|
||||||
|
.copyWith(
|
||||||
|
fontWeight: FontWeight.w400,
|
||||||
|
color: Constant.textPrimary),
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
if (pengambilanAkhirLoc.value["lat"] != "" ||
|
||||||
|
pengambilanAkhirLoc.value['long'] != "")
|
||||||
|
InkWell(
|
||||||
|
onTap: () {
|
||||||
|
MapsLauncher.launchCoordinates(
|
||||||
|
double.parse(
|
||||||
|
pengambilanAkhirLoc.value["lat"]!),
|
||||||
|
double.parse(
|
||||||
|
pengambilanAkhirLoc.value["long"]!));
|
||||||
|
},
|
||||||
|
child: Row(
|
||||||
|
children: [
|
||||||
|
Text(
|
||||||
|
"Sudah ditandai",
|
||||||
|
style: Constant.body1(context: context)
|
||||||
|
.copyWith(
|
||||||
|
fontWeight: FontWeight.w600,
|
||||||
|
color: Constant.primaryBlue),
|
||||||
|
),
|
||||||
|
SizedBox(
|
||||||
|
width: Constant.getActualX(
|
||||||
|
context: context, x: 4),
|
||||||
|
),
|
||||||
|
Icon(
|
||||||
|
Icons.map_outlined,
|
||||||
|
color: Constant.primaryBlue,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
if (petugasPengambilan.value.isNotEmpty ||
|
||||||
|
catatanPengambilan.value.isNotEmpty)
|
||||||
|
SizedBox(
|
||||||
|
height:
|
||||||
|
Constant.getActualY(context: context, y: 12),
|
||||||
|
),
|
||||||
|
if (petugasPengambilan.value.isNotEmpty ||
|
||||||
|
catatanPengambilan.value.isNotEmpty)
|
||||||
|
Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.start,
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Expanded(
|
||||||
|
child: Text(
|
||||||
|
"Petugas Penyerahan",
|
||||||
|
style: Constant.body1(context: context)
|
||||||
|
.copyWith(
|
||||||
|
fontWeight: FontWeight.w400,
|
||||||
|
color: Constant.textPrimary),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Expanded(
|
||||||
|
child: Text(
|
||||||
|
" : ${petugasPengambilan.value}",
|
||||||
|
maxLines: 2,
|
||||||
|
overflow: TextOverflow.ellipsis,
|
||||||
|
style: Constant.body1(context: context)
|
||||||
|
.copyWith(
|
||||||
|
fontWeight: FontWeight.w400,
|
||||||
|
color: Constant.textPrimary),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
if (petugasPengambilan.value.isNotEmpty ||
|
||||||
|
catatanPengambilan.value.isNotEmpty)
|
||||||
|
SizedBox(
|
||||||
|
height:
|
||||||
|
Constant.getActualY(context: context, y: 12),
|
||||||
|
),
|
||||||
|
if (petugasPengambilan.value.isNotEmpty ||
|
||||||
|
catatanPengambilan.value.isNotEmpty)
|
||||||
|
Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.start,
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Expanded(
|
||||||
|
child: Text(
|
||||||
|
"Catatan",
|
||||||
|
style: Constant.body1(context: context)
|
||||||
|
.copyWith(
|
||||||
|
fontWeight: FontWeight.w400,
|
||||||
|
color: Constant.textPrimary),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Expanded(
|
||||||
|
child: Text(
|
||||||
|
" : ${catatanPengambilan.value} ",
|
||||||
|
overflow: TextOverflow.visible,
|
||||||
|
style: Constant.body1(context: context)
|
||||||
|
.copyWith(
|
||||||
|
fontWeight: FontWeight.w400,
|
||||||
|
color: Constant.textPrimary),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
SizedBox(
|
||||||
|
height: Constant.getActualY(context: context, y: 12),
|
||||||
|
),
|
||||||
|
if (int.parse(prop.tipeId) == 1 ||
|
||||||
|
int.parse(prop.tipeId) == 2 ||
|
||||||
|
int.parse(prop.tipeId) == 3)
|
||||||
|
Text(
|
||||||
|
"Pengantaran Hasil",
|
||||||
|
// maxLines: 5,
|
||||||
|
overflow: TextOverflow.visible,
|
||||||
|
style: Constant.body1(context: context).copyWith(
|
||||||
|
fontWeight: FontWeight.w600,
|
||||||
|
color: Constant.textPrimary),
|
||||||
|
),
|
||||||
|
if (int.parse(prop.tipeId) == 5)
|
||||||
|
Text(
|
||||||
|
"Pengantaran Bahan",
|
||||||
|
// maxLines: 5,
|
||||||
|
overflow: TextOverflow.visible,
|
||||||
|
style: Constant.body1(context: context).copyWith(
|
||||||
|
fontWeight: FontWeight.w600,
|
||||||
|
color: Constant.textPrimary),
|
||||||
|
),
|
||||||
|
if (int.parse(prop.tipeId) == 4)
|
||||||
|
Text(
|
||||||
|
"Penerima",
|
||||||
|
// maxLines: 5,
|
||||||
|
overflow: TextOverflow.visible,
|
||||||
|
style: Constant.body1(context: context).copyWith(
|
||||||
|
fontWeight: FontWeight.w600,
|
||||||
|
color: Constant.textPrimary),
|
||||||
|
),
|
||||||
|
SizedBox(
|
||||||
|
height: Constant.getActualY(context: context, y: 12),
|
||||||
|
),
|
||||||
|
Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.start,
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Expanded(
|
||||||
|
child: Text(
|
||||||
|
"Alamat Pengantaran",
|
||||||
|
style: Constant.body1(context: context)
|
||||||
|
.copyWith(
|
||||||
|
fontWeight: FontWeight.w400,
|
||||||
|
color: Constant.textPrimary),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Expanded(
|
||||||
|
child: Text(
|
||||||
|
": ${detailData.value.alamatPengantaran}",
|
||||||
|
maxLines: 2,
|
||||||
|
overflow: TextOverflow.ellipsis,
|
||||||
|
style: Constant.body1(context: context)
|
||||||
|
.copyWith(
|
||||||
|
fontWeight: FontWeight.w400,
|
||||||
|
color: Constant.textPrimary),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
SizedBox(
|
||||||
|
height: Constant.getActualY(context: context, y: 12),
|
||||||
|
),
|
||||||
|
Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
|
children: [
|
||||||
|
Row(
|
||||||
|
children: [
|
||||||
|
if (pengantaranAwalLoc.value["lat"] == "" ||
|
||||||
|
pengantaranAwalLoc.value['long'] == "")
|
||||||
|
Icon(
|
||||||
|
Icons.location_on,
|
||||||
|
color: Constant.primaryBlue,
|
||||||
|
),
|
||||||
|
if (pengantaranAwalLoc.value["lat"] == "" ||
|
||||||
|
pengantaranAwalLoc.value['long'] == "")
|
||||||
|
SizedBox(
|
||||||
|
width: Constant.getActualX(
|
||||||
|
context: context, x: 4),
|
||||||
|
),
|
||||||
|
Text(
|
||||||
|
"Lokasi Awal",
|
||||||
|
style: Constant.body1(context: context)
|
||||||
|
.copyWith(
|
||||||
|
fontWeight: FontWeight.w400,
|
||||||
|
color: Constant.textPrimary),
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
if (pengantaranAwalLoc.value["lat"] != "" ||
|
||||||
|
pengantaranAwalLoc.value['long'] != "")
|
||||||
|
InkWell(
|
||||||
|
onTap: () {
|
||||||
|
MapsLauncher.launchCoordinates(
|
||||||
|
double.parse(
|
||||||
|
pengantaranAwalLoc.value["lat"]!),
|
||||||
|
double.parse(
|
||||||
|
pengantaranAwalLoc.value["long"]!));
|
||||||
|
},
|
||||||
|
child: Row(
|
||||||
|
children: [
|
||||||
|
Text(
|
||||||
|
"Sudah ditandai",
|
||||||
|
style: Constant.body1(context: context)
|
||||||
|
.copyWith(
|
||||||
|
fontWeight: FontWeight.w600,
|
||||||
|
color: Constant.primaryBlue),
|
||||||
|
),
|
||||||
|
SizedBox(
|
||||||
|
width: Constant.getActualX(
|
||||||
|
context: context, x: 4),
|
||||||
|
),
|
||||||
|
Icon(
|
||||||
|
Icons.map_outlined,
|
||||||
|
color: Constant.primaryBlue,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
SizedBox(
|
||||||
|
height: Constant.getActualY(context: context, y: 12),
|
||||||
|
),
|
||||||
|
Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
|
children: [
|
||||||
|
Row(
|
||||||
|
children: [
|
||||||
|
if (pengantaranAkhirLoc.value["lat"] == "" ||
|
||||||
|
pengantaranAkhirLoc.value['long'] == "")
|
||||||
|
Icon(
|
||||||
|
Icons.location_on,
|
||||||
|
color: Constant.primaryBlue,
|
||||||
|
),
|
||||||
|
if (pengantaranAkhirLoc.value["lat"] == "" ||
|
||||||
|
pengantaranAkhirLoc.value['long'] == "")
|
||||||
|
SizedBox(
|
||||||
|
width: Constant.getActualX(
|
||||||
|
context: context, x: 4),
|
||||||
|
),
|
||||||
|
Text(
|
||||||
|
"Lokasi Akhir",
|
||||||
|
style: Constant.body1(context: context)
|
||||||
|
.copyWith(
|
||||||
|
fontWeight: FontWeight.w400,
|
||||||
|
color: Constant.textPrimary),
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
if (pengantaranAkhirLoc.value["lat"] != "" ||
|
||||||
|
pengantaranAkhirLoc.value['long'] != "")
|
||||||
|
InkWell(
|
||||||
|
onTap: () {
|
||||||
|
MapsLauncher.launchCoordinates(
|
||||||
|
double.parse(
|
||||||
|
pengantaranAkhirLoc.value["lat"]!),
|
||||||
|
double.parse(
|
||||||
|
pengantaranAkhirLoc.value["long"]!));
|
||||||
|
},
|
||||||
|
child: Row(
|
||||||
|
children: [
|
||||||
|
Text(
|
||||||
|
"Sudah ditandai",
|
||||||
|
style: Constant.body1(context: context)
|
||||||
|
.copyWith(
|
||||||
|
fontWeight: FontWeight.w600,
|
||||||
|
color: Constant.primaryBlue),
|
||||||
|
),
|
||||||
|
SizedBox(
|
||||||
|
width: Constant.getActualX(
|
||||||
|
context: context, x: 4),
|
||||||
|
),
|
||||||
|
Icon(
|
||||||
|
Icons.map_outlined,
|
||||||
|
color: Constant.primaryBlue,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
if (petugasPengantaran.value.isNotEmpty ||
|
||||||
|
catatanPengantaran.value.isNotEmpty)
|
||||||
|
SizedBox(
|
||||||
|
height:
|
||||||
|
Constant.getActualY(context: context, y: 12),
|
||||||
|
),
|
||||||
|
if (petugasPengantaran.value.isNotEmpty ||
|
||||||
|
catatanPengantaran.value.isNotEmpty)
|
||||||
|
Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.start,
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Expanded(
|
||||||
|
child: Text(
|
||||||
|
"Penerima",
|
||||||
|
style: Constant.body1(context: context)
|
||||||
|
.copyWith(
|
||||||
|
fontWeight: FontWeight.w400,
|
||||||
|
color: Constant.textPrimary),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Expanded(
|
||||||
|
child: Text(
|
||||||
|
" : ${petugasPengantaran.value}",
|
||||||
|
maxLines: 2,
|
||||||
|
overflow: TextOverflow.ellipsis,
|
||||||
|
style: Constant.body1(context: context)
|
||||||
|
.copyWith(
|
||||||
|
fontWeight: FontWeight.w400,
|
||||||
|
color: Constant.textPrimary),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
if (petugasPengantaran.value.isNotEmpty ||
|
||||||
|
catatanPengantaran.value.isNotEmpty)
|
||||||
|
SizedBox(
|
||||||
|
height:
|
||||||
|
Constant.getActualY(context: context, y: 12),
|
||||||
|
),
|
||||||
|
if (petugasPengantaran.value.isNotEmpty ||
|
||||||
|
catatanPengantaran.value.isNotEmpty)
|
||||||
|
Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.start,
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Expanded(
|
||||||
|
child: Text(
|
||||||
|
"Catatan",
|
||||||
|
style: Constant.body1(context: context)
|
||||||
|
.copyWith(
|
||||||
|
fontWeight: FontWeight.w400,
|
||||||
|
color: Constant.textPrimary),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Expanded(
|
||||||
|
child: Text(
|
||||||
|
" : ${catatanPengantaran.value} ",
|
||||||
|
overflow: TextOverflow.visible,
|
||||||
|
style: Constant.body1(context: context)
|
||||||
|
.copyWith(
|
||||||
|
fontWeight: FontWeight.w400,
|
||||||
|
color: Constant.textPrimary),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
SizedBox(
|
||||||
|
height: Constant.getActualY(context: context, y: 14),
|
||||||
|
),
|
||||||
|
Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
|
children: [
|
||||||
|
Text(
|
||||||
|
"Total Jarak",
|
||||||
|
style: Constant.heading4(context: context)
|
||||||
|
.copyWith(
|
||||||
|
fontWeight: FontWeight.w600,
|
||||||
|
color: Constant.textPrimary),
|
||||||
|
),
|
||||||
|
Text(
|
||||||
|
" ${detailData.value.distance ?? ''} KM",
|
||||||
|
overflow: TextOverflow.visible,
|
||||||
|
style: Constant.heading3(context: context)
|
||||||
|
.copyWith(
|
||||||
|
fontWeight: FontWeight.w600,
|
||||||
|
color: Constant.textPrimary),
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
if (detailData.value.patients != null)
|
||||||
|
ExpansionTile(
|
||||||
|
tilePadding: EdgeInsets.symmetric(horizontal: 0),
|
||||||
|
title: Text(
|
||||||
|
"List (${detailData.value.patients?.length} pasien)",
|
||||||
|
style: Constant.body1(context: context)
|
||||||
|
.copyWith(fontWeight: FontWeight.w400),
|
||||||
|
),
|
||||||
|
children: detailData.value.patients!
|
||||||
|
.map((e) => PatientCard(
|
||||||
|
name: e.pasien.toString(),
|
||||||
|
noLab: e.tOrderHeaderLabNumber.toString(),
|
||||||
|
note: e.courierConfirmNote ?? "",
|
||||||
|
))
|
||||||
|
.toList(),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
]),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget displayDetailText(BuildContext context, String teks, String value) {
|
||||||
|
return Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.start,
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Expanded(
|
||||||
|
child: Text(
|
||||||
|
teks,
|
||||||
|
style: Constant.heading4(context: context).copyWith(
|
||||||
|
fontWeight: FontWeight.w600, color: Constant.textPrimary),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Expanded(
|
||||||
|
child: Text(
|
||||||
|
" : ${value}",
|
||||||
|
maxLines: 2,
|
||||||
|
overflow: TextOverflow.ellipsis,
|
||||||
|
style: Constant.heading4(context: context).copyWith(
|
||||||
|
fontWeight: FontWeight.w600, color: Constant.textPrimary),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget headerCard(
|
||||||
|
BuildContext context, Color bgColor, String teks, Color textColor) {
|
||||||
|
return Container(
|
||||||
|
height: Constant.getActualY(context: context, y: 44),
|
||||||
|
decoration:
|
||||||
|
BoxDecoration(color: bgColor, borderRadius: BorderRadius.circular(8)),
|
||||||
|
child: Align(
|
||||||
|
child: Text(
|
||||||
|
"${teks}",
|
||||||
|
style: Constant.heading4(context: context)
|
||||||
|
.copyWith(fontWeight: FontWeight.w600, color: textColor),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
207
lib/screen/history_screen/history_list_card.dart
Normal file
@@ -0,0 +1,207 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||||
|
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||||
|
import '/models/history_model.dart';
|
||||||
|
import '/screen/detail_history_screen/detail_history_screen.dart';
|
||||||
|
import '/widget/chip_type.dart';
|
||||||
|
import 'package:intl/intl.dart';
|
||||||
|
|
||||||
|
import '../../app/constant.dart';
|
||||||
|
import '../../provider/current_user_provider.dart';
|
||||||
|
|
||||||
|
class HistoryListCard extends HookConsumerWidget {
|
||||||
|
const HistoryListCard({
|
||||||
|
super.key,
|
||||||
|
required this.ListRiwayat,
|
||||||
|
});
|
||||||
|
|
||||||
|
final List<HistoryModel> ListRiwayat;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context, WidgetRef ref) {
|
||||||
|
final mCourirID =
|
||||||
|
ref.watch(currentUserProvider)?.model.user?.mCourierID ?? "0";
|
||||||
|
return ListView.builder(
|
||||||
|
itemCount: ListRiwayat.length,
|
||||||
|
itemBuilder: (context, index) {
|
||||||
|
var data = ListRiwayat[index];
|
||||||
|
String originalDateString = data.cdate.toString();
|
||||||
|
DateTime originalDate =
|
||||||
|
DateFormat('dd-MM-yyyy HH:mm:ss').parse(originalDateString);
|
||||||
|
// String formattedDate = DateFormat.yMMMMd('id').format(originalDate);
|
||||||
|
String formattedDate = DateFormat('d MMM HH:mm').format(originalDate);
|
||||||
|
// Output: 30 Mei 2023
|
||||||
|
return Container(
|
||||||
|
margin: EdgeInsets.only(
|
||||||
|
top: Constant.getActualY(context: context, y: 24)),
|
||||||
|
padding: EdgeInsets.symmetric(
|
||||||
|
horizontal: Constant.getActualX(context: context, x: 31)),
|
||||||
|
child: ElevatedButton(
|
||||||
|
onPressed: () {
|
||||||
|
showModalBottomSheet(
|
||||||
|
enableDrag: true,
|
||||||
|
isScrollControlled: true,
|
||||||
|
shape: const RoundedRectangleBorder(
|
||||||
|
borderRadius: BorderRadius.only(
|
||||||
|
topLeft: Radius.circular(16),
|
||||||
|
topRight: Radius.circular(16)),
|
||||||
|
),
|
||||||
|
backgroundColor: Theme.of(context).scaffoldBackgroundColor,
|
||||||
|
context: context,
|
||||||
|
builder: (context) {
|
||||||
|
return DraggableScrollableSheet(
|
||||||
|
initialChildSize: 0.9,
|
||||||
|
maxChildSize: 0.95,
|
||||||
|
minChildSize: 0.5,
|
||||||
|
expand: false,
|
||||||
|
builder: (_, scrollController) => Stack(
|
||||||
|
children: [
|
||||||
|
Container(
|
||||||
|
padding: EdgeInsets.symmetric(
|
||||||
|
horizontal: Constant.getActualX(
|
||||||
|
context: context, x: 125)),
|
||||||
|
child: Divider(
|
||||||
|
thickness: 3,
|
||||||
|
color: Constant.textPrimary,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
SingleChildScrollView(
|
||||||
|
controller: scrollController,
|
||||||
|
child: DetailHistoryScreen(
|
||||||
|
data: {
|
||||||
|
"id": "1",
|
||||||
|
"alamat": "Cabang Kertajaya",
|
||||||
|
"jarak": "1,2 KM",
|
||||||
|
"tanggal": "02 Desember 14:50",
|
||||||
|
"tipe": "Pengantaran hasil Instansi",
|
||||||
|
"tipe_id": 4
|
||||||
|
},
|
||||||
|
prop: DetailHistoryProp(
|
||||||
|
data.tipeid.toString(),
|
||||||
|
mCourirID,
|
||||||
|
data.id.toString()),
|
||||||
|
)),
|
||||||
|
],
|
||||||
|
));
|
||||||
|
},
|
||||||
|
);
|
||||||
|
},
|
||||||
|
style: ElevatedButton.styleFrom(
|
||||||
|
padding: const EdgeInsets.all(10),
|
||||||
|
elevation: 0,
|
||||||
|
shape: RoundedRectangleBorder(
|
||||||
|
borderRadius: BorderRadius.all(Radius.circular(16))),
|
||||||
|
backgroundColor: data.ispending == 'N'
|
||||||
|
? Constant.historyCardColor
|
||||||
|
: Constant.historyCardColorPending,
|
||||||
|
foregroundColor: Colors.grey),
|
||||||
|
child: Column(
|
||||||
|
children: [
|
||||||
|
SizedBox(
|
||||||
|
height: Constant.getActualY(context: context, y: 14),
|
||||||
|
),
|
||||||
|
Row(
|
||||||
|
children: [
|
||||||
|
Image.asset(
|
||||||
|
"assets/icon_riwayat_motor.png",
|
||||||
|
width: Constant.getActualX(context: context, x: 64),
|
||||||
|
height: Constant.getActualX(context: context, x: 64),
|
||||||
|
),
|
||||||
|
SizedBox(
|
||||||
|
width: Constant.getActualX(context: context, x: 12),
|
||||||
|
),
|
||||||
|
Container(
|
||||||
|
height: Constant.getActualX(context: context, x: 70),
|
||||||
|
width: Constant.getActualX(context: context, x: 232),
|
||||||
|
child: Column(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.end,
|
||||||
|
children: [
|
||||||
|
Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.end,
|
||||||
|
children: [
|
||||||
|
Container(
|
||||||
|
constraints: BoxConstraints(
|
||||||
|
maxWidth: Constant.getActualX(
|
||||||
|
context: context, x: 130)),
|
||||||
|
child: Column(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.start,
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Text(
|
||||||
|
data.noSuratJalan.toString(),
|
||||||
|
textAlign: TextAlign.start,
|
||||||
|
style: Constant.caption1(context: context)
|
||||||
|
.copyWith(
|
||||||
|
fontWeight: FontWeight.w600,
|
||||||
|
color: Constant.primaryBlue),
|
||||||
|
),
|
||||||
|
Text(
|
||||||
|
data.nama.toString(),
|
||||||
|
maxLines: 2,
|
||||||
|
overflow: TextOverflow.ellipsis,
|
||||||
|
style: Constant.caption2(context: context)
|
||||||
|
.copyWith(
|
||||||
|
fontWeight: FontWeight.w600,
|
||||||
|
color: Constant.textBlack),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Container(
|
||||||
|
constraints: BoxConstraints(
|
||||||
|
maxWidth: Constant.getActualX(
|
||||||
|
context: context, x: 100)),
|
||||||
|
child: Text(
|
||||||
|
"${data.distance ?? '0'} Km",
|
||||||
|
style: Constant.heading3(context: context)
|
||||||
|
.copyWith(
|
||||||
|
fontWeight: FontWeight.w600,
|
||||||
|
color: Constant.textBlack),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
|
children: [
|
||||||
|
Expanded(
|
||||||
|
child: Text(
|
||||||
|
formattedDate,
|
||||||
|
maxLines: 2,
|
||||||
|
overflow: TextOverflow.ellipsis,
|
||||||
|
style: Constant.caption1(context: context)
|
||||||
|
.copyWith(
|
||||||
|
fontWeight: FontWeight.w500,
|
||||||
|
color: Constant.textBlack),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Container(
|
||||||
|
constraints: BoxConstraints(
|
||||||
|
maxWidth: Constant.getActualX(
|
||||||
|
context: context, x: 150)),
|
||||||
|
child: ChipType(
|
||||||
|
name: data.tipe.toString(),
|
||||||
|
tipe: data.tipeid!,
|
||||||
|
isDetailHistory: false,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
],
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
SizedBox(
|
||||||
|
height: Constant.getActualY(context: context, y: 14),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
69
lib/screen/history_screen/history_list_provider.dart
Normal file
@@ -0,0 +1,69 @@
|
|||||||
|
import 'package:equatable/equatable.dart';
|
||||||
|
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||||
|
import '/models/history_model.dart';
|
||||||
|
import '../../repository/history_screen_repository.dart';
|
||||||
|
import '/screen/history_screen/history_screen.dart';
|
||||||
|
|
||||||
|
import '../../models/pending_work_model.dart';
|
||||||
|
import '../../provider/dio_provider.dart';
|
||||||
|
import '../../repository/base_repository.dart';
|
||||||
|
import '../../repository/home_screen_repository.dart';
|
||||||
|
|
||||||
|
abstract class HistoryListState extends Equatable {
|
||||||
|
final DateTime date;
|
||||||
|
const HistoryListState(this.date);
|
||||||
|
@override
|
||||||
|
List<Object?> get props => [date];
|
||||||
|
}
|
||||||
|
|
||||||
|
class HistoryListStateInit extends HistoryListState {
|
||||||
|
HistoryListStateInit() : super(DateTime.now());
|
||||||
|
}
|
||||||
|
|
||||||
|
class HistoryListStateLoading extends HistoryListState {
|
||||||
|
HistoryListStateLoading() : super(DateTime.now());
|
||||||
|
}
|
||||||
|
|
||||||
|
class HistoryListStateError extends HistoryListState {
|
||||||
|
final String message;
|
||||||
|
HistoryListStateError({
|
||||||
|
required this.message,
|
||||||
|
}) : super(DateTime.now());
|
||||||
|
}
|
||||||
|
|
||||||
|
class HistoryListStateDone extends HistoryListState {
|
||||||
|
final List<HistoryModel> model;
|
||||||
|
HistoryListStateDone({
|
||||||
|
required this.model,
|
||||||
|
}) : super(DateTime.now());
|
||||||
|
}
|
||||||
|
|
||||||
|
//notifier
|
||||||
|
class HistoryListNotifier extends StateNotifier<HistoryListState> {
|
||||||
|
final Ref ref;
|
||||||
|
HistoryListNotifier({
|
||||||
|
required this.ref,
|
||||||
|
}) : super(HistoryListStateInit());
|
||||||
|
|
||||||
|
void getData(
|
||||||
|
{required String id, required String date, required String type}) async {
|
||||||
|
try {
|
||||||
|
state = HistoryListStateLoading();
|
||||||
|
final dio = ref.read(dioProvider);
|
||||||
|
final resp = await HistoryRepository(dio: dio)
|
||||||
|
.getData(date: date, id: id, type: type);
|
||||||
|
state = HistoryListStateDone(model: resp);
|
||||||
|
} catch (e) {
|
||||||
|
if (e is BaseRepositoryException) {
|
||||||
|
state = HistoryListStateError(message: e.message.toString());
|
||||||
|
} else {
|
||||||
|
state = HistoryListStateError(message: e.toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//provider
|
||||||
|
final HistoryListProvider =
|
||||||
|
StateNotifierProvider<HistoryListNotifier, HistoryListState>(
|
||||||
|
(ref) => HistoryListNotifier(ref: ref));
|
||||||
466
lib/screen/history_screen/history_screen.dart
Normal file
@@ -0,0 +1,466 @@
|
|||||||
|
import 'dart:async';
|
||||||
|
import 'dart:convert';
|
||||||
|
|
||||||
|
import 'package:dropdown_button2/dropdown_button2.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_hooks/flutter_hooks.dart';
|
||||||
|
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||||
|
import 'package:intl/intl.dart';
|
||||||
|
import '/models/history_model.dart';
|
||||||
|
import '/models/history_type_model.dart';
|
||||||
|
import '/provider/history_filter_provider.dart';
|
||||||
|
import '/screen/history_screen/history_list_card.dart';
|
||||||
|
import '/screen/history_screen/history_list_provider.dart';
|
||||||
|
import '/screen/history_screen/history_type_provider.dart';
|
||||||
|
import 'package:loading_animation_widget/loading_animation_widget.dart';
|
||||||
|
// import 'package:eva_icons_flutter/eva_icons_flutter.dart';
|
||||||
|
|
||||||
|
import '../../app/constant.dart';
|
||||||
|
import '../../provider/current_user_provider.dart';
|
||||||
|
import '../../widget/header_widget.dart';
|
||||||
|
import '../../widget/snackbar_widget.dart';
|
||||||
|
|
||||||
|
class HistoryScreen extends HookConsumerWidget {
|
||||||
|
const HistoryScreen({super.key});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context, WidgetRef ref) {
|
||||||
|
final historyListData = useState<List<HistoryModel>>([]);
|
||||||
|
final historyListLoading = useState(false);
|
||||||
|
final isMounted = useIsMounted();
|
||||||
|
final mCourirID =
|
||||||
|
ref.watch(currentUserProvider)?.model.user?.mCourierID ?? "0";
|
||||||
|
final dateFilter =
|
||||||
|
DateFormat('d MMM y').format(ref.watch(dateFilterProvider));
|
||||||
|
final SelectedTypeFilter = ref.watch(selectedTypeProvider);
|
||||||
|
|
||||||
|
fetchData() {
|
||||||
|
ref.read(HistoryListProvider.notifier).getData(
|
||||||
|
id: mCourirID,
|
||||||
|
date: DateFormat('dd-MM-yyyy').format(ref.watch(dateFilterProvider)),
|
||||||
|
type: SelectedTypeFilter.tipeid.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
final dateInput = useTextEditingController(
|
||||||
|
text: DateFormat('yyyy-MM-dd').format(DateTime.now()));
|
||||||
|
|
||||||
|
// ref.watch(dateFilterProvider);
|
||||||
|
|
||||||
|
ref.listen<HistoryListState>(
|
||||||
|
HistoryListProvider,
|
||||||
|
(previous, next) {
|
||||||
|
if (next is HistoryListStateLoading) {
|
||||||
|
historyListLoading.value = true;
|
||||||
|
} else if (next is HistoryListStateError) {
|
||||||
|
print(next.message);
|
||||||
|
historyListLoading.value = false;
|
||||||
|
SanckbarWidget(context, next.message, snackbarType.error);
|
||||||
|
} else if (next is HistoryListStateDone) {
|
||||||
|
print(next.model);
|
||||||
|
historyListData.value = next.model;
|
||||||
|
historyListLoading.value = false;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
);
|
||||||
|
useEffect(() {
|
||||||
|
// final cancellationSource = CancellationSource();
|
||||||
|
if (isMounted.call()) {
|
||||||
|
WidgetsBinding.instance.addPostFrameCallback((timeStamp) async {
|
||||||
|
fetchData();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return () {};
|
||||||
|
}, []);
|
||||||
|
return RefreshIndicator(
|
||||||
|
onRefresh: () async {
|
||||||
|
fetchData();
|
||||||
|
},
|
||||||
|
child: Container(
|
||||||
|
// color: const Color(0XFFF4F6F8),
|
||||||
|
child: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Container(
|
||||||
|
color: Colors.white,
|
||||||
|
height: Constant.getActualY(context: context, y: 56),
|
||||||
|
),
|
||||||
|
HeaderWidget(teks: "Riwayat"),
|
||||||
|
SizedBox(
|
||||||
|
height: Constant.getActualY(context: context, y: 24),
|
||||||
|
),
|
||||||
|
Container(
|
||||||
|
width: double.infinity,
|
||||||
|
margin: EdgeInsets.only(
|
||||||
|
left: Constant.getActualX(context: context, x: 31),
|
||||||
|
right: Constant.getActualX(context: context, x: 31)),
|
||||||
|
child: Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
|
children: [
|
||||||
|
Row(
|
||||||
|
children: [
|
||||||
|
Text(
|
||||||
|
SelectedTypeFilter.tipename.toString(),
|
||||||
|
style: Constant.body1(context: context)
|
||||||
|
.copyWith(fontWeight: FontWeight.w600),
|
||||||
|
),
|
||||||
|
SizedBox(
|
||||||
|
width: Constant.getActualX(context: context, x: 5),
|
||||||
|
),
|
||||||
|
Icon(
|
||||||
|
Icons.fiber_manual_record_rounded,
|
||||||
|
size: 9,
|
||||||
|
),
|
||||||
|
SizedBox(
|
||||||
|
width: Constant.getActualX(context: context, x: 5),
|
||||||
|
),
|
||||||
|
Chip(
|
||||||
|
label: Text(
|
||||||
|
dateFilter,
|
||||||
|
style: Constant.body3(context: context).copyWith(
|
||||||
|
fontWeight: FontWeight.w700,
|
||||||
|
color: Colors.grey.shade600),
|
||||||
|
),
|
||||||
|
shape: RoundedRectangleBorder(
|
||||||
|
borderRadius: BorderRadius.all(Radius.circular(6))),
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
InkWell(
|
||||||
|
onTap: () {
|
||||||
|
showModalBottomSheet<void>(
|
||||||
|
isScrollControlled: true,
|
||||||
|
context: context,
|
||||||
|
builder: (BuildContext context) {
|
||||||
|
return HookConsumer(
|
||||||
|
builder: (BuildContext context, WidgetRef ref, a) {
|
||||||
|
final typeLoading = useState(false);
|
||||||
|
final typeData =
|
||||||
|
useState<List<HistoryTypeModel>>(List.empty());
|
||||||
|
final dateCtr = useTextEditingController(
|
||||||
|
// d MMMM y'
|
||||||
|
text: DateFormat('yyyy-MM-dd')
|
||||||
|
.format(ref.read(dateFilterProvider)));
|
||||||
|
final selectedType = useState<HistoryTypeModel>(
|
||||||
|
ref.watch(selectedTypeProvider));
|
||||||
|
getData() {
|
||||||
|
ref
|
||||||
|
.read(HistoryTypeListProvider.notifier)
|
||||||
|
.getHistoryType();
|
||||||
|
}
|
||||||
|
|
||||||
|
useEffect(() {
|
||||||
|
WidgetsBinding.instance
|
||||||
|
.addPostFrameCallback((timeStamp) async {
|
||||||
|
getData();
|
||||||
|
});
|
||||||
|
|
||||||
|
return () {};
|
||||||
|
}, []);
|
||||||
|
ref.listen(HistoryTypeListProvider, (previous, next) {
|
||||||
|
if (next is HistoryTypeListStateInit) {
|
||||||
|
typeLoading.value = true;
|
||||||
|
} else if (next is HistoryTypeListStateLoading) {
|
||||||
|
typeLoading.value = true;
|
||||||
|
} else if (next is HistoryTypeListStateError) {
|
||||||
|
typeLoading.value = false;
|
||||||
|
} else if (next is HistoryTypeListStateDone) {
|
||||||
|
print(jsonEncode(next.model));
|
||||||
|
typeData.value = next.model;
|
||||||
|
typeLoading.value = false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return Container(
|
||||||
|
margin: EdgeInsets.symmetric(
|
||||||
|
horizontal: Constant.getActualX(
|
||||||
|
context: context, x: 31)),
|
||||||
|
height:
|
||||||
|
Constant.getActualY(context: context, y: 370),
|
||||||
|
child: Column(
|
||||||
|
// mainAxisAlignment: MainAxisAlignment.center,
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
children: <Widget>[
|
||||||
|
SizedBox(
|
||||||
|
height: Constant.getActualY(
|
||||||
|
context: context, y: 20),
|
||||||
|
),
|
||||||
|
SizedBox(
|
||||||
|
width: Constant.getActualX(
|
||||||
|
context: context, x: 100),
|
||||||
|
child: Divider(
|
||||||
|
color: Colors.grey,
|
||||||
|
height: 2,
|
||||||
|
thickness: 2,
|
||||||
|
)),
|
||||||
|
SizedBox(
|
||||||
|
height: Constant.getActualY(
|
||||||
|
context: context, y: 20),
|
||||||
|
),
|
||||||
|
Text(
|
||||||
|
"Filter",
|
||||||
|
style: Constant.heading3(context: context)
|
||||||
|
.copyWith(
|
||||||
|
fontWeight: FontWeight.w600,
|
||||||
|
color: Constant.primaryBlue),
|
||||||
|
),
|
||||||
|
SizedBox(
|
||||||
|
height: Constant.getActualY(
|
||||||
|
context: context, y: 20),
|
||||||
|
),
|
||||||
|
TextField(
|
||||||
|
controller: dateCtr,
|
||||||
|
decoration: InputDecoration(
|
||||||
|
suffixIcon: Icon(Icons.today_rounded),
|
||||||
|
border: OutlineInputBorder(
|
||||||
|
borderRadius: BorderRadius.all(
|
||||||
|
Radius.circular(8))),
|
||||||
|
labelText:
|
||||||
|
"Tanggal (yyyy-mm-dd)" //label text of field
|
||||||
|
),
|
||||||
|
readOnly: true,
|
||||||
|
onTap: () async {
|
||||||
|
DateTime? pickedDate = await showDatePicker(
|
||||||
|
context: context,
|
||||||
|
initialDate:
|
||||||
|
DateTime.parse(dateCtr.text),
|
||||||
|
// initialDate:
|
||||||
|
// DateTime.parse(dateCtr.text),
|
||||||
|
firstDate: DateTime(1950),
|
||||||
|
initialEntryMode:
|
||||||
|
DatePickerEntryMode.calendarOnly,
|
||||||
|
//DateTime.now() - not to allow to choose before today.
|
||||||
|
lastDate: DateTime(2100));
|
||||||
|
|
||||||
|
if (pickedDate != null) {
|
||||||
|
print(
|
||||||
|
pickedDate); //pickedDate output format => 2021-03-10 00:00:00.000
|
||||||
|
String formattedDate =
|
||||||
|
DateFormat('yyyy-MM-dd')
|
||||||
|
.format(pickedDate);
|
||||||
|
print(
|
||||||
|
formattedDate); //formatted date output using intl package => 2021-03-16
|
||||||
|
dateCtr.text =
|
||||||
|
formattedDate; //set output date to TextField value.
|
||||||
|
// ref
|
||||||
|
// .read(dateFilterProvider.notifier)
|
||||||
|
// .state = pickedDate;
|
||||||
|
} else {}
|
||||||
|
},
|
||||||
|
),
|
||||||
|
SizedBox(
|
||||||
|
height: Constant.getActualY(
|
||||||
|
context: context, y: 20),
|
||||||
|
),
|
||||||
|
Container(
|
||||||
|
// width: Constant.getActualX(
|
||||||
|
// context: context, x: 320),
|
||||||
|
// height: Constant.getActualY(
|
||||||
|
// context: context, y: 56),
|
||||||
|
child: DropdownButtonHideUnderline(
|
||||||
|
child: DropdownButton2<HistoryTypeModel>(
|
||||||
|
isExpanded: true,
|
||||||
|
hint: Row(
|
||||||
|
children: [
|
||||||
|
Expanded(
|
||||||
|
child: Text(
|
||||||
|
'Select Item',
|
||||||
|
style: Constant.body1(
|
||||||
|
context: context)
|
||||||
|
.copyWith(
|
||||||
|
fontWeight:
|
||||||
|
FontWeight.w600,
|
||||||
|
color:
|
||||||
|
Constant.primaryDark),
|
||||||
|
overflow: TextOverflow.ellipsis,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
items: typeData.value
|
||||||
|
.map((HistoryTypeModel option) {
|
||||||
|
return DropdownMenuItem<
|
||||||
|
HistoryTypeModel>(
|
||||||
|
value: option,
|
||||||
|
child: Text(
|
||||||
|
option.tipename.toString(),
|
||||||
|
style: Constant.body1(
|
||||||
|
context: context)
|
||||||
|
.copyWith(
|
||||||
|
color: Constant.textBlack,
|
||||||
|
fontWeight:
|
||||||
|
FontWeight.w600),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}).toList(),
|
||||||
|
value: selectedType.value,
|
||||||
|
onChanged: (HistoryTypeModel? newValue) {
|
||||||
|
selectedType.value = newValue!;
|
||||||
|
// if (newValue) {
|
||||||
|
// ref
|
||||||
|
// .read(selectedTypeProvider.notifier)
|
||||||
|
// .state = newValue!;
|
||||||
|
print(
|
||||||
|
"Branch ID Selected : ${selectedType.value.tipename}");
|
||||||
|
print(
|
||||||
|
"Branch Code Selected : ${selectedType.value.tipename}");
|
||||||
|
// }
|
||||||
|
},
|
||||||
|
buttonStyleData: ButtonStyleData(
|
||||||
|
padding: EdgeInsets.only(
|
||||||
|
left: Constant.getActualX(
|
||||||
|
context: context, x: 10),
|
||||||
|
right: Constant.getActualX(
|
||||||
|
context: context, x: 10),
|
||||||
|
),
|
||||||
|
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
// color: Colors.white,
|
||||||
|
border: Border.all(
|
||||||
|
color: Colors.grey.shade400),
|
||||||
|
|
||||||
|
borderRadius:
|
||||||
|
BorderRadius.circular(8),
|
||||||
|
),
|
||||||
|
// elevation: 2,
|
||||||
|
),
|
||||||
|
iconStyleData: IconStyleData(
|
||||||
|
icon: typeLoading.value
|
||||||
|
? LoadingAnimationWidget
|
||||||
|
.discreteCircle(
|
||||||
|
color: Constant.primaryBlue,
|
||||||
|
size: 20)
|
||||||
|
: Icon(
|
||||||
|
Icons
|
||||||
|
.keyboard_arrow_down_outlined,
|
||||||
|
),
|
||||||
|
iconSize: 24,
|
||||||
|
iconEnabledColor: Constant.textBlack,
|
||||||
|
iconDisabledColor: Colors.grey,
|
||||||
|
),
|
||||||
|
dropdownStyleData: DropdownStyleData(
|
||||||
|
maxHeight: Constant.getActualY(
|
||||||
|
context: context, y: 120),
|
||||||
|
width: Constant.getActualX(
|
||||||
|
context: context, x: 320),
|
||||||
|
padding: EdgeInsets.only(
|
||||||
|
top: Constant.getActualY(
|
||||||
|
context: context, y: 10),
|
||||||
|
left: Constant.getActualX(
|
||||||
|
context: context, x: 10),
|
||||||
|
right: Constant.getActualX(
|
||||||
|
context: context, x: 10),
|
||||||
|
bottom: Constant.getActualY(
|
||||||
|
context: context, y: 10),
|
||||||
|
),
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
// color: Constant.backgroundWhite,
|
||||||
|
borderRadius:
|
||||||
|
BorderRadius.circular(8),
|
||||||
|
),
|
||||||
|
// elevation: 8,
|
||||||
|
scrollbarTheme: ScrollbarThemeData(
|
||||||
|
radius: const Radius.circular(40),
|
||||||
|
thickness:
|
||||||
|
MaterialStateProperty.all<double>(
|
||||||
|
6),
|
||||||
|
thumbVisibility:
|
||||||
|
MaterialStateProperty.all<bool>(
|
||||||
|
true),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
menuItemStyleData: MenuItemStyleData(
|
||||||
|
height: Constant.getActualY(
|
||||||
|
context: context, y: 56),
|
||||||
|
padding: EdgeInsets.only(
|
||||||
|
top: Constant.getActualY(
|
||||||
|
context: context, y: 10),
|
||||||
|
left: Constant.getActualX(
|
||||||
|
context: context, x: 10),
|
||||||
|
right: Constant.getActualX(
|
||||||
|
context: context, x: 10),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
SizedBox(
|
||||||
|
height: Constant.getActualY(
|
||||||
|
context: context, y: 40),
|
||||||
|
),
|
||||||
|
Container(
|
||||||
|
width: double.infinity,
|
||||||
|
height: Constant.getActualY(
|
||||||
|
context: context, y: 48),
|
||||||
|
child: ElevatedButton(
|
||||||
|
onPressed: () {
|
||||||
|
ref
|
||||||
|
.read(selectedTypeProvider.notifier)
|
||||||
|
.state = selectedType.value;
|
||||||
|
ref
|
||||||
|
.read(dateFilterProvider.notifier)
|
||||||
|
.state = DateTime.parse(dateCtr.text);
|
||||||
|
ref
|
||||||
|
.read(HistoryListProvider.notifier)
|
||||||
|
.getData(
|
||||||
|
id: mCourirID,
|
||||||
|
date: DateFormat('dd-MM-yyyy')
|
||||||
|
.format(ref.watch(
|
||||||
|
dateFilterProvider)),
|
||||||
|
type: ref
|
||||||
|
.watch(selectedTypeProvider)
|
||||||
|
.tipeid!);
|
||||||
|
Navigator.pop(context);
|
||||||
|
},
|
||||||
|
child: Text(
|
||||||
|
"Cari",
|
||||||
|
style: Constant.heading3(context: context)
|
||||||
|
.copyWith(
|
||||||
|
fontWeight: FontWeight.w700),
|
||||||
|
),
|
||||||
|
style: ButtonStyle(
|
||||||
|
backgroundColor:
|
||||||
|
MaterialStateColor.resolveWith(
|
||||||
|
(st) => Constant.primaryBlue),
|
||||||
|
shape: MaterialStateProperty.all<
|
||||||
|
RoundedRectangleBorder>(
|
||||||
|
RoundedRectangleBorder(
|
||||||
|
borderRadius:
|
||||||
|
BorderRadius.circular(8),
|
||||||
|
// side: BorderSide(color: Colors.red),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
shadowColor: MaterialStateProperty.all(
|
||||||
|
const Color(0xffff48423d)),
|
||||||
|
elevation: MaterialStateProperty.all(4.0),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
);
|
||||||
|
},
|
||||||
|
child: Icon(
|
||||||
|
Icons.filter_alt_outlined,
|
||||||
|
size: 25,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Container(
|
||||||
|
// color: Colors.red,
|
||||||
|
height: Constant.getActualY(context: context, y: 588),
|
||||||
|
child: historyListLoading.value
|
||||||
|
? Center(
|
||||||
|
child: LoadingAnimationWidget.fourRotatingDots(
|
||||||
|
color: Constant.primaryBlue, size: 50),
|
||||||
|
)
|
||||||
|
: HistoryListCard(ListRiwayat: historyListData.value),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
)),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
68
lib/screen/history_screen/history_type_provider.dart
Normal file
@@ -0,0 +1,68 @@
|
|||||||
|
import 'package:equatable/equatable.dart';
|
||||||
|
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||||
|
import '/models/history_model.dart';
|
||||||
|
import '../../repository/history_screen_repository.dart';
|
||||||
|
import '/screen/history_screen/history_screen.dart';
|
||||||
|
|
||||||
|
import '../../models/history_type_model.dart';
|
||||||
|
import '../../models/pending_work_model.dart';
|
||||||
|
import '../../provider/dio_provider.dart';
|
||||||
|
import '../../repository/base_repository.dart';
|
||||||
|
import '../../repository/home_screen_repository.dart';
|
||||||
|
|
||||||
|
abstract class HistoryTypeListState extends Equatable {
|
||||||
|
final DateTime date;
|
||||||
|
const HistoryTypeListState(this.date);
|
||||||
|
@override
|
||||||
|
List<Object?> get props => [date];
|
||||||
|
}
|
||||||
|
|
||||||
|
class HistoryTypeListStateInit extends HistoryTypeListState {
|
||||||
|
HistoryTypeListStateInit() : super(DateTime.now());
|
||||||
|
}
|
||||||
|
|
||||||
|
class HistoryTypeListStateLoading extends HistoryTypeListState {
|
||||||
|
HistoryTypeListStateLoading() : super(DateTime.now());
|
||||||
|
}
|
||||||
|
|
||||||
|
class HistoryTypeListStateError extends HistoryTypeListState {
|
||||||
|
final String message;
|
||||||
|
HistoryTypeListStateError({
|
||||||
|
required this.message,
|
||||||
|
}) : super(DateTime.now());
|
||||||
|
}
|
||||||
|
|
||||||
|
class HistoryTypeListStateDone extends HistoryTypeListState {
|
||||||
|
final List<HistoryTypeModel> model;
|
||||||
|
HistoryTypeListStateDone({
|
||||||
|
required this.model,
|
||||||
|
}) : super(DateTime.now());
|
||||||
|
}
|
||||||
|
|
||||||
|
//notifier
|
||||||
|
class HistoryTypeListNotifier extends StateNotifier<HistoryTypeListState> {
|
||||||
|
final Ref ref;
|
||||||
|
HistoryTypeListNotifier({
|
||||||
|
required this.ref,
|
||||||
|
}) : super(HistoryTypeListStateInit());
|
||||||
|
|
||||||
|
void getHistoryType() async {
|
||||||
|
try {
|
||||||
|
state = HistoryTypeListStateLoading();
|
||||||
|
final dio = ref.read(dioProvider);
|
||||||
|
final resp = await HistoryRepository(dio: dio).getHistoryType();
|
||||||
|
state = HistoryTypeListStateDone(model: resp);
|
||||||
|
} catch (e) {
|
||||||
|
if (e is BaseRepositoryException) {
|
||||||
|
state = HistoryTypeListStateError(message: e.message.toString());
|
||||||
|
} else {
|
||||||
|
state = HistoryTypeListStateError(message: e.toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//provider
|
||||||
|
final HistoryTypeListProvider =
|
||||||
|
StateNotifierProvider<HistoryTypeListNotifier, HistoryTypeListState>(
|
||||||
|
(ref) => HistoryTypeListNotifier(ref: ref));
|
||||||
434
lib/screen/home_screen/home_screen.dart
Normal file
@@ -0,0 +1,434 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_hooks/flutter_hooks.dart';
|
||||||
|
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||||
|
import '/app/route.dart';
|
||||||
|
import '/screen/home_screen/pending_work_provider.dart';
|
||||||
|
import '/screen/home_screen/total_work_provider.dart';
|
||||||
|
import '/widget/information_rpt_card.dart';
|
||||||
|
import '/widget/pending_card.dart';
|
||||||
|
import 'package:loading_animation_widget/loading_animation_widget.dart';
|
||||||
|
|
||||||
|
import '../../app/constant.dart';
|
||||||
|
import '../../models/pending_work_model.dart';
|
||||||
|
import '../../models/work_total_model.dart';
|
||||||
|
import '../../provider/current_user_provider.dart';
|
||||||
|
import '../../widget/information_card.dart';
|
||||||
|
import '../../widget/snackbar_widget.dart';
|
||||||
|
import '../../widget/work_card.dart';
|
||||||
|
|
||||||
|
class HomeScreen extends HookConsumerWidget {
|
||||||
|
const HomeScreen({
|
||||||
|
super.key,
|
||||||
|
});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context, WidgetRef ref) {
|
||||||
|
final totalWork = useState<WorkTotalModel>(WorkTotalModel());
|
||||||
|
final totalWorkLoading = useState(false);
|
||||||
|
final pendingWork = useState<List<PendingWorkModel>>([]);
|
||||||
|
final pendingWorkLoading = useState(false);
|
||||||
|
final mUsername =
|
||||||
|
ref.watch(currentUserProvider)?.model.user?.mStaffName ?? "0";
|
||||||
|
|
||||||
|
final mCourirID =
|
||||||
|
ref.watch(currentUserProvider)?.model.user?.mCourierID ?? "0";
|
||||||
|
|
||||||
|
fetchData() {
|
||||||
|
// ref.read(TotalWorkProvider.notifier).getData(
|
||||||
|
// id: ref.watch(currentUserProvider)?.model.user?.mCourierID ?? "0");
|
||||||
|
ref.read(PendingWorkProvider.notifier).getData(
|
||||||
|
id: ref.watch(currentUserProvider)?.model.user?.mCourierID ?? "0");
|
||||||
|
}
|
||||||
|
|
||||||
|
useEffect(() {
|
||||||
|
WidgetsBinding.instance.addPostFrameCallback((timeStamp) async {
|
||||||
|
fetchData();
|
||||||
|
});
|
||||||
|
return () {};
|
||||||
|
}, [mCourirID]);
|
||||||
|
useEffect(() {
|
||||||
|
WidgetsBinding.instance.addPostFrameCallback((timeStamp) async {
|
||||||
|
fetchData();
|
||||||
|
});
|
||||||
|
return () {};
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
ref.listen(
|
||||||
|
TotalWorkProvider,
|
||||||
|
(previous, next) {
|
||||||
|
if (next is TotalWorkStateLoading) {
|
||||||
|
totalWorkLoading.value = true;
|
||||||
|
} else if (next is TotalWorkStateError) {
|
||||||
|
print(next.message);
|
||||||
|
totalWorkLoading.value = false;
|
||||||
|
SanckbarWidget(context, next.message, snackbarType.error);
|
||||||
|
} else if (next is TotalWorkStateDone) {
|
||||||
|
print(next.model);
|
||||||
|
totalWork.value = next.model;
|
||||||
|
totalWorkLoading.value = false;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
);
|
||||||
|
ref.listen(
|
||||||
|
PendingWorkProvider,
|
||||||
|
(previous, next) {
|
||||||
|
if (next is PendingWorkStateLoading) {
|
||||||
|
pendingWorkLoading.value = true;
|
||||||
|
} else if (next is PendingWorkStateError) {
|
||||||
|
print(next.message);
|
||||||
|
pendingWorkLoading.value = false;
|
||||||
|
SanckbarWidget(context, next.message, snackbarType.error);
|
||||||
|
} else if (next is PendingWorkStateDone) {
|
||||||
|
// print(jsonEncode(next.model));
|
||||||
|
// print(next.model.length);
|
||||||
|
pendingWork.value = next.model;
|
||||||
|
pendingWorkLoading.value = false;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
);
|
||||||
|
return RefreshIndicator(
|
||||||
|
onRefresh: () async {
|
||||||
|
fetchData();
|
||||||
|
},
|
||||||
|
triggerMode: RefreshIndicatorTriggerMode.onEdge,
|
||||||
|
child: SingleChildScrollView(
|
||||||
|
physics: const AlwaysScrollableScrollPhysics(),
|
||||||
|
child: Container(
|
||||||
|
// color: Colors.red,
|
||||||
|
padding: EdgeInsets.fromLTRB(
|
||||||
|
Constant.getActualX(context: context, x: 40),
|
||||||
|
Constant.getActualY(context: context, y: 68),
|
||||||
|
Constant.getActualX(context: context, x: 40),
|
||||||
|
0),
|
||||||
|
child: Column(
|
||||||
|
children: [
|
||||||
|
SizedBox(
|
||||||
|
height: Constant.getActualY(context: context, y: 48),
|
||||||
|
child: Row(
|
||||||
|
children: [
|
||||||
|
Expanded(
|
||||||
|
flex: 10,
|
||||||
|
child: SizedBox(
|
||||||
|
child: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Text(
|
||||||
|
"Hi $mUsername",
|
||||||
|
overflow: TextOverflow.ellipsis,
|
||||||
|
style: Constant.heading4(context: context)
|
||||||
|
.copyWith(
|
||||||
|
color: Constant.primaryBlue,
|
||||||
|
fontWeight: FontWeight.w600),
|
||||||
|
),
|
||||||
|
Text(
|
||||||
|
"Silahkan lakukan pengantaran",
|
||||||
|
overflow: TextOverflow.ellipsis,
|
||||||
|
style: Constant.caption1(context: context)
|
||||||
|
.copyWith(fontWeight: FontWeight.w500),
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
)),
|
||||||
|
Expanded(
|
||||||
|
flex: 2,
|
||||||
|
child: Container(
|
||||||
|
alignment: Alignment.topRight,
|
||||||
|
// color: Colors.red,
|
||||||
|
child: Image.asset(
|
||||||
|
"assets/icon_home_bell_blue.png",
|
||||||
|
width: Constant.getActualY(context: context, y: 24),
|
||||||
|
height:
|
||||||
|
Constant.getActualY(context: context, y: 24),
|
||||||
|
),
|
||||||
|
))
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
SizedBox(
|
||||||
|
height: Constant.getActualY(context: context, y: 20),
|
||||||
|
),
|
||||||
|
// InformationCard(
|
||||||
|
// data: totalWork.value,
|
||||||
|
// loading: totalWorkLoading.value,
|
||||||
|
// bgColor: Color(0XFFF3F7FB),
|
||||||
|
// elevation: false,
|
||||||
|
// ),
|
||||||
|
InformationRptCard(mCourirID),
|
||||||
|
SizedBox(
|
||||||
|
height: Constant.getActualY(context: context, y: 25),
|
||||||
|
),
|
||||||
|
SizedBox(
|
||||||
|
// color: Colors.blue,
|
||||||
|
child: Column(
|
||||||
|
children: [
|
||||||
|
Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
|
children: [
|
||||||
|
Text(
|
||||||
|
"Ambil Pekerjaan Baru",
|
||||||
|
style: Constant.heading4(context: context).copyWith(
|
||||||
|
fontWeight: FontWeight.w400,
|
||||||
|
color: Constant.textPrimary),
|
||||||
|
),
|
||||||
|
// InkWell(
|
||||||
|
// onTap: () {},
|
||||||
|
// child: Row(
|
||||||
|
// children: [
|
||||||
|
// Text(
|
||||||
|
// "Detail",
|
||||||
|
// style: Constant.caption1(context: context)
|
||||||
|
// .copyWith(
|
||||||
|
// color: Constant.textPrimary,
|
||||||
|
// fontWeight: FontWeight.w500),
|
||||||
|
// ),
|
||||||
|
// SizedBox(
|
||||||
|
// width: Constant.getActualX(
|
||||||
|
// context: context, x: 5),
|
||||||
|
// ),
|
||||||
|
// const Icon(
|
||||||
|
// Icons.arrow_forward_ios_outlined,
|
||||||
|
// size: 15,
|
||||||
|
// )
|
||||||
|
// ],
|
||||||
|
// ))
|
||||||
|
],
|
||||||
|
),
|
||||||
|
SizedBox(
|
||||||
|
height: Constant.getActualY(context: context, y: 20),
|
||||||
|
),
|
||||||
|
Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
|
children: [
|
||||||
|
Container(
|
||||||
|
// color: Colors.red,
|
||||||
|
height: Constant.getActualY(context: context, y: 80),
|
||||||
|
width: Constant.getActualX(context: context, x: 86),
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
// color: Colors.red,
|
||||||
|
boxShadow: [
|
||||||
|
BoxShadow(
|
||||||
|
color: Color(0XFF919EAB).withOpacity(0.12),
|
||||||
|
offset: Offset(0.0, 12), //(x,y)
|
||||||
|
blurRadius: 24,
|
||||||
|
spreadRadius: -4),
|
||||||
|
BoxShadow(
|
||||||
|
color: Color(0XFF919EAB).withOpacity(0.2),
|
||||||
|
offset: Offset(0.0, 0), //(x,y)
|
||||||
|
blurRadius: 2,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
borderRadius: BorderRadius.circular(12)),
|
||||||
|
child: ElevatedButton(
|
||||||
|
style: ElevatedButton.styleFrom(
|
||||||
|
elevation: 0.2,
|
||||||
|
shape: RoundedRectangleBorder(
|
||||||
|
borderRadius: BorderRadius.circular(12),
|
||||||
|
),
|
||||||
|
surfaceTintColor: Colors.grey,
|
||||||
|
foregroundColor: Colors.grey,
|
||||||
|
backgroundColor: Colors.white),
|
||||||
|
onPressed: () {
|
||||||
|
Navigator.of(context).pushNamed(inputPekerjaan,
|
||||||
|
arguments: inputPekerjaanProp(0, 0));
|
||||||
|
},
|
||||||
|
child: Column(
|
||||||
|
mainAxisAlignment:
|
||||||
|
MainAxisAlignment.spaceEvenly,
|
||||||
|
children: [
|
||||||
|
Image.asset(
|
||||||
|
width: Constant.getActualX(
|
||||||
|
context: context, x: 24),
|
||||||
|
height: Constant.getActualX(
|
||||||
|
context: context, x: 24),
|
||||||
|
"assets/icon_home_hasil_blue.png"),
|
||||||
|
Text(
|
||||||
|
"Hasil",
|
||||||
|
style: Constant.body3(context: context)
|
||||||
|
.copyWith(
|
||||||
|
fontWeight: FontWeight.w600,
|
||||||
|
color: Constant.textSecondary),
|
||||||
|
)
|
||||||
|
],
|
||||||
|
)),
|
||||||
|
),
|
||||||
|
Container(
|
||||||
|
// color: Colors.red,
|
||||||
|
height: Constant.getActualY(context: context, y: 80),
|
||||||
|
width: Constant.getActualX(context: context, x: 86),
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
// color: Colors.red,
|
||||||
|
boxShadow: [
|
||||||
|
BoxShadow(
|
||||||
|
color: Color(0XFF919EAB).withOpacity(0.12),
|
||||||
|
offset: Offset(0.0, 12), //(x,y)
|
||||||
|
blurRadius: 24,
|
||||||
|
spreadRadius: -4),
|
||||||
|
BoxShadow(
|
||||||
|
color: Color(0XFF919EAB).withOpacity(0.2),
|
||||||
|
offset: Offset(0.0, 0), //(x,y)
|
||||||
|
blurRadius: 2,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
borderRadius: BorderRadius.circular(12)),
|
||||||
|
child: ElevatedButton(
|
||||||
|
style: ElevatedButton.styleFrom(
|
||||||
|
elevation: 0.2,
|
||||||
|
shape: RoundedRectangleBorder(
|
||||||
|
side: const BorderSide(
|
||||||
|
width: 0.1, color: Colors.grey),
|
||||||
|
borderRadius: BorderRadius.circular(12),
|
||||||
|
),
|
||||||
|
surfaceTintColor: Colors.grey,
|
||||||
|
foregroundColor: Colors.grey,
|
||||||
|
backgroundColor: Colors.white),
|
||||||
|
onPressed: () {
|
||||||
|
Navigator.of(context).pushNamed(inputPekerjaan,
|
||||||
|
arguments: inputPekerjaanProp(1, 0));
|
||||||
|
},
|
||||||
|
child: Column(
|
||||||
|
mainAxisAlignment:
|
||||||
|
MainAxisAlignment.spaceEvenly,
|
||||||
|
children: [
|
||||||
|
Image.asset(
|
||||||
|
width: Constant.getActualX(
|
||||||
|
context: context, x: 24),
|
||||||
|
height: Constant.getActualX(
|
||||||
|
context: context, x: 24),
|
||||||
|
"assets/icon_home_sample_blue.png"),
|
||||||
|
Text(
|
||||||
|
"Sample",
|
||||||
|
style: Constant.body3(context: context)
|
||||||
|
.copyWith(
|
||||||
|
fontWeight: FontWeight.w600,
|
||||||
|
color: Constant.textSecondary),
|
||||||
|
)
|
||||||
|
],
|
||||||
|
)),
|
||||||
|
),
|
||||||
|
Container(
|
||||||
|
// color: Colors.red,
|
||||||
|
height: Constant.getActualY(context: context, y: 80),
|
||||||
|
width: Constant.getActualX(context: context, x: 86),
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
// color: Colors.red,
|
||||||
|
boxShadow: [
|
||||||
|
BoxShadow(
|
||||||
|
color: Color(0XFF919EAB).withOpacity(0.12),
|
||||||
|
offset: Offset(0.0, 12), //(x,y)
|
||||||
|
blurRadius: 24,
|
||||||
|
spreadRadius: -4),
|
||||||
|
BoxShadow(
|
||||||
|
color: Color(0XFF919EAB).withOpacity(0.2),
|
||||||
|
offset: Offset(0.0, 0), //(x,y)
|
||||||
|
blurRadius: 2,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
borderRadius: BorderRadius.circular(12)),
|
||||||
|
child: ElevatedButton(
|
||||||
|
style: ElevatedButton.styleFrom(
|
||||||
|
elevation: 0.2,
|
||||||
|
shape: RoundedRectangleBorder(
|
||||||
|
side: const BorderSide(
|
||||||
|
width: 0.1, color: Colors.grey),
|
||||||
|
borderRadius: BorderRadius.circular(12),
|
||||||
|
),
|
||||||
|
surfaceTintColor: Colors.grey,
|
||||||
|
foregroundColor: Colors.grey,
|
||||||
|
backgroundColor: Colors.white),
|
||||||
|
onPressed: () {
|
||||||
|
Navigator.of(context).pushNamed(inputPekerjaan,
|
||||||
|
arguments: inputPekerjaanProp(2, 0));
|
||||||
|
},
|
||||||
|
child: Column(
|
||||||
|
mainAxisAlignment:
|
||||||
|
MainAxisAlignment.spaceEvenly,
|
||||||
|
children: [
|
||||||
|
Image.asset(
|
||||||
|
width: Constant.getActualX(
|
||||||
|
context: context, x: 24),
|
||||||
|
height: Constant.getActualX(
|
||||||
|
context: context, x: 24),
|
||||||
|
"assets/icon_home_lainnya_blue.png"),
|
||||||
|
Text(
|
||||||
|
"Lainya",
|
||||||
|
style: Constant.body3(context: context)
|
||||||
|
.copyWith(
|
||||||
|
fontWeight: FontWeight.w600,
|
||||||
|
color: Constant.textSecondary),
|
||||||
|
)
|
||||||
|
],
|
||||||
|
)),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
SizedBox(
|
||||||
|
height: Constant.getActualY(context: context, y: 30),
|
||||||
|
),
|
||||||
|
SizedBox(
|
||||||
|
child: Column(
|
||||||
|
children: [
|
||||||
|
Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
|
children: [
|
||||||
|
Text(
|
||||||
|
"Pending List Pekerjaan",
|
||||||
|
overflow: TextOverflow.ellipsis,
|
||||||
|
style: Constant.heading4(context: context).copyWith(
|
||||||
|
fontWeight: FontWeight.w400,
|
||||||
|
color: Constant.textPrimary),
|
||||||
|
),
|
||||||
|
// InkWell(
|
||||||
|
// onTap: () {},
|
||||||
|
// child: Row(
|
||||||
|
// children: [
|
||||||
|
// Text(
|
||||||
|
// "Detail",
|
||||||
|
// style: Constant.caption1(context: context)
|
||||||
|
// .copyWith(
|
||||||
|
// color: Constant.textPrimary,
|
||||||
|
// fontWeight: FontWeight.w500),
|
||||||
|
// ),
|
||||||
|
// SizedBox(
|
||||||
|
// width: Constant.getActualX(
|
||||||
|
// context: context, x: 5),
|
||||||
|
// ),
|
||||||
|
// const Icon(
|
||||||
|
// Icons.arrow_forward_ios_outlined,
|
||||||
|
// size: 15,
|
||||||
|
// )
|
||||||
|
// ],
|
||||||
|
// ))
|
||||||
|
],
|
||||||
|
),
|
||||||
|
SizedBox(
|
||||||
|
height: Constant.getActualY(context: context, y: 20),
|
||||||
|
),
|
||||||
|
Container(
|
||||||
|
// color: Colors.red,
|
||||||
|
padding:
|
||||||
|
EdgeInsets.symmetric(horizontal: 0.9, vertical: 0.5),
|
||||||
|
height: Constant.getActualY(context: context, y: 235),
|
||||||
|
child: pendingWorkLoading.value
|
||||||
|
? LoadingAnimationWidget.fourRotatingDots(
|
||||||
|
color: Constant.primaryBlue, size: 50)
|
||||||
|
: ListView.builder(
|
||||||
|
itemCount: pendingWork.value.length,
|
||||||
|
itemBuilder: (context, index) {
|
||||||
|
return PendingCardWidget(
|
||||||
|
data: pendingWork.value[index]);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
64
lib/screen/home_screen/pending_work_provider.dart
Normal file
@@ -0,0 +1,64 @@
|
|||||||
|
import 'package:equatable/equatable.dart';
|
||||||
|
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||||
|
|
||||||
|
import '../../models/pending_work_model.dart';
|
||||||
|
import '../../provider/dio_provider.dart';
|
||||||
|
import '../../repository/base_repository.dart';
|
||||||
|
import '../../repository/home_screen_repository.dart';
|
||||||
|
|
||||||
|
abstract class PendingWorkState extends Equatable {
|
||||||
|
final DateTime date;
|
||||||
|
const PendingWorkState(this.date);
|
||||||
|
@override
|
||||||
|
List<Object?> get props => [date];
|
||||||
|
}
|
||||||
|
|
||||||
|
class PendingWorkStateInit extends PendingWorkState {
|
||||||
|
PendingWorkStateInit() : super(DateTime.now());
|
||||||
|
}
|
||||||
|
|
||||||
|
class PendingWorkStateLoading extends PendingWorkState {
|
||||||
|
PendingWorkStateLoading() : super(DateTime.now());
|
||||||
|
}
|
||||||
|
|
||||||
|
class PendingWorkStateError extends PendingWorkState {
|
||||||
|
final String message;
|
||||||
|
PendingWorkStateError({
|
||||||
|
required this.message,
|
||||||
|
}) : super(DateTime.now());
|
||||||
|
}
|
||||||
|
|
||||||
|
class PendingWorkStateDone extends PendingWorkState {
|
||||||
|
final List<PendingWorkModel> model;
|
||||||
|
PendingWorkStateDone({
|
||||||
|
required this.model,
|
||||||
|
}) : super(DateTime.now());
|
||||||
|
}
|
||||||
|
|
||||||
|
//notifier
|
||||||
|
class PendingWorkNotifier extends StateNotifier<PendingWorkState> {
|
||||||
|
final Ref ref;
|
||||||
|
PendingWorkNotifier({
|
||||||
|
required this.ref,
|
||||||
|
}) : super(PendingWorkStateInit());
|
||||||
|
|
||||||
|
void getData({required String id}) async {
|
||||||
|
try {
|
||||||
|
state = PendingWorkStateLoading();
|
||||||
|
final dio = ref.read(dioProvider);
|
||||||
|
final resp = await HomeScreenRepository(dio: dio).getPendingWork(id: id);
|
||||||
|
state = PendingWorkStateDone(model: resp);
|
||||||
|
} catch (e) {
|
||||||
|
if (e is BaseRepositoryException) {
|
||||||
|
state = PendingWorkStateError(message: e.message.toString());
|
||||||
|
} else {
|
||||||
|
state = PendingWorkStateError(message: e.toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//provider
|
||||||
|
final PendingWorkProvider =
|
||||||
|
StateNotifierProvider<PendingWorkNotifier, PendingWorkState>(
|
||||||
|
(ref) => PendingWorkNotifier(ref: ref));
|
||||||
64
lib/screen/home_screen/total_work_provider.dart
Normal file
@@ -0,0 +1,64 @@
|
|||||||
|
import 'package:equatable/equatable.dart';
|
||||||
|
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||||
|
|
||||||
|
import '../../models/work_total_model.dart';
|
||||||
|
import '../../provider/dio_provider.dart';
|
||||||
|
import '../../repository/base_repository.dart';
|
||||||
|
import '../../repository/home_screen_repository.dart';
|
||||||
|
|
||||||
|
abstract class TotalWorkState extends Equatable {
|
||||||
|
final DateTime date;
|
||||||
|
const TotalWorkState(this.date);
|
||||||
|
@override
|
||||||
|
List<Object?> get props => [date];
|
||||||
|
}
|
||||||
|
|
||||||
|
class TotalWorkStateInit extends TotalWorkState {
|
||||||
|
TotalWorkStateInit() : super(DateTime.now());
|
||||||
|
}
|
||||||
|
|
||||||
|
class TotalWorkStateLoading extends TotalWorkState {
|
||||||
|
TotalWorkStateLoading() : super(DateTime.now());
|
||||||
|
}
|
||||||
|
|
||||||
|
class TotalWorkStateError extends TotalWorkState {
|
||||||
|
final String message;
|
||||||
|
TotalWorkStateError({
|
||||||
|
required this.message,
|
||||||
|
}) : super(DateTime.now());
|
||||||
|
}
|
||||||
|
|
||||||
|
class TotalWorkStateDone extends TotalWorkState {
|
||||||
|
final WorkTotalModel model;
|
||||||
|
TotalWorkStateDone({
|
||||||
|
required this.model,
|
||||||
|
}) : super(DateTime.now());
|
||||||
|
}
|
||||||
|
|
||||||
|
//notifier
|
||||||
|
class TotalWorkNotifier extends StateNotifier<TotalWorkState> {
|
||||||
|
final Ref ref;
|
||||||
|
TotalWorkNotifier({
|
||||||
|
required this.ref,
|
||||||
|
}) : super(TotalWorkStateInit());
|
||||||
|
|
||||||
|
void getData({required String id}) async {
|
||||||
|
try {
|
||||||
|
state = TotalWorkStateLoading();
|
||||||
|
final dio = ref.read(dioProvider);
|
||||||
|
final resp = await HomeScreenRepository(dio: dio).getTotalWork(id: id);
|
||||||
|
state = TotalWorkStateDone(model: resp);
|
||||||
|
} catch (e) {
|
||||||
|
if (e is BaseRepositoryException) {
|
||||||
|
state = TotalWorkStateError(message: e.message.toString());
|
||||||
|
} else {
|
||||||
|
state = TotalWorkStateError(message: e.toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//provider
|
||||||
|
final TotalWorkProvider =
|
||||||
|
StateNotifierProvider<TotalWorkNotifier, TotalWorkState>(
|
||||||
|
(ref) => TotalWorkNotifier(ref: ref));
|
||||||
@@ -0,0 +1,61 @@
|
|||||||
|
import 'package:equatable/equatable.dart';
|
||||||
|
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||||
|
import '/models/response_list_branch_model.dart';
|
||||||
|
import '../../provider/dio_provider.dart';
|
||||||
|
import '../../repository/base_repository.dart';
|
||||||
|
import '../../repository/input_lain_lain_repository.dart';
|
||||||
|
|
||||||
|
// 3. state provider
|
||||||
|
final inputLainLainCabang = StateNotifierProvider<InputLainLainNotifier, InputLainLainState>(
|
||||||
|
(ref) => InputLainLainNotifier(ref: ref));
|
||||||
|
|
||||||
|
// 2. notifier
|
||||||
|
class InputLainLainNotifier extends StateNotifier<InputLainLainState> {
|
||||||
|
final Ref ref;
|
||||||
|
InputLainLainNotifier({required this.ref}) : super(InputLainLainStateInit());
|
||||||
|
void loadListCabangInputLainLain() async {
|
||||||
|
try {
|
||||||
|
state = InputLainLainStateLoading();
|
||||||
|
final resp = await InputLainLainRepository(dio: ref.read(dioProvider))
|
||||||
|
.loadListCabangInputLainLain();
|
||||||
|
|
||||||
|
state = InputLainLainStateDone(model: resp);
|
||||||
|
} catch (e) {
|
||||||
|
if (e is BaseRepositoryException) {
|
||||||
|
state = InputLainLainStateError(message: e.message ?? "");
|
||||||
|
} else {
|
||||||
|
state = InputLainLainStateError(message: e.toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 1. state
|
||||||
|
abstract class InputLainLainState extends Equatable {
|
||||||
|
final DateTime date;
|
||||||
|
const InputLainLainState(this.date);
|
||||||
|
@override
|
||||||
|
List<Object?> get props => [date];
|
||||||
|
}
|
||||||
|
|
||||||
|
class InputLainLainStateInit extends InputLainLainState {
|
||||||
|
InputLainLainStateInit() : super(DateTime.now());
|
||||||
|
}
|
||||||
|
|
||||||
|
class InputLainLainStateLoading extends InputLainLainState {
|
||||||
|
InputLainLainStateLoading() : super(DateTime.now());
|
||||||
|
}
|
||||||
|
|
||||||
|
class InputLainLainStateError extends InputLainLainState {
|
||||||
|
final String? message;
|
||||||
|
InputLainLainStateError({
|
||||||
|
required this.message,
|
||||||
|
}) : super(DateTime.now());
|
||||||
|
}
|
||||||
|
|
||||||
|
class InputLainLainStateDone extends InputLainLainState {
|
||||||
|
final List<ResponseListBranchModel> model;
|
||||||
|
InputLainLainStateDone({
|
||||||
|
required this.model,
|
||||||
|
}) : super(DateTime.now());
|
||||||
|
}
|
||||||
@@ -0,0 +1,81 @@
|
|||||||
|
import 'package:equatable/equatable.dart';
|
||||||
|
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||||
|
import '../../repository/input_lain_lain_repository.dart';
|
||||||
|
import '../../models/response_save_pengantaran_hasil_model.dart';
|
||||||
|
import '../../provider/dio_provider.dart';
|
||||||
|
import '../../repository/base_repository.dart';
|
||||||
|
import '../../repository/pengambilan_bahan_repository.dart';
|
||||||
|
import '../../repository/pengantaran_hasil_dokter_repository.dart';
|
||||||
|
|
||||||
|
// 3. state provider
|
||||||
|
final inputLainLainSave = StateNotifierProvider<InputLainLainSaveNotifier,
|
||||||
|
InputLainLainSaveState>((ref) => InputLainLainSaveNotifier(ref: ref));
|
||||||
|
|
||||||
|
// 2. notifier
|
||||||
|
class InputLainLainSaveNotifier
|
||||||
|
extends StateNotifier<InputLainLainSaveState> {
|
||||||
|
final Ref ref;
|
||||||
|
InputLainLainSaveNotifier({required this.ref})
|
||||||
|
: super(InputLainLainSaveStateInit());
|
||||||
|
void inputLainLainSave({
|
||||||
|
required String courierID,
|
||||||
|
required String tipeID,
|
||||||
|
required String branchID,
|
||||||
|
required String branchCode,
|
||||||
|
required String pickup,
|
||||||
|
required String destination,
|
||||||
|
required String note
|
||||||
|
}) async {
|
||||||
|
try {
|
||||||
|
state = InputLainLainSaveStateLoading();
|
||||||
|
final resp = await InputLainLainRepository(dio: ref.read(dioProvider))
|
||||||
|
.inputLainLainSave(
|
||||||
|
courierID: courierID,
|
||||||
|
tipeID: tipeID,
|
||||||
|
branchID: branchID,
|
||||||
|
branchCode: branchCode,
|
||||||
|
pickup: pickup,
|
||||||
|
destination: destination,
|
||||||
|
note: note
|
||||||
|
);
|
||||||
|
|
||||||
|
state = InputLainLainSaveStateDone(model: resp);
|
||||||
|
} catch (e) {
|
||||||
|
if (e is BaseRepositoryException) {
|
||||||
|
state = InputLainLainSaveStateError(message: e.message ?? "");
|
||||||
|
} else {
|
||||||
|
state = InputLainLainSaveStateError(message: e.toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 1. state
|
||||||
|
abstract class InputLainLainSaveState extends Equatable {
|
||||||
|
final DateTime date;
|
||||||
|
const InputLainLainSaveState(this.date);
|
||||||
|
@override
|
||||||
|
List<Object?> get props => [date];
|
||||||
|
}
|
||||||
|
|
||||||
|
class InputLainLainSaveStateInit extends InputLainLainSaveState {
|
||||||
|
InputLainLainSaveStateInit() : super(DateTime.now());
|
||||||
|
}
|
||||||
|
|
||||||
|
class InputLainLainSaveStateLoading extends InputLainLainSaveState {
|
||||||
|
InputLainLainSaveStateLoading() : super(DateTime.now());
|
||||||
|
}
|
||||||
|
|
||||||
|
class InputLainLainSaveStateError extends InputLainLainSaveState {
|
||||||
|
final String? message;
|
||||||
|
InputLainLainSaveStateError({
|
||||||
|
required this.message,
|
||||||
|
}) : super(DateTime.now());
|
||||||
|
}
|
||||||
|
|
||||||
|
class InputLainLainSaveStateDone extends InputLainLainSaveState {
|
||||||
|
final ResponseSavePengantaranHasilModel model;
|
||||||
|
InputLainLainSaveStateDone({
|
||||||
|
required this.model,
|
||||||
|
}) : super(DateTime.now());
|
||||||
|
}
|
||||||
432
lib/screen/input_pekerjaan/input_lain_lain_screen.dart
Normal file
@@ -0,0 +1,432 @@
|
|||||||
|
import 'dart:async';
|
||||||
|
|
||||||
|
import 'package:dropdown_button2/dropdown_button2.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_hooks/flutter_hooks.dart';
|
||||||
|
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||||
|
import 'package:loading_animation_widget/loading_animation_widget.dart';
|
||||||
|
|
||||||
|
import '../../app/constant.dart';
|
||||||
|
import '../../app/route.dart';
|
||||||
|
import '../../models/response_list_branch_model.dart';
|
||||||
|
import '../../provider/current_user_provider.dart';
|
||||||
|
import '../../widget/custom_textfield.dart';
|
||||||
|
import '../../widget/sas_textfield.dart';
|
||||||
|
import '../../widget/snackbar_widget.dart';
|
||||||
|
import 'input_lain_lain_loadcabang_provider.dart';
|
||||||
|
import 'input_lain_lain_save_provider.dart';
|
||||||
|
|
||||||
|
class InputLainLain extends HookConsumerWidget {
|
||||||
|
// const InputLainLain({super.key});
|
||||||
|
|
||||||
|
const InputLainLain({super.key, required this.data});
|
||||||
|
final Map<String, dynamic> data;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context, WidgetRef ref) {
|
||||||
|
print(data);
|
||||||
|
final mCourirID =
|
||||||
|
ref.watch(currentUserProvider)?.model.user?.mCourierID ?? "0";
|
||||||
|
|
||||||
|
final tipePekerjaanIDSave = data['tipePekerjaan'];
|
||||||
|
final focusNodeCatatan = useFocusNode();
|
||||||
|
final catatanhasFocus = useState(false);
|
||||||
|
|
||||||
|
final focusNodeAlamatPengambilan = useFocusNode();
|
||||||
|
final alamatPengambilanhasFocus = useState(false);
|
||||||
|
|
||||||
|
final focusNodeAlamatPengantaran = useFocusNode();
|
||||||
|
final alamatPengantaranhasFocus = useState(false);
|
||||||
|
|
||||||
|
final ctrlCatatan = useTextEditingController(text: "");
|
||||||
|
final ctrlAlamatPengambilan = useTextEditingController(text: "");
|
||||||
|
final ctrlAlamatPengantaran = useTextEditingController(text: "");
|
||||||
|
|
||||||
|
// cabang
|
||||||
|
final selectedDropdownCabang = useState<ResponseListBranchModel>(
|
||||||
|
ResponseListBranchModel(
|
||||||
|
branchid: "", branchaddress: "", branchcode: "", branchname: ""));
|
||||||
|
final dropdownItemsCabang =
|
||||||
|
useState<List<ResponseListBranchModel>>(List.empty(growable: true));
|
||||||
|
|
||||||
|
final isLoading = useState(false);
|
||||||
|
final errorMessage = useState("");
|
||||||
|
|
||||||
|
focusNodeCatatan.addListener(() {
|
||||||
|
if (focusNodeCatatan.hasFocus) {
|
||||||
|
catatanhasFocus.value = true;
|
||||||
|
} else {
|
||||||
|
catatanhasFocus.value = false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
focusNodeAlamatPengambilan.addListener(() {
|
||||||
|
if (focusNodeAlamatPengambilan.hasFocus) {
|
||||||
|
alamatPengambilanhasFocus.value = true;
|
||||||
|
} else {
|
||||||
|
alamatPengambilanhasFocus.value = false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
focusNodeAlamatPengantaran.addListener(() {
|
||||||
|
if (focusNodeAlamatPengantaran.hasFocus) {
|
||||||
|
alamatPengantaranhasFocus.value = true;
|
||||||
|
} else {
|
||||||
|
alamatPengantaranhasFocus.value = false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// populate list cabang
|
||||||
|
ref.listen(inputLainLainCabang, (prev, next) {
|
||||||
|
if (next is InputLainLainStateLoading) {
|
||||||
|
isLoading.value = true;
|
||||||
|
} else if (next is InputLainLainStateError) {
|
||||||
|
isLoading.value = false;
|
||||||
|
errorMessage.value = next.message ?? "";
|
||||||
|
SanckbarWidget(context, "${next.message}", snackbarType.error);
|
||||||
|
Timer(const Duration(seconds: 3), () {
|
||||||
|
errorMessage.value = "";
|
||||||
|
});
|
||||||
|
} else if (next is InputLainLainStateDone) {
|
||||||
|
if (next.model.isNotEmpty) {
|
||||||
|
dropdownItemsCabang.value = next.model;
|
||||||
|
selectedDropdownCabang.value = next.model[0];
|
||||||
|
} else {
|
||||||
|
dropdownItemsCabang.value = [
|
||||||
|
ResponseListBranchModel(
|
||||||
|
branchid: "0",
|
||||||
|
branchcode: "",
|
||||||
|
branchname: "Cabang Belum Ada",
|
||||||
|
branchaddress: ""),
|
||||||
|
];
|
||||||
|
|
||||||
|
selectedDropdownCabang.value = dropdownItemsCabang.value[0];
|
||||||
|
SanckbarWidget(context, "Data Cabang Belum Ada", snackbarType.error);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
isLoading.value = false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
useEffect(() {
|
||||||
|
WidgetsBinding.instance.addPostFrameCallback((timeStamp) async {
|
||||||
|
ref.read(inputLainLainCabang.notifier).loadListCabangInputLainLain();
|
||||||
|
});
|
||||||
|
return () {};
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
// save pengambilan bahan
|
||||||
|
ref.listen(inputLainLainSave, (prev, next) {
|
||||||
|
if (next is InputLainLainSaveStateLoading) {
|
||||||
|
isLoading.value = true;
|
||||||
|
} else if (next is InputLainLainSaveStateError) {
|
||||||
|
isLoading.value = false;
|
||||||
|
errorMessage.value = next.message ?? "";
|
||||||
|
SanckbarWidget(context, "${next.message}", snackbarType.error);
|
||||||
|
Timer(const Duration(seconds: 3), () {
|
||||||
|
errorMessage.value = "";
|
||||||
|
});
|
||||||
|
} else if (next is InputLainLainSaveStateDone) {
|
||||||
|
if (next.model.status != "OK") {
|
||||||
|
SanckbarWidget(context, "${next.model.message}", snackbarType.error);
|
||||||
|
} else {
|
||||||
|
Navigator.of(context).pushNamedAndRemoveUntil(
|
||||||
|
konfirmasiRoute,
|
||||||
|
(route) => false,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
isLoading.value = false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return Column(
|
||||||
|
children: [
|
||||||
|
// dropdown cabang
|
||||||
|
Container(
|
||||||
|
width: Constant.getActualX(context: context, x: 320),
|
||||||
|
height: Constant.getActualY(context: context, y: 56),
|
||||||
|
child: DropdownButtonHideUnderline(
|
||||||
|
child: DropdownButton2<ResponseListBranchModel>(
|
||||||
|
isExpanded: true,
|
||||||
|
hint: Row(
|
||||||
|
children: [
|
||||||
|
Expanded(
|
||||||
|
child: Text(
|
||||||
|
'Select Item',
|
||||||
|
style: Constant.body1(context: context).copyWith(
|
||||||
|
fontWeight: FontWeight.w600,
|
||||||
|
color: Constant.primaryDark),
|
||||||
|
overflow: TextOverflow.ellipsis,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
items: dropdownItemsCabang.value
|
||||||
|
.map((ResponseListBranchModel option) {
|
||||||
|
return DropdownMenuItem<ResponseListBranchModel>(
|
||||||
|
value: option,
|
||||||
|
child: Text(
|
||||||
|
option.branchname.toString(),
|
||||||
|
style: Constant.body1(context: context).copyWith(
|
||||||
|
color: Constant.primaryBlue,
|
||||||
|
fontWeight: FontWeight.w600),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}).toList(),
|
||||||
|
value: selectedDropdownCabang.value,
|
||||||
|
onChanged: (ResponseListBranchModel? newValue) {
|
||||||
|
// if (newValue) {
|
||||||
|
selectedDropdownCabang.value = newValue!;
|
||||||
|
print(
|
||||||
|
"Branch ID Selected : ${selectedDropdownCabang.value.branchid}");
|
||||||
|
print(
|
||||||
|
"Branch Code Selected : ${selectedDropdownCabang.value.branchcode}");
|
||||||
|
// }
|
||||||
|
},
|
||||||
|
buttonStyleData: ButtonStyleData(
|
||||||
|
height: Constant.getActualY(context: context, y: 56),
|
||||||
|
width: Constant.getActualX(context: context, x: 320),
|
||||||
|
padding: EdgeInsets.only(
|
||||||
|
left: Constant.getActualX(context: context, x: 10),
|
||||||
|
right: Constant.getActualX(context: context, x: 10),
|
||||||
|
),
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: Constant.backgroundWhite,
|
||||||
|
border: Border.all(color: Constant.textBlack, width: 1),
|
||||||
|
borderRadius: BorderRadius.circular(8),
|
||||||
|
),
|
||||||
|
elevation: 2,
|
||||||
|
),
|
||||||
|
iconStyleData: IconStyleData(
|
||||||
|
icon: isLoading.value
|
||||||
|
? LoadingAnimationWidget.discreteCircle(
|
||||||
|
color: Constant.primaryBlue, size: 20)
|
||||||
|
: Icon(
|
||||||
|
Icons.keyboard_arrow_down_outlined,
|
||||||
|
),
|
||||||
|
iconSize: 24,
|
||||||
|
iconEnabledColor: Constant.textBlack,
|
||||||
|
iconDisabledColor: Colors.grey,
|
||||||
|
),
|
||||||
|
dropdownStyleData: DropdownStyleData(
|
||||||
|
maxHeight: Constant.getActualY(context: context, y: 200),
|
||||||
|
width: Constant.getActualX(context: context, x: 320),
|
||||||
|
padding: EdgeInsets.only(
|
||||||
|
top: Constant.getActualY(context: context, y: 10),
|
||||||
|
left: Constant.getActualX(context: context, x: 10),
|
||||||
|
right: Constant.getActualX(context: context, x: 10),
|
||||||
|
bottom: Constant.getActualY(context: context, y: 10),
|
||||||
|
),
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: Constant.backgroundWhite,
|
||||||
|
borderRadius: BorderRadius.circular(8),
|
||||||
|
boxShadow: [
|
||||||
|
BoxShadow(
|
||||||
|
color: Colors.grey,
|
||||||
|
blurRadius: 20.0,
|
||||||
|
spreadRadius: 2.0,
|
||||||
|
offset: Offset(0.0, 0.0),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
elevation: 8,
|
||||||
|
offset: const Offset(0, -10),
|
||||||
|
scrollbarTheme: ScrollbarThemeData(
|
||||||
|
radius: const Radius.circular(40),
|
||||||
|
thickness: MaterialStateProperty.all<double>(6),
|
||||||
|
thumbVisibility: MaterialStateProperty.all<bool>(true),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
menuItemStyleData: MenuItemStyleData(
|
||||||
|
height: Constant.getActualY(context: context, y: 56),
|
||||||
|
padding: EdgeInsets.only(
|
||||||
|
top: Constant.getActualY(context: context, y: 10),
|
||||||
|
left: Constant.getActualX(context: context, x: 10),
|
||||||
|
right: Constant.getActualX(context: context, x: 10),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
SizedBox(
|
||||||
|
height: Constant.getActualY(context: context, y: 28),
|
||||||
|
),
|
||||||
|
|
||||||
|
// catatan
|
||||||
|
Container(
|
||||||
|
width: Constant.getActualX(context: context, x: 320),
|
||||||
|
height: Constant.getActualY(context: context, y: 120),
|
||||||
|
// color: Colors.green,
|
||||||
|
child: SasTextFieldArea(
|
||||||
|
controller: ctrlCatatan,
|
||||||
|
hintText: "Catatan",
|
||||||
|
labelText: "Catatan",
|
||||||
|
hasFocus: catatanhasFocus.value,
|
||||||
|
focusNode: focusNodeCatatan,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
SizedBox(
|
||||||
|
height: Constant.getActualY(context: context, y: 28),
|
||||||
|
),
|
||||||
|
// alamat pengambilan
|
||||||
|
Container(
|
||||||
|
width: Constant.getActualX(context: context, x: 320),
|
||||||
|
height: Constant.getActualY(context: context, y: 120),
|
||||||
|
// color: Colors.green,
|
||||||
|
child: SasTextFieldArea(
|
||||||
|
controller: ctrlAlamatPengambilan,
|
||||||
|
hintText: "Alamat Pengambilan",
|
||||||
|
labelText: "Alamat Pengambilan",
|
||||||
|
hasFocus: alamatPengambilanhasFocus.value,
|
||||||
|
focusNode: focusNodeAlamatPengambilan,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
SizedBox(
|
||||||
|
height: Constant.getActualY(context: context, y: 28),
|
||||||
|
),
|
||||||
|
// alamat pengantaran
|
||||||
|
Container(
|
||||||
|
width: Constant.getActualX(context: context, x: 320),
|
||||||
|
height: Constant.getActualY(context: context, y: 120),
|
||||||
|
// color: Colors.green,
|
||||||
|
child: SasTextFieldArea(
|
||||||
|
controller: ctrlAlamatPengantaran,
|
||||||
|
hintText: "Alamat Pengantaran",
|
||||||
|
labelText: "Alamat Pengantaran",
|
||||||
|
hasFocus: alamatPengantaranhasFocus.value,
|
||||||
|
focusNode: focusNodeAlamatPengantaran,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
|
||||||
|
SizedBox(
|
||||||
|
height: Constant.getActualY(context: context, y: 30),
|
||||||
|
),
|
||||||
|
|
||||||
|
// loading
|
||||||
|
// if (isLoading.value) ...[
|
||||||
|
// // Center(
|
||||||
|
// // child: SizedBox(
|
||||||
|
// // width: Constant.getActualX(context: context, x: 20),
|
||||||
|
// // height: Constant.getActualY(context: context, y: 20),
|
||||||
|
// // child: CircularProgressIndicator(),
|
||||||
|
// // ),
|
||||||
|
// // ),
|
||||||
|
// const Center(
|
||||||
|
// child: CircularProgressIndicator(),
|
||||||
|
// ),
|
||||||
|
// ],
|
||||||
|
|
||||||
|
// SizedBox(
|
||||||
|
// height: Constant.getActualY(context: context, y: 60),
|
||||||
|
// ),
|
||||||
|
|
||||||
|
// button batal & simpan
|
||||||
|
Align(
|
||||||
|
alignment: Alignment.bottomCenter,
|
||||||
|
child: Container(
|
||||||
|
width: Constant.getActualX(context: context, x: 317),
|
||||||
|
height: Constant.getActualY(context: context, y: 36),
|
||||||
|
// color: Colors.pink,
|
||||||
|
child: Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
|
children: [
|
||||||
|
// batal
|
||||||
|
ElevatedButton(
|
||||||
|
onPressed: isLoading.value
|
||||||
|
? null
|
||||||
|
: () {
|
||||||
|
Navigator.pop(context);
|
||||||
|
},
|
||||||
|
style: ButtonStyle(
|
||||||
|
backgroundColor: MaterialStateColor.resolveWith(
|
||||||
|
(st) => Constant.backgroundWhite),
|
||||||
|
shape: MaterialStateProperty.all<RoundedRectangleBorder>(
|
||||||
|
RoundedRectangleBorder(
|
||||||
|
borderRadius: BorderRadius.circular(8),
|
||||||
|
side: BorderSide(color: Constant.blueButton),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
shadowColor: MaterialStateProperty.all(Color(0xffff48423d)),
|
||||||
|
elevation: MaterialStateProperty.all(4.0),
|
||||||
|
),
|
||||||
|
child: Align(
|
||||||
|
alignment: Alignment.center,
|
||||||
|
child: Text(
|
||||||
|
'Batal',
|
||||||
|
style: Constant.body3(context: context).copyWith(
|
||||||
|
color: Constant.blueButton,
|
||||||
|
fontWeight: FontWeight.w700,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
|
||||||
|
// simpan
|
||||||
|
ElevatedButton(
|
||||||
|
onPressed: (isLoading.value)
|
||||||
|
? null
|
||||||
|
: () {
|
||||||
|
if (ctrlCatatan.text == "" ||
|
||||||
|
ctrlAlamatPengambilan.text == "" ||
|
||||||
|
ctrlAlamatPengantaran.text == "") {
|
||||||
|
SanckbarWidget(
|
||||||
|
context,
|
||||||
|
"Catatan atau Alamat Pengambilan atau Alamat Pengantaran Silahkan Diisi",
|
||||||
|
snackbarType.warning);
|
||||||
|
} else {
|
||||||
|
print(selectedDropdownCabang.value.branchid);
|
||||||
|
if (selectedDropdownCabang.value.branchid == "") {
|
||||||
|
SanckbarWidget(context, "Data Cabang Belum Ada",
|
||||||
|
snackbarType.warning);
|
||||||
|
} else {
|
||||||
|
ref
|
||||||
|
.read(inputLainLainSave.notifier)
|
||||||
|
.inputLainLainSave(
|
||||||
|
courierID: mCourirID,
|
||||||
|
tipeID: tipePekerjaanIDSave,
|
||||||
|
branchID: selectedDropdownCabang
|
||||||
|
.value.branchid
|
||||||
|
.toString(),
|
||||||
|
branchCode: selectedDropdownCabang
|
||||||
|
.value.branchcode
|
||||||
|
.toString(),
|
||||||
|
pickup: ctrlAlamatPengambilan.text,
|
||||||
|
destination: ctrlAlamatPengantaran.text,
|
||||||
|
note: ctrlCatatan.text);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
style: ButtonStyle(
|
||||||
|
backgroundColor: MaterialStateColor.resolveWith(
|
||||||
|
(st) => Constant.blueButton),
|
||||||
|
shape: MaterialStateProperty.all<RoundedRectangleBorder>(
|
||||||
|
RoundedRectangleBorder(
|
||||||
|
borderRadius: BorderRadius.circular(8),
|
||||||
|
// side: BorderSide(color: Constant.blueButton),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
shadowColor: MaterialStateProperty.all(Color(0xffff48423d)),
|
||||||
|
elevation: MaterialStateProperty.all(4.0),
|
||||||
|
),
|
||||||
|
child: Align(
|
||||||
|
alignment: Alignment.center,
|
||||||
|
child: isLoading.value
|
||||||
|
? LoadingAnimationWidget.staggeredDotsWave(
|
||||||
|
color: Colors.white, size: 30)
|
||||||
|
: Text(
|
||||||
|
'Simpan',
|
||||||
|
style: Constant.body3(context: context).copyWith(
|
||||||
|
color: Constant.backgroundWhite,
|
||||||
|
fontWeight: FontWeight.w700,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
241
lib/screen/input_pekerjaan/input_pekerjaan_lain_lain.dart
Normal file
@@ -0,0 +1,241 @@
|
|||||||
|
import 'dart:async';
|
||||||
|
|
||||||
|
import 'package:dropdown_button2/dropdown_button2.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_hooks/flutter_hooks.dart';
|
||||||
|
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||||
|
import '/screen/input_pekerjaan/input_lain_lain_screen.dart';
|
||||||
|
|
||||||
|
import '../../app/constant.dart';
|
||||||
|
import 'input_pengambilan_bahan_screen.dart';
|
||||||
|
import 'input_pengantaran_hasil_dokter_screen.dart';
|
||||||
|
import 'input_pengantaran_hasil_instansi_screen.dart';
|
||||||
|
import 'input_pengantaran_hasil_pasien_screen.dart';
|
||||||
|
|
||||||
|
class DummyDropdownTipe {
|
||||||
|
final String options;
|
||||||
|
final int id;
|
||||||
|
|
||||||
|
DummyDropdownTipe(this.options, this.id);
|
||||||
|
}
|
||||||
|
|
||||||
|
class DummyRadioTipe {
|
||||||
|
final String text;
|
||||||
|
final int id;
|
||||||
|
|
||||||
|
DummyRadioTipe(this.text, this.id);
|
||||||
|
}
|
||||||
|
|
||||||
|
class InputPekerjaanPekerjaanLainLain extends HookConsumerWidget {
|
||||||
|
const InputPekerjaanPekerjaanLainLain({super.key});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context, WidgetRef ref) {
|
||||||
|
final selectedDropdown =
|
||||||
|
useState<DummyDropdownTipe>(DummyDropdownTipe("", 0));
|
||||||
|
final dropdownItems =
|
||||||
|
useState<List<DummyDropdownTipe>>(List.empty(growable: true));
|
||||||
|
|
||||||
|
final radioButtonItems =
|
||||||
|
useState<List<DummyRadioTipe>>(List.empty(growable: true));
|
||||||
|
final selectedRadio = useState<DummyRadioTipe>(DummyRadioTipe("", 0));
|
||||||
|
|
||||||
|
useEffect(() {
|
||||||
|
dropdownItems.value = [
|
||||||
|
DummyDropdownTipe("Pengantaran Hasil", 1),
|
||||||
|
DummyDropdownTipe("Pengambilan Bahan", 2),
|
||||||
|
DummyDropdownTipe("Lain-lain", 3),
|
||||||
|
];
|
||||||
|
|
||||||
|
selectedDropdown.value = dropdownItems.value[2];
|
||||||
|
// selectedDropdown.value = dropdownItems.value[1];
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
final isLoading = useState(false);
|
||||||
|
final isMounted = useIsMounted();
|
||||||
|
|
||||||
|
return GestureDetector(
|
||||||
|
onTap: () => FocusManager.instance.primaryFocus?.unfocus(),
|
||||||
|
child: Scaffold(
|
||||||
|
backgroundColor: Constant.backgroundWhite,
|
||||||
|
appBar: AppBar(
|
||||||
|
toolbarHeight: Constant.getActualY(context: context, y: 110),
|
||||||
|
backgroundColor: Constant.backgroundWhite,
|
||||||
|
elevation: 0,
|
||||||
|
titleSpacing: 0,
|
||||||
|
centerTitle: false,
|
||||||
|
title: Text(
|
||||||
|
'Kembali',
|
||||||
|
style: Constant.body1(context: context).copyWith(
|
||||||
|
color: Constant.textBlack,
|
||||||
|
fontWeight: FontWeight.w600,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
leading: GestureDetector(
|
||||||
|
child: Icon(
|
||||||
|
Icons.arrow_back_ios,
|
||||||
|
color: Constant.textBlack,
|
||||||
|
size: Constant.getActualY(context: context, y: 16),
|
||||||
|
),
|
||||||
|
onTap: () {
|
||||||
|
Navigator.pop(context);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
automaticallyImplyLeading: true,
|
||||||
|
),
|
||||||
|
body: SingleChildScrollView(
|
||||||
|
child: SizedBox(
|
||||||
|
width: Constant.getActualX(context: context, x: 390),
|
||||||
|
height: Constant.getActualY(context: context, y: 760),
|
||||||
|
child: Padding(
|
||||||
|
padding: EdgeInsets.only(
|
||||||
|
left: Constant.getActualX(context: context, x: 35),
|
||||||
|
right: Constant.getActualX(context: context, x: 35),
|
||||||
|
// bottom: Constant.getActualY(context: context, y: 40)
|
||||||
|
),
|
||||||
|
child: Column(
|
||||||
|
children: [
|
||||||
|
// dropdown
|
||||||
|
if (dropdownItems.value.isEmpty) ...[
|
||||||
|
Text('Dropdown No Data')
|
||||||
|
] else ...[
|
||||||
|
DropdownButtonHideUnderline(
|
||||||
|
child: DropdownButton2<DummyDropdownTipe>(
|
||||||
|
isExpanded: true,
|
||||||
|
hint: Row(
|
||||||
|
children: [
|
||||||
|
Expanded(
|
||||||
|
child: Text(
|
||||||
|
'Select Item',
|
||||||
|
style: Constant.body1(context: context)
|
||||||
|
.copyWith(
|
||||||
|
fontWeight: FontWeight.w600,
|
||||||
|
color: Constant.primaryDark),
|
||||||
|
overflow: TextOverflow.ellipsis,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
items:
|
||||||
|
dropdownItems.value.map((DummyDropdownTipe option) {
|
||||||
|
return DropdownMenuItem<DummyDropdownTipe>(
|
||||||
|
value: option,
|
||||||
|
child: Text(
|
||||||
|
option.options,
|
||||||
|
style: Constant.body1(context: context).copyWith(
|
||||||
|
color: Constant.primaryBlue,
|
||||||
|
fontWeight: FontWeight.w600),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}).toList(),
|
||||||
|
value: selectedDropdown.value,
|
||||||
|
// onChanged: (DummyDropdownTipe? newValue) {
|
||||||
|
// // if (newValue) {
|
||||||
|
// selectedDropdown.value = newValue!;
|
||||||
|
// print(selectedDropdown.value.id);
|
||||||
|
// // }
|
||||||
|
// },
|
||||||
|
onChanged: null,
|
||||||
|
buttonStyleData: ButtonStyleData(
|
||||||
|
height: Constant.getActualY(context: context, y: 56),
|
||||||
|
width: Constant.getActualX(context: context, x: 320),
|
||||||
|
padding: EdgeInsets.only(
|
||||||
|
left: Constant.getActualX(context: context, x: 10),
|
||||||
|
right: Constant.getActualX(context: context, x: 10),
|
||||||
|
),
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: Constant.backgroundWhite,
|
||||||
|
border:
|
||||||
|
Border.all(color: Constant.textBlack, width: 1),
|
||||||
|
borderRadius: BorderRadius.circular(8),
|
||||||
|
),
|
||||||
|
elevation: 2,
|
||||||
|
),
|
||||||
|
iconStyleData: IconStyleData(
|
||||||
|
icon: Icon(
|
||||||
|
Icons.keyboard_arrow_down_outlined,
|
||||||
|
),
|
||||||
|
iconSize: 24,
|
||||||
|
iconEnabledColor: Constant.textBlack,
|
||||||
|
iconDisabledColor: Colors.grey,
|
||||||
|
),
|
||||||
|
dropdownStyleData: DropdownStyleData(
|
||||||
|
maxHeight:
|
||||||
|
Constant.getActualY(context: context, y: 200),
|
||||||
|
width: Constant.getActualX(context: context, x: 320),
|
||||||
|
padding: EdgeInsets.only(
|
||||||
|
top: Constant.getActualY(context: context, y: 10),
|
||||||
|
left: Constant.getActualX(context: context, x: 10),
|
||||||
|
right: Constant.getActualX(context: context, x: 10),
|
||||||
|
bottom:
|
||||||
|
Constant.getActualY(context: context, y: 10),
|
||||||
|
),
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: Constant.backgroundWhite,
|
||||||
|
borderRadius: BorderRadius.circular(8),
|
||||||
|
boxShadow: [
|
||||||
|
BoxShadow(
|
||||||
|
color: Colors.grey,
|
||||||
|
blurRadius: 20.0,
|
||||||
|
spreadRadius: 2.0,
|
||||||
|
offset: Offset(0.0, 0.0),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
elevation: 8,
|
||||||
|
offset: const Offset(0, -10),
|
||||||
|
scrollbarTheme: ScrollbarThemeData(
|
||||||
|
radius: const Radius.circular(40),
|
||||||
|
thickness: MaterialStateProperty.all<double>(6),
|
||||||
|
thumbVisibility:
|
||||||
|
MaterialStateProperty.all<bool>(true),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
menuItemStyleData: MenuItemStyleData(
|
||||||
|
height: Constant.getActualY(context: context, y: 56),
|
||||||
|
padding: EdgeInsets.only(
|
||||||
|
top: Constant.getActualY(context: context, y: 10),
|
||||||
|
left: Constant.getActualX(context: context, x: 10),
|
||||||
|
right: Constant.getActualX(context: context, x: 10),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
|
||||||
|
SizedBox(
|
||||||
|
height: Constant.getActualY(context: context, y: 32),
|
||||||
|
),
|
||||||
|
|
||||||
|
// form
|
||||||
|
Container(
|
||||||
|
width: Constant.getActualX(context: context, x: 320),
|
||||||
|
height: Constant.getActualY(context: context, y: 612),
|
||||||
|
// color: Colors.green,
|
||||||
|
child: Column(
|
||||||
|
children: [
|
||||||
|
if (selectedDropdown.value.id == 3) ...[
|
||||||
|
const InputLainLain(
|
||||||
|
data: {
|
||||||
|
"tipePekerjaan": "4",
|
||||||
|
"tipePengantaranHasil": ""
|
||||||
|
},
|
||||||
|
)
|
||||||
|
]
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
|
||||||
|
// spacing
|
||||||
|
SizedBox(
|
||||||
|
height: Constant.getActualY(context: context, y: 32),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,249 @@
|
|||||||
|
import 'dart:async';
|
||||||
|
|
||||||
|
import 'package:dropdown_button2/dropdown_button2.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_hooks/flutter_hooks.dart';
|
||||||
|
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||||
|
import '/screen/input_pekerjaan/input_lain_lain_screen.dart';
|
||||||
|
|
||||||
|
import '../../app/constant.dart';
|
||||||
|
import 'input_pengambilan_bahan_screen.dart';
|
||||||
|
import 'input_pengantaran_hasil_dokter_screen.dart';
|
||||||
|
import 'input_pengantaran_hasil_instansi_screen.dart';
|
||||||
|
import 'input_pengantaran_hasil_pasien_screen.dart';
|
||||||
|
|
||||||
|
class DummyDropdownTipe {
|
||||||
|
final String options;
|
||||||
|
final int id;
|
||||||
|
|
||||||
|
DummyDropdownTipe(this.options, this.id);
|
||||||
|
}
|
||||||
|
|
||||||
|
class DummyRadioTipe {
|
||||||
|
final String text;
|
||||||
|
final int id;
|
||||||
|
|
||||||
|
DummyRadioTipe(this.text, this.id);
|
||||||
|
}
|
||||||
|
|
||||||
|
class InputPekerjaanPengambilanBahan extends HookConsumerWidget {
|
||||||
|
const InputPekerjaanPengambilanBahan({super.key});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context, WidgetRef ref) {
|
||||||
|
final selectedDropdown =
|
||||||
|
useState<DummyDropdownTipe>(DummyDropdownTipe("", 0));
|
||||||
|
final dropdownItems =
|
||||||
|
useState<List<DummyDropdownTipe>>(List.empty(growable: true));
|
||||||
|
|
||||||
|
final radioButtonItems =
|
||||||
|
useState<List<DummyRadioTipe>>(List.empty(growable: true));
|
||||||
|
final selectedRadio = useState<DummyRadioTipe>(DummyRadioTipe("", 0));
|
||||||
|
|
||||||
|
useEffect(() {
|
||||||
|
dropdownItems.value = [
|
||||||
|
DummyDropdownTipe("Pengantaran Hasil", 1),
|
||||||
|
DummyDropdownTipe("Pengambilan Bahan", 2),
|
||||||
|
DummyDropdownTipe("Lain-lain", 3),
|
||||||
|
];
|
||||||
|
|
||||||
|
selectedDropdown.value = dropdownItems.value[1];
|
||||||
|
// selectedDropdown.value = dropdownItems.value[1];
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
final isLoading = useState(false);
|
||||||
|
final isMounted = useIsMounted();
|
||||||
|
|
||||||
|
return GestureDetector(
|
||||||
|
onTap: () => FocusManager.instance.primaryFocus?.unfocus(),
|
||||||
|
child: Scaffold(
|
||||||
|
backgroundColor: Constant.backgroundWhite,
|
||||||
|
appBar: AppBar(
|
||||||
|
toolbarHeight: Constant.getActualY(context: context, y: 110),
|
||||||
|
backgroundColor: Constant.backgroundWhite,
|
||||||
|
elevation: 0,
|
||||||
|
titleSpacing: 0,
|
||||||
|
centerTitle: false,
|
||||||
|
title: Text(
|
||||||
|
'Kembali',
|
||||||
|
style: Constant.body1(context: context).copyWith(
|
||||||
|
color: Constant.textBlack,
|
||||||
|
fontWeight: FontWeight.w600,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
leading: GestureDetector(
|
||||||
|
child: Icon(
|
||||||
|
Icons.arrow_back_ios,
|
||||||
|
color: Constant.textBlack,
|
||||||
|
size: Constant.getActualY(context: context, y: 16),
|
||||||
|
),
|
||||||
|
onTap: () {
|
||||||
|
Navigator.pop(context);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
automaticallyImplyLeading: true,
|
||||||
|
),
|
||||||
|
body: SingleChildScrollView(
|
||||||
|
child: SizedBox(
|
||||||
|
width: Constant.getActualX(context: context, x: 390),
|
||||||
|
height: Constant.getActualY(context: context, y: 760),
|
||||||
|
child: Padding(
|
||||||
|
padding: EdgeInsets.only(
|
||||||
|
left: Constant.getActualX(context: context, x: 35),
|
||||||
|
right: Constant.getActualX(context: context, x: 35),
|
||||||
|
// bottom: Constant.getActualY(context: context, y: 40)
|
||||||
|
),
|
||||||
|
child: Column(
|
||||||
|
children: [
|
||||||
|
// dropdown
|
||||||
|
if (dropdownItems.value.isEmpty) ...[
|
||||||
|
Text('Dropdown No Data')
|
||||||
|
] else ...[
|
||||||
|
DropdownButtonHideUnderline(
|
||||||
|
child: DropdownButton2<DummyDropdownTipe>(
|
||||||
|
isExpanded: true,
|
||||||
|
hint: Row(
|
||||||
|
children: [
|
||||||
|
Expanded(
|
||||||
|
child: Text(
|
||||||
|
'Select Item',
|
||||||
|
style: Constant.body1(context: context)
|
||||||
|
.copyWith(
|
||||||
|
fontWeight: FontWeight.w600,
|
||||||
|
color: Constant.primaryDark),
|
||||||
|
overflow: TextOverflow.ellipsis,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
items:
|
||||||
|
dropdownItems.value.map((DummyDropdownTipe option) {
|
||||||
|
return DropdownMenuItem<DummyDropdownTipe>(
|
||||||
|
value: option,
|
||||||
|
child: Text(
|
||||||
|
option.options,
|
||||||
|
style: Constant.body1(context: context).copyWith(
|
||||||
|
color: Constant.primaryBlue,
|
||||||
|
fontWeight: FontWeight.w600),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}).toList(),
|
||||||
|
value: selectedDropdown.value,
|
||||||
|
// onChanged: (DummyDropdownTipe? newValue) {
|
||||||
|
// // if (newValue) {
|
||||||
|
// selectedDropdown.value = newValue!;
|
||||||
|
// print(selectedDropdown.value.id);
|
||||||
|
// // }
|
||||||
|
// },
|
||||||
|
onChanged: null,
|
||||||
|
buttonStyleData: ButtonStyleData(
|
||||||
|
height: Constant.getActualY(context: context, y: 56),
|
||||||
|
width: Constant.getActualX(context: context, x: 320),
|
||||||
|
padding: EdgeInsets.only(
|
||||||
|
left: Constant.getActualX(context: context, x: 10),
|
||||||
|
right: Constant.getActualX(context: context, x: 10),
|
||||||
|
),
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: Constant.backgroundWhite,
|
||||||
|
border:
|
||||||
|
Border.all(color: Constant.textBlack, width: 1),
|
||||||
|
borderRadius: BorderRadius.circular(8),
|
||||||
|
),
|
||||||
|
elevation: 2,
|
||||||
|
),
|
||||||
|
iconStyleData: IconStyleData(
|
||||||
|
icon: Icon(
|
||||||
|
Icons.keyboard_arrow_down_outlined,
|
||||||
|
),
|
||||||
|
iconSize: 24,
|
||||||
|
iconEnabledColor: Constant.textBlack,
|
||||||
|
iconDisabledColor: Colors.grey,
|
||||||
|
),
|
||||||
|
dropdownStyleData: DropdownStyleData(
|
||||||
|
maxHeight:
|
||||||
|
Constant.getActualY(context: context, y: 200),
|
||||||
|
width: Constant.getActualX(context: context, x: 320),
|
||||||
|
padding: EdgeInsets.only(
|
||||||
|
top: Constant.getActualY(context: context, y: 10),
|
||||||
|
left: Constant.getActualX(context: context, x: 10),
|
||||||
|
right: Constant.getActualX(context: context, x: 10),
|
||||||
|
bottom:
|
||||||
|
Constant.getActualY(context: context, y: 10),
|
||||||
|
),
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: Constant.backgroundWhite,
|
||||||
|
borderRadius: BorderRadius.circular(8),
|
||||||
|
boxShadow: [
|
||||||
|
BoxShadow(
|
||||||
|
color: Colors.grey,
|
||||||
|
blurRadius: 20.0,
|
||||||
|
spreadRadius: 2.0,
|
||||||
|
offset: Offset(0.0, 0.0),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
elevation: 8,
|
||||||
|
offset: const Offset(0, -10),
|
||||||
|
scrollbarTheme: ScrollbarThemeData(
|
||||||
|
radius: const Radius.circular(40),
|
||||||
|
thickness: MaterialStateProperty.all<double>(6),
|
||||||
|
thumbVisibility:
|
||||||
|
MaterialStateProperty.all<bool>(true),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
menuItemStyleData: MenuItemStyleData(
|
||||||
|
height: Constant.getActualY(context: context, y: 56),
|
||||||
|
padding: EdgeInsets.only(
|
||||||
|
top: Constant.getActualY(context: context, y: 10),
|
||||||
|
left: Constant.getActualX(context: context, x: 10),
|
||||||
|
right: Constant.getActualX(context: context, x: 10),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
|
||||||
|
SizedBox(
|
||||||
|
height: Constant.getActualY(context: context, y: 32),
|
||||||
|
),
|
||||||
|
|
||||||
|
// form
|
||||||
|
Container(
|
||||||
|
width: Constant.getActualX(context: context, x: 320),
|
||||||
|
height: Constant.getActualY(context: context, y: 612),
|
||||||
|
// color: Colors.green,
|
||||||
|
child: Column(
|
||||||
|
children: [
|
||||||
|
if (selectedDropdown.value.id == 2) ...[
|
||||||
|
// Text('Antar Bahan')
|
||||||
|
Container(
|
||||||
|
width:
|
||||||
|
Constant.getActualX(context: context, x: 320),
|
||||||
|
height:
|
||||||
|
Constant.getActualY(context: context, y: 612),
|
||||||
|
// color: Colors.amber,
|
||||||
|
child: const InputPengambilanBahanScreen(
|
||||||
|
data: {
|
||||||
|
"tipePekerjaan": "5",
|
||||||
|
"tipePengantaranHasil": ""
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
|
||||||
|
// spacing
|
||||||
|
SizedBox(
|
||||||
|
height: Constant.getActualY(context: context, y: 32),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,338 @@
|
|||||||
|
import 'dart:async';
|
||||||
|
|
||||||
|
import 'package:dropdown_button2/dropdown_button2.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_hooks/flutter_hooks.dart';
|
||||||
|
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||||
|
import '/screen/input_pekerjaan/input_lain_lain_screen.dart';
|
||||||
|
|
||||||
|
import '../../app/constant.dart';
|
||||||
|
import 'input_pengambilan_bahan_screen.dart';
|
||||||
|
import 'input_pengantaran_hasil_dokter_screen.dart';
|
||||||
|
import 'input_pengantaran_hasil_instansi_screen.dart';
|
||||||
|
import 'input_pengantaran_hasil_pasien_screen.dart';
|
||||||
|
|
||||||
|
class DummyDropdownTipe {
|
||||||
|
final String options;
|
||||||
|
final int id;
|
||||||
|
|
||||||
|
DummyDropdownTipe(this.options, this.id);
|
||||||
|
}
|
||||||
|
|
||||||
|
class DummyRadioTipe {
|
||||||
|
final String text;
|
||||||
|
final int id;
|
||||||
|
|
||||||
|
DummyRadioTipe(this.text, this.id);
|
||||||
|
}
|
||||||
|
|
||||||
|
class InputPekerjaanPengantaranHasil extends HookConsumerWidget {
|
||||||
|
const InputPekerjaanPengantaranHasil({super.key});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context, WidgetRef ref) {
|
||||||
|
final selectedDropdown =
|
||||||
|
useState<DummyDropdownTipe>(DummyDropdownTipe("", 0));
|
||||||
|
final dropdownItems =
|
||||||
|
useState<List<DummyDropdownTipe>>(List.empty(growable: true));
|
||||||
|
|
||||||
|
final radioButtonItems =
|
||||||
|
useState<List<DummyRadioTipe>>(List.empty(growable: true));
|
||||||
|
final selectedRadio = useState<DummyRadioTipe>(DummyRadioTipe("", 0));
|
||||||
|
|
||||||
|
useEffect(() {
|
||||||
|
dropdownItems.value = [
|
||||||
|
DummyDropdownTipe("Pengantaran Hasil", 1),
|
||||||
|
DummyDropdownTipe("Pengambilan Bahan", 2),
|
||||||
|
DummyDropdownTipe("Lain-lain", 3),
|
||||||
|
];
|
||||||
|
|
||||||
|
selectedDropdown.value = dropdownItems.value[0];
|
||||||
|
// selectedDropdown.value = dropdownItems.value[1];
|
||||||
|
|
||||||
|
radioButtonItems.value = [
|
||||||
|
DummyRadioTipe("Pasien", 1),
|
||||||
|
DummyRadioTipe("Instansi", 2),
|
||||||
|
DummyRadioTipe("Dokter", 3),
|
||||||
|
];
|
||||||
|
|
||||||
|
selectedRadio.value = radioButtonItems.value[0];
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
final isLoading = useState(false);
|
||||||
|
final isMounted = useIsMounted();
|
||||||
|
|
||||||
|
return GestureDetector(
|
||||||
|
onTap: () => FocusManager.instance.primaryFocus?.unfocus(),
|
||||||
|
child: Scaffold(
|
||||||
|
backgroundColor: Constant.backgroundWhite,
|
||||||
|
resizeToAvoidBottomInset: false,
|
||||||
|
appBar: AppBar(
|
||||||
|
toolbarHeight: Constant.getActualY(context: context, y: 110),
|
||||||
|
backgroundColor: Constant.backgroundWhite,
|
||||||
|
elevation: 0,
|
||||||
|
titleSpacing: 0,
|
||||||
|
centerTitle: false,
|
||||||
|
title: Text(
|
||||||
|
'Kembali',
|
||||||
|
style: Constant.body1(context: context).copyWith(
|
||||||
|
color: Constant.textBlack,
|
||||||
|
fontWeight: FontWeight.w600,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
leading: GestureDetector(
|
||||||
|
child: Icon(
|
||||||
|
Icons.arrow_back_ios,
|
||||||
|
color: Constant.textBlack,
|
||||||
|
size: Constant.getActualY(context: context, y: 16),
|
||||||
|
),
|
||||||
|
onTap: () {
|
||||||
|
Navigator.pop(context);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
automaticallyImplyLeading: true,
|
||||||
|
),
|
||||||
|
body: SizedBox(
|
||||||
|
width: Constant.getActualX(context: context, x: 390),
|
||||||
|
height: Constant.getActualY(context: context, y: 760),
|
||||||
|
child: Padding(
|
||||||
|
padding: EdgeInsets.only(
|
||||||
|
left: Constant.getActualX(context: context, x: 35),
|
||||||
|
right: Constant.getActualX(context: context, x: 35),
|
||||||
|
// bottom: Constant.getActualY(context: context, y: 40)
|
||||||
|
),
|
||||||
|
child: Column(
|
||||||
|
children: [
|
||||||
|
// dropdown
|
||||||
|
if (dropdownItems.value.isEmpty) ...[
|
||||||
|
Text('Dropdown No Data')
|
||||||
|
] else ...[
|
||||||
|
DropdownButtonHideUnderline(
|
||||||
|
child: DropdownButton2<DummyDropdownTipe>(
|
||||||
|
isExpanded: true,
|
||||||
|
hint: Row(
|
||||||
|
children: [
|
||||||
|
Expanded(
|
||||||
|
child: Text(
|
||||||
|
'Select Item',
|
||||||
|
style: Constant.body1(context: context)
|
||||||
|
.copyWith(
|
||||||
|
fontWeight: FontWeight.w600,
|
||||||
|
color: Constant.primaryDark),
|
||||||
|
overflow: TextOverflow.ellipsis,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
items:
|
||||||
|
dropdownItems.value.map((DummyDropdownTipe option) {
|
||||||
|
return DropdownMenuItem<DummyDropdownTipe>(
|
||||||
|
value: option,
|
||||||
|
child: Text(
|
||||||
|
option.options,
|
||||||
|
style: Constant.body1(context: context).copyWith(
|
||||||
|
color: Constant.primaryBlue,
|
||||||
|
fontWeight: FontWeight.w600),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}).toList(),
|
||||||
|
value: selectedDropdown.value,
|
||||||
|
// onChanged: (DummyDropdownTipe? newValue) {
|
||||||
|
// // if (newValue) {
|
||||||
|
// selectedDropdown.value = newValue!;
|
||||||
|
// print(selectedDropdown.value.id);
|
||||||
|
// // }
|
||||||
|
// },
|
||||||
|
onChanged: null,
|
||||||
|
buttonStyleData: ButtonStyleData(
|
||||||
|
height: Constant.getActualY(context: context, y: 56),
|
||||||
|
width: Constant.getActualX(context: context, x: 320),
|
||||||
|
padding: EdgeInsets.only(
|
||||||
|
left: Constant.getActualX(context: context, x: 10),
|
||||||
|
right: Constant.getActualX(context: context, x: 10),
|
||||||
|
),
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: Constant.backgroundWhite,
|
||||||
|
border:
|
||||||
|
Border.all(color: Constant.textBlack, width: 1),
|
||||||
|
borderRadius: BorderRadius.circular(8),
|
||||||
|
),
|
||||||
|
elevation: 2,
|
||||||
|
),
|
||||||
|
iconStyleData: IconStyleData(
|
||||||
|
icon: Icon(
|
||||||
|
Icons.keyboard_arrow_down_outlined,
|
||||||
|
),
|
||||||
|
iconSize: 24,
|
||||||
|
iconEnabledColor: Constant.textBlack,
|
||||||
|
iconDisabledColor: Colors.grey,
|
||||||
|
),
|
||||||
|
dropdownStyleData: DropdownStyleData(
|
||||||
|
maxHeight:
|
||||||
|
Constant.getActualY(context: context, y: 200),
|
||||||
|
width: Constant.getActualX(context: context, x: 320),
|
||||||
|
padding: EdgeInsets.only(
|
||||||
|
top: Constant.getActualY(context: context, y: 10),
|
||||||
|
left: Constant.getActualX(context: context, x: 10),
|
||||||
|
right: Constant.getActualX(context: context, x: 10),
|
||||||
|
bottom:
|
||||||
|
Constant.getActualY(context: context, y: 10),
|
||||||
|
),
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: Constant.backgroundWhite,
|
||||||
|
borderRadius: BorderRadius.circular(8),
|
||||||
|
boxShadow: [
|
||||||
|
BoxShadow(
|
||||||
|
color: Colors.grey,
|
||||||
|
blurRadius: 20.0,
|
||||||
|
spreadRadius: 2.0,
|
||||||
|
offset: Offset(0.0, 0.0),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
elevation: 8,
|
||||||
|
offset: const Offset(0, -10),
|
||||||
|
scrollbarTheme: ScrollbarThemeData(
|
||||||
|
radius: const Radius.circular(40),
|
||||||
|
thickness: MaterialStateProperty.all<double>(6),
|
||||||
|
thumbVisibility:
|
||||||
|
MaterialStateProperty.all<bool>(true),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
menuItemStyleData: MenuItemStyleData(
|
||||||
|
height: Constant.getActualY(context: context, y: 56),
|
||||||
|
padding: EdgeInsets.only(
|
||||||
|
top: Constant.getActualY(context: context, y: 10),
|
||||||
|
left: Constant.getActualX(context: context, x: 10),
|
||||||
|
right: Constant.getActualX(context: context, x: 10),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
|
||||||
|
SizedBox(
|
||||||
|
height: Constant.getActualY(context: context, y: 32),
|
||||||
|
),
|
||||||
|
|
||||||
|
// form
|
||||||
|
Container(
|
||||||
|
width: Constant.getActualX(context: context, x: 320),
|
||||||
|
height: Constant.getActualY(context: context, y: 612),
|
||||||
|
// color: Colors.green,
|
||||||
|
child: Column(
|
||||||
|
children: [
|
||||||
|
if (selectedDropdown.value.id == 1) ...[
|
||||||
|
// radio button
|
||||||
|
SizedBox(
|
||||||
|
width:
|
||||||
|
Constant.getActualX(context: context, x: 320),
|
||||||
|
height:
|
||||||
|
Constant.getActualY(context: context, y: 36),
|
||||||
|
// color: Colors.green,
|
||||||
|
child: Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceAround,
|
||||||
|
children: [
|
||||||
|
if (radioButtonItems.value.isEmpty) ...[
|
||||||
|
Text('Radio Button Empty')
|
||||||
|
] else ...[
|
||||||
|
for (var i = 0;
|
||||||
|
i < radioButtonItems.value.length;
|
||||||
|
i++) ...[
|
||||||
|
Expanded(
|
||||||
|
flex: 1,
|
||||||
|
child: Row(
|
||||||
|
children: [
|
||||||
|
Radio<DummyRadioTipe>(
|
||||||
|
activeColor: Constant.primaryMain,
|
||||||
|
value: radioButtonItems.value[i],
|
||||||
|
groupValue: selectedRadio.value,
|
||||||
|
onChanged: (DummyRadioTipe? index) {
|
||||||
|
if (isMounted()) {
|
||||||
|
selectedRadio.value = index!;
|
||||||
|
} else {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
),
|
||||||
|
Expanded(
|
||||||
|
child: Text(
|
||||||
|
radioButtonItems.value[i].text,
|
||||||
|
style: Constant.body3(
|
||||||
|
context: context)
|
||||||
|
.copyWith(
|
||||||
|
color:
|
||||||
|
Constant.textPrimary,
|
||||||
|
fontWeight:
|
||||||
|
FontWeight.w400),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
]
|
||||||
|
]
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
SizedBox(
|
||||||
|
height:
|
||||||
|
Constant.getActualY(context: context, y: 32),
|
||||||
|
),
|
||||||
|
|
||||||
|
// form scan dan inputan
|
||||||
|
Container(
|
||||||
|
width:
|
||||||
|
Constant.getActualX(context: context, x: 320),
|
||||||
|
height:
|
||||||
|
Constant.getActualY(context: context, y: 544),
|
||||||
|
// color: Colors.amber,
|
||||||
|
child: Column(
|
||||||
|
children: [
|
||||||
|
if (selectedRadio.value.id == 1) ...[
|
||||||
|
// InputPengantaranHasilPasienScreen(data: {
|
||||||
|
// "tipePekerjaan": selectedDropdown.value.id.toString(),
|
||||||
|
// "tipePengantaranHasil": selectedRadio.value.id.toString()
|
||||||
|
// }),
|
||||||
|
|
||||||
|
const InputPengantaranHasilPasienScreen(
|
||||||
|
data: {
|
||||||
|
"tipePekerjaan": "1",
|
||||||
|
"tipePengantaranHasil": ""
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
if (selectedRadio.value.id == 2) ...[
|
||||||
|
const InputPengantaranHasilInstansiScreen(
|
||||||
|
data: {
|
||||||
|
"tipePekerjaan": "2",
|
||||||
|
"tipePengantaranHasil": ""
|
||||||
|
})
|
||||||
|
],
|
||||||
|
if (selectedRadio.value.id == 3) ...[
|
||||||
|
const InputPengantaranHasilDokterScreen(
|
||||||
|
data: {
|
||||||
|
"tipePekerjaan": "3",
|
||||||
|
"tipePengantaranHasil": ""
|
||||||
|
},
|
||||||
|
)
|
||||||
|
]
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
]
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
|
||||||
|
// spacing
|
||||||
|
SizedBox(
|
||||||
|
height: Constant.getActualY(context: context, y: 32),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
376
lib/screen/input_pekerjaan/input_pekerjaan_screen.dart
Normal file
@@ -0,0 +1,376 @@
|
|||||||
|
import 'dart:async';
|
||||||
|
|
||||||
|
import 'package:dropdown_button2/dropdown_button2.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_hooks/flutter_hooks.dart';
|
||||||
|
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||||
|
import '/screen/input_pekerjaan/input_lain_lain_screen.dart';
|
||||||
|
|
||||||
|
import '../../app/constant.dart';
|
||||||
|
import '../../provider/current_scan_provider.dart';
|
||||||
|
import 'input_pengambilan_bahan_screen.dart';
|
||||||
|
import 'input_pengantaran_hasil_dokter_screen.dart';
|
||||||
|
import 'input_pengantaran_hasil_instansi_screen.dart';
|
||||||
|
import 'input_pengantaran_hasil_pasien_screen.dart';
|
||||||
|
|
||||||
|
class DummyDropdownTipe {
|
||||||
|
final String options;
|
||||||
|
final int id;
|
||||||
|
|
||||||
|
DummyDropdownTipe(this.options, this.id);
|
||||||
|
}
|
||||||
|
|
||||||
|
class DummyRadioTipe {
|
||||||
|
final String text;
|
||||||
|
final int id;
|
||||||
|
|
||||||
|
DummyRadioTipe(this.text, this.id);
|
||||||
|
}
|
||||||
|
|
||||||
|
class InputPekerjaan extends HookConsumerWidget {
|
||||||
|
const InputPekerjaan({super.key, required this.input, required this.tipe});
|
||||||
|
final int input;
|
||||||
|
final int tipe;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context, WidgetRef ref) {
|
||||||
|
final selectedDropdown =
|
||||||
|
useState<DummyDropdownTipe>(DummyDropdownTipe("", 0));
|
||||||
|
final dropdownItems =
|
||||||
|
useState<List<DummyDropdownTipe>>(List.empty(growable: true));
|
||||||
|
|
||||||
|
final radioButtonItems =
|
||||||
|
useState<List<DummyRadioTipe>>(List.empty(growable: true));
|
||||||
|
final selectedRadio = useState<DummyRadioTipe>(DummyRadioTipe("", 0));
|
||||||
|
|
||||||
|
useEffect(() {
|
||||||
|
dropdownItems.value = [
|
||||||
|
DummyDropdownTipe("Pengantaran Hasil", 1),
|
||||||
|
DummyDropdownTipe("Pengambilan Bahan", 2),
|
||||||
|
DummyDropdownTipe("Lain-lain", 3),
|
||||||
|
];
|
||||||
|
|
||||||
|
selectedDropdown.value = dropdownItems.value[input];
|
||||||
|
// selectedDropdown.value = dropdownItems.value[1];
|
||||||
|
|
||||||
|
radioButtonItems.value = [
|
||||||
|
DummyRadioTipe("Pasien", 1),
|
||||||
|
DummyRadioTipe("Instansi", 2),
|
||||||
|
DummyRadioTipe("Dokter", 3),
|
||||||
|
];
|
||||||
|
|
||||||
|
selectedRadio.value = radioButtonItems.value[tipe];
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
final isLoading = useState(false);
|
||||||
|
final isMounted = useIsMounted();
|
||||||
|
|
||||||
|
return GestureDetector(
|
||||||
|
onTap: () => FocusManager.instance.primaryFocus?.unfocus(),
|
||||||
|
child: Scaffold(
|
||||||
|
resizeToAvoidBottomInset: true,
|
||||||
|
backgroundColor: Constant.backgroundWhite,
|
||||||
|
appBar: AppBar(
|
||||||
|
toolbarHeight: Constant.getActualY(context: context, y: 110),
|
||||||
|
backgroundColor: Constant.backgroundWhite,
|
||||||
|
elevation: 0,
|
||||||
|
titleSpacing: 0,
|
||||||
|
centerTitle: false,
|
||||||
|
title: Text(
|
||||||
|
'Kembali',
|
||||||
|
style: Constant.body1(context: context).copyWith(
|
||||||
|
color: Constant.textBlack,
|
||||||
|
fontWeight: FontWeight.w600,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
leading: GestureDetector(
|
||||||
|
child: Icon(
|
||||||
|
Icons.arrow_back_ios,
|
||||||
|
color: Constant.textBlack,
|
||||||
|
size: Constant.getActualY(context: context, y: 16),
|
||||||
|
),
|
||||||
|
onTap: () {
|
||||||
|
Navigator.pop(context);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
automaticallyImplyLeading: true,
|
||||||
|
),
|
||||||
|
body: SingleChildScrollView(
|
||||||
|
child: SizedBox(
|
||||||
|
width: Constant.getActualX(context: context, x: 390),
|
||||||
|
height: Constant.getActualY(context: context, y: 760),
|
||||||
|
child: Padding(
|
||||||
|
padding: EdgeInsets.only(
|
||||||
|
left: Constant.getActualX(context: context, x: 35),
|
||||||
|
right: Constant.getActualX(context: context, x: 35),
|
||||||
|
// bottom: Constant.getActualY(context: context, y: 40)
|
||||||
|
),
|
||||||
|
child: Column(
|
||||||
|
children: [
|
||||||
|
// dropdown
|
||||||
|
if (dropdownItems.value.isEmpty) ...[
|
||||||
|
Text('Dropdown No Data')
|
||||||
|
] else ...[
|
||||||
|
DropdownButtonHideUnderline(
|
||||||
|
child: DropdownButton2<DummyDropdownTipe>(
|
||||||
|
isExpanded: true,
|
||||||
|
hint: Row(
|
||||||
|
children: [
|
||||||
|
Expanded(
|
||||||
|
child: Text(
|
||||||
|
'Select Item',
|
||||||
|
style: Constant.body1(context: context)
|
||||||
|
.copyWith(
|
||||||
|
fontWeight: FontWeight.w600,
|
||||||
|
color: Constant.primaryDark),
|
||||||
|
overflow: TextOverflow.ellipsis,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
items:
|
||||||
|
dropdownItems.value.map((DummyDropdownTipe option) {
|
||||||
|
return DropdownMenuItem<DummyDropdownTipe>(
|
||||||
|
value: option,
|
||||||
|
child: Text(
|
||||||
|
option.options,
|
||||||
|
style: Constant.body1(context: context).copyWith(
|
||||||
|
color: Constant.primaryBlue,
|
||||||
|
fontWeight: FontWeight.w600),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}).toList(),
|
||||||
|
value: selectedDropdown.value,
|
||||||
|
onChanged: (DummyDropdownTipe? newValue) {
|
||||||
|
// if (newValue) {
|
||||||
|
selectedDropdown.value = newValue!;
|
||||||
|
print(selectedDropdown.value.id);
|
||||||
|
// }
|
||||||
|
},
|
||||||
|
buttonStyleData: ButtonStyleData(
|
||||||
|
height: Constant.getActualY(context: context, y: 56),
|
||||||
|
width: Constant.getActualX(context: context, x: 320),
|
||||||
|
padding: EdgeInsets.only(
|
||||||
|
left: Constant.getActualX(context: context, x: 10),
|
||||||
|
right: Constant.getActualX(context: context, x: 10),
|
||||||
|
),
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: Constant.backgroundWhite,
|
||||||
|
border:
|
||||||
|
Border.all(color: Constant.textBlack, width: 1),
|
||||||
|
borderRadius: BorderRadius.circular(8),
|
||||||
|
),
|
||||||
|
elevation: 2,
|
||||||
|
),
|
||||||
|
iconStyleData: IconStyleData(
|
||||||
|
icon: Icon(
|
||||||
|
Icons.keyboard_arrow_down_outlined,
|
||||||
|
),
|
||||||
|
iconSize: 24,
|
||||||
|
iconEnabledColor: Constant.textBlack,
|
||||||
|
iconDisabledColor: Colors.grey,
|
||||||
|
),
|
||||||
|
dropdownStyleData: DropdownStyleData(
|
||||||
|
maxHeight:
|
||||||
|
Constant.getActualY(context: context, y: 200),
|
||||||
|
width: Constant.getActualX(context: context, x: 320),
|
||||||
|
padding: EdgeInsets.only(
|
||||||
|
top: Constant.getActualY(context: context, y: 10),
|
||||||
|
left: Constant.getActualX(context: context, x: 10),
|
||||||
|
right: Constant.getActualX(context: context, x: 10),
|
||||||
|
bottom:
|
||||||
|
Constant.getActualY(context: context, y: 10),
|
||||||
|
),
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: Constant.backgroundWhite,
|
||||||
|
borderRadius: BorderRadius.circular(8),
|
||||||
|
boxShadow: [
|
||||||
|
BoxShadow(
|
||||||
|
color: Colors.grey,
|
||||||
|
blurRadius: 20.0,
|
||||||
|
spreadRadius: 2.0,
|
||||||
|
offset: Offset(0.0, 0.0),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
elevation: 8,
|
||||||
|
offset: const Offset(0, -10),
|
||||||
|
scrollbarTheme: ScrollbarThemeData(
|
||||||
|
radius: const Radius.circular(40),
|
||||||
|
thickness: MaterialStateProperty.all<double>(6),
|
||||||
|
thumbVisibility:
|
||||||
|
MaterialStateProperty.all<bool>(true),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
menuItemStyleData: MenuItemStyleData(
|
||||||
|
height: Constant.getActualY(context: context, y: 56),
|
||||||
|
padding: EdgeInsets.only(
|
||||||
|
top: Constant.getActualY(context: context, y: 10),
|
||||||
|
left: Constant.getActualX(context: context, x: 10),
|
||||||
|
right: Constant.getActualX(context: context, x: 10),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
|
||||||
|
SizedBox(
|
||||||
|
height: Constant.getActualY(context: context, y: 32),
|
||||||
|
),
|
||||||
|
|
||||||
|
// form
|
||||||
|
Container(
|
||||||
|
width: Constant.getActualX(context: context, x: 320),
|
||||||
|
height: Constant.getActualY(context: context, y: 612),
|
||||||
|
// color: Colors.green,
|
||||||
|
child: Column(
|
||||||
|
children: [
|
||||||
|
if (selectedDropdown.value.id == 1) ...[
|
||||||
|
// radio button
|
||||||
|
SizedBox(
|
||||||
|
width:
|
||||||
|
Constant.getActualX(context: context, x: 320),
|
||||||
|
height:
|
||||||
|
Constant.getActualY(context: context, y: 36),
|
||||||
|
// color: Colors.green,
|
||||||
|
child: Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceAround,
|
||||||
|
children: [
|
||||||
|
if (radioButtonItems.value.isEmpty) ...[
|
||||||
|
Text('Radio Button Empty')
|
||||||
|
] else ...[
|
||||||
|
for (var i = 0;
|
||||||
|
i < radioButtonItems.value.length;
|
||||||
|
i++) ...[
|
||||||
|
Expanded(
|
||||||
|
flex: 1,
|
||||||
|
child: Row(
|
||||||
|
children: [
|
||||||
|
Radio<DummyRadioTipe>(
|
||||||
|
activeColor: Constant.primaryMain,
|
||||||
|
value: radioButtonItems.value[i],
|
||||||
|
groupValue: selectedRadio.value,
|
||||||
|
onChanged: (DummyRadioTipe? index) {
|
||||||
|
if (isMounted()) {
|
||||||
|
selectedRadio.value = index!;
|
||||||
|
ref
|
||||||
|
.read(barcodeScanResult
|
||||||
|
.notifier)
|
||||||
|
.update((state) => "");
|
||||||
|
ref
|
||||||
|
.read(isFromScanScreen
|
||||||
|
.notifier)
|
||||||
|
.update((state) => false);
|
||||||
|
} else {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
),
|
||||||
|
Expanded(
|
||||||
|
child: Text(
|
||||||
|
radioButtonItems.value[i].text,
|
||||||
|
style: Constant.body3(
|
||||||
|
context: context)
|
||||||
|
.copyWith(
|
||||||
|
color:
|
||||||
|
Constant.textPrimary,
|
||||||
|
fontWeight:
|
||||||
|
FontWeight.w400),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
]
|
||||||
|
]
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
SizedBox(
|
||||||
|
height:
|
||||||
|
Constant.getActualY(context: context, y: 32),
|
||||||
|
),
|
||||||
|
|
||||||
|
// form scan dan inputan
|
||||||
|
Container(
|
||||||
|
width:
|
||||||
|
Constant.getActualX(context: context, x: 320),
|
||||||
|
height:
|
||||||
|
Constant.getActualY(context: context, y: 544),
|
||||||
|
// color: Colors.amber,
|
||||||
|
child: Wrap(
|
||||||
|
children: [
|
||||||
|
if (selectedRadio.value.id == 1) ...[
|
||||||
|
// InputPengantaranHasilPasienScreen(data: {
|
||||||
|
// "tipePekerjaan": selectedDropdown.value.id.toString(),
|
||||||
|
// "tipePengantaranHasil": selectedRadio.value.id.toString()
|
||||||
|
// }),
|
||||||
|
|
||||||
|
const InputPengantaranHasilPasienScreen(
|
||||||
|
data: {
|
||||||
|
"tipePekerjaan": "1",
|
||||||
|
"tipePengantaranHasil": ""
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
if (selectedRadio.value.id == 2) ...[
|
||||||
|
const InputPengantaranHasilInstansiScreen(
|
||||||
|
data: {
|
||||||
|
"tipePekerjaan": "2",
|
||||||
|
"tipePengantaranHasil": ""
|
||||||
|
})
|
||||||
|
],
|
||||||
|
if (selectedRadio.value.id == 3) ...[
|
||||||
|
const InputPengantaranHasilDokterScreen(
|
||||||
|
data: {
|
||||||
|
"tipePekerjaan": "3",
|
||||||
|
"tipePengantaranHasil": ""
|
||||||
|
},
|
||||||
|
)
|
||||||
|
]
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
] else ...[
|
||||||
|
// height 36 + 544 + 32
|
||||||
|
if (selectedDropdown.value.id == 2) ...[
|
||||||
|
// Text('Antar Bahan')
|
||||||
|
Container(
|
||||||
|
width:
|
||||||
|
Constant.getActualX(context: context, x: 320),
|
||||||
|
height:
|
||||||
|
Constant.getActualY(context: context, y: 612),
|
||||||
|
// color: Colors.amber,
|
||||||
|
child: const InputPengambilanBahanScreen(
|
||||||
|
data: {
|
||||||
|
"tipePekerjaan": "5",
|
||||||
|
"tipePengantaranHasil": ""
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
if (selectedDropdown.value.id == 3) ...[
|
||||||
|
const InputLainLain(
|
||||||
|
data: {
|
||||||
|
"tipePekerjaan": "4",
|
||||||
|
"tipePengantaranHasil": ""
|
||||||
|
},
|
||||||
|
)
|
||||||
|
]
|
||||||
|
]
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
|
||||||
|
// spacing
|
||||||
|
SizedBox(
|
||||||
|
height: Constant.getActualY(context: context, y: 32),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
614
lib/screen/input_pekerjaan/input_pengambilan_bahan_screen.dart
Normal file
@@ -0,0 +1,614 @@
|
|||||||
|
import 'dart:async';
|
||||||
|
import 'dart:convert';
|
||||||
|
|
||||||
|
import 'package:dio/dio.dart';
|
||||||
|
import 'package:dropdown_button2/dropdown_button2.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_hooks/flutter_hooks.dart';
|
||||||
|
import 'package:flutter_typeahead/flutter_typeahead.dart';
|
||||||
|
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||||
|
import '/models/company_model.dart';
|
||||||
|
import '/models/response_list_branch_model.dart';
|
||||||
|
import '../../repository/company_repository.dart';
|
||||||
|
import '/screen/input_pekerjaan/pengambilan_bahan_loadcabang_provider.dart';
|
||||||
|
import '/screen/input_pekerjaan/search_company_provider.dart';
|
||||||
|
import 'package:loading_animation_widget/loading_animation_widget.dart';
|
||||||
|
|
||||||
|
import '../../app/constant.dart';
|
||||||
|
import '../../app/route.dart';
|
||||||
|
import '../../provider/current_user_provider.dart';
|
||||||
|
import '../../provider/dio_provider.dart';
|
||||||
|
import '../../widget/custom_textfield.dart';
|
||||||
|
import '../../widget/sas_textfield.dart';
|
||||||
|
import '../../widget/snackbar_widget.dart';
|
||||||
|
import 'pengambilan_bahan_save_provider.dart';
|
||||||
|
import 'pengantaran_hasil_dokter_save_provider.dart';
|
||||||
|
|
||||||
|
class DummyCabang {
|
||||||
|
final String namaCabang;
|
||||||
|
final int idCabang;
|
||||||
|
|
||||||
|
DummyCabang(this.namaCabang, this.idCabang);
|
||||||
|
}
|
||||||
|
|
||||||
|
class InputPengambilanBahanScreen extends HookConsumerWidget {
|
||||||
|
// const InputPengambilanBahanScreen({super.key});
|
||||||
|
|
||||||
|
const InputPengambilanBahanScreen({super.key, required this.data});
|
||||||
|
final Map<String, dynamic> data;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context, WidgetRef ref) {
|
||||||
|
// print(data);
|
||||||
|
final mCourirID =
|
||||||
|
ref.watch(currentUserProvider)?.model.user?.mCourierID ?? "0";
|
||||||
|
|
||||||
|
final tipePekerjaanIDSave = data['tipePekerjaan'];
|
||||||
|
final deliveryIDSave = useState<String>("");
|
||||||
|
// cabang
|
||||||
|
final selectedDropdownCabang = useState<ResponseListBranchModel>(
|
||||||
|
ResponseListBranchModel(
|
||||||
|
branchid: "", branchaddress: "", branchcode: "", branchname: ""));
|
||||||
|
final dropdownItemsCabang =
|
||||||
|
useState<List<ResponseListBranchModel>>(List.empty(growable: true));
|
||||||
|
|
||||||
|
final selectedCompany = useState<CompanyModel>(CompanyModel());
|
||||||
|
final companyInput = useTextEditingController();
|
||||||
|
final searchCompanyLoading = useState(false);
|
||||||
|
|
||||||
|
final searchCompanyErrorMsg = useState("");
|
||||||
|
|
||||||
|
final focusNodeNamaTujuan = useFocusNode();
|
||||||
|
final namaTujuanhasFocus = useState(false);
|
||||||
|
|
||||||
|
final focusNodeAlamat = useFocusNode();
|
||||||
|
final alamathasFocus = useState(false);
|
||||||
|
|
||||||
|
final ctrlAlamat = useTextEditingController(text: "");
|
||||||
|
final ctrlNamaTujuan = useTextEditingController(text: "");
|
||||||
|
|
||||||
|
final isLoading = useState(false);
|
||||||
|
final errorMessage = useState("");
|
||||||
|
|
||||||
|
focusNodeNamaTujuan.addListener(() {
|
||||||
|
if (focusNodeNamaTujuan.hasFocus) {
|
||||||
|
namaTujuanhasFocus.value = true;
|
||||||
|
} else {
|
||||||
|
namaTujuanhasFocus.value = false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
focusNodeAlamat.addListener(() {
|
||||||
|
if (focusNodeAlamat.hasFocus) {
|
||||||
|
alamathasFocus.value = true;
|
||||||
|
} else {
|
||||||
|
alamathasFocus.value = false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// populate list cabang
|
||||||
|
ref.listen(pengambilanBahanListCabang, (prev, next) {
|
||||||
|
if (next is PengambilanBahanStateLoading) {
|
||||||
|
isLoading.value = true;
|
||||||
|
} else if (next is PengambilanBahanStateError) {
|
||||||
|
isLoading.value = false;
|
||||||
|
errorMessage.value = next.message ?? "";
|
||||||
|
SanckbarWidget(context, "${next.message}", snackbarType.error);
|
||||||
|
Timer(const Duration(seconds: 3), () {
|
||||||
|
errorMessage.value = "";
|
||||||
|
});
|
||||||
|
} else if (next is PengambilanBahanStateDone) {
|
||||||
|
if (next.model.isNotEmpty) {
|
||||||
|
dropdownItemsCabang.value = next.model;
|
||||||
|
selectedDropdownCabang.value = next.model[0];
|
||||||
|
} else {
|
||||||
|
dropdownItemsCabang.value = [
|
||||||
|
ResponseListBranchModel(
|
||||||
|
branchid: "0",
|
||||||
|
branchcode: "",
|
||||||
|
branchname: "Cabang Belum Ada",
|
||||||
|
branchaddress: ""),
|
||||||
|
];
|
||||||
|
|
||||||
|
selectedDropdownCabang.value = dropdownItemsCabang.value[0];
|
||||||
|
SanckbarWidget(context, "Data Cabang Belum Ada", snackbarType.error);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
isLoading.value = false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
useEffect(() {
|
||||||
|
WidgetsBinding.instance.addPostFrameCallback((timeStamp) async {
|
||||||
|
ref
|
||||||
|
.read(pengambilanBahanListCabang.notifier)
|
||||||
|
.loadListCabangPengambilanBahan();
|
||||||
|
});
|
||||||
|
return () {};
|
||||||
|
}, []);
|
||||||
|
useEffect(() {
|
||||||
|
WidgetsBinding.instance.addPostFrameCallback((timeStamp) async {
|
||||||
|
ref
|
||||||
|
.read(pengambilanBahanListCabang.notifier)
|
||||||
|
.loadListCabangPengambilanBahan();
|
||||||
|
});
|
||||||
|
return () {};
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
// save pengambilan bahan
|
||||||
|
ref.listen(pengambilanBahanSave, (prev, next) {
|
||||||
|
if (next is PengambilanBahanSaveStateLoading) {
|
||||||
|
isLoading.value = true;
|
||||||
|
} else if (next is PengambilanBahanSaveStateError) {
|
||||||
|
isLoading.value = false;
|
||||||
|
errorMessage.value = next.message ?? "";
|
||||||
|
SanckbarWidget(context, "${next.message}", snackbarType.error);
|
||||||
|
Timer(const Duration(seconds: 3), () {
|
||||||
|
errorMessage.value = "";
|
||||||
|
});
|
||||||
|
} else if (next is PengambilanBahanSaveStateDone) {
|
||||||
|
if (next.model.status != "OK") {
|
||||||
|
SanckbarWidget(context, "${next.model.message}", snackbarType.error);
|
||||||
|
} else {
|
||||||
|
Navigator.of(context).pushNamedAndRemoveUntil(
|
||||||
|
konfirmasiRoute,
|
||||||
|
(route) => false,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
isLoading.value = false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
Future<List<CompanyModel>> searchCompany({required String keyword}) async {
|
||||||
|
// http: //10.9.9.3/one-api/v1/courier/mobile/inputcourier/search_company_all/?search=sas
|
||||||
|
try {
|
||||||
|
searchCompanyLoading.value = true;
|
||||||
|
// final url =
|
||||||
|
// "${Constant.baseUrl}/v1/courier/mobile/inputcourier/search_comsdfpany_all/?search=$keyword";
|
||||||
|
final url =
|
||||||
|
"${Constant.baseUrl}/v1/courier/mobile/inputcourier/search_company_all/?search=$keyword";
|
||||||
|
final coba = await Dio().get(url);
|
||||||
|
final resp = jsonDecode(coba.toString());
|
||||||
|
// final resp = await get(service: url);
|
||||||
|
List<CompanyModel> data;
|
||||||
|
// print(resp['data']);
|
||||||
|
if (resp['status'] == 'OK') {
|
||||||
|
data = [];
|
||||||
|
if (resp['data'] != null) {
|
||||||
|
resp['data']['records'].forEach((e) {
|
||||||
|
final model = CompanyModel.fromJson(e);
|
||||||
|
data.add(model);
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
data = [];
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
data = [];
|
||||||
|
}
|
||||||
|
print("company repo");
|
||||||
|
print(jsonEncode(data));
|
||||||
|
|
||||||
|
searchCompanyLoading.value = false;
|
||||||
|
return data;
|
||||||
|
} catch (e) {
|
||||||
|
searchCompanyErrorMsg.value = e.toString();
|
||||||
|
SanckbarWidget(context, e.toString(), snackbarType.error);
|
||||||
|
searchCompanyLoading.value = false;
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return Column(
|
||||||
|
children: [
|
||||||
|
// nama tujuan
|
||||||
|
// Container(
|
||||||
|
// width: Constant.getActualX(context: context, x: 320),
|
||||||
|
// height: Constant.getActualY(context: context, y: 56),
|
||||||
|
// child: SasTextField(
|
||||||
|
// controller: ctrlNamaTujuan,
|
||||||
|
// hintText: "Nama Tujuan",
|
||||||
|
// labelText: "Nama Tujuan",
|
||||||
|
// hasFocus: namaTujuanhasFocus.value,
|
||||||
|
// focusNode: focusNodeNamaTujuan,
|
||||||
|
// ),
|
||||||
|
// ),
|
||||||
|
|
||||||
|
Autocomplete<CompanyModel>(
|
||||||
|
fieldViewBuilder:
|
||||||
|
(context, textEditingController, focusNode, onFieldSubmitted) {
|
||||||
|
ctrlNamaTujuan.text = textEditingController.text;
|
||||||
|
return TextField(
|
||||||
|
controller: textEditingController,
|
||||||
|
focusNode: focusNode,
|
||||||
|
decoration: InputDecoration(
|
||||||
|
hintText: "Nama Tujuan",
|
||||||
|
labelText: "Nama Tujuan",
|
||||||
|
enabledBorder: OutlineInputBorder(
|
||||||
|
borderRadius: BorderRadius.circular(8),
|
||||||
|
borderSide: BorderSide(
|
||||||
|
color: Constant.textGrey,
|
||||||
|
width: 2,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
focusedBorder: OutlineInputBorder(
|
||||||
|
borderRadius: BorderRadius.circular(8),
|
||||||
|
borderSide: BorderSide(
|
||||||
|
color: Constant.primaryMain,
|
||||||
|
width: 2,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
border: OutlineInputBorder(
|
||||||
|
borderRadius: BorderRadius.circular(8),
|
||||||
|
borderSide: BorderSide(
|
||||||
|
color: Constant.primaryBlue,
|
||||||
|
width: 3,
|
||||||
|
),
|
||||||
|
)));
|
||||||
|
},
|
||||||
|
optionsBuilder: (tv) async {
|
||||||
|
final debouncer = Debouncer(milliseconds: 500);
|
||||||
|
|
||||||
|
final search = tv.text.toString();
|
||||||
|
List<CompanyModel> data = List.empty(growable: true);
|
||||||
|
// print(tv.text.length);
|
||||||
|
|
||||||
|
if (search == "" || search.isEmpty) {
|
||||||
|
data = List.empty();
|
||||||
|
} else {
|
||||||
|
// var data = await searchCompany(keyword: search);
|
||||||
|
if (search.length >= 3) {
|
||||||
|
final dio = ref.read(dioProvider);
|
||||||
|
data = await searchCompany(keyword: search);
|
||||||
|
|
||||||
|
// return CompanyRepository(dio: dio).search(keyword: search);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return data;
|
||||||
|
},
|
||||||
|
displayStringForOption: (option) {
|
||||||
|
return option.mCompanyName.toString();
|
||||||
|
},
|
||||||
|
optionsViewBuilder: (BuildContext context, onSelected, options) {
|
||||||
|
return Align(
|
||||||
|
alignment: Alignment.topLeft,
|
||||||
|
child: Material(
|
||||||
|
elevation: 10,
|
||||||
|
// borderRadius: BorderRadius.all(Radius.circular(50)),
|
||||||
|
color: Colors.white,
|
||||||
|
borderRadius: const BorderRadius.only(
|
||||||
|
bottomLeft: Radius.circular(10),
|
||||||
|
bottomRight: Radius.circular(10)),
|
||||||
|
child: Container(
|
||||||
|
width: Constant.getActualX(context: context, x: 320),
|
||||||
|
height: searchCompanyLoading.value
|
||||||
|
? Constant.getActualY(context: context, y: 50)
|
||||||
|
: Constant.getActualY(context: context, y: 250),
|
||||||
|
decoration: const BoxDecoration(
|
||||||
|
// color: Colors.white,
|
||||||
|
borderRadius: BorderRadius.only(
|
||||||
|
bottomLeft: Radius.circular(10),
|
||||||
|
bottomRight: Radius.circular(10))),
|
||||||
|
child: searchCompanyLoading.value
|
||||||
|
? Center(
|
||||||
|
child: LoadingAnimationWidget.staggeredDotsWave(
|
||||||
|
color: Constant.primaryBlue, size: 30),
|
||||||
|
)
|
||||||
|
: Scrollbar(
|
||||||
|
trackVisibility: true,
|
||||||
|
// isAlwaysShown: true,
|
||||||
|
child: ListView.builder(
|
||||||
|
shrinkWrap: true,
|
||||||
|
padding: EdgeInsets.all(10.0),
|
||||||
|
itemCount: options.length,
|
||||||
|
itemBuilder: (BuildContext context, int index) {
|
||||||
|
final CompanyModel option =
|
||||||
|
options.elementAt(index);
|
||||||
|
|
||||||
|
return SizedBox(
|
||||||
|
child: ListTile(
|
||||||
|
// tileColor: Colors.green,
|
||||||
|
onTap: () {
|
||||||
|
onSelected(option);
|
||||||
|
selectedCompany.value = option;
|
||||||
|
companyInput.text =
|
||||||
|
option.mCompanyName ?? "";
|
||||||
|
ctrlAlamat.text =
|
||||||
|
option.mCompanyAddress ?? "";
|
||||||
|
ctrlNamaTujuan.text =
|
||||||
|
option.mCompanyName ?? "";
|
||||||
|
},
|
||||||
|
// leading: Icon(Icons.location_on),
|
||||||
|
title: Text(option.mCompanyName.toString(),
|
||||||
|
style:
|
||||||
|
const TextStyle(color: Colors.black)),
|
||||||
|
subtitle:
|
||||||
|
Text(option.mCompanyAddress.toString()),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
|
||||||
|
SizedBox(
|
||||||
|
height: Constant.getActualY(context: context, y: 28),
|
||||||
|
),
|
||||||
|
// alamat pengambilan
|
||||||
|
Container(
|
||||||
|
width: Constant.getActualX(context: context, x: 320),
|
||||||
|
height: Constant.getActualY(context: context, y: 120),
|
||||||
|
// color: Colors.green,
|
||||||
|
child: SasTextFieldArea(
|
||||||
|
controller: ctrlAlamat,
|
||||||
|
hintText: "Alamat Pengambilan",
|
||||||
|
labelText: "Alamat Pengambilan",
|
||||||
|
hasFocus: alamathasFocus.value,
|
||||||
|
focusNode: focusNodeAlamat,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
SizedBox(
|
||||||
|
height: Constant.getActualY(context: context, y: 28),
|
||||||
|
),
|
||||||
|
// dropdown cabang
|
||||||
|
Container(
|
||||||
|
width: Constant.getActualX(context: context, x: 320),
|
||||||
|
height: Constant.getActualY(context: context, y: 56),
|
||||||
|
child: DropdownButtonHideUnderline(
|
||||||
|
child: DropdownButton2<ResponseListBranchModel>(
|
||||||
|
isExpanded: true,
|
||||||
|
hint: Row(
|
||||||
|
children: [
|
||||||
|
Expanded(
|
||||||
|
child: Text(
|
||||||
|
'Select Item',
|
||||||
|
style: Constant.body1(context: context).copyWith(
|
||||||
|
fontWeight: FontWeight.w600,
|
||||||
|
color: Constant.primaryDark),
|
||||||
|
overflow: TextOverflow.ellipsis,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
items: dropdownItemsCabang.value
|
||||||
|
.map((ResponseListBranchModel option) {
|
||||||
|
return DropdownMenuItem<ResponseListBranchModel>(
|
||||||
|
value: option,
|
||||||
|
child: Text(
|
||||||
|
option.branchname.toString(),
|
||||||
|
style: Constant.body1(context: context).copyWith(
|
||||||
|
color: Constant.primaryBlue,
|
||||||
|
fontWeight: FontWeight.w600),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}).toList(),
|
||||||
|
value: selectedDropdownCabang.value,
|
||||||
|
onChanged: (ResponseListBranchModel? newValue) {
|
||||||
|
// if (newValue) {
|
||||||
|
selectedDropdownCabang.value = newValue!;
|
||||||
|
print(
|
||||||
|
"Branch ID Selected : ${selectedDropdownCabang.value.branchid}");
|
||||||
|
print(
|
||||||
|
"Branch Code Selected : ${selectedDropdownCabang.value.branchcode}");
|
||||||
|
// }
|
||||||
|
},
|
||||||
|
buttonStyleData: ButtonStyleData(
|
||||||
|
height: Constant.getActualY(context: context, y: 56),
|
||||||
|
width: Constant.getActualX(context: context, x: 320),
|
||||||
|
padding: EdgeInsets.only(
|
||||||
|
left: Constant.getActualX(context: context, x: 10),
|
||||||
|
right: Constant.getActualX(context: context, x: 10),
|
||||||
|
),
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: Constant.backgroundWhite,
|
||||||
|
border: Border.all(color: Constant.textBlack, width: 1),
|
||||||
|
borderRadius: BorderRadius.circular(8),
|
||||||
|
),
|
||||||
|
elevation: 2,
|
||||||
|
),
|
||||||
|
iconStyleData: IconStyleData(
|
||||||
|
icon: isLoading.value
|
||||||
|
? LoadingAnimationWidget.discreteCircle(
|
||||||
|
color: Constant.primaryBlue, size: 20)
|
||||||
|
: Icon(
|
||||||
|
Icons.keyboard_arrow_down_outlined,
|
||||||
|
),
|
||||||
|
iconSize: 24,
|
||||||
|
iconEnabledColor: Constant.textBlack,
|
||||||
|
iconDisabledColor: Colors.grey,
|
||||||
|
),
|
||||||
|
dropdownStyleData: DropdownStyleData(
|
||||||
|
maxHeight: Constant.getActualY(context: context, y: 200),
|
||||||
|
width: Constant.getActualX(context: context, x: 320),
|
||||||
|
padding: EdgeInsets.only(
|
||||||
|
top: Constant.getActualY(context: context, y: 10),
|
||||||
|
left: Constant.getActualX(context: context, x: 10),
|
||||||
|
right: Constant.getActualX(context: context, x: 10),
|
||||||
|
bottom: Constant.getActualY(context: context, y: 10),
|
||||||
|
),
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: Constant.backgroundWhite,
|
||||||
|
borderRadius: BorderRadius.circular(8),
|
||||||
|
boxShadow: [
|
||||||
|
BoxShadow(
|
||||||
|
color: Colors.grey,
|
||||||
|
blurRadius: 20.0,
|
||||||
|
spreadRadius: 2.0,
|
||||||
|
offset: Offset(0.0, 0.0),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
elevation: 8,
|
||||||
|
offset: const Offset(0, -10),
|
||||||
|
scrollbarTheme: ScrollbarThemeData(
|
||||||
|
radius: const Radius.circular(40),
|
||||||
|
thickness: MaterialStateProperty.all<double>(6),
|
||||||
|
thumbVisibility: MaterialStateProperty.all<bool>(true),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
menuItemStyleData: MenuItemStyleData(
|
||||||
|
height: Constant.getActualY(context: context, y: 56),
|
||||||
|
padding: EdgeInsets.only(
|
||||||
|
top: Constant.getActualY(context: context, y: 10),
|
||||||
|
left: Constant.getActualX(context: context, x: 10),
|
||||||
|
right: Constant.getActualX(context: context, x: 10),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
|
||||||
|
SizedBox(
|
||||||
|
height: Constant.getActualY(context: context, y: 30),
|
||||||
|
),
|
||||||
|
|
||||||
|
// loading
|
||||||
|
// if (isLoading.value) ...[
|
||||||
|
// // Center(
|
||||||
|
// // child: SizedBox(
|
||||||
|
// // width: Constant.getActualX(context: context, x: 20),
|
||||||
|
// // height: Constant.getActualY(context: context, y: 20),
|
||||||
|
// // child: CircularProgressIndicator(),
|
||||||
|
// // ),
|
||||||
|
// // ),
|
||||||
|
// const Center(
|
||||||
|
// child: CircularProgressIndicator(),
|
||||||
|
// ),
|
||||||
|
// SizedBox(
|
||||||
|
// height: Constant.getActualY(context: context, y: 20),
|
||||||
|
// ),
|
||||||
|
// ],
|
||||||
|
|
||||||
|
// button batal & simpan
|
||||||
|
Align(
|
||||||
|
alignment: Alignment.bottomCenter,
|
||||||
|
child: Container(
|
||||||
|
width: Constant.getActualX(context: context, x: 317),
|
||||||
|
height: Constant.getActualY(context: context, y: 36),
|
||||||
|
// color: Colors.pink,
|
||||||
|
child: Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
|
children: [
|
||||||
|
// batal
|
||||||
|
SizedBox(
|
||||||
|
width: Constant.getActualX(context: context, x: 80),
|
||||||
|
height: Constant.getActualY(context: context, y: 36),
|
||||||
|
child: ElevatedButton(
|
||||||
|
onPressed: isLoading.value
|
||||||
|
? null
|
||||||
|
: () {
|
||||||
|
Navigator.pop(context);
|
||||||
|
},
|
||||||
|
style: ButtonStyle(
|
||||||
|
backgroundColor: MaterialStateColor.resolveWith(
|
||||||
|
(st) => Constant.backgroundWhite),
|
||||||
|
shape: MaterialStateProperty.all<RoundedRectangleBorder>(
|
||||||
|
RoundedRectangleBorder(
|
||||||
|
borderRadius: BorderRadius.circular(8),
|
||||||
|
side: BorderSide(color: Constant.blueButton),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
shadowColor:
|
||||||
|
MaterialStateProperty.all(Color(0xffff48423d)),
|
||||||
|
elevation: MaterialStateProperty.all(4.0),
|
||||||
|
),
|
||||||
|
child: Align(
|
||||||
|
alignment: Alignment.center,
|
||||||
|
child: Text(
|
||||||
|
'Batal',
|
||||||
|
style: Constant.body3(context: context).copyWith(
|
||||||
|
color: Constant.blueButton,
|
||||||
|
fontWeight: FontWeight.w700,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
|
||||||
|
// simpan
|
||||||
|
SizedBox(
|
||||||
|
// width: Constant.getActualX(context: context, x: 83),
|
||||||
|
height: Constant.getActualY(context: context, y: 36),
|
||||||
|
child: ElevatedButton(
|
||||||
|
onPressed: (isLoading.value)
|
||||||
|
? null
|
||||||
|
: () {
|
||||||
|
if (ctrlNamaTujuan.text == "" ||
|
||||||
|
ctrlAlamat.text == "") {
|
||||||
|
SanckbarWidget(
|
||||||
|
context,
|
||||||
|
"Nama dan Alamat Silahkan Diisi",
|
||||||
|
snackbarType.warning);
|
||||||
|
} else {
|
||||||
|
print(selectedDropdownCabang.value.branchid);
|
||||||
|
if (selectedDropdownCabang.value.branchid == "") {
|
||||||
|
SanckbarWidget(context, "Data Cabang Belum Ada",
|
||||||
|
snackbarType.warning);
|
||||||
|
} else {
|
||||||
|
ref
|
||||||
|
.read(pengambilanBahanSave.notifier)
|
||||||
|
.pengambilanBahanSave(
|
||||||
|
courierID: mCourirID,
|
||||||
|
tipeID: tipePekerjaanIDSave,
|
||||||
|
branchID: selectedDropdownCabang
|
||||||
|
.value.branchid
|
||||||
|
.toString(),
|
||||||
|
branchCode: selectedDropdownCabang
|
||||||
|
.value.branchcode
|
||||||
|
.toString(),
|
||||||
|
destination: ctrlAlamat.text,
|
||||||
|
name: ctrlNamaTujuan.text);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
style: ButtonStyle(
|
||||||
|
backgroundColor: MaterialStateColor.resolveWith(
|
||||||
|
(st) => Constant.blueButton),
|
||||||
|
shape: MaterialStateProperty.all<RoundedRectangleBorder>(
|
||||||
|
RoundedRectangleBorder(
|
||||||
|
borderRadius: BorderRadius.circular(8),
|
||||||
|
// side: BorderSide(color: Constant.blueButton),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
shadowColor:
|
||||||
|
MaterialStateProperty.all(Color(0xffff48423d)),
|
||||||
|
elevation: MaterialStateProperty.all(4.0),
|
||||||
|
),
|
||||||
|
child: Align(
|
||||||
|
alignment: Alignment.center,
|
||||||
|
child: isLoading.value
|
||||||
|
? LoadingAnimationWidget.staggeredDotsWave(
|
||||||
|
color: Colors.white, size: 20)
|
||||||
|
: Text(
|
||||||
|
'Simpan',
|
||||||
|
style: Constant.body3(context: context).copyWith(
|
||||||
|
color: Constant.backgroundWhite,
|
||||||
|
fontWeight: FontWeight.w700,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class Debouncer {
|
||||||
|
Debouncer({required this.milliseconds});
|
||||||
|
final int milliseconds;
|
||||||
|
Timer? _timer;
|
||||||
|
run(action) {
|
||||||
|
if (_timer?.isActive ?? false) {
|
||||||
|
_timer?.cancel();
|
||||||
|
}
|
||||||
|
_timer = Timer(Duration(milliseconds: milliseconds), action);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,794 @@
|
|||||||
|
import 'dart:async';
|
||||||
|
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_hooks/flutter_hooks.dart';
|
||||||
|
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||||
|
import '/app/route.dart';
|
||||||
|
import '/models/patient_model.dart';
|
||||||
|
import '/widget/patient_card.dart';
|
||||||
|
|
||||||
|
import '../../app/constant.dart';
|
||||||
|
import '../../models/response_search_pengantaran_hasil_model.dart';
|
||||||
|
import '../../provider/current_scan_provider.dart';
|
||||||
|
import '../../provider/current_user_provider.dart';
|
||||||
|
import '../../provider/dio_provider.dart';
|
||||||
|
import '../../repository/pengantaran_hasil_dokter_repository.dart';
|
||||||
|
import '../../widget/custom_textfield.dart';
|
||||||
|
import '../../widget/sas_textfield.dart';
|
||||||
|
import '../../widget/snackbar_widget.dart';
|
||||||
|
import 'pengantaran_hasil_dokter_loadnolab_provider.dart';
|
||||||
|
import 'pengantaran_hasil_dokter_save_provider.dart';
|
||||||
|
|
||||||
|
class InputPengantaranHasilDokterScreen extends HookConsumerWidget {
|
||||||
|
const InputPengantaranHasilDokterScreen({super.key, required this.data});
|
||||||
|
final Map<String, dynamic> data;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context, WidgetRef ref) {
|
||||||
|
print(data);
|
||||||
|
|
||||||
|
final tipePekerjaanIDSave = data['tipePekerjaan'];
|
||||||
|
final deliveryIDSave = useState<String>("");
|
||||||
|
final mCourirID =
|
||||||
|
ref.watch(currentUserProvider)?.model.user?.mCourierID ?? "0";
|
||||||
|
|
||||||
|
final isForm = useState(true);
|
||||||
|
final isScan = useState(false);
|
||||||
|
|
||||||
|
final hasilSearchData = useState<List<ResponseSearchPengantaranHasilModel>>(
|
||||||
|
List.empty(growable: true));
|
||||||
|
final focusNodeNoDokter = useFocusNode();
|
||||||
|
final nodokterhasFocus = useState(false);
|
||||||
|
final isLoadingSearchNoDokter = useState(false);
|
||||||
|
final ctrlNoDokter = useTextEditingController(text: "");
|
||||||
|
|
||||||
|
final ctrlNama = useTextEditingController(text: "");
|
||||||
|
final focusNodeNama = useFocusNode();
|
||||||
|
final namahasFocus = useState(false);
|
||||||
|
|
||||||
|
final ctrlAlamat = useTextEditingController(text: "");
|
||||||
|
final focusNodeAlamat = useFocusNode();
|
||||||
|
final alamathasFocus = useState(false);
|
||||||
|
final errorMessage = useState("");
|
||||||
|
|
||||||
|
final isFromScanScreenProvider = ref.read(isFromScanScreen);
|
||||||
|
|
||||||
|
final listPatient =
|
||||||
|
useState<List<PatientModel>>(List.empty(growable: true));
|
||||||
|
|
||||||
|
final listViewBuilderShow = useState(false);
|
||||||
|
final singleListSearchShow = useState(true);
|
||||||
|
|
||||||
|
focusNodeNoDokter.addListener(() {
|
||||||
|
if (focusNodeNoDokter.hasFocus) {
|
||||||
|
nodokterhasFocus.value = true;
|
||||||
|
} else {
|
||||||
|
nodokterhasFocus.value = false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
focusNodeNama.addListener(() {
|
||||||
|
if (focusNodeNama.hasFocus) {
|
||||||
|
namahasFocus.value = true;
|
||||||
|
} else {
|
||||||
|
namahasFocus.value = false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
focusNodeAlamat.addListener(() {
|
||||||
|
if (focusNodeAlamat.hasFocus) {
|
||||||
|
alamathasFocus.value = true;
|
||||||
|
} else {
|
||||||
|
alamathasFocus.value = false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// useEffect(() {
|
||||||
|
// isForm.value = true;
|
||||||
|
// isScan.value = false;
|
||||||
|
// }, []);
|
||||||
|
|
||||||
|
// search
|
||||||
|
ref.listen(pengantaranHasilDokterSearch, (prev, next) {
|
||||||
|
if (next is PengantaranhasilDokterStateLoading) {
|
||||||
|
isLoadingSearchNoDokter.value = true;
|
||||||
|
} else if (next is PengantaranhasilDokterStateError) {
|
||||||
|
isLoadingSearchNoDokter.value = false;
|
||||||
|
errorMessage.value = next.message ?? "";
|
||||||
|
Timer(const Duration(seconds: 3), () {
|
||||||
|
errorMessage.value = "";
|
||||||
|
});
|
||||||
|
} else if (next is PengantaranhasilDokterStateDone) {
|
||||||
|
isLoadingSearchNoDokter.value = false;
|
||||||
|
if (next.model.isNotEmpty) {
|
||||||
|
hasilSearchData.value = next.model;
|
||||||
|
|
||||||
|
// klu lebih dari 1 length nya dibikin list view builder
|
||||||
|
// klu cm 1 seperti ini
|
||||||
|
|
||||||
|
if (hasilSearchData.value.length > 1) {
|
||||||
|
listViewBuilderShow.value = true;
|
||||||
|
singleListSearchShow.value = false;
|
||||||
|
} else {
|
||||||
|
// deliveryid merupakan json dari id
|
||||||
|
print('Delivery ID : ${hasilSearchData.value[0].deliveryid}');
|
||||||
|
print('Tipe ID : ${hasilSearchData.value[0].tipeid}');
|
||||||
|
print('Selected No Lab : ${hasilSearchData.value[0].nomor}');
|
||||||
|
print('Selected Nama : ${hasilSearchData.value[0].nama}');
|
||||||
|
print('Selected Alamat : ${hasilSearchData.value[0].alamat}');
|
||||||
|
|
||||||
|
// ctrlNoDokter.text = hasilSearchData.value[0].nomor.toString();
|
||||||
|
ctrlNoDokter.text = hasilSearchData.value[0].detail.toString();
|
||||||
|
ctrlNama.text = hasilSearchData.value[0].nama.toString();
|
||||||
|
ctrlAlamat.text = hasilSearchData.value[0].alamat.toString();
|
||||||
|
deliveryIDSave.value =
|
||||||
|
hasilSearchData.value[0].deliveryid.toString();
|
||||||
|
|
||||||
|
if (hasilSearchData.value[0].patients!.isNotEmpty) {
|
||||||
|
// hasilSearchData.value[0].patients?.forEach((element) {
|
||||||
|
// listPatient.value.add(element);
|
||||||
|
// });
|
||||||
|
listPatient.value = hasilSearchData.value[0].patients!;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
listPatient.value = [];
|
||||||
|
hasilSearchData.value = [];
|
||||||
|
ctrlNoDokter.text = "";
|
||||||
|
ctrlNama.text = "";
|
||||||
|
ctrlAlamat.text = "";
|
||||||
|
SanckbarWidget(context, "Data Tidak Ditemukan", snackbarType.warning);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// save pengantaran hasil
|
||||||
|
ref.listen(pengantaranHasilDokterSave, (prev, next) {
|
||||||
|
if (next is PengantaranhasilDokterSaveStateLoading) {
|
||||||
|
isLoadingSearchNoDokter.value = true;
|
||||||
|
} else if (next is PengantaranhasilDokterSaveStateError) {
|
||||||
|
isLoadingSearchNoDokter.value = false;
|
||||||
|
errorMessage.value = next.message ?? "";
|
||||||
|
SanckbarWidget(context, "${next.message}", snackbarType.error);
|
||||||
|
Timer(const Duration(seconds: 3), () {
|
||||||
|
errorMessage.value = "";
|
||||||
|
});
|
||||||
|
} else if (next is PengantaranhasilDokterSaveStateDone) {
|
||||||
|
isLoadingSearchNoDokter.value = false;
|
||||||
|
if (next.model.status != "OK") {
|
||||||
|
SanckbarWidget(context, "${next.model.message}", snackbarType.error);
|
||||||
|
} else {
|
||||||
|
Navigator.of(context).pushNamedAndRemoveUntil(
|
||||||
|
konfirmasiRoute,
|
||||||
|
(route) => false,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// check kalau pake scan
|
||||||
|
useEffect(() {
|
||||||
|
WidgetsBinding.instance.addPostFrameCallback((timeStamp) async {
|
||||||
|
final barcodeScanResultValue = ref.read(barcodeScanResult);
|
||||||
|
print("barcode Scan Result: $barcodeScanResultValue");
|
||||||
|
print("Is from scan : ${isFromScanScreen}");
|
||||||
|
|
||||||
|
if (isFromScanScreenProvider == true) {
|
||||||
|
if (barcodeScanResultValue != "") {
|
||||||
|
isForm.value = true;
|
||||||
|
isScan.value = false;
|
||||||
|
ref
|
||||||
|
.read(pengantaranHasilDokterSearch.notifier)
|
||||||
|
.loadListNoDokterPengantaranHasilDokter(
|
||||||
|
search: barcodeScanResultValue,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
ref.read(barcodeScanResult.notifier).update((state) => "");
|
||||||
|
ref.read(isFromScanScreen.notifier).update((state) => false);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
return Container(
|
||||||
|
width: Constant.getActualX(context: context, x: 320),
|
||||||
|
height: Constant.getActualY(context: context, y: 544),
|
||||||
|
padding: EdgeInsets.only(
|
||||||
|
bottom: Constant.getActualY(context: context, y: 20),
|
||||||
|
),
|
||||||
|
// color: Colors.pink,
|
||||||
|
child: ListView(
|
||||||
|
children: [
|
||||||
|
// tab nolab & scanner
|
||||||
|
Container(
|
||||||
|
width: Constant.getActualX(context: context, x: 320),
|
||||||
|
height: Constant.getActualY(context: context, y: 36),
|
||||||
|
child: Row(
|
||||||
|
children: [
|
||||||
|
// button form kiri
|
||||||
|
SizedBox(
|
||||||
|
width: Constant.getActualX(context: context, x: 156),
|
||||||
|
height: Constant.getActualY(context: context, y: 36),
|
||||||
|
child: ElevatedButton(
|
||||||
|
// onPressed: () {
|
||||||
|
// isForm.value = !isForm.value;
|
||||||
|
// isScan.value = !isScan.value;
|
||||||
|
// },
|
||||||
|
onPressed: () {
|
||||||
|
if (isForm.value == true) {
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
isForm.value = true;
|
||||||
|
isScan.value = false;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
style: ButtonStyle(
|
||||||
|
backgroundColor: (isForm.value == true)
|
||||||
|
? MaterialStateColor.resolveWith(
|
||||||
|
(st) => Constant.primaryMain)
|
||||||
|
: MaterialStateColor.resolveWith(
|
||||||
|
(st) => Constant.buttonIsNotActive),
|
||||||
|
shape: MaterialStateProperty.all<RoundedRectangleBorder>(
|
||||||
|
RoundedRectangleBorder(
|
||||||
|
borderRadius: BorderRadius.only(
|
||||||
|
bottomLeft: Radius.circular(12),
|
||||||
|
topLeft: Radius.circular(12)),
|
||||||
|
// side: BorderSide(color: Colors.red),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
shadowColor:
|
||||||
|
MaterialStateProperty.all(Color(0xffff48423d)),
|
||||||
|
elevation: MaterialStateProperty.all(4.0),
|
||||||
|
),
|
||||||
|
child: Align(
|
||||||
|
alignment: Alignment.center,
|
||||||
|
child: Text(
|
||||||
|
'Form',
|
||||||
|
style: Constant.buttonLarge(context: context).copyWith(
|
||||||
|
color: (isForm.value == true)
|
||||||
|
? Constant.backgroundWhite
|
||||||
|
: Constant.textBlack,
|
||||||
|
fontWeight: FontWeight.w700,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
|
||||||
|
SizedBox(
|
||||||
|
width: Constant.getActualX(context: context, x: 8),
|
||||||
|
),
|
||||||
|
// button scan kanan
|
||||||
|
|
||||||
|
SizedBox(
|
||||||
|
width: Constant.getActualX(context: context, x: 156),
|
||||||
|
height: Constant.getActualY(context: context, y: 36),
|
||||||
|
child: ElevatedButton(
|
||||||
|
// onPressed: () {
|
||||||
|
// isScan.value = !isScan.value;
|
||||||
|
// isForm.value = !isForm.value;
|
||||||
|
// },
|
||||||
|
onPressed: () {
|
||||||
|
// isScan.value = !isScan.value;
|
||||||
|
// isForm.value = !isForm.value;
|
||||||
|
|
||||||
|
if (isScan.value == true) {
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
isForm.value = false;
|
||||||
|
isScan.value = true;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
style: ButtonStyle(
|
||||||
|
backgroundColor: (isScan.value == true)
|
||||||
|
? MaterialStateColor.resolveWith(
|
||||||
|
(st) => Constant.primaryMain)
|
||||||
|
: MaterialStateColor.resolveWith(
|
||||||
|
(st) => Constant.buttonIsNotActive),
|
||||||
|
shape: MaterialStateProperty.all<RoundedRectangleBorder>(
|
||||||
|
RoundedRectangleBorder(
|
||||||
|
borderRadius: BorderRadius.only(
|
||||||
|
bottomRight: Radius.circular(12),
|
||||||
|
topRight: Radius.circular(12),
|
||||||
|
),
|
||||||
|
// side: BorderSide(color: Colors.red),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
shadowColor:
|
||||||
|
MaterialStateProperty.all(Color(0xffff48423d)),
|
||||||
|
elevation: MaterialStateProperty.all(4.0),
|
||||||
|
),
|
||||||
|
child: Align(
|
||||||
|
alignment: Alignment.center,
|
||||||
|
child: Text(
|
||||||
|
'Scan',
|
||||||
|
style: Constant.buttonLarge(context: context).copyWith(
|
||||||
|
color: (isScan.value == true)
|
||||||
|
? Constant.backgroundWhite
|
||||||
|
: Constant.textBlack,
|
||||||
|
fontWeight: FontWeight.w700,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
|
||||||
|
if (isForm.value == true) ...[
|
||||||
|
// button batal & simpan jika isForm true
|
||||||
|
SizedBox(
|
||||||
|
height: Constant.getActualY(context: context, y: 20),
|
||||||
|
),
|
||||||
|
|
||||||
|
// loading
|
||||||
|
if (isLoadingSearchNoDokter.value) ...[
|
||||||
|
// Center(
|
||||||
|
// child: SizedBox(
|
||||||
|
// width: Constant.getActualX(context: context, x: 20),
|
||||||
|
// height: Constant.getActualY(context: context, y: 20),
|
||||||
|
// child: CircularProgressIndicator(),
|
||||||
|
// ),
|
||||||
|
// ),
|
||||||
|
const Center(
|
||||||
|
child: CircularProgressIndicator(),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
|
||||||
|
SizedBox(
|
||||||
|
height: Constant.getActualY(context: context, y: 20),
|
||||||
|
),
|
||||||
|
|
||||||
|
// muncul jika hasil search data > 1
|
||||||
|
if (listViewBuilderShow.value) ...[
|
||||||
|
Container(
|
||||||
|
width: Constant.getActualX(context: context, x: 320),
|
||||||
|
// height: Constant.getActualY(context: context, y: 56),
|
||||||
|
child: SasTextFieldSearch(
|
||||||
|
controller: ctrlNoDokter,
|
||||||
|
hintText: "Nama[Kode]",
|
||||||
|
labelText: "Nama[Kode]",
|
||||||
|
focusNode: focusNodeNoDokter,
|
||||||
|
hasFocus: nodokterhasFocus.value,
|
||||||
|
isReadOnly: false,
|
||||||
|
onPressed: () {
|
||||||
|
if (ctrlNoDokter.text != "" ||
|
||||||
|
ctrlNoDokter.text.isNotEmpty) {
|
||||||
|
if (ctrlNoDokter.text.length >= 3) {
|
||||||
|
ref
|
||||||
|
.read(pengantaranHasilDokterSearch.notifier)
|
||||||
|
.loadListNoDokterPengantaranHasilDokter(
|
||||||
|
search: ctrlNoDokter.text.toString(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
SanckbarWidget(
|
||||||
|
context,
|
||||||
|
"Silahkan Masukkan Keyword Pencarian",
|
||||||
|
snackbarType.warning);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
SizedBox(
|
||||||
|
height: Constant.getActualY(context: context, y: 10),
|
||||||
|
),
|
||||||
|
Container(
|
||||||
|
padding: EdgeInsets.symmetric(horizontal: 0.9, vertical: 0.5),
|
||||||
|
height: Constant.getActualY(context: context, y: 290),
|
||||||
|
child: ListView.builder(
|
||||||
|
itemCount: hasilSearchData.value.length,
|
||||||
|
itemBuilder: (context, index) {
|
||||||
|
return InkWell(
|
||||||
|
onTap: () {
|
||||||
|
// ctrlNoDokter.text =
|
||||||
|
// hasilSearchData.value[index].nomor.toString();
|
||||||
|
ctrlNoDokter.text =
|
||||||
|
hasilSearchData.value[index].detail.toString();
|
||||||
|
ctrlNama.text =
|
||||||
|
hasilSearchData.value[index].nama.toString();
|
||||||
|
ctrlAlamat.text =
|
||||||
|
hasilSearchData.value[index].alamat.toString();
|
||||||
|
deliveryIDSave.value = hasilSearchData
|
||||||
|
.value[index].deliveryid
|
||||||
|
.toString();
|
||||||
|
|
||||||
|
if (hasilSearchData
|
||||||
|
.value[index].patients!.isNotEmpty) {
|
||||||
|
// hasilSearchData.value[index].patients?.forEach((element) {
|
||||||
|
// listPatient.value.add(element);
|
||||||
|
// });
|
||||||
|
listPatient.value =
|
||||||
|
hasilSearchData.value[index].patients!;
|
||||||
|
}
|
||||||
|
listViewBuilderShow.value = false;
|
||||||
|
singleListSearchShow.value = true;
|
||||||
|
},
|
||||||
|
child: Padding(
|
||||||
|
padding: const EdgeInsets.only(bottom: 10),
|
||||||
|
child: Container(
|
||||||
|
padding: EdgeInsets.symmetric(
|
||||||
|
horizontal: Constant.getActualX(
|
||||||
|
context: context, x: 24),
|
||||||
|
vertical: Constant.getActualY(
|
||||||
|
context: context, y: 20)),
|
||||||
|
margin: EdgeInsets.symmetric(
|
||||||
|
vertical:
|
||||||
|
Constant.getActualY(context: context, y: 4),
|
||||||
|
horizontal: Constant.getActualX(
|
||||||
|
context: context, x: 1)),
|
||||||
|
// height: Constant.getActualY(context: context, y: 76),
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: Colors.white,
|
||||||
|
border:
|
||||||
|
Border.all(color: Colors.grey, width: 0.1),
|
||||||
|
boxShadow: [
|
||||||
|
BoxShadow(
|
||||||
|
color: Colors.grey.shade300,
|
||||||
|
offset: const Offset(0.0, 1), //(x,y)
|
||||||
|
blurRadius: 2,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
borderRadius: BorderRadius.circular(12)),
|
||||||
|
child: Column(
|
||||||
|
children: [
|
||||||
|
Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.start,
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Expanded(
|
||||||
|
child: Text(
|
||||||
|
"Nomor",
|
||||||
|
style: Constant.caption1(
|
||||||
|
context: context)
|
||||||
|
.copyWith(
|
||||||
|
fontWeight: FontWeight.w400,
|
||||||
|
color: Constant.textPrimary),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Expanded(
|
||||||
|
child: Text(
|
||||||
|
hasilSearchData.value[index].nomor
|
||||||
|
.toString(),
|
||||||
|
// 's',
|
||||||
|
maxLines: 2,
|
||||||
|
overflow: TextOverflow.ellipsis,
|
||||||
|
style: Constant.caption1(
|
||||||
|
context: context)
|
||||||
|
.copyWith(
|
||||||
|
fontWeight: FontWeight.w400,
|
||||||
|
color: Constant.textPrimary),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
SizedBox(
|
||||||
|
height: Constant.getActualY(
|
||||||
|
context: context, y: 4),
|
||||||
|
),
|
||||||
|
Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.start,
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Expanded(
|
||||||
|
child: Text(
|
||||||
|
"Nama",
|
||||||
|
style: Constant.caption1(
|
||||||
|
context: context)
|
||||||
|
.copyWith(
|
||||||
|
fontWeight: FontWeight.w400,
|
||||||
|
color: Constant.textPrimary),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Expanded(
|
||||||
|
child: Text(
|
||||||
|
hasilSearchData.value[index].nama
|
||||||
|
.toString(),
|
||||||
|
// 's',
|
||||||
|
maxLines: 2,
|
||||||
|
overflow: TextOverflow.ellipsis,
|
||||||
|
style: Constant.caption1(
|
||||||
|
context: context)
|
||||||
|
.copyWith(
|
||||||
|
fontWeight: FontWeight.w400,
|
||||||
|
color: Constant.textPrimary),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.start,
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Expanded(
|
||||||
|
child: Text(
|
||||||
|
"Alamat Pengantaran",
|
||||||
|
style: Constant.caption1(
|
||||||
|
context: context)
|
||||||
|
.copyWith(
|
||||||
|
fontWeight: FontWeight.w400,
|
||||||
|
color: Constant.textPrimary),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Expanded(
|
||||||
|
child: Text(
|
||||||
|
hasilSearchData.value[index].alamat
|
||||||
|
.toString(),
|
||||||
|
// 's',
|
||||||
|
maxLines: 2,
|
||||||
|
overflow: TextOverflow.ellipsis,
|
||||||
|
style: Constant.caption1(
|
||||||
|
context: context)
|
||||||
|
.copyWith(
|
||||||
|
fontWeight: FontWeight.w400,
|
||||||
|
color: Constant.textPrimary),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
|
||||||
|
// single list show
|
||||||
|
if (singleListSearchShow.value) ...[
|
||||||
|
// no lab autocomplete
|
||||||
|
Container(
|
||||||
|
width: Constant.getActualX(context: context, x: 320),
|
||||||
|
// height: Constant.getActualY(context: context, y: 56),
|
||||||
|
child: SasTextFieldSearch(
|
||||||
|
controller: ctrlNoDokter,
|
||||||
|
hintText: "Nama[Kode]",
|
||||||
|
labelText: "Nama[Kode]",
|
||||||
|
focusNode: focusNodeNoDokter,
|
||||||
|
hasFocus: nodokterhasFocus.value,
|
||||||
|
isReadOnly: false,
|
||||||
|
onPressed: () {
|
||||||
|
if (ctrlNoDokter.text != "" ||
|
||||||
|
ctrlNoDokter.text.isNotEmpty) {
|
||||||
|
if (ctrlNoDokter.text.length >= 3) {
|
||||||
|
ref
|
||||||
|
.read(pengantaranHasilDokterSearch.notifier)
|
||||||
|
.loadListNoDokterPengantaranHasilDokter(
|
||||||
|
search: ctrlNoDokter.text.toString(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
SanckbarWidget(
|
||||||
|
context,
|
||||||
|
"Silahkan Masukkan Keyword Pencarian",
|
||||||
|
snackbarType.warning);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
|
||||||
|
SizedBox(
|
||||||
|
height: Constant.getActualY(context: context, y: 20),
|
||||||
|
),
|
||||||
|
|
||||||
|
// // nama
|
||||||
|
// Container(
|
||||||
|
// width: Constant.getActualX(context: context, x: 320),
|
||||||
|
// height: Constant.getActualY(context: context, y: 56),
|
||||||
|
// child: SasTextField(
|
||||||
|
// hintText: "Nama",
|
||||||
|
// labelText: "Nama",
|
||||||
|
// focusNode: focusNodeNama,
|
||||||
|
// hasFocus: namahasFocus.value,
|
||||||
|
// controller: ctrlNama,
|
||||||
|
// isReadOnly: true,
|
||||||
|
// ),
|
||||||
|
// ),
|
||||||
|
// SizedBox(
|
||||||
|
// height: Constant.getActualY(context: context, y: 20),
|
||||||
|
// ),
|
||||||
|
// alamat
|
||||||
|
Container(
|
||||||
|
width: Constant.getActualX(context: context, x: 320),
|
||||||
|
height: Constant.getActualY(context: context, y: 120),
|
||||||
|
// color: Colors.green,
|
||||||
|
child: SasTextFieldArea(
|
||||||
|
hintText: "Alamat Pengantaran",
|
||||||
|
labelText: "Alamat Pengantaran",
|
||||||
|
focusNode: focusNodeAlamat,
|
||||||
|
hasFocus: alamathasFocus.value,
|
||||||
|
controller: ctrlAlamat,
|
||||||
|
isReadOnly: true,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
|
||||||
|
SizedBox(
|
||||||
|
height: Constant.getActualY(context: context, y: 10),
|
||||||
|
),
|
||||||
|
|
||||||
|
if (listPatient.value.isNotEmpty) ...[
|
||||||
|
for (var i = 0; i < listPatient.value.length; i++) ...[
|
||||||
|
Padding(
|
||||||
|
padding: EdgeInsets.only(
|
||||||
|
bottom: Constant.getActualY(context: context, y: 10)),
|
||||||
|
child: PatientCard(
|
||||||
|
name: listPatient.value[i].pasien.toString(),
|
||||||
|
noLab:
|
||||||
|
listPatient.value[i].tOrderHeaderLabNumber.toString(),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
] else ...[
|
||||||
|
SizedBox.shrink(),
|
||||||
|
SizedBox(
|
||||||
|
height: Constant.getActualY(context: context, y: 40),
|
||||||
|
)
|
||||||
|
],
|
||||||
|
],
|
||||||
|
|
||||||
|
// SizedBox(
|
||||||
|
// height: Constant.getActualY(context: context, y: 100),
|
||||||
|
// ),
|
||||||
|
|
||||||
|
Padding(
|
||||||
|
padding: EdgeInsets.only(
|
||||||
|
top: Constant.getActualY(context: context, y: 20),
|
||||||
|
bottom: Constant.getActualY(context: context, y: 20),
|
||||||
|
),
|
||||||
|
child: Align(
|
||||||
|
alignment: Alignment.bottomCenter,
|
||||||
|
child: Container(
|
||||||
|
// width: Constant.getActualX(context: context, x: 317),
|
||||||
|
// height: Constant.getActualY(context: context, y: 36),
|
||||||
|
// padding: EdgeInsets.symmetric(
|
||||||
|
// horizontal: Constant.getActualX(context: context, x: 10)),
|
||||||
|
height: Constant.getActualY(context: context, y: 36),
|
||||||
|
// color: Colors.pink,
|
||||||
|
child: Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
|
children: [
|
||||||
|
// batal
|
||||||
|
ElevatedButton(
|
||||||
|
onPressed: () {
|
||||||
|
Navigator.pop(context);
|
||||||
|
},
|
||||||
|
style: ButtonStyle(
|
||||||
|
backgroundColor: MaterialStateColor.resolveWith(
|
||||||
|
(st) => Constant.backgroundWhite),
|
||||||
|
shape:
|
||||||
|
MaterialStateProperty.all<RoundedRectangleBorder>(
|
||||||
|
RoundedRectangleBorder(
|
||||||
|
borderRadius: BorderRadius.circular(8),
|
||||||
|
side: BorderSide(color: Constant.blueButton),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
shadowColor:
|
||||||
|
MaterialStateProperty.all(Color(0xffff48423d)),
|
||||||
|
elevation: MaterialStateProperty.all(4.0),
|
||||||
|
),
|
||||||
|
child: Align(
|
||||||
|
alignment: Alignment.center,
|
||||||
|
child: Text(
|
||||||
|
'Batal',
|
||||||
|
style: Constant.body3(context: context).copyWith(
|
||||||
|
color: Constant.blueButton,
|
||||||
|
fontWeight: FontWeight.w700,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
|
||||||
|
// simpan
|
||||||
|
ElevatedButton(
|
||||||
|
onPressed: (isLoadingSearchNoDokter.value)
|
||||||
|
? null
|
||||||
|
: () {
|
||||||
|
print("kurir id : $mCourirID");
|
||||||
|
print("tipe id : $tipePekerjaanIDSave");
|
||||||
|
print("delivery id : ${deliveryIDSave.value}");
|
||||||
|
|
||||||
|
if (deliveryIDSave.value == "") {
|
||||||
|
SanckbarWidget(
|
||||||
|
context,
|
||||||
|
"Silahkan Cari No Dokter",
|
||||||
|
snackbarType.warning);
|
||||||
|
} else {
|
||||||
|
ref
|
||||||
|
.read(pengantaranHasilDokterSave.notifier)
|
||||||
|
.pengantaranHasilDokterSave(
|
||||||
|
courierID: mCourirID,
|
||||||
|
tipeID: tipePekerjaanIDSave,
|
||||||
|
deliveryID: deliveryIDSave.value,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
style: ButtonStyle(
|
||||||
|
backgroundColor: MaterialStateColor.resolveWith(
|
||||||
|
(st) => Constant.blueButton,
|
||||||
|
),
|
||||||
|
shape:
|
||||||
|
MaterialStateProperty.all<RoundedRectangleBorder>(
|
||||||
|
RoundedRectangleBorder(
|
||||||
|
borderRadius: BorderRadius.circular(8),
|
||||||
|
// side: BorderSide(color: Constant.blueButton),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
shadowColor:
|
||||||
|
MaterialStateProperty.all(Color(0xffff48423d)),
|
||||||
|
elevation: MaterialStateProperty.all(4.0),
|
||||||
|
),
|
||||||
|
child: Align(
|
||||||
|
alignment: Alignment.center,
|
||||||
|
child: Text(
|
||||||
|
'Simpan',
|
||||||
|
style: Constant.body3(context: context).copyWith(
|
||||||
|
color: Constant.backgroundWhite,
|
||||||
|
fontWeight: FontWeight.w700,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
] else ...[
|
||||||
|
// button scan barcode
|
||||||
|
SizedBox(
|
||||||
|
height: Constant.getActualY(context: context, y: 445),
|
||||||
|
),
|
||||||
|
Container(
|
||||||
|
width: Constant.getActualX(context: context, x: 317),
|
||||||
|
height: Constant.getActualY(context: context, y: 36),
|
||||||
|
// color: Colors.pink,
|
||||||
|
child: SizedBox(
|
||||||
|
width: Constant.getActualX(context: context, x: 83),
|
||||||
|
height: Constant.getActualY(context: context, y: 36),
|
||||||
|
child: ElevatedButton(
|
||||||
|
onPressed: () {
|
||||||
|
FocusManager.instance.primaryFocus?.unfocus();
|
||||||
|
ref.read(isFromScanScreen.notifier).update((state) => true);
|
||||||
|
Navigator.of(context).pushNamedAndRemoveUntil(
|
||||||
|
inputScanRoute, (route) => false,
|
||||||
|
arguments: InputScanPekerjaanProp(0, 2));
|
||||||
|
},
|
||||||
|
style: ButtonStyle(
|
||||||
|
backgroundColor: MaterialStateColor.resolveWith(
|
||||||
|
(st) => Constant.blueButton),
|
||||||
|
shape: MaterialStateProperty.all<RoundedRectangleBorder>(
|
||||||
|
RoundedRectangleBorder(
|
||||||
|
borderRadius: BorderRadius.circular(8),
|
||||||
|
// side: BorderSide(color: Constant.blueButton),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
shadowColor: MaterialStateProperty.all(Color(0xffff48423d)),
|
||||||
|
elevation: MaterialStateProperty.all(4.0),
|
||||||
|
),
|
||||||
|
child: Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
|
children: [
|
||||||
|
Icon(Icons.document_scanner),
|
||||||
|
SizedBox(
|
||||||
|
width: Constant.getActualX(context: context, x: 10),
|
||||||
|
),
|
||||||
|
Text(
|
||||||
|
'Scan Barcode',
|
||||||
|
style: Constant.body3(context: context).copyWith(
|
||||||
|
color: Constant.backgroundWhite,
|
||||||
|
fontWeight: FontWeight.w700,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,811 @@
|
|||||||
|
import 'dart:async';
|
||||||
|
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_hooks/flutter_hooks.dart';
|
||||||
|
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||||
|
import '/app/route.dart';
|
||||||
|
|
||||||
|
import '../../app/constant.dart';
|
||||||
|
import '../../models/patient_model.dart';
|
||||||
|
import '../../models/response_search_pengantaran_hasil_model.dart';
|
||||||
|
import '../../provider/current_scan_provider.dart';
|
||||||
|
import '../../provider/current_user_provider.dart';
|
||||||
|
import '../../provider/dio_provider.dart';
|
||||||
|
import '../../repository/pengantaran_hasil_instansi_repository.dart';
|
||||||
|
import '../../widget/custom_textfield.dart';
|
||||||
|
import '../../widget/patient_card.dart';
|
||||||
|
import '../../widget/sas_textfield.dart';
|
||||||
|
import '../../widget/snackbar_widget.dart';
|
||||||
|
import 'pengantaran_hasil_instansi_loadnosuratjalan_provider.dart';
|
||||||
|
import 'pengantaran_hasil_instansi_save_provider.dart';
|
||||||
|
|
||||||
|
class InputPengantaranHasilInstansiScreen extends HookConsumerWidget {
|
||||||
|
// const InputPengantaranHasilInstansiScreen({
|
||||||
|
// super.key,
|
||||||
|
// });
|
||||||
|
|
||||||
|
const InputPengantaranHasilInstansiScreen({super.key, required this.data});
|
||||||
|
final Map<String, dynamic> data;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context, WidgetRef ref) {
|
||||||
|
print(data);
|
||||||
|
|
||||||
|
final tipePekerjaanIDSave = data['tipePekerjaan'];
|
||||||
|
final deliveryIDSave = useState<String>("");
|
||||||
|
final mCourirID =
|
||||||
|
ref.watch(currentUserProvider)?.model.user?.mCourierID ?? "0";
|
||||||
|
|
||||||
|
final isForm = useState(true);
|
||||||
|
final isScan = useState(false);
|
||||||
|
|
||||||
|
final dummySuratJalan =
|
||||||
|
useState<List<DummyNoSuratJalan>>(List.empty(growable: true));
|
||||||
|
|
||||||
|
final focusNodeCompany = useFocusNode();
|
||||||
|
final companyhasFocus = useState(false);
|
||||||
|
final isLoadingSearchSuratJalan = useState(false);
|
||||||
|
final ctrlNoCompany = useTextEditingController(text: "");
|
||||||
|
|
||||||
|
final dummyInstansiList =
|
||||||
|
useState<List<DummyNoSuratJalan>>(List.empty(growable: true));
|
||||||
|
|
||||||
|
final listPatient =
|
||||||
|
useState<List<PatientModel>>(List.empty(growable: true));
|
||||||
|
|
||||||
|
final hasilSearchData = useState<List<ResponseSearchPengantaranHasilModel>>(
|
||||||
|
List.empty(growable: true));
|
||||||
|
|
||||||
|
final ctrlNama = useTextEditingController(text: "");
|
||||||
|
final focusNodeNama = useFocusNode();
|
||||||
|
final namahasFocus = useState(false);
|
||||||
|
|
||||||
|
final ctrlAlamat = useTextEditingController(text: "");
|
||||||
|
final focusNodeAlamat = useFocusNode();
|
||||||
|
final alamathasFocus = useState(false);
|
||||||
|
final errorMessage = useState("");
|
||||||
|
|
||||||
|
final isFromScanScreenProvider = ref.read(isFromScanScreen);
|
||||||
|
|
||||||
|
final listViewBuilderShow = useState(false);
|
||||||
|
final singleListSearchShow = useState(true);
|
||||||
|
|
||||||
|
focusNodeCompany.addListener(() {
|
||||||
|
if (focusNodeCompany.hasFocus) {
|
||||||
|
companyhasFocus.value = true;
|
||||||
|
} else {
|
||||||
|
companyhasFocus.value = false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
focusNodeNama.addListener(() {
|
||||||
|
if (focusNodeNama.hasFocus) {
|
||||||
|
namahasFocus.value = true;
|
||||||
|
} else {
|
||||||
|
namahasFocus.value = false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
focusNodeAlamat.addListener(() {
|
||||||
|
if (focusNodeAlamat.hasFocus) {
|
||||||
|
alamathasFocus.value = true;
|
||||||
|
} else {
|
||||||
|
alamathasFocus.value = false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// useEffect(() {
|
||||||
|
// isForm.value = true;
|
||||||
|
// isScan.value = false;
|
||||||
|
// }, []);
|
||||||
|
|
||||||
|
// search
|
||||||
|
ref.listen(pengantaranHasilInstansi, (prev, next) {
|
||||||
|
if (next is PengantaranhasilInstansiStateLoading) {
|
||||||
|
isLoadingSearchSuratJalan.value = true;
|
||||||
|
} else if (next is PengantaranhasilInstansiStateError) {
|
||||||
|
isLoadingSearchSuratJalan.value = false;
|
||||||
|
errorMessage.value = next.message ?? "";
|
||||||
|
Timer(const Duration(seconds: 3), () {
|
||||||
|
errorMessage.value = "";
|
||||||
|
});
|
||||||
|
} else if (next is PengantaranhasilInstansiStateDone) {
|
||||||
|
isLoadingSearchSuratJalan.value = false;
|
||||||
|
// listSearch.value = next.model;
|
||||||
|
|
||||||
|
if (next.model.isNotEmpty) {
|
||||||
|
hasilSearchData.value = next.model;
|
||||||
|
|
||||||
|
// klu lebih dari 1 length nya dibikin list view builder
|
||||||
|
// klu cm 1 seperti ini
|
||||||
|
|
||||||
|
if (hasilSearchData.value.length > 1) {
|
||||||
|
listViewBuilderShow.value = true;
|
||||||
|
singleListSearchShow.value = false;
|
||||||
|
} else {
|
||||||
|
// hanya 1
|
||||||
|
listViewBuilderShow.value = false;
|
||||||
|
singleListSearchShow.value = true;
|
||||||
|
// deliveryid merupakan json dari id
|
||||||
|
print('Delivery ID : ${hasilSearchData.value[0].deliveryid}');
|
||||||
|
print('Tipe ID : ${hasilSearchData.value[0].tipeid}');
|
||||||
|
print('Selected No Instansi : ${hasilSearchData.value[0].nomor}');
|
||||||
|
print('Selected Detail : ${hasilSearchData.value[0].detail}');
|
||||||
|
print('Selected Nama : ${hasilSearchData.value[0].nama}');
|
||||||
|
print('Selected Alamat : ${hasilSearchData.value[0].alamat}');
|
||||||
|
|
||||||
|
// ctrlNoCompany.text = hasilSearchData.value[0].nomor.toString();
|
||||||
|
ctrlNoCompany.text = hasilSearchData.value[0].detail.toString();
|
||||||
|
ctrlNama.text = hasilSearchData.value[0].nama.toString();
|
||||||
|
ctrlAlamat.text = hasilSearchData.value[0].alamat.toString();
|
||||||
|
deliveryIDSave.value =
|
||||||
|
hasilSearchData.value[0].deliveryid.toString();
|
||||||
|
|
||||||
|
if (hasilSearchData.value[0].patients!.isNotEmpty) {
|
||||||
|
// hasilSearchData.value[0].patients?.forEach((element) {
|
||||||
|
// listPatient.value.add(element);
|
||||||
|
// });
|
||||||
|
listPatient.value = hasilSearchData.value[0].patients!;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
listPatient.value = [];
|
||||||
|
hasilSearchData.value = [];
|
||||||
|
ctrlNoCompany.text = "";
|
||||||
|
ctrlNama.text = "";
|
||||||
|
ctrlAlamat.text = "";
|
||||||
|
ref.read(barcodeScanResult.notifier).update((state) => "");
|
||||||
|
ref.read(isFromScanScreen.notifier).update((state) => false);
|
||||||
|
SanckbarWidget(context, "Data Tidak Ditemukan", snackbarType.warning);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// save pengantaran hasil
|
||||||
|
ref.listen(pengantaranHasilCompanySave, (prev, next) {
|
||||||
|
if (next is PengantaranhasilCompanySaveStateLoading) {
|
||||||
|
isLoadingSearchSuratJalan.value = true;
|
||||||
|
} else if (next is PengantaranhasilCompanySaveStateError) {
|
||||||
|
isLoadingSearchSuratJalan.value = false;
|
||||||
|
errorMessage.value = next.message ?? "";
|
||||||
|
SanckbarWidget(context, "${next.message}", snackbarType.error);
|
||||||
|
Timer(const Duration(seconds: 3), () {
|
||||||
|
errorMessage.value = "";
|
||||||
|
});
|
||||||
|
} else if (next is PengantaranhasilCompanySaveStateDone) {
|
||||||
|
isLoadingSearchSuratJalan.value = false;
|
||||||
|
if (next.model.status != "OK") {
|
||||||
|
SanckbarWidget(context, "${next.model.message}", snackbarType.error);
|
||||||
|
} else {
|
||||||
|
Navigator.of(context).pushNamedAndRemoveUntil(
|
||||||
|
konfirmasiRoute,
|
||||||
|
(route) => false,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// check kalau pake scan
|
||||||
|
useEffect(() {
|
||||||
|
WidgetsBinding.instance.addPostFrameCallback((timeStamp) async {
|
||||||
|
final barcodeScanResultValue = ref.read(barcodeScanResult);
|
||||||
|
print("barcode Scan Result: $barcodeScanResultValue");
|
||||||
|
print("Is from scan : ${isFromScanScreen}");
|
||||||
|
|
||||||
|
if (isFromScanScreenProvider == true) {
|
||||||
|
if (barcodeScanResultValue != "") {
|
||||||
|
isForm.value = true;
|
||||||
|
isScan.value = false;
|
||||||
|
ref
|
||||||
|
.read(pengantaranHasilInstansi.notifier)
|
||||||
|
.loadListNoSuratJalanPengantaranHasilInstansi(
|
||||||
|
search: barcodeScanResultValue,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
ref.read(barcodeScanResult.notifier).update((state) => "");
|
||||||
|
ref.read(isFromScanScreen.notifier).update((state) => false);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
return Container(
|
||||||
|
width: Constant.getActualX(context: context, x: 320),
|
||||||
|
height: Constant.getActualY(context: context, y: 544),
|
||||||
|
// color: Colors.pink,
|
||||||
|
child: ListView(
|
||||||
|
children: [
|
||||||
|
// tab nolab & scanner
|
||||||
|
Container(
|
||||||
|
width: Constant.getActualX(context: context, x: 320),
|
||||||
|
height: Constant.getActualY(context: context, y: 36),
|
||||||
|
child: Row(
|
||||||
|
children: [
|
||||||
|
// button form kiri
|
||||||
|
SizedBox(
|
||||||
|
width: Constant.getActualX(context: context, x: 156),
|
||||||
|
height: Constant.getActualY(context: context, y: 36),
|
||||||
|
child: ElevatedButton(
|
||||||
|
// onPressed: () {
|
||||||
|
// isForm.value = !isForm.value;
|
||||||
|
// isScan.value = !isScan.value;
|
||||||
|
// },
|
||||||
|
onPressed: () {
|
||||||
|
if (isForm.value == true) {
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
isForm.value = true;
|
||||||
|
isScan.value = false;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
style: ButtonStyle(
|
||||||
|
backgroundColor: (isForm.value == true)
|
||||||
|
? MaterialStateColor.resolveWith(
|
||||||
|
(st) => Constant.primaryMain)
|
||||||
|
: MaterialStateColor.resolveWith(
|
||||||
|
(st) => Constant.buttonIsNotActive),
|
||||||
|
shape: MaterialStateProperty.all<RoundedRectangleBorder>(
|
||||||
|
RoundedRectangleBorder(
|
||||||
|
borderRadius: BorderRadius.only(
|
||||||
|
bottomLeft: Radius.circular(12),
|
||||||
|
topLeft: Radius.circular(12)),
|
||||||
|
// side: BorderSide(color: Colors.red),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
shadowColor:
|
||||||
|
MaterialStateProperty.all(Color(0xffff48423d)),
|
||||||
|
elevation: MaterialStateProperty.all(4.0),
|
||||||
|
),
|
||||||
|
child: Align(
|
||||||
|
alignment: Alignment.center,
|
||||||
|
child: Text(
|
||||||
|
'Form',
|
||||||
|
style: Constant.buttonLarge(context: context).copyWith(
|
||||||
|
color: (isForm.value == true)
|
||||||
|
? Constant.backgroundWhite
|
||||||
|
: Constant.textBlack,
|
||||||
|
fontWeight: FontWeight.w700,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
|
||||||
|
SizedBox(
|
||||||
|
width: Constant.getActualX(context: context, x: 8),
|
||||||
|
),
|
||||||
|
// button scan kanan
|
||||||
|
|
||||||
|
SizedBox(
|
||||||
|
width: Constant.getActualX(context: context, x: 156),
|
||||||
|
height: Constant.getActualY(context: context, y: 36),
|
||||||
|
child: ElevatedButton(
|
||||||
|
// onPressed: () {
|
||||||
|
// isScan.value = !isScan.value;
|
||||||
|
// isForm.value = !isForm.value;
|
||||||
|
// },
|
||||||
|
onPressed: () {
|
||||||
|
if (isScan.value == true) {
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
isForm.value = false;
|
||||||
|
isScan.value = true;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
style: ButtonStyle(
|
||||||
|
backgroundColor: (isScan.value == true)
|
||||||
|
? MaterialStateColor.resolveWith(
|
||||||
|
(st) => Constant.primaryMain)
|
||||||
|
: MaterialStateColor.resolveWith(
|
||||||
|
(st) => Constant.buttonIsNotActive),
|
||||||
|
shape: MaterialStateProperty.all<RoundedRectangleBorder>(
|
||||||
|
RoundedRectangleBorder(
|
||||||
|
borderRadius: BorderRadius.only(
|
||||||
|
bottomRight: Radius.circular(12),
|
||||||
|
topRight: Radius.circular(12),
|
||||||
|
),
|
||||||
|
// side: BorderSide(color: Colors.red),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
shadowColor:
|
||||||
|
MaterialStateProperty.all(Color(0xffff48423d)),
|
||||||
|
elevation: MaterialStateProperty.all(4.0),
|
||||||
|
),
|
||||||
|
child: Align(
|
||||||
|
alignment: Alignment.center,
|
||||||
|
child: Text(
|
||||||
|
'Scan',
|
||||||
|
style: Constant.buttonLarge(context: context).copyWith(
|
||||||
|
color: (isScan.value == true)
|
||||||
|
? Constant.backgroundWhite
|
||||||
|
: Constant.textBlack,
|
||||||
|
fontWeight: FontWeight.w700,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
|
||||||
|
if (isForm.value == true) ...[
|
||||||
|
// button batal & simpan jika isForm true
|
||||||
|
SizedBox(
|
||||||
|
height: Constant.getActualY(context: context, y: 20),
|
||||||
|
),
|
||||||
|
|
||||||
|
// loading
|
||||||
|
if (isLoadingSearchSuratJalan.value) ...[
|
||||||
|
// Center(
|
||||||
|
// child: SizedBox(
|
||||||
|
// width: Constant.getActualX(context: context, x: 20),
|
||||||
|
// height: Constant.getActualY(context: context, y: 20),
|
||||||
|
// child: CircularProgressIndicator(),
|
||||||
|
// ),
|
||||||
|
// ),
|
||||||
|
const Center(
|
||||||
|
child: CircularProgressIndicator(),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
|
||||||
|
SizedBox(
|
||||||
|
height: Constant.getActualY(context: context, y: 20),
|
||||||
|
),
|
||||||
|
|
||||||
|
// muncul jika hasil search data > 1
|
||||||
|
if (listViewBuilderShow.value) ...[
|
||||||
|
Container(
|
||||||
|
width: Constant.getActualX(context: context, x: 320),
|
||||||
|
// height: Constant.getActualY(context: context, y: 56),
|
||||||
|
child: SasTextFieldSearch(
|
||||||
|
controller: ctrlNoCompany,
|
||||||
|
// hintText: "No Company",
|
||||||
|
// labelText: "No Company",
|
||||||
|
hintText: "Nama[Kode]",
|
||||||
|
labelText: "Nama[Kode]",
|
||||||
|
focusNode: focusNodeCompany,
|
||||||
|
hasFocus: companyhasFocus.value,
|
||||||
|
isReadOnly: false,
|
||||||
|
onPressed: () {
|
||||||
|
if (ctrlNoCompany.text != "" ||
|
||||||
|
ctrlNoCompany.text.isNotEmpty) {
|
||||||
|
if (ctrlNoCompany.text.length >= 3) {
|
||||||
|
ref
|
||||||
|
.read(pengantaranHasilInstansi.notifier)
|
||||||
|
.loadListNoSuratJalanPengantaranHasilInstansi(
|
||||||
|
search: ctrlNoCompany.text.toString(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
SanckbarWidget(
|
||||||
|
context,
|
||||||
|
"Silahkan Masukkan Keyword Pencarian",
|
||||||
|
snackbarType.warning);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
SizedBox(
|
||||||
|
height: Constant.getActualY(context: context, y: 10),
|
||||||
|
),
|
||||||
|
Container(
|
||||||
|
padding: EdgeInsets.symmetric(horizontal: 0.9, vertical: 0.5),
|
||||||
|
height: Constant.getActualY(context: context, y: 290),
|
||||||
|
child: ListView.builder(
|
||||||
|
itemCount: hasilSearchData.value.length,
|
||||||
|
itemBuilder: (context, index) {
|
||||||
|
return InkWell(
|
||||||
|
onTap: () {
|
||||||
|
// ctrlNoCompany.text =
|
||||||
|
// hasilSearchData.value[index].nomor.toString();
|
||||||
|
ctrlNoCompany.text =
|
||||||
|
hasilSearchData.value[index].detail.toString();
|
||||||
|
ctrlNama.text =
|
||||||
|
hasilSearchData.value[index].nama.toString();
|
||||||
|
ctrlAlamat.text =
|
||||||
|
hasilSearchData.value[index].alamat.toString();
|
||||||
|
|
||||||
|
if (hasilSearchData
|
||||||
|
.value[index].patients!.isNotEmpty) {
|
||||||
|
// hasilSearchData.value[index].patients?.forEach((element) {
|
||||||
|
// listPatient.value.add(element);
|
||||||
|
// });
|
||||||
|
listPatient.value =
|
||||||
|
hasilSearchData.value[index].patients!;
|
||||||
|
}
|
||||||
|
deliveryIDSave.value =
|
||||||
|
hasilSearchData.value[index].deliveryid.toString();
|
||||||
|
listViewBuilderShow.value = false;
|
||||||
|
singleListSearchShow.value = true;
|
||||||
|
},
|
||||||
|
child: Padding(
|
||||||
|
padding: const EdgeInsets.only(bottom: 10),
|
||||||
|
child: Container(
|
||||||
|
padding: EdgeInsets.symmetric(
|
||||||
|
horizontal: Constant.getActualX(
|
||||||
|
context: context, x: 24),
|
||||||
|
vertical: Constant.getActualY(
|
||||||
|
context: context, y: 20)),
|
||||||
|
margin: EdgeInsets.symmetric(
|
||||||
|
vertical:
|
||||||
|
Constant.getActualY(context: context, y: 4),
|
||||||
|
horizontal: Constant.getActualX(
|
||||||
|
context: context, x: 1)),
|
||||||
|
// height: Constant.getActualY(context: context, y: 76),
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: Colors.white,
|
||||||
|
border:
|
||||||
|
Border.all(color: Colors.grey, width: 0.1),
|
||||||
|
boxShadow: [
|
||||||
|
BoxShadow(
|
||||||
|
color: Colors.grey.shade300,
|
||||||
|
offset: const Offset(0.0, 1), //(x,y)
|
||||||
|
blurRadius: 2,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
borderRadius: BorderRadius.circular(12)),
|
||||||
|
child: Column(
|
||||||
|
children: [
|
||||||
|
Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.start,
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Expanded(
|
||||||
|
child: Text(
|
||||||
|
"Nomor",
|
||||||
|
style: Constant.caption1(
|
||||||
|
context: context)
|
||||||
|
.copyWith(
|
||||||
|
fontWeight: FontWeight.w400,
|
||||||
|
color: Constant.textPrimary),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Expanded(
|
||||||
|
child: Text(
|
||||||
|
hasilSearchData.value[index].nomor
|
||||||
|
.toString(),
|
||||||
|
// 's',
|
||||||
|
maxLines: 2,
|
||||||
|
overflow: TextOverflow.ellipsis,
|
||||||
|
style: Constant.caption1(
|
||||||
|
context: context)
|
||||||
|
.copyWith(
|
||||||
|
fontWeight: FontWeight.w400,
|
||||||
|
color: Constant.textPrimary),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
SizedBox(
|
||||||
|
height: Constant.getActualY(
|
||||||
|
context: context, y: 4),
|
||||||
|
),
|
||||||
|
Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.start,
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Expanded(
|
||||||
|
child: Text(
|
||||||
|
"Nama",
|
||||||
|
style: Constant.caption1(
|
||||||
|
context: context)
|
||||||
|
.copyWith(
|
||||||
|
fontWeight: FontWeight.w400,
|
||||||
|
color: Constant.textPrimary),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Expanded(
|
||||||
|
child: Text(
|
||||||
|
hasilSearchData.value[index].nama
|
||||||
|
.toString(),
|
||||||
|
// 's',
|
||||||
|
maxLines: 2,
|
||||||
|
overflow: TextOverflow.ellipsis,
|
||||||
|
style: Constant.caption1(
|
||||||
|
context: context)
|
||||||
|
.copyWith(
|
||||||
|
fontWeight: FontWeight.w400,
|
||||||
|
color: Constant.textPrimary),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.start,
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Expanded(
|
||||||
|
child: Text(
|
||||||
|
"Alamat Pengantaran",
|
||||||
|
style: Constant.caption1(
|
||||||
|
context: context)
|
||||||
|
.copyWith(
|
||||||
|
fontWeight: FontWeight.w400,
|
||||||
|
color: Constant.textPrimary),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Expanded(
|
||||||
|
child: Text(
|
||||||
|
hasilSearchData.value[index].alamat
|
||||||
|
.toString(),
|
||||||
|
// 's',
|
||||||
|
maxLines: 2,
|
||||||
|
overflow: TextOverflow.ellipsis,
|
||||||
|
style: Constant.caption1(
|
||||||
|
context: context)
|
||||||
|
.copyWith(
|
||||||
|
fontWeight: FontWeight.w400,
|
||||||
|
color: Constant.textPrimary),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
],
|
||||||
|
|
||||||
|
// single list show
|
||||||
|
if (singleListSearchShow.value) ...[
|
||||||
|
// no lab autocomplete
|
||||||
|
Container(
|
||||||
|
width: Constant.getActualX(context: context, x: 320),
|
||||||
|
// height: Constant.getActualY(context: context, y: 56),
|
||||||
|
child: SasTextFieldSearch(
|
||||||
|
controller: ctrlNoCompany,
|
||||||
|
hintText: "Nama[Kode]",
|
||||||
|
labelText: "Nama[Kode]",
|
||||||
|
// labelText: "No Company",
|
||||||
|
focusNode: focusNodeCompany,
|
||||||
|
hasFocus: companyhasFocus.value,
|
||||||
|
isReadOnly: false,
|
||||||
|
onPressed: () {
|
||||||
|
if (ctrlNoCompany.text != "" ||
|
||||||
|
ctrlNoCompany.text.isNotEmpty) {
|
||||||
|
if (ctrlNoCompany.text.length >= 3) {
|
||||||
|
ref
|
||||||
|
.read(pengantaranHasilInstansi.notifier)
|
||||||
|
.loadListNoSuratJalanPengantaranHasilInstansi(
|
||||||
|
search: ctrlNoCompany.text.toString(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
SanckbarWidget(
|
||||||
|
context,
|
||||||
|
"Silahkan Masukkan Keyword Pencarian",
|
||||||
|
snackbarType.warning);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
|
||||||
|
// SizedBox(
|
||||||
|
// height: Constant.getActualY(context: context, y: 20),
|
||||||
|
// ),
|
||||||
|
// // nama
|
||||||
|
// Container(
|
||||||
|
// width: Constant.getActualX(context: context, x: 320),
|
||||||
|
// height: Constant.getActualY(context: context, y: 56),
|
||||||
|
// child: SasTextField(
|
||||||
|
// hintText: "Nama",
|
||||||
|
// labelText: "Nama",
|
||||||
|
// focusNode: focusNodeNama,
|
||||||
|
// hasFocus: namahasFocus.value,
|
||||||
|
// controller: ctrlNama,
|
||||||
|
// isReadOnly: true,
|
||||||
|
// ),
|
||||||
|
// ),
|
||||||
|
|
||||||
|
SizedBox(
|
||||||
|
height: Constant.getActualY(context: context, y: 20),
|
||||||
|
),
|
||||||
|
// alamat
|
||||||
|
Container(
|
||||||
|
width: Constant.getActualX(context: context, x: 320),
|
||||||
|
height: Constant.getActualY(context: context, y: 120),
|
||||||
|
// color: Colors.green,
|
||||||
|
child: SasTextFieldArea(
|
||||||
|
hintText: "Alamat Pengantaran",
|
||||||
|
labelText: "Alamat Pengantaran",
|
||||||
|
focusNode: focusNodeAlamat,
|
||||||
|
hasFocus: alamathasFocus.value,
|
||||||
|
controller: ctrlAlamat,
|
||||||
|
isReadOnly: true,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
|
||||||
|
SizedBox(
|
||||||
|
height: Constant.getActualY(context: context, y: 10),
|
||||||
|
),
|
||||||
|
|
||||||
|
if (listPatient.value.isNotEmpty) ...[
|
||||||
|
for (var i = 0; i < listPatient.value.length; i++) ...[
|
||||||
|
Padding(
|
||||||
|
padding: EdgeInsets.only(
|
||||||
|
bottom: Constant.getActualY(context: context, y: 10),
|
||||||
|
),
|
||||||
|
child: PatientCard(
|
||||||
|
name: listPatient.value[i].pasien.toString(),
|
||||||
|
noLab:
|
||||||
|
listPatient.value[i].tOrderHeaderLabNumber.toString(),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
] else ...[
|
||||||
|
SizedBox.shrink(),
|
||||||
|
SizedBox(
|
||||||
|
height: Constant.getActualY(context: context, y: 40),
|
||||||
|
)
|
||||||
|
],
|
||||||
|
],
|
||||||
|
|
||||||
|
// SizedBox(
|
||||||
|
// height: Constant.getActualY(context: context, y: 156),
|
||||||
|
// ),
|
||||||
|
|
||||||
|
Padding(
|
||||||
|
padding: EdgeInsets.only(
|
||||||
|
top: Constant.getActualY(context: context, y: 20),
|
||||||
|
bottom: Constant.getActualY(context: context, y: 20),
|
||||||
|
),
|
||||||
|
child: Align(
|
||||||
|
alignment: Alignment.bottomCenter,
|
||||||
|
child: Container(
|
||||||
|
// width: Constant.getActualX(context: context, x: 317),
|
||||||
|
// height: Constant.getActualY(context: context, y: 36),
|
||||||
|
// padding: EdgeInsets.symmetric(
|
||||||
|
// horizontal: Constant.getActualX(context: context, x: 10),
|
||||||
|
// ),
|
||||||
|
height: Constant.getActualY(context: context, y: 36),
|
||||||
|
child: Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
|
children: [
|
||||||
|
// batal
|
||||||
|
ElevatedButton(
|
||||||
|
onPressed: () {
|
||||||
|
Navigator.pop(context);
|
||||||
|
},
|
||||||
|
style: ButtonStyle(
|
||||||
|
backgroundColor: MaterialStateColor.resolveWith(
|
||||||
|
(st) => Constant.backgroundWhite),
|
||||||
|
shape:
|
||||||
|
MaterialStateProperty.all<RoundedRectangleBorder>(
|
||||||
|
RoundedRectangleBorder(
|
||||||
|
borderRadius: BorderRadius.circular(8),
|
||||||
|
side: BorderSide(color: Constant.blueButton),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
shadowColor:
|
||||||
|
MaterialStateProperty.all(Color(0xffff48423d)),
|
||||||
|
elevation: MaterialStateProperty.all(4.0),
|
||||||
|
),
|
||||||
|
child: Align(
|
||||||
|
alignment: Alignment.center,
|
||||||
|
child: Text(
|
||||||
|
'Batal',
|
||||||
|
style: Constant.body3(context: context).copyWith(
|
||||||
|
color: Constant.blueButton,
|
||||||
|
fontWeight: FontWeight.w700,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
|
||||||
|
// simpan
|
||||||
|
ElevatedButton(
|
||||||
|
onPressed: (isLoadingSearchSuratJalan.value)
|
||||||
|
? null
|
||||||
|
: () {
|
||||||
|
print("kurir id : $mCourirID");
|
||||||
|
print("tipe id : $tipePekerjaanIDSave");
|
||||||
|
print("delivery id : ${deliveryIDSave.value}");
|
||||||
|
|
||||||
|
if (deliveryIDSave.value == "") {
|
||||||
|
SanckbarWidget(
|
||||||
|
context,
|
||||||
|
"Silahkan Cari No Company",
|
||||||
|
snackbarType.warning);
|
||||||
|
} else {
|
||||||
|
ref
|
||||||
|
.read(
|
||||||
|
pengantaranHasilCompanySave.notifier)
|
||||||
|
.pengantaranHasilCompanySave(
|
||||||
|
courierID: mCourirID,
|
||||||
|
tipeID: tipePekerjaanIDSave,
|
||||||
|
deliveryID: deliveryIDSave.value,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
style: ButtonStyle(
|
||||||
|
backgroundColor: MaterialStateColor.resolveWith(
|
||||||
|
(st) => Constant.blueButton,
|
||||||
|
),
|
||||||
|
shape:
|
||||||
|
MaterialStateProperty.all<RoundedRectangleBorder>(
|
||||||
|
RoundedRectangleBorder(
|
||||||
|
borderRadius: BorderRadius.circular(8),
|
||||||
|
// side: BorderSide(color: Constant.blueButton),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
shadowColor:
|
||||||
|
MaterialStateProperty.all(Color(0xffff48423d)),
|
||||||
|
elevation: MaterialStateProperty.all(4.0),
|
||||||
|
),
|
||||||
|
child: Align(
|
||||||
|
alignment: Alignment.center,
|
||||||
|
child: Text(
|
||||||
|
'Simpan',
|
||||||
|
style: Constant.body3(context: context).copyWith(
|
||||||
|
color: Constant.backgroundWhite,
|
||||||
|
fontWeight: FontWeight.w700,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
] else ...[
|
||||||
|
// button scan barcode
|
||||||
|
SizedBox(
|
||||||
|
height: Constant.getActualY(context: context, y: 445),
|
||||||
|
),
|
||||||
|
Container(
|
||||||
|
width: Constant.getActualX(context: context, x: 317),
|
||||||
|
height: Constant.getActualY(context: context, y: 36),
|
||||||
|
// color: Colors.pink,
|
||||||
|
child: SizedBox(
|
||||||
|
width: Constant.getActualX(context: context, x: 83),
|
||||||
|
height: Constant.getActualY(context: context, y: 36),
|
||||||
|
child: ElevatedButton(
|
||||||
|
onPressed: () {
|
||||||
|
FocusManager.instance.primaryFocus?.unfocus();
|
||||||
|
ref.read(isFromScanScreen.notifier).update((state) => true);
|
||||||
|
Navigator.of(context).pushNamedAndRemoveUntil(
|
||||||
|
inputScanRoute, (route) => false,
|
||||||
|
arguments: InputScanPekerjaanProp(0, 1));
|
||||||
|
},
|
||||||
|
style: ButtonStyle(
|
||||||
|
backgroundColor: MaterialStateColor.resolveWith(
|
||||||
|
(st) => Constant.blueButton),
|
||||||
|
shape: MaterialStateProperty.all<RoundedRectangleBorder>(
|
||||||
|
RoundedRectangleBorder(
|
||||||
|
borderRadius: BorderRadius.circular(8),
|
||||||
|
// side: BorderSide(color: Constant.blueButton),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
shadowColor: MaterialStateProperty.all(Color(0xffff48423d)),
|
||||||
|
elevation: MaterialStateProperty.all(4.0),
|
||||||
|
),
|
||||||
|
child: Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
|
children: [
|
||||||
|
Icon(Icons.document_scanner),
|
||||||
|
SizedBox(
|
||||||
|
width: Constant.getActualX(context: context, x: 10),
|
||||||
|
),
|
||||||
|
Text(
|
||||||
|
'Scan Barcode',
|
||||||
|
style: Constant.body3(context: context).copyWith(
|
||||||
|
color: Constant.backgroundWhite,
|
||||||
|
fontWeight: FontWeight.w700,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,545 @@
|
|||||||
|
import 'dart:async';
|
||||||
|
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_hooks/flutter_hooks.dart';
|
||||||
|
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||||
|
import '/app/route.dart';
|
||||||
|
import '/screen/input_pekerjaan/pengantaran_hasil_pasien_loadnolab_provider.dart';
|
||||||
|
import '/widget/sas_textfield.dart';
|
||||||
|
|
||||||
|
import '../../app/constant.dart';
|
||||||
|
import '../../models/response_search_pengantaran_hasil_model.dart';
|
||||||
|
import '../../provider/current_scan_provider.dart';
|
||||||
|
import '../../provider/current_user_provider.dart';
|
||||||
|
import '../../provider/dio_provider.dart';
|
||||||
|
import '../../repository/pengantaran_hasil_pasien_repository.dart';
|
||||||
|
import '../../widget/custom_textfield.dart';
|
||||||
|
import '../../widget/snackbar_widget.dart';
|
||||||
|
import 'pengantaran_hasil_pasien_save_provider.dart';
|
||||||
|
|
||||||
|
class InputPengantaranHasilPasienScreen extends HookConsumerWidget {
|
||||||
|
// const InputPengantaranHasilPasienScreen({
|
||||||
|
// super.key,
|
||||||
|
// });
|
||||||
|
|
||||||
|
const InputPengantaranHasilPasienScreen({super.key, required this.data});
|
||||||
|
final Map<String, dynamic> data;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context, WidgetRef ref) {
|
||||||
|
print(data);
|
||||||
|
final isForm = useState(true);
|
||||||
|
final isScan = useState(false);
|
||||||
|
|
||||||
|
final mCourirID =
|
||||||
|
ref.watch(currentUserProvider)?.model.user?.mCourierID ?? "0";
|
||||||
|
|
||||||
|
final isFromScanScreenProvider = ref.read(isFromScanScreen);
|
||||||
|
|
||||||
|
final tipePekerjaanIDSave = data['tipePekerjaan'];
|
||||||
|
final deliveryIDSave = useState<String>("");
|
||||||
|
|
||||||
|
final hasilSearchData = useState<List<ResponseSearchPengantaranHasilModel>>(
|
||||||
|
List.empty(growable: true));
|
||||||
|
|
||||||
|
final isLoadingSearchNoLab = useState(false);
|
||||||
|
final focusNodeNoLab = useFocusNode();
|
||||||
|
final nolabhasFocus = useState(false);
|
||||||
|
final ctrlNoLab = useTextEditingController(text: "");
|
||||||
|
|
||||||
|
final ctrlNama = useTextEditingController(text: "");
|
||||||
|
final focusNodeNama = useFocusNode();
|
||||||
|
final namahasFocus = useState(false);
|
||||||
|
|
||||||
|
final ctrlAlamat = useTextEditingController(text: "");
|
||||||
|
final focusNodeAlamat = useFocusNode();
|
||||||
|
final alamathasFocus = useState(false);
|
||||||
|
final errorMessage = useState("");
|
||||||
|
|
||||||
|
focusNodeNoLab.addListener(() {
|
||||||
|
if (focusNodeNoLab.hasFocus) {
|
||||||
|
nolabhasFocus.value = true;
|
||||||
|
} else {
|
||||||
|
nolabhasFocus.value = false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
focusNodeNama.addListener(() {
|
||||||
|
if (focusNodeNama.hasFocus) {
|
||||||
|
namahasFocus.value = true;
|
||||||
|
} else {
|
||||||
|
namahasFocus.value = false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
focusNodeAlamat.addListener(() {
|
||||||
|
if (focusNodeAlamat.hasFocus) {
|
||||||
|
alamathasFocus.value = true;
|
||||||
|
} else {
|
||||||
|
alamathasFocus.value = false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// useEffect(() {
|
||||||
|
// isForm.value = true;
|
||||||
|
// isScan.value = false;
|
||||||
|
// }, []);
|
||||||
|
|
||||||
|
// search no lab
|
||||||
|
ref.listen(pengantaranHasilPasienSearchNoLab, (prev, next) {
|
||||||
|
if (next is PengantaranhasilPasienStateLoading) {
|
||||||
|
isLoadingSearchNoLab.value = true;
|
||||||
|
} else if (next is PengantaranhasilPasienStateError) {
|
||||||
|
isLoadingSearchNoLab.value = false;
|
||||||
|
errorMessage.value = next.message ?? "";
|
||||||
|
SanckbarWidget(context, "${next.message}", snackbarType.error);
|
||||||
|
Timer(const Duration(seconds: 3), () {
|
||||||
|
errorMessage.value = "";
|
||||||
|
});
|
||||||
|
} else if (next is PengantaranhasilPasienStateDone) {
|
||||||
|
isLoadingSearchNoLab.value = false;
|
||||||
|
if (next.model.isNotEmpty) {
|
||||||
|
hasilSearchData.value = next.model;
|
||||||
|
// deliveryid merupakan json dari id
|
||||||
|
print('Delivery ID : ${hasilSearchData.value[0].deliveryid}');
|
||||||
|
print('Tipe ID : ${hasilSearchData.value[0].tipeid}');
|
||||||
|
print('Selected No Lab : ${hasilSearchData.value[0].nomor}');
|
||||||
|
print('Selected Nama : ${hasilSearchData.value[0].nama}');
|
||||||
|
print('Selected Alamat : ${hasilSearchData.value[0].alamat}');
|
||||||
|
|
||||||
|
ctrlNoLab.text = hasilSearchData.value[0].nomor.toString();
|
||||||
|
ctrlNama.text = hasilSearchData.value[0].nama.toString();
|
||||||
|
ctrlAlamat.text = hasilSearchData.value[0].alamat.toString();
|
||||||
|
deliveryIDSave.value = hasilSearchData.value[0].deliveryid.toString();
|
||||||
|
} else {
|
||||||
|
hasilSearchData.value = [];
|
||||||
|
ctrlNoLab.text = "";
|
||||||
|
ctrlNama.text = "";
|
||||||
|
ctrlAlamat.text = "";
|
||||||
|
SanckbarWidget(context, "Data Tidak Ditemukan", snackbarType.warning);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// save pengantaran hasil
|
||||||
|
ref.listen(pengantaranHasilPasienSave, (prev, next) {
|
||||||
|
if (next is PengantaranhasilPasienSaveStateLoading) {
|
||||||
|
isLoadingSearchNoLab.value = true;
|
||||||
|
} else if (next is PengantaranhasilPasienSaveStateError) {
|
||||||
|
isLoadingSearchNoLab.value = false;
|
||||||
|
errorMessage.value = next.message ?? "";
|
||||||
|
SanckbarWidget(context, "${next.message}", snackbarType.error);
|
||||||
|
Timer(const Duration(seconds: 3), () {
|
||||||
|
errorMessage.value = "";
|
||||||
|
});
|
||||||
|
} else if (next is PengantaranhasilPasienSaveStateDone) {
|
||||||
|
isLoadingSearchNoLab.value = false;
|
||||||
|
ref.read(barcodeScanResult.notifier).update((state) => "");
|
||||||
|
if (next.model.status != "OK") {
|
||||||
|
SanckbarWidget(context, "${next.model.message}", snackbarType.error);
|
||||||
|
} else {
|
||||||
|
Navigator.of(context).pushNamedAndRemoveUntil(
|
||||||
|
konfirmasiRoute,
|
||||||
|
(route) => false,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// check kalau pake scan
|
||||||
|
useEffect(() {
|
||||||
|
WidgetsBinding.instance.addPostFrameCallback((timeStamp) async {
|
||||||
|
final barcodeScanResultValue = ref.read(barcodeScanResult);
|
||||||
|
print("barcode Scan Result: $barcodeScanResultValue");
|
||||||
|
print("Is from scan : ${isFromScanScreen}");
|
||||||
|
|
||||||
|
if (isFromScanScreenProvider == true) {
|
||||||
|
if (barcodeScanResultValue != "") {
|
||||||
|
isForm.value = true;
|
||||||
|
isScan.value = false;
|
||||||
|
ref
|
||||||
|
.read(pengantaranHasilPasienSearchNoLab.notifier)
|
||||||
|
.loadListNoLabPengantaranHasilPasien(
|
||||||
|
search: barcodeScanResultValue,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
ref.read(barcodeScanResult.notifier).update((state) => "");
|
||||||
|
ref.read(isFromScanScreen.notifier).update((state) => false);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
return Container(
|
||||||
|
width: Constant.getActualX(context: context, x: 320),
|
||||||
|
height: Constant.getActualY(context: context, y: 544),
|
||||||
|
// color: Colors.pink,
|
||||||
|
child: ListView(
|
||||||
|
children: [
|
||||||
|
// tab nolab & scanner
|
||||||
|
Container(
|
||||||
|
width: Constant.getActualX(context: context, x: 320),
|
||||||
|
height: Constant.getActualY(context: context, y: 36),
|
||||||
|
child: Row(
|
||||||
|
children: [
|
||||||
|
// button form kiri
|
||||||
|
SizedBox(
|
||||||
|
width: Constant.getActualX(context: context, x: 156),
|
||||||
|
height: Constant.getActualY(context: context, y: 36),
|
||||||
|
child: ElevatedButton(
|
||||||
|
onPressed: () {
|
||||||
|
if (isForm.value == true) {
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
isForm.value = true;
|
||||||
|
isScan.value = false;
|
||||||
|
}
|
||||||
|
// isForm.value = !isForm.value;
|
||||||
|
// isScan.value = !isScan.value;
|
||||||
|
},
|
||||||
|
// onPressed: null,
|
||||||
|
style: ButtonStyle(
|
||||||
|
backgroundColor: (isForm.value == true)
|
||||||
|
? MaterialStateColor.resolveWith(
|
||||||
|
(st) => Constant.primaryMain)
|
||||||
|
: MaterialStateColor.resolveWith(
|
||||||
|
(st) => Constant.buttonIsNotActive),
|
||||||
|
shape: MaterialStateProperty.all<RoundedRectangleBorder>(
|
||||||
|
RoundedRectangleBorder(
|
||||||
|
borderRadius: BorderRadius.only(
|
||||||
|
bottomLeft: Radius.circular(12),
|
||||||
|
topLeft: Radius.circular(12)),
|
||||||
|
// side: BorderSide(color: Colors.red),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
shadowColor:
|
||||||
|
MaterialStateProperty.all(Color(0xffff48423d)),
|
||||||
|
elevation: MaterialStateProperty.all(4.0),
|
||||||
|
),
|
||||||
|
child: Align(
|
||||||
|
alignment: Alignment.center,
|
||||||
|
child: Text(
|
||||||
|
'Form',
|
||||||
|
style: Constant.buttonLarge(context: context).copyWith(
|
||||||
|
color: (isForm.value == true)
|
||||||
|
? Constant.backgroundWhite
|
||||||
|
: Constant.textBlack,
|
||||||
|
fontWeight: FontWeight.w700,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
|
||||||
|
SizedBox(
|
||||||
|
width: Constant.getActualX(context: context, x: 8),
|
||||||
|
),
|
||||||
|
// button scan kanan
|
||||||
|
|
||||||
|
SizedBox(
|
||||||
|
width: Constant.getActualX(context: context, x: 156),
|
||||||
|
height: Constant.getActualY(context: context, y: 36),
|
||||||
|
child: ElevatedButton(
|
||||||
|
onPressed: () {
|
||||||
|
// isScan.value = !isScan.value;
|
||||||
|
// isForm.value = !isForm.value;
|
||||||
|
|
||||||
|
if (isScan.value == true) {
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
isForm.value = false;
|
||||||
|
isScan.value = true;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// onPressed: null,
|
||||||
|
style: ButtonStyle(
|
||||||
|
backgroundColor: (isScan.value == true)
|
||||||
|
? MaterialStateColor.resolveWith(
|
||||||
|
(st) => Constant.primaryMain)
|
||||||
|
: MaterialStateColor.resolveWith(
|
||||||
|
(st) => Constant.buttonIsNotActive),
|
||||||
|
shape: MaterialStateProperty.all<RoundedRectangleBorder>(
|
||||||
|
RoundedRectangleBorder(
|
||||||
|
borderRadius: BorderRadius.only(
|
||||||
|
bottomRight: Radius.circular(12),
|
||||||
|
topRight: Radius.circular(12),
|
||||||
|
),
|
||||||
|
// side: BorderSide(color: Colors.red),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
shadowColor:
|
||||||
|
MaterialStateProperty.all(Color(0xffff48423d)),
|
||||||
|
elevation: MaterialStateProperty.all(4.0),
|
||||||
|
),
|
||||||
|
child: Align(
|
||||||
|
alignment: Alignment.center,
|
||||||
|
child: Text(
|
||||||
|
'Scan',
|
||||||
|
style: Constant.buttonLarge(context: context).copyWith(
|
||||||
|
color: (isScan.value == true)
|
||||||
|
? Constant.backgroundWhite
|
||||||
|
: Constant.textBlack,
|
||||||
|
fontWeight: FontWeight.w700,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
|
||||||
|
if (isForm.value == true) ...[
|
||||||
|
// button batal & simpan jika isForm true
|
||||||
|
SizedBox(
|
||||||
|
height: Constant.getActualY(context: context, y: 20),
|
||||||
|
),
|
||||||
|
|
||||||
|
// loading
|
||||||
|
if (isLoadingSearchNoLab.value) ...[
|
||||||
|
// Center(
|
||||||
|
// child: SizedBox(
|
||||||
|
// width: Constant.getActualX(context: context, x: 20),
|
||||||
|
// height: Constant.getActualY(context: context, y: 20),
|
||||||
|
// child: CircularProgressIndicator(),
|
||||||
|
// ),
|
||||||
|
// ),
|
||||||
|
const Center(
|
||||||
|
child: CircularProgressIndicator(),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
|
||||||
|
SizedBox(
|
||||||
|
height: Constant.getActualY(context: context, y: 20),
|
||||||
|
),
|
||||||
|
|
||||||
|
// no lab search with icon
|
||||||
|
Container(
|
||||||
|
width: Constant.getActualX(context: context, x: 320),
|
||||||
|
height: Constant.getActualY(context: context, y: 56),
|
||||||
|
child: SasTextFieldSearch(
|
||||||
|
controller: ctrlNoLab,
|
||||||
|
hintText: "No Lab",
|
||||||
|
labelText: "No Lab",
|
||||||
|
focusNode: focusNodeNoLab,
|
||||||
|
hasFocus: nolabhasFocus.value,
|
||||||
|
isReadOnly: false,
|
||||||
|
onPressed: () {
|
||||||
|
if (ctrlNoLab.text != "" || ctrlNoLab.text.isNotEmpty) {
|
||||||
|
if (ctrlNoLab.text.length > 3) {
|
||||||
|
ref
|
||||||
|
.read(pengantaranHasilPasienSearchNoLab.notifier)
|
||||||
|
.loadListNoLabPengantaranHasilPasien(
|
||||||
|
search: ctrlNoLab.text.toString(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
SanckbarWidget(
|
||||||
|
context,
|
||||||
|
"Silahkan Masukkan Keyword Pencarian",
|
||||||
|
snackbarType.warning);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
|
||||||
|
SizedBox(
|
||||||
|
height: Constant.getActualY(context: context, y: 20),
|
||||||
|
),
|
||||||
|
|
||||||
|
// nama
|
||||||
|
Container(
|
||||||
|
width: Constant.getActualX(context: context, x: 320),
|
||||||
|
height: Constant.getActualY(context: context, y: 56),
|
||||||
|
child: SasTextField(
|
||||||
|
hintText: "Nama",
|
||||||
|
labelText: "Nama",
|
||||||
|
focusNode: focusNodeNama,
|
||||||
|
hasFocus: namahasFocus.value,
|
||||||
|
controller: ctrlNama,
|
||||||
|
isReadOnly: true,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
SizedBox(
|
||||||
|
height: Constant.getActualY(context: context, y: 20),
|
||||||
|
),
|
||||||
|
// alamat
|
||||||
|
Container(
|
||||||
|
width: Constant.getActualX(context: context, x: 320),
|
||||||
|
height: Constant.getActualY(context: context, y: 120),
|
||||||
|
// color: Colors.green,
|
||||||
|
child: SasTextFieldArea(
|
||||||
|
hintText: "Alamat Pengantaran",
|
||||||
|
labelText: "Alamat Pengantaran",
|
||||||
|
focusNode: focusNodeAlamat,
|
||||||
|
hasFocus: alamathasFocus.value,
|
||||||
|
controller: ctrlAlamat,
|
||||||
|
isReadOnly: true,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
|
||||||
|
SizedBox(
|
||||||
|
height: Constant.getActualY(context: context, y: 50),
|
||||||
|
),
|
||||||
|
|
||||||
|
Padding(
|
||||||
|
padding: EdgeInsets.only(
|
||||||
|
top: Constant.getActualY(context: context, y: 20),
|
||||||
|
bottom: Constant.getActualY(context: context, y: 20),
|
||||||
|
),
|
||||||
|
child: Align(
|
||||||
|
alignment: Alignment.bottomCenter,
|
||||||
|
child: Container(
|
||||||
|
// width: Constant.getActualX(context: context, x: 317),
|
||||||
|
// height: Constant.getActualY(context: context, y: 36),
|
||||||
|
// padding: EdgeInsets.symmetric(
|
||||||
|
// horizontal: Constant.getActualX(context: context, x: 10)),
|
||||||
|
height: Constant.getActualY(context: context, y: 36),
|
||||||
|
// color: Colors.pink,
|
||||||
|
child: Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
|
children: [
|
||||||
|
// batal
|
||||||
|
ElevatedButton(
|
||||||
|
onPressed: () {
|
||||||
|
Navigator.pop(context);
|
||||||
|
},
|
||||||
|
style: ButtonStyle(
|
||||||
|
backgroundColor: MaterialStateColor.resolveWith(
|
||||||
|
(st) => Constant.backgroundWhite),
|
||||||
|
shape:
|
||||||
|
MaterialStateProperty.all<RoundedRectangleBorder>(
|
||||||
|
RoundedRectangleBorder(
|
||||||
|
borderRadius: BorderRadius.circular(8),
|
||||||
|
side: BorderSide(
|
||||||
|
color: Constant.blueButton,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
shadowColor:
|
||||||
|
MaterialStateProperty.all(Color(0xffff48423d)),
|
||||||
|
elevation: MaterialStateProperty.all(4.0),
|
||||||
|
),
|
||||||
|
child: Align(
|
||||||
|
alignment: Alignment.center,
|
||||||
|
child: Text(
|
||||||
|
'Batal',
|
||||||
|
style: Constant.body3(context: context).copyWith(
|
||||||
|
color: Constant.blueButton,
|
||||||
|
fontWeight: FontWeight.w700,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
|
||||||
|
// simpan
|
||||||
|
ElevatedButton(
|
||||||
|
onPressed: (isLoadingSearchNoLab.value)
|
||||||
|
? null
|
||||||
|
: () {
|
||||||
|
print("kurir id : $mCourirID");
|
||||||
|
print("tipe id : $tipePekerjaanIDSave");
|
||||||
|
print("delivery id : ${deliveryIDSave.value}");
|
||||||
|
|
||||||
|
if (deliveryIDSave.value == "") {
|
||||||
|
SanckbarWidget(
|
||||||
|
context,
|
||||||
|
"Silahkan Cari No Lab",
|
||||||
|
snackbarType.warning);
|
||||||
|
} else {
|
||||||
|
ref
|
||||||
|
.read(pengantaranHasilPasienSave.notifier)
|
||||||
|
.pengantaranHasilPasienSave(
|
||||||
|
courierID: mCourirID,
|
||||||
|
tipeID: tipePekerjaanIDSave,
|
||||||
|
deliveryID: deliveryIDSave.value,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
style: ButtonStyle(
|
||||||
|
backgroundColor: MaterialStateColor.resolveWith(
|
||||||
|
(st) => Constant.blueButton,
|
||||||
|
),
|
||||||
|
shape:
|
||||||
|
MaterialStateProperty.all<RoundedRectangleBorder>(
|
||||||
|
RoundedRectangleBorder(
|
||||||
|
borderRadius: BorderRadius.circular(8),
|
||||||
|
// side: BorderSide(color: Constant.blueButton),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
shadowColor:
|
||||||
|
MaterialStateProperty.all(Color(0xffff48423d)),
|
||||||
|
elevation: MaterialStateProperty.all(4.0),
|
||||||
|
),
|
||||||
|
child: Align(
|
||||||
|
alignment: Alignment.center,
|
||||||
|
child: Text(
|
||||||
|
'Simpan',
|
||||||
|
style: Constant.body3(context: context).copyWith(
|
||||||
|
color: Constant.backgroundWhite,
|
||||||
|
fontWeight: FontWeight.w700,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
] else ...[
|
||||||
|
// button scan barcode
|
||||||
|
SizedBox(
|
||||||
|
height: Constant.getActualY(context: context, y: 445),
|
||||||
|
),
|
||||||
|
Container(
|
||||||
|
width: Constant.getActualX(context: context, x: 317),
|
||||||
|
height: Constant.getActualY(context: context, y: 36),
|
||||||
|
// color: Colors.pink,
|
||||||
|
child: SizedBox(
|
||||||
|
width: Constant.getActualX(context: context, x: 83),
|
||||||
|
height: Constant.getActualY(context: context, y: 36),
|
||||||
|
child: ElevatedButton(
|
||||||
|
onPressed: () {
|
||||||
|
FocusManager.instance.primaryFocus?.unfocus();
|
||||||
|
ref.read(isFromScanScreen.notifier).update((state) => true);
|
||||||
|
Navigator.of(context).popAndPushNamed(inputScanRoute,
|
||||||
|
arguments: InputScanPekerjaanProp(0, 0));
|
||||||
|
},
|
||||||
|
style: ButtonStyle(
|
||||||
|
backgroundColor: MaterialStateColor.resolveWith(
|
||||||
|
(st) => Constant.blueButton),
|
||||||
|
shape: MaterialStateProperty.all<RoundedRectangleBorder>(
|
||||||
|
RoundedRectangleBorder(
|
||||||
|
borderRadius: BorderRadius.circular(8),
|
||||||
|
// side: BorderSide(color: Constant.blueButton),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
shadowColor: MaterialStateProperty.all(Color(0xffff48423d)),
|
||||||
|
elevation: MaterialStateProperty.all(4.0),
|
||||||
|
),
|
||||||
|
child: Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
|
children: [
|
||||||
|
Icon(Icons.document_scanner),
|
||||||
|
SizedBox(
|
||||||
|
width: Constant.getActualX(context: context, x: 10),
|
||||||
|
),
|
||||||
|
Text(
|
||||||
|
'Scan Barcode',
|
||||||
|
style: Constant.body3(context: context).copyWith(
|
||||||
|
color: Constant.backgroundWhite,
|
||||||
|
fontWeight: FontWeight.w700,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
103
lib/screen/input_pekerjaan/input_scan_screen.dart
Normal file
@@ -0,0 +1,103 @@
|
|||||||
|
import 'dart:async';
|
||||||
|
import 'dart:typed_data';
|
||||||
|
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_hooks/flutter_hooks.dart';
|
||||||
|
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||||
|
import 'package:mobile_scanner/mobile_scanner.dart';
|
||||||
|
|
||||||
|
import '../../app/route.dart';
|
||||||
|
import '../../provider/current_scan_provider.dart';
|
||||||
|
|
||||||
|
class InputScanScreen extends HookConsumerWidget {
|
||||||
|
const InputScanScreen({super.key, required this.data});
|
||||||
|
final InputScanPekerjaanProp data;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context, WidgetRef ref) {
|
||||||
|
print("DATAXSCAN : ${data.input} - ${data.tipe}");
|
||||||
|
MobileScannerController cameraController = MobileScannerController();
|
||||||
|
final hasilScan = useState<String>("");
|
||||||
|
|
||||||
|
return Scaffold(
|
||||||
|
appBar: AppBar(
|
||||||
|
title: const Text('Scan Barcode'),
|
||||||
|
actions: [
|
||||||
|
IconButton(
|
||||||
|
color: Colors.white,
|
||||||
|
icon: ValueListenableBuilder(
|
||||||
|
valueListenable: cameraController.torchState,
|
||||||
|
builder: (context, state, child) {
|
||||||
|
switch (state as TorchState) {
|
||||||
|
case TorchState.off:
|
||||||
|
return const Icon(Icons.flash_off, color: Colors.grey);
|
||||||
|
case TorchState.on:
|
||||||
|
return const Icon(Icons.flash_on, color: Colors.yellow);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
),
|
||||||
|
iconSize: 32.0,
|
||||||
|
onPressed: () => cameraController.toggleTorch(),
|
||||||
|
),
|
||||||
|
IconButton(
|
||||||
|
color: Colors.white,
|
||||||
|
icon: ValueListenableBuilder(
|
||||||
|
valueListenable: cameraController.cameraFacingState,
|
||||||
|
builder: (context, state, child) {
|
||||||
|
switch (state as CameraFacing) {
|
||||||
|
case CameraFacing.front:
|
||||||
|
return const Icon(Icons.camera_front);
|
||||||
|
case CameraFacing.back:
|
||||||
|
return const Icon(Icons.camera_rear);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
),
|
||||||
|
iconSize: 32.0,
|
||||||
|
onPressed: () => cameraController.switchCamera(),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
body: MobileScanner(
|
||||||
|
// fit: BoxFit.contain,
|
||||||
|
controller: cameraController,
|
||||||
|
onDetect: (capture) {
|
||||||
|
final List<Barcode> barcodes = capture.barcodes;
|
||||||
|
for (final barcode in barcodes) {
|
||||||
|
hasilScan.value = barcode.rawValue.toString();
|
||||||
|
debugPrint('Barcode found! ${barcode.rawValue}');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hasilScan.value.isNotEmpty) {
|
||||||
|
// set ke provider global
|
||||||
|
ref
|
||||||
|
.read(barcodeScanResult.notifier)
|
||||||
|
.update((state) => hasilScan.value);
|
||||||
|
|
||||||
|
if (data.tipe == 0) {
|
||||||
|
Navigator.of(context).popAndPushNamed(
|
||||||
|
inputPekerjaan,
|
||||||
|
arguments: inputPekerjaanProp(0, 0),
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
if (data.tipe == 1) {
|
||||||
|
Navigator.of(context).popAndPushNamed(
|
||||||
|
inputPekerjaan,
|
||||||
|
arguments: inputPekerjaanProp(0, 1),
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
if (data.tipe == 2) {
|
||||||
|
Navigator.of(context).popAndPushNamed(
|
||||||
|
inputPekerjaan,
|
||||||
|
arguments: inputPekerjaanProp(0, 2),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Navigator.pop(context);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,63 @@
|
|||||||
|
import 'package:equatable/equatable.dart';
|
||||||
|
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||||
|
import '/models/response_list_branch_model.dart';
|
||||||
|
import '/models/response_search_pengantaran_hasil_model.dart';
|
||||||
|
import '../../provider/dio_provider.dart';
|
||||||
|
import '../../repository/base_repository.dart';
|
||||||
|
import '../../repository/pengambilan_bahan_repository.dart';
|
||||||
|
import '../../repository/pengantaran_hasil_pasien_repository.dart';
|
||||||
|
|
||||||
|
// 3. state provider
|
||||||
|
final pengambilanBahanListCabang = StateNotifierProvider<PengambilanBahanNotifier, PengambilanBahanState>(
|
||||||
|
(ref) => PengambilanBahanNotifier(ref: ref));
|
||||||
|
|
||||||
|
// 2. notifier
|
||||||
|
class PengambilanBahanNotifier extends StateNotifier<PengambilanBahanState> {
|
||||||
|
final Ref ref;
|
||||||
|
PengambilanBahanNotifier({required this.ref}) : super(PengambilanBahanStateInit());
|
||||||
|
void loadListCabangPengambilanBahan() async {
|
||||||
|
try {
|
||||||
|
state = PengambilanBahanStateLoading();
|
||||||
|
final resp = await PengambilanBahanRepository(dio: ref.read(dioProvider))
|
||||||
|
.loadListCabangPengambilanBahan();
|
||||||
|
|
||||||
|
state = PengambilanBahanStateDone(model: resp);
|
||||||
|
} catch (e) {
|
||||||
|
if (e is BaseRepositoryException) {
|
||||||
|
state = PengambilanBahanStateError(message: e.message ?? "");
|
||||||
|
} else {
|
||||||
|
state = PengambilanBahanStateError(message: e.toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 1. state
|
||||||
|
abstract class PengambilanBahanState extends Equatable {
|
||||||
|
final DateTime date;
|
||||||
|
const PengambilanBahanState(this.date);
|
||||||
|
@override
|
||||||
|
List<Object?> get props => [date];
|
||||||
|
}
|
||||||
|
|
||||||
|
class PengambilanBahanStateInit extends PengambilanBahanState {
|
||||||
|
PengambilanBahanStateInit() : super(DateTime.now());
|
||||||
|
}
|
||||||
|
|
||||||
|
class PengambilanBahanStateLoading extends PengambilanBahanState {
|
||||||
|
PengambilanBahanStateLoading() : super(DateTime.now());
|
||||||
|
}
|
||||||
|
|
||||||
|
class PengambilanBahanStateError extends PengambilanBahanState {
|
||||||
|
final String? message;
|
||||||
|
PengambilanBahanStateError({
|
||||||
|
required this.message,
|
||||||
|
}) : super(DateTime.now());
|
||||||
|
}
|
||||||
|
|
||||||
|
class PengambilanBahanStateDone extends PengambilanBahanState {
|
||||||
|
final List<ResponseListBranchModel> model;
|
||||||
|
PengambilanBahanStateDone({
|
||||||
|
required this.model,
|
||||||
|
}) : super(DateTime.now());
|
||||||
|
}
|
||||||
@@ -0,0 +1,77 @@
|
|||||||
|
import 'package:equatable/equatable.dart';
|
||||||
|
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||||
|
import '../../models/response_save_pengantaran_hasil_model.dart';
|
||||||
|
import '../../provider/dio_provider.dart';
|
||||||
|
import '../../repository/base_repository.dart';
|
||||||
|
import '../../repository/pengambilan_bahan_repository.dart';
|
||||||
|
import '../../repository/pengantaran_hasil_dokter_repository.dart';
|
||||||
|
|
||||||
|
// 3. state provider
|
||||||
|
final pengambilanBahanSave = StateNotifierProvider<PengambilanBahanSaveNotifier,
|
||||||
|
PengambilanBahanSaveState>((ref) => PengambilanBahanSaveNotifier(ref: ref));
|
||||||
|
|
||||||
|
// 2. notifier
|
||||||
|
class PengambilanBahanSaveNotifier
|
||||||
|
extends StateNotifier<PengambilanBahanSaveState> {
|
||||||
|
final Ref ref;
|
||||||
|
PengambilanBahanSaveNotifier({required this.ref})
|
||||||
|
: super(PengambilanBahanSaveStateInit());
|
||||||
|
void pengambilanBahanSave({
|
||||||
|
required String courierID,
|
||||||
|
required String tipeID,
|
||||||
|
required String branchID,
|
||||||
|
required String branchCode,
|
||||||
|
required String name,
|
||||||
|
required String destination,
|
||||||
|
}) async {
|
||||||
|
try {
|
||||||
|
state = PengambilanBahanSaveStateLoading();
|
||||||
|
final resp = await PengambilanBahanRepository(dio: ref.read(dioProvider))
|
||||||
|
.pengambilanBahanSave(
|
||||||
|
courierID: courierID,
|
||||||
|
tipeID: tipeID,
|
||||||
|
branchID: branchID,
|
||||||
|
branchCode: branchCode,
|
||||||
|
name: name,
|
||||||
|
destination: destination);
|
||||||
|
|
||||||
|
state = PengambilanBahanSaveStateDone(model: resp);
|
||||||
|
} catch (e) {
|
||||||
|
if (e is BaseRepositoryException) {
|
||||||
|
state = PengambilanBahanSaveStateError(message: e.message ?? "");
|
||||||
|
} else {
|
||||||
|
state = PengambilanBahanSaveStateError(message: e.toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 1. state
|
||||||
|
abstract class PengambilanBahanSaveState extends Equatable {
|
||||||
|
final DateTime date;
|
||||||
|
const PengambilanBahanSaveState(this.date);
|
||||||
|
@override
|
||||||
|
List<Object?> get props => [date];
|
||||||
|
}
|
||||||
|
|
||||||
|
class PengambilanBahanSaveStateInit extends PengambilanBahanSaveState {
|
||||||
|
PengambilanBahanSaveStateInit() : super(DateTime.now());
|
||||||
|
}
|
||||||
|
|
||||||
|
class PengambilanBahanSaveStateLoading extends PengambilanBahanSaveState {
|
||||||
|
PengambilanBahanSaveStateLoading() : super(DateTime.now());
|
||||||
|
}
|
||||||
|
|
||||||
|
class PengambilanBahanSaveStateError extends PengambilanBahanSaveState {
|
||||||
|
final String? message;
|
||||||
|
PengambilanBahanSaveStateError({
|
||||||
|
required this.message,
|
||||||
|
}) : super(DateTime.now());
|
||||||
|
}
|
||||||
|
|
||||||
|
class PengambilanBahanSaveStateDone extends PengambilanBahanSaveState {
|
||||||
|
final ResponseSavePengantaranHasilModel model;
|
||||||
|
PengambilanBahanSaveStateDone({
|
||||||
|
required this.model,
|
||||||
|
}) : super(DateTime.now());
|
||||||
|
}
|
||||||
@@ -0,0 +1,64 @@
|
|||||||
|
import 'package:equatable/equatable.dart';
|
||||||
|
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||||
|
import '../../models/response_search_pengantaran_hasil_model.dart';
|
||||||
|
import '../../provider/dio_provider.dart';
|
||||||
|
import '../../repository/base_repository.dart';
|
||||||
|
import '../../repository/pengantaran_hasil_dokter_repository.dart';
|
||||||
|
|
||||||
|
// 3. state provider
|
||||||
|
final pengantaranHasilDokterSearch = StateNotifierProvider<PengantaranhasilDokterNotifier, PengantaranhasilDokterState>(
|
||||||
|
(ref) => PengantaranhasilDokterNotifier(ref: ref));
|
||||||
|
|
||||||
|
// 2. notifier
|
||||||
|
class PengantaranhasilDokterNotifier extends StateNotifier<PengantaranhasilDokterState> {
|
||||||
|
final Ref ref;
|
||||||
|
PengantaranhasilDokterNotifier({required this.ref}) : super(PengantaranhasilDokterStateInit());
|
||||||
|
void loadListNoDokterPengantaranHasilDokter(
|
||||||
|
{
|
||||||
|
required String search
|
||||||
|
}) async {
|
||||||
|
try {
|
||||||
|
state = PengantaranhasilDokterStateLoading();
|
||||||
|
final resp = await PengantaranHasilDokterRepository(dio: ref.read(dioProvider))
|
||||||
|
.loadListNoDokterPengantaranHasilDokter(search: search);
|
||||||
|
|
||||||
|
state = PengantaranhasilDokterStateDone(model: resp);
|
||||||
|
} catch (e) {
|
||||||
|
if (e is BaseRepositoryException) {
|
||||||
|
state = PengantaranhasilDokterStateError(message: e.message ?? "");
|
||||||
|
} else {
|
||||||
|
state = PengantaranhasilDokterStateError(message: e.toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 1. state
|
||||||
|
abstract class PengantaranhasilDokterState extends Equatable {
|
||||||
|
final DateTime date;
|
||||||
|
const PengantaranhasilDokterState(this.date);
|
||||||
|
@override
|
||||||
|
List<Object?> get props => [date];
|
||||||
|
}
|
||||||
|
|
||||||
|
class PengantaranhasilDokterStateInit extends PengantaranhasilDokterState {
|
||||||
|
PengantaranhasilDokterStateInit() : super(DateTime.now());
|
||||||
|
}
|
||||||
|
|
||||||
|
class PengantaranhasilDokterStateLoading extends PengantaranhasilDokterState {
|
||||||
|
PengantaranhasilDokterStateLoading() : super(DateTime.now());
|
||||||
|
}
|
||||||
|
|
||||||
|
class PengantaranhasilDokterStateError extends PengantaranhasilDokterState {
|
||||||
|
final String? message;
|
||||||
|
PengantaranhasilDokterStateError({
|
||||||
|
required this.message,
|
||||||
|
}) : super(DateTime.now());
|
||||||
|
}
|
||||||
|
|
||||||
|
class PengantaranhasilDokterStateDone extends PengantaranhasilDokterState {
|
||||||
|
final List<ResponseSearchPengantaranHasilModel> model;
|
||||||
|
PengantaranhasilDokterStateDone({
|
||||||
|
required this.model,
|
||||||
|
}) : super(DateTime.now());
|
||||||
|
}
|
||||||
@@ -0,0 +1,77 @@
|
|||||||
|
import 'package:equatable/equatable.dart';
|
||||||
|
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||||
|
import '../../models/response_save_pengantaran_hasil_model.dart';
|
||||||
|
import '../../provider/dio_provider.dart';
|
||||||
|
import '../../repository/base_repository.dart';
|
||||||
|
import '../../repository/pengantaran_hasil_dokter_repository.dart';
|
||||||
|
|
||||||
|
// 3. state provider
|
||||||
|
final pengantaranHasilDokterSave = StateNotifierProvider<
|
||||||
|
PengantaranhasilDokterSaveNotifier, PengantaranhasilDokterSaveState>(
|
||||||
|
(ref) => PengantaranhasilDokterSaveNotifier(ref: ref));
|
||||||
|
|
||||||
|
// 2. notifier
|
||||||
|
class PengantaranhasilDokterSaveNotifier
|
||||||
|
extends StateNotifier<PengantaranhasilDokterSaveState> {
|
||||||
|
final Ref ref;
|
||||||
|
PengantaranhasilDokterSaveNotifier({required this.ref})
|
||||||
|
: super(PengantaranhasilDokterSaveStateInit());
|
||||||
|
void pengantaranHasilDokterSave({
|
||||||
|
required String courierID,
|
||||||
|
required String tipeID,
|
||||||
|
required String deliveryID,
|
||||||
|
}) async {
|
||||||
|
try {
|
||||||
|
state = PengantaranhasilDokterSaveStateLoading();
|
||||||
|
final resp =
|
||||||
|
await PengantaranHasilDokterRepository(dio: ref.read(dioProvider))
|
||||||
|
.pengantaranHasilDokterSave(
|
||||||
|
courierID: courierID,
|
||||||
|
tipeID: tipeID,
|
||||||
|
deliveryID: deliveryID
|
||||||
|
);
|
||||||
|
|
||||||
|
state = PengantaranhasilDokterSaveStateDone(model: resp);
|
||||||
|
} catch (e) {
|
||||||
|
if (e is BaseRepositoryException) {
|
||||||
|
state = PengantaranhasilDokterSaveStateError(message: e.message ?? "");
|
||||||
|
} else {
|
||||||
|
state = PengantaranhasilDokterSaveStateError(message: e.toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 1. state
|
||||||
|
abstract class PengantaranhasilDokterSaveState extends Equatable {
|
||||||
|
final DateTime date;
|
||||||
|
const PengantaranhasilDokterSaveState(this.date);
|
||||||
|
@override
|
||||||
|
List<Object?> get props => [date];
|
||||||
|
}
|
||||||
|
|
||||||
|
class PengantaranhasilDokterSaveStateInit
|
||||||
|
extends PengantaranhasilDokterSaveState {
|
||||||
|
PengantaranhasilDokterSaveStateInit() : super(DateTime.now());
|
||||||
|
}
|
||||||
|
|
||||||
|
class PengantaranhasilDokterSaveStateLoading
|
||||||
|
extends PengantaranhasilDokterSaveState {
|
||||||
|
PengantaranhasilDokterSaveStateLoading() : super(DateTime.now());
|
||||||
|
}
|
||||||
|
|
||||||
|
class PengantaranhasilDokterSaveStateError
|
||||||
|
extends PengantaranhasilDokterSaveState {
|
||||||
|
final String? message;
|
||||||
|
PengantaranhasilDokterSaveStateError({
|
||||||
|
required this.message,
|
||||||
|
}) : super(DateTime.now());
|
||||||
|
}
|
||||||
|
|
||||||
|
class PengantaranhasilDokterSaveStateDone
|
||||||
|
extends PengantaranhasilDokterSaveState {
|
||||||
|
final ResponseSavePengantaranHasilModel model;
|
||||||
|
PengantaranhasilDokterSaveStateDone({
|
||||||
|
required this.model,
|
||||||
|
}) : super(DateTime.now());
|
||||||
|
}
|
||||||
@@ -0,0 +1,65 @@
|
|||||||
|
import 'package:equatable/equatable.dart';
|
||||||
|
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||||
|
import '../../models/response_search_pengantaran_hasil_model.dart';
|
||||||
|
import '../../provider/dio_provider.dart';
|
||||||
|
import '../../repository/base_repository.dart';
|
||||||
|
import '../../repository/pengantaran_hasil_instansi_repository.dart';
|
||||||
|
import '../../repository/pengantaran_hasil_pasien_repository.dart';
|
||||||
|
|
||||||
|
// 3. state provider
|
||||||
|
final pengantaranHasilInstansi = StateNotifierProvider<PengantaranhasilInstansiNotifier, PengantaranhasilInstansiState>(
|
||||||
|
(ref) => PengantaranhasilInstansiNotifier(ref: ref));
|
||||||
|
|
||||||
|
// 2. notifier
|
||||||
|
class PengantaranhasilInstansiNotifier extends StateNotifier<PengantaranhasilInstansiState> {
|
||||||
|
final Ref ref;
|
||||||
|
PengantaranhasilInstansiNotifier({required this.ref}) : super(PengantaranhasilInstansiStateInit());
|
||||||
|
void loadListNoSuratJalanPengantaranHasilInstansi(
|
||||||
|
{
|
||||||
|
required String search
|
||||||
|
}) async {
|
||||||
|
try {
|
||||||
|
state = PengantaranhasilInstansiStateLoading();
|
||||||
|
final resp = await PengantaranHasilInstansiRepository(dio: ref.read(dioProvider))
|
||||||
|
.loadListNoSuratJalanPengantaranHasilInstansi(search: search);
|
||||||
|
|
||||||
|
state = PengantaranhasilInstansiStateDone(model: resp);
|
||||||
|
} catch (e) {
|
||||||
|
if (e is BaseRepositoryException) {
|
||||||
|
state = PengantaranhasilInstansiStateError(message: e.message ?? "");
|
||||||
|
} else {
|
||||||
|
state = PengantaranhasilInstansiStateError(message: e.toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 1. state
|
||||||
|
abstract class PengantaranhasilInstansiState extends Equatable {
|
||||||
|
final DateTime date;
|
||||||
|
const PengantaranhasilInstansiState(this.date);
|
||||||
|
@override
|
||||||
|
List<Object?> get props => [date];
|
||||||
|
}
|
||||||
|
|
||||||
|
class PengantaranhasilInstansiStateInit extends PengantaranhasilInstansiState {
|
||||||
|
PengantaranhasilInstansiStateInit() : super(DateTime.now());
|
||||||
|
}
|
||||||
|
|
||||||
|
class PengantaranhasilInstansiStateLoading extends PengantaranhasilInstansiState {
|
||||||
|
PengantaranhasilInstansiStateLoading() : super(DateTime.now());
|
||||||
|
}
|
||||||
|
|
||||||
|
class PengantaranhasilInstansiStateError extends PengantaranhasilInstansiState {
|
||||||
|
final String? message;
|
||||||
|
PengantaranhasilInstansiStateError({
|
||||||
|
required this.message,
|
||||||
|
}) : super(DateTime.now());
|
||||||
|
}
|
||||||
|
|
||||||
|
class PengantaranhasilInstansiStateDone extends PengantaranhasilInstansiState {
|
||||||
|
final List<ResponseSearchPengantaranHasilModel> model;
|
||||||
|
PengantaranhasilInstansiStateDone({
|
||||||
|
required this.model,
|
||||||
|
}) : super(DateTime.now());
|
||||||
|
}
|
||||||
@@ -0,0 +1,78 @@
|
|||||||
|
import 'package:equatable/equatable.dart';
|
||||||
|
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||||
|
import '../../models/response_save_pengantaran_hasil_model.dart';
|
||||||
|
import '../../provider/dio_provider.dart';
|
||||||
|
import '../../repository/base_repository.dart';
|
||||||
|
import '../../repository/pengantaran_hasil_dokter_repository.dart';
|
||||||
|
import '../../repository/pengantaran_hasil_instansi_repository.dart';
|
||||||
|
|
||||||
|
// 3. state provider
|
||||||
|
final pengantaranHasilCompanySave = StateNotifierProvider<
|
||||||
|
PengantaranhasilCompanySaveNotifier, PengantaranhasilCompanySaveState>(
|
||||||
|
(ref) => PengantaranhasilCompanySaveNotifier(ref: ref));
|
||||||
|
|
||||||
|
// 2. notifier
|
||||||
|
class PengantaranhasilCompanySaveNotifier
|
||||||
|
extends StateNotifier<PengantaranhasilCompanySaveState> {
|
||||||
|
final Ref ref;
|
||||||
|
PengantaranhasilCompanySaveNotifier({required this.ref})
|
||||||
|
: super(PengantaranhasilCompanySaveStateInit());
|
||||||
|
void pengantaranHasilCompanySave({
|
||||||
|
required String courierID,
|
||||||
|
required String tipeID,
|
||||||
|
required String deliveryID,
|
||||||
|
}) async {
|
||||||
|
try {
|
||||||
|
state = PengantaranhasilCompanySaveStateLoading();
|
||||||
|
final resp =
|
||||||
|
await PengantaranHasilInstansiRepository(dio: ref.read(dioProvider))
|
||||||
|
.pengantaranHasilInstansiSave(
|
||||||
|
courierID: courierID,
|
||||||
|
tipeID: tipeID,
|
||||||
|
deliveryID: deliveryID
|
||||||
|
);
|
||||||
|
|
||||||
|
state = PengantaranhasilCompanySaveStateDone(model: resp);
|
||||||
|
} catch (e) {
|
||||||
|
if (e is BaseRepositoryException) {
|
||||||
|
state = PengantaranhasilCompanySaveStateError(message: e.message ?? "");
|
||||||
|
} else {
|
||||||
|
state = PengantaranhasilCompanySaveStateError(message: e.toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 1. state
|
||||||
|
abstract class PengantaranhasilCompanySaveState extends Equatable {
|
||||||
|
final DateTime date;
|
||||||
|
const PengantaranhasilCompanySaveState(this.date);
|
||||||
|
@override
|
||||||
|
List<Object?> get props => [date];
|
||||||
|
}
|
||||||
|
|
||||||
|
class PengantaranhasilCompanySaveStateInit
|
||||||
|
extends PengantaranhasilCompanySaveState {
|
||||||
|
PengantaranhasilCompanySaveStateInit() : super(DateTime.now());
|
||||||
|
}
|
||||||
|
|
||||||
|
class PengantaranhasilCompanySaveStateLoading
|
||||||
|
extends PengantaranhasilCompanySaveState {
|
||||||
|
PengantaranhasilCompanySaveStateLoading() : super(DateTime.now());
|
||||||
|
}
|
||||||
|
|
||||||
|
class PengantaranhasilCompanySaveStateError
|
||||||
|
extends PengantaranhasilCompanySaveState {
|
||||||
|
final String? message;
|
||||||
|
PengantaranhasilCompanySaveStateError({
|
||||||
|
required this.message,
|
||||||
|
}) : super(DateTime.now());
|
||||||
|
}
|
||||||
|
|
||||||
|
class PengantaranhasilCompanySaveStateDone
|
||||||
|
extends PengantaranhasilCompanySaveState {
|
||||||
|
final ResponseSavePengantaranHasilModel model;
|
||||||
|
PengantaranhasilCompanySaveStateDone({
|
||||||
|
required this.model,
|
||||||
|
}) : super(DateTime.now());
|
||||||
|
}
|
||||||
@@ -0,0 +1,64 @@
|
|||||||
|
import 'package:equatable/equatable.dart';
|
||||||
|
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||||
|
import '/models/response_search_pengantaran_hasil_model.dart';
|
||||||
|
import '../../provider/dio_provider.dart';
|
||||||
|
import '../../repository/base_repository.dart';
|
||||||
|
import '../../repository/pengantaran_hasil_pasien_repository.dart';
|
||||||
|
|
||||||
|
// 3. state provider
|
||||||
|
final pengantaranHasilPasienSearchNoLab = StateNotifierProvider<PengantaranhasilPasienNotifier, PengantaranhasilPasienState>(
|
||||||
|
(ref) => PengantaranhasilPasienNotifier(ref: ref));
|
||||||
|
|
||||||
|
// 2. notifier
|
||||||
|
class PengantaranhasilPasienNotifier extends StateNotifier<PengantaranhasilPasienState> {
|
||||||
|
final Ref ref;
|
||||||
|
PengantaranhasilPasienNotifier({required this.ref}) : super(PengantaranhasilPasienStateInit());
|
||||||
|
void loadListNoLabPengantaranHasilPasien(
|
||||||
|
{
|
||||||
|
required String search
|
||||||
|
}) async {
|
||||||
|
try {
|
||||||
|
state = PengantaranhasilPasienStateLoading();
|
||||||
|
final resp = await PengantaranHasilPasienRepository(dio: ref.read(dioProvider))
|
||||||
|
.loadListNoLabPengantaranHasilPasien(search: search);
|
||||||
|
|
||||||
|
state = PengantaranhasilPasienStateDone(model: resp);
|
||||||
|
} catch (e) {
|
||||||
|
if (e is BaseRepositoryException) {
|
||||||
|
state = PengantaranhasilPasienStateError(message: e.message ?? "");
|
||||||
|
} else {
|
||||||
|
state = PengantaranhasilPasienStateError(message: e.toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 1. state
|
||||||
|
abstract class PengantaranhasilPasienState extends Equatable {
|
||||||
|
final DateTime date;
|
||||||
|
const PengantaranhasilPasienState(this.date);
|
||||||
|
@override
|
||||||
|
List<Object?> get props => [date];
|
||||||
|
}
|
||||||
|
|
||||||
|
class PengantaranhasilPasienStateInit extends PengantaranhasilPasienState {
|
||||||
|
PengantaranhasilPasienStateInit() : super(DateTime.now());
|
||||||
|
}
|
||||||
|
|
||||||
|
class PengantaranhasilPasienStateLoading extends PengantaranhasilPasienState {
|
||||||
|
PengantaranhasilPasienStateLoading() : super(DateTime.now());
|
||||||
|
}
|
||||||
|
|
||||||
|
class PengantaranhasilPasienStateError extends PengantaranhasilPasienState {
|
||||||
|
final String? message;
|
||||||
|
PengantaranhasilPasienStateError({
|
||||||
|
required this.message,
|
||||||
|
}) : super(DateTime.now());
|
||||||
|
}
|
||||||
|
|
||||||
|
class PengantaranhasilPasienStateDone extends PengantaranhasilPasienState {
|
||||||
|
final List<ResponseSearchPengantaranHasilModel> model;
|
||||||
|
PengantaranhasilPasienStateDone({
|
||||||
|
required this.model,
|
||||||
|
}) : super(DateTime.now());
|
||||||
|
}
|
||||||
@@ -0,0 +1,77 @@
|
|||||||
|
import 'package:equatable/equatable.dart';
|
||||||
|
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||||
|
import '../../models/response_save_pengantaran_hasil_model.dart';
|
||||||
|
import '../../provider/dio_provider.dart';
|
||||||
|
import '../../repository/base_repository.dart';
|
||||||
|
import '../../repository/pengantaran_hasil_pasien_repository.dart';
|
||||||
|
|
||||||
|
// 3. state provider
|
||||||
|
final pengantaranHasilPasienSave = StateNotifierProvider<
|
||||||
|
PengantaranhasilPasienSaveNotifier, PengantaranhasilPasienSaveState>(
|
||||||
|
(ref) => PengantaranhasilPasienSaveNotifier(ref: ref));
|
||||||
|
|
||||||
|
// 2. notifier
|
||||||
|
class PengantaranhasilPasienSaveNotifier
|
||||||
|
extends StateNotifier<PengantaranhasilPasienSaveState> {
|
||||||
|
final Ref ref;
|
||||||
|
PengantaranhasilPasienSaveNotifier({required this.ref})
|
||||||
|
: super(PengantaranhasilPasienSaveStateInit());
|
||||||
|
void pengantaranHasilPasienSave({
|
||||||
|
required String courierID,
|
||||||
|
required String tipeID,
|
||||||
|
required String deliveryID,
|
||||||
|
}) async {
|
||||||
|
try {
|
||||||
|
state = PengantaranhasilPasienSaveStateLoading();
|
||||||
|
final resp =
|
||||||
|
await PengantaranHasilPasienRepository(dio: ref.read(dioProvider))
|
||||||
|
.pengantaranHasilPasienSave(
|
||||||
|
courierID: courierID,
|
||||||
|
tipeID: tipeID,
|
||||||
|
deliveryID: deliveryID
|
||||||
|
);
|
||||||
|
|
||||||
|
state = PengantaranhasilPasienSaveStateDone(model: resp);
|
||||||
|
} catch (e) {
|
||||||
|
if (e is BaseRepositoryException) {
|
||||||
|
state = PengantaranhasilPasienSaveStateError(message: e.message ?? "");
|
||||||
|
} else {
|
||||||
|
state = PengantaranhasilPasienSaveStateError(message: e.toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 1. state
|
||||||
|
abstract class PengantaranhasilPasienSaveState extends Equatable {
|
||||||
|
final DateTime date;
|
||||||
|
const PengantaranhasilPasienSaveState(this.date);
|
||||||
|
@override
|
||||||
|
List<Object?> get props => [date];
|
||||||
|
}
|
||||||
|
|
||||||
|
class PengantaranhasilPasienSaveStateInit
|
||||||
|
extends PengantaranhasilPasienSaveState {
|
||||||
|
PengantaranhasilPasienSaveStateInit() : super(DateTime.now());
|
||||||
|
}
|
||||||
|
|
||||||
|
class PengantaranhasilPasienSaveStateLoading
|
||||||
|
extends PengantaranhasilPasienSaveState {
|
||||||
|
PengantaranhasilPasienSaveStateLoading() : super(DateTime.now());
|
||||||
|
}
|
||||||
|
|
||||||
|
class PengantaranhasilPasienSaveStateError
|
||||||
|
extends PengantaranhasilPasienSaveState {
|
||||||
|
final String? message;
|
||||||
|
PengantaranhasilPasienSaveStateError({
|
||||||
|
required this.message,
|
||||||
|
}) : super(DateTime.now());
|
||||||
|
}
|
||||||
|
|
||||||
|
class PengantaranhasilPasienSaveStateDone
|
||||||
|
extends PengantaranhasilPasienSaveState {
|
||||||
|
final ResponseSavePengantaranHasilModel model;
|
||||||
|
PengantaranhasilPasienSaveStateDone({
|
||||||
|
required this.model,
|
||||||
|
}) : super(DateTime.now());
|
||||||
|
}
|
||||||
68
lib/screen/input_pekerjaan/search_company_provider.dart
Normal file
@@ -0,0 +1,68 @@
|
|||||||
|
import 'package:equatable/equatable.dart';
|
||||||
|
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||||
|
import '/models/company_model.dart';
|
||||||
|
import '/models/work_list_model.dart';
|
||||||
|
import '../../repository/company_repository.dart';
|
||||||
|
import '../../repository/work_list_repository.dart';
|
||||||
|
|
||||||
|
import '../../models/pending_work_model.dart';
|
||||||
|
import '../../provider/dio_provider.dart';
|
||||||
|
import '../../repository/base_repository.dart';
|
||||||
|
import '../../repository/home_screen_repository.dart';
|
||||||
|
|
||||||
|
abstract class SearchCompanyState extends Equatable {
|
||||||
|
final DateTime date;
|
||||||
|
const SearchCompanyState(this.date);
|
||||||
|
@override
|
||||||
|
List<Object?> get props => [date];
|
||||||
|
}
|
||||||
|
|
||||||
|
class SearchCompanyStateInit extends SearchCompanyState {
|
||||||
|
SearchCompanyStateInit() : super(DateTime.now());
|
||||||
|
}
|
||||||
|
|
||||||
|
class SearchCompanyStateLoading extends SearchCompanyState {
|
||||||
|
SearchCompanyStateLoading() : super(DateTime.now());
|
||||||
|
}
|
||||||
|
|
||||||
|
class SearchCompanyStateError extends SearchCompanyState {
|
||||||
|
final String message;
|
||||||
|
SearchCompanyStateError({
|
||||||
|
required this.message,
|
||||||
|
}) : super(DateTime.now());
|
||||||
|
}
|
||||||
|
|
||||||
|
class SearchCompanyStateDone extends SearchCompanyState {
|
||||||
|
final List<CompanyModel> model;
|
||||||
|
SearchCompanyStateDone({
|
||||||
|
required this.model,
|
||||||
|
}) : super(DateTime.now());
|
||||||
|
}
|
||||||
|
|
||||||
|
//notifier
|
||||||
|
class SearchCompanyNotifier extends StateNotifier<SearchCompanyState> {
|
||||||
|
final Ref ref;
|
||||||
|
SearchCompanyNotifier({
|
||||||
|
required this.ref,
|
||||||
|
}) : super(SearchCompanyStateInit());
|
||||||
|
|
||||||
|
void getData({required String keyword}) async {
|
||||||
|
try {
|
||||||
|
state = SearchCompanyStateLoading();
|
||||||
|
final dio = ref.read(dioProvider);
|
||||||
|
final resp = await CompanyRepository(dio: dio).search(keyword: keyword);
|
||||||
|
state = SearchCompanyStateDone(model: resp);
|
||||||
|
} catch (e) {
|
||||||
|
if (e is BaseRepositoryException) {
|
||||||
|
state = SearchCompanyStateError(message: e.message.toString());
|
||||||
|
} else {
|
||||||
|
state = SearchCompanyStateError(message: e.toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//provider
|
||||||
|
final SearchCompanyProvider =
|
||||||
|
StateNotifierProvider<SearchCompanyNotifier, SearchCompanyState>(
|
||||||
|
(ref) => SearchCompanyNotifier(ref: ref));
|
||||||
91
lib/screen/konfirmasi/konfirmasi_screen.dart
Normal file
@@ -0,0 +1,91 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import '/app/route.dart';
|
||||||
|
|
||||||
|
import '../../app/constant.dart';
|
||||||
|
|
||||||
|
class KonfirmasiScreen extends StatelessWidget {
|
||||||
|
const KonfirmasiScreen({super.key});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Scaffold(
|
||||||
|
resizeToAvoidBottomInset: true,
|
||||||
|
backgroundColor: Constant.backgroundWhite,
|
||||||
|
body: SizedBox(
|
||||||
|
width: Constant.getActualX(context: context, x: 390),
|
||||||
|
height: Constant.getActualY(context: context, y: 844),
|
||||||
|
child: Column(
|
||||||
|
children: [
|
||||||
|
// image
|
||||||
|
Padding(
|
||||||
|
padding: EdgeInsets.only(
|
||||||
|
top: Constant.getActualY(context: context, y: 196),
|
||||||
|
left: Constant.getActualX(context: context, x: 30),
|
||||||
|
right: Constant.getActualX(context: context, x: 30),
|
||||||
|
),
|
||||||
|
child: Container(
|
||||||
|
// width: Constant.getActualX(context: context, x: 251),
|
||||||
|
// height: Constant.getActualY(context: context, y: 78),
|
||||||
|
// color: Colors.green,
|
||||||
|
child: Image.asset(
|
||||||
|
"assets/logo_kurir_konfirmasiv2.png",
|
||||||
|
// fit: BoxFit.fill,
|
||||||
|
// scale: 1,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
SizedBox(
|
||||||
|
height: Constant.getActualY(context: context, y: 40),
|
||||||
|
),
|
||||||
|
SizedBox(
|
||||||
|
width: Constant.getActualX(context: context, x: 268),
|
||||||
|
height: Constant.getActualY(context: context, y: 40),
|
||||||
|
child: Text(
|
||||||
|
'Input pekerjaan baru berhasil. Harap menunggu konfirmasi.',
|
||||||
|
style: Constant.body3(
|
||||||
|
context: context,
|
||||||
|
).copyWith(fontWeight: FontWeight.w600),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
SizedBox(
|
||||||
|
height: Constant.getActualY(context: context, y: 68),
|
||||||
|
),
|
||||||
|
// button konfirmasi
|
||||||
|
SizedBox(
|
||||||
|
width: Constant.getActualX(context: context, x: 320),
|
||||||
|
height: Constant.getActualY(context: context, y: 46),
|
||||||
|
child: ElevatedButton(
|
||||||
|
onPressed: () {
|
||||||
|
Navigator.of(context)
|
||||||
|
.pushNamedAndRemoveUntil(menuRoute, (route) => false);
|
||||||
|
},
|
||||||
|
style: ButtonStyle(
|
||||||
|
backgroundColor: MaterialStateColor.resolveWith(
|
||||||
|
(st) => Constant.primaryDark),
|
||||||
|
shape: MaterialStateProperty.all<RoundedRectangleBorder>(
|
||||||
|
RoundedRectangleBorder(
|
||||||
|
borderRadius: BorderRadius.circular(8),
|
||||||
|
// side: BorderSide(color: Colors.red),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
shadowColor: MaterialStateProperty.all(Color(0xffff48423d)),
|
||||||
|
elevation: MaterialStateProperty.all(4.0),
|
||||||
|
),
|
||||||
|
child: Align(
|
||||||
|
alignment: Alignment.center,
|
||||||
|
child: Text(
|
||||||
|
'Kembali ke Beranda',
|
||||||
|
style: Constant.buttonLarge(context: context).copyWith(
|
||||||
|
color: Constant.backgroundWhite,
|
||||||
|
fontWeight: FontWeight.w700,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
70
lib/screen/kurir_konfirmasi_screen/kurir_tolak_provider.dart
Normal file
@@ -0,0 +1,70 @@
|
|||||||
|
import 'dart:convert';
|
||||||
|
|
||||||
|
import 'package:equatable/equatable.dart';
|
||||||
|
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||||
|
import '../../repository/base_repository.dart';
|
||||||
|
|
||||||
|
import '../../provider/dio_provider.dart';
|
||||||
|
import '../../repository/kurir_tolak_repository.dart';
|
||||||
|
|
||||||
|
//provider
|
||||||
|
final kurirTolakProvider =
|
||||||
|
StateNotifierProvider<KurirTolakNotifier, KurirTolakState>(
|
||||||
|
(ref) => KurirTolakNotifier(ref: ref));
|
||||||
|
|
||||||
|
// notifier
|
||||||
|
class KurirTolakNotifier extends StateNotifier<KurirTolakState> {
|
||||||
|
final Ref ref;
|
||||||
|
KurirTolakNotifier({
|
||||||
|
required this.ref,
|
||||||
|
}) : super(KurirTolakStateInit());
|
||||||
|
|
||||||
|
void tolakKurir(
|
||||||
|
{required String id,
|
||||||
|
required String tipeId,
|
||||||
|
required String deliveryId,
|
||||||
|
required String note}) async {
|
||||||
|
try {
|
||||||
|
state = KurirTolakStateLoading();
|
||||||
|
final dio = ref.read(dioProvider);
|
||||||
|
final resp = await KurirTolakRepository(dio: dio).getKurirTolak(
|
||||||
|
id: id, tipeId: tipeId, deliveryId: deliveryId, note: note);
|
||||||
|
state = KurirTolakStateDone(model: resp);
|
||||||
|
} catch (e) {
|
||||||
|
if (e is BaseRepositoryException) {
|
||||||
|
state = KurirTolakStateError(message: e.message.toString());
|
||||||
|
} else {
|
||||||
|
state = KurirTolakStateError(message: e.toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract class KurirTolakState extends Equatable {
|
||||||
|
final DateTime date;
|
||||||
|
const KurirTolakState(this.date);
|
||||||
|
@override
|
||||||
|
List<Object?> get props => [date];
|
||||||
|
}
|
||||||
|
|
||||||
|
class KurirTolakStateInit extends KurirTolakState {
|
||||||
|
KurirTolakStateInit() : super(DateTime.now());
|
||||||
|
}
|
||||||
|
|
||||||
|
class KurirTolakStateLoading extends KurirTolakState {
|
||||||
|
KurirTolakStateLoading() : super(DateTime.now());
|
||||||
|
}
|
||||||
|
|
||||||
|
class KurirTolakStateError extends KurirTolakState {
|
||||||
|
final String message;
|
||||||
|
KurirTolakStateError({
|
||||||
|
required this.message,
|
||||||
|
}) : super(DateTime.now());
|
||||||
|
}
|
||||||
|
|
||||||
|
class KurirTolakStateDone extends KurirTolakState {
|
||||||
|
final bool model;
|
||||||
|
KurirTolakStateDone({
|
||||||
|
required this.model,
|
||||||
|
}) : super(DateTime.now());
|
||||||
|
}
|
||||||
94
lib/screen/login/login_provider.dart
Normal file
@@ -0,0 +1,94 @@
|
|||||||
|
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 '../../models/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 password,
|
||||||
|
bool isRememberMe = false}) async {
|
||||||
|
try {
|
||||||
|
state = LoginStateLoading();
|
||||||
|
final resp = await AuthRepository(dio: ref.read(dioProvider))
|
||||||
|
.login(username: username, password: password);
|
||||||
|
|
||||||
|
state = LoginStateDone(model: resp);
|
||||||
|
//Simpan ke token jk remember me
|
||||||
|
if (isRememberMe == true) {
|
||||||
|
final shared = await SharedPreferences.getInstance();
|
||||||
|
final token = {"date": DateTime.now().toString(), "model": resp.model};
|
||||||
|
final tokenEncode = jsonEncode(token);
|
||||||
|
await shared.setString(Constant.tokenName, tokenEncode);
|
||||||
|
await shared.setString("usernameX", username);
|
||||||
|
await shared.setString("passwordX", password);
|
||||||
|
await shared.setBool("isRememberMeX", isRememberMe);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// share pref di remove karena remember me tidak di centang
|
||||||
|
final shared = await SharedPreferences.getInstance();
|
||||||
|
await shared.remove("usernameX");
|
||||||
|
await shared.remove("passwordX");
|
||||||
|
await shared.remove("isRememberMeX");
|
||||||
|
}
|
||||||
|
|
||||||
|
ref.read(currentUserProvider.notifier).state = AuthModel(
|
||||||
|
token: resp.token,
|
||||||
|
model: resp.model,
|
||||||
|
);
|
||||||
|
|
||||||
|
// 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());
|
||||||
|
}
|
||||||
325
lib/screen/login/login_screen.dart
Normal file
@@ -0,0 +1,325 @@
|
|||||||
|
import 'dart:async';
|
||||||
|
import 'dart:convert';
|
||||||
|
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_hooks/flutter_hooks.dart';
|
||||||
|
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||||
|
import 'package:shared_preferences/shared_preferences.dart';
|
||||||
|
|
||||||
|
import '../../app/constant.dart';
|
||||||
|
import '../../app/route.dart';
|
||||||
|
import '../../models/auth_model.dart';
|
||||||
|
import '../../provider/current_user_provider.dart';
|
||||||
|
import '../../widget/sas_textfield.dart';
|
||||||
|
import 'login_provider.dart';
|
||||||
|
|
||||||
|
class LoginScreen extends HookConsumerWidget {
|
||||||
|
const LoginScreen({super.key});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context, WidgetRef ref) {
|
||||||
|
final isPasswordObscured = useState<bool>(true);
|
||||||
|
final ctrlUsername = useTextEditingController(text: "");
|
||||||
|
final ctrlPassword = useTextEditingController(text: "");
|
||||||
|
final focusNodeUsername = useFocusNode();
|
||||||
|
final focusNodePassword = useFocusNode();
|
||||||
|
|
||||||
|
final usernamehasFocus = useState(false);
|
||||||
|
final passwordhasFocus = useState(false);
|
||||||
|
|
||||||
|
final isRememberMe = useState(false);
|
||||||
|
final errorMessage = useState("");
|
||||||
|
final isLoading = useState(false);
|
||||||
|
final isSuccess = useState(false);
|
||||||
|
final isValidEntry = useState(false);
|
||||||
|
|
||||||
|
final usernameFromSharePref = useState("");
|
||||||
|
final passwordFromSharePref = useState("");
|
||||||
|
|
||||||
|
focusNodeUsername.addListener(() {
|
||||||
|
if (focusNodeUsername.hasFocus) {
|
||||||
|
usernamehasFocus.value = true;
|
||||||
|
passwordhasFocus.value = false;
|
||||||
|
} else {
|
||||||
|
usernamehasFocus.value = false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
focusNodePassword.addListener(() {
|
||||||
|
if (focusNodePassword.hasFocus) {
|
||||||
|
usernamehasFocus.value = false;
|
||||||
|
passwordhasFocus.value = true;
|
||||||
|
} else {
|
||||||
|
passwordhasFocus.value = false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// aksi login
|
||||||
|
ref.listen(loginProvider, (prev, next) async {
|
||||||
|
if (next is LoginStateLoading) {
|
||||||
|
isLoading.value = true;
|
||||||
|
} else if (next is LoginStateError) {
|
||||||
|
isLoading.value = false;
|
||||||
|
errorMessage.value = next.message ?? "";
|
||||||
|
// print(errorMessage.value);
|
||||||
|
Timer(const Duration(seconds: 3), () {
|
||||||
|
errorMessage.value = "";
|
||||||
|
});
|
||||||
|
} else if (next is LoginStateDone) {
|
||||||
|
isLoading.value = false;
|
||||||
|
isSuccess.value = true;
|
||||||
|
Navigator.of(context)
|
||||||
|
.pushNamedAndRemoveUntil(menuRoute, (route) => false);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
ctrlUsername.addListener(
|
||||||
|
() {
|
||||||
|
if (ctrlUsername.text.isEmpty || ctrlPassword.text.isEmpty) {
|
||||||
|
isValidEntry.value = false;
|
||||||
|
} else {
|
||||||
|
isValidEntry.value = true;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
ctrlPassword.addListener(
|
||||||
|
() {
|
||||||
|
if (ctrlUsername.text.isEmpty || ctrlPassword.text.isEmpty) {
|
||||||
|
isValidEntry.value = false;
|
||||||
|
} else {
|
||||||
|
isValidEntry.value = true;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
return GestureDetector(
|
||||||
|
onTap: () => FocusManager.instance.primaryFocus?.unfocus(),
|
||||||
|
child: Scaffold(
|
||||||
|
resizeToAvoidBottomInset: true,
|
||||||
|
backgroundColor: Constant.backgroundWhite,
|
||||||
|
body: SizedBox(
|
||||||
|
width: Constant.getActualX(context: context, x: 390),
|
||||||
|
height: Constant.getActualY(context: context, y: 844),
|
||||||
|
child: ListView(
|
||||||
|
children: [
|
||||||
|
// bg login
|
||||||
|
Padding(
|
||||||
|
padding: EdgeInsets.only(
|
||||||
|
top: Constant.getActualY(context: context, y: 80),
|
||||||
|
left: Constant.getActualX(context: context, x: 16),
|
||||||
|
right: Constant.getActualX(context: context, x: 16),
|
||||||
|
),
|
||||||
|
child: Image.asset(
|
||||||
|
"assets/bg_login.png",
|
||||||
|
// fit: BoxFit.fill,
|
||||||
|
// scale: 1,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
SizedBox(
|
||||||
|
height: Constant.getActualY(context: context, y: 10),
|
||||||
|
),
|
||||||
|
|
||||||
|
// Error From Backend Start
|
||||||
|
if (errorMessage.value != "")
|
||||||
|
Padding(
|
||||||
|
padding: EdgeInsets.only(
|
||||||
|
top: Constant.getActualY(context: context, y: 27),
|
||||||
|
left: Constant.getActualX(context: context, x: 38),
|
||||||
|
right: Constant.getActualX(context: context, x: 32),
|
||||||
|
),
|
||||||
|
child: Align(
|
||||||
|
alignment: Alignment.center,
|
||||||
|
child: Text(
|
||||||
|
"Peringatan : ${errorMessage.value}",
|
||||||
|
style: Constant.body1(context: context)
|
||||||
|
.copyWith(color: Constant.primaryRed),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
// Error From Backend End
|
||||||
|
|
||||||
|
// loading
|
||||||
|
if (isLoading.value)
|
||||||
|
Padding(
|
||||||
|
padding: EdgeInsets.only(
|
||||||
|
top: Constant.getActualY(context: context, y: 10),
|
||||||
|
left: Constant.getActualX(context: context, x: 38),
|
||||||
|
right: Constant.getActualX(context: context, x: 32),
|
||||||
|
),
|
||||||
|
child: Center(
|
||||||
|
child: SizedBox(
|
||||||
|
width: Constant.getActualX(context: context, x: 40),
|
||||||
|
height: Constant.getActualY(context: context, y: 40),
|
||||||
|
child: CircularProgressIndicator(
|
||||||
|
color: Constant.primaryBlue,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
|
||||||
|
SizedBox(
|
||||||
|
height: Constant.getActualY(context: context, y: 10),
|
||||||
|
),
|
||||||
|
|
||||||
|
Padding(
|
||||||
|
padding: EdgeInsets.only(
|
||||||
|
top: Constant.getActualY(context: context, y: 27),
|
||||||
|
left: Constant.getActualX(context: context, x: 38),
|
||||||
|
right: Constant.getActualX(context: context, x: 32),
|
||||||
|
),
|
||||||
|
child: SizedBox(
|
||||||
|
width: Constant.getActualX(context: context, x: 320),
|
||||||
|
height: Constant.getActualY(context: context, y: 412),
|
||||||
|
// color: Colors.amber,
|
||||||
|
child: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Text(
|
||||||
|
"Login",
|
||||||
|
style: Constant.heading2(context: context).copyWith(
|
||||||
|
color: Constant.textPrimary,
|
||||||
|
fontWeight: FontWeight.w600),
|
||||||
|
),
|
||||||
|
SizedBox(
|
||||||
|
height: Constant.getActualY(context: context, y: 20),
|
||||||
|
),
|
||||||
|
SasTextField(
|
||||||
|
hintText: "Username",
|
||||||
|
labelText: "Username",
|
||||||
|
controller: ctrlUsername,
|
||||||
|
focusNode: focusNodeUsername,
|
||||||
|
hasFocus: usernamehasFocus.value,
|
||||||
|
style: Constant.body1(context: context)
|
||||||
|
.copyWith(color: Constant.textBlack),
|
||||||
|
),
|
||||||
|
SizedBox(
|
||||||
|
height: Constant.getActualY(context: context, y: 16),
|
||||||
|
),
|
||||||
|
SasTextFieldPassword(
|
||||||
|
hintText: "Password",
|
||||||
|
labelText: "Password",
|
||||||
|
controller: ctrlPassword,
|
||||||
|
focusNode: focusNodePassword,
|
||||||
|
hasFocus: passwordhasFocus.value,
|
||||||
|
onToggle: () {
|
||||||
|
isPasswordObscured.value = !isPasswordObscured.value;
|
||||||
|
},
|
||||||
|
obscureText:
|
||||||
|
(isPasswordObscured.value == true) ? true : false,
|
||||||
|
),
|
||||||
|
SizedBox(
|
||||||
|
height: Constant.getActualY(context: context, y: 16),
|
||||||
|
),
|
||||||
|
SizedBox(
|
||||||
|
width: Constant.getActualX(context: context, x: 320),
|
||||||
|
height: Constant.getActualY(context: context, y: 20),
|
||||||
|
// color: Colors.green,
|
||||||
|
child: Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Checkbox(
|
||||||
|
value: isRememberMe.value,
|
||||||
|
onChanged: (value) {
|
||||||
|
if (value != null) {
|
||||||
|
isRememberMe.value = value;
|
||||||
|
// checkIsLogin(isRememberMe.value);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
),
|
||||||
|
const SizedBox(width: 8.0),
|
||||||
|
Text(
|
||||||
|
"Ingat saya",
|
||||||
|
style:
|
||||||
|
Constant.caption1(context: context).copyWith(
|
||||||
|
color: Constant.textPrimary,
|
||||||
|
fontWeight: FontWeight.w400,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
SizedBox(
|
||||||
|
height: Constant.getActualY(context: context, y: 32),
|
||||||
|
),
|
||||||
|
// button login
|
||||||
|
SizedBox(
|
||||||
|
width: Constant.getActualX(context: context, x: 320),
|
||||||
|
height: Constant.getActualY(context: context, y: 48),
|
||||||
|
child: ElevatedButton(
|
||||||
|
onPressed: (isLoading.value == true)
|
||||||
|
? null
|
||||||
|
: () {
|
||||||
|
if (ctrlUsername.text.isEmpty ||
|
||||||
|
ctrlPassword.text.isEmpty) {
|
||||||
|
isLoading.value = false;
|
||||||
|
errorMessage.value = 'Inputan harus diisi';
|
||||||
|
Timer(const Duration(seconds: 3), () {
|
||||||
|
isLoading.value = false;
|
||||||
|
errorMessage.value = "";
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
ref.read(loginProvider.notifier).login(
|
||||||
|
username: ctrlUsername.text,
|
||||||
|
password: ctrlPassword.text,
|
||||||
|
isRememberMe: isRememberMe.value,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
style: ButtonStyle(
|
||||||
|
backgroundColor: MaterialStateColor.resolveWith(
|
||||||
|
(st) => Constant.primaryMain),
|
||||||
|
shape: MaterialStateProperty.all<
|
||||||
|
RoundedRectangleBorder>(
|
||||||
|
RoundedRectangleBorder(
|
||||||
|
borderRadius: BorderRadius.circular(8),
|
||||||
|
// side: BorderSide(color: Colors.red),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
shadowColor: MaterialStateProperty.all(
|
||||||
|
const Color(0xffff48423d)),
|
||||||
|
elevation: MaterialStateProperty.all(4.0),
|
||||||
|
),
|
||||||
|
child: Align(
|
||||||
|
alignment: Alignment.center,
|
||||||
|
child: Text(
|
||||||
|
'Login',
|
||||||
|
style: Constant.buttonLarge(context: context)
|
||||||
|
.copyWith(
|
||||||
|
color: Constant.backgroundWhite,
|
||||||
|
fontWeight: FontWeight.w700,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
SizedBox(
|
||||||
|
height: Constant.getActualY(context: context, y: 16),
|
||||||
|
),
|
||||||
|
// Center(
|
||||||
|
// child: InkWell(
|
||||||
|
// onTap: () {
|
||||||
|
// Navigator.of(context).pushNamedAndRemoveUntil(
|
||||||
|
// problemLoginRoute,
|
||||||
|
// (route) => true,
|
||||||
|
// );
|
||||||
|
// },
|
||||||
|
// child: Text(
|
||||||
|
// "Problem login",
|
||||||
|
// style: Constant.caption1(context: context).copyWith(
|
||||||
|
// color: Constant.errorDark,
|
||||||
|
// fontWeight: FontWeight.w400),
|
||||||
|
// ),
|
||||||
|
// ),
|
||||||
|
// ),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
64
lib/screen/login/logout_provider.dart
Normal file
@@ -0,0 +1,64 @@
|
|||||||
|
import 'package:equatable/equatable.dart';
|
||||||
|
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||||
|
import '../../provider/dio_provider.dart';
|
||||||
|
import '../../repository/auth_repository.dart';
|
||||||
|
import '../../repository/base_repository.dart';
|
||||||
|
|
||||||
|
// 3. state provider
|
||||||
|
final logoutProvider = StateNotifierProvider<LogoutNotifier, LogoutState>(
|
||||||
|
(ref) => LogoutNotifier(ref: ref));
|
||||||
|
|
||||||
|
// 2. notifier
|
||||||
|
class LogoutNotifier extends StateNotifier<LogoutState> {
|
||||||
|
final Ref ref;
|
||||||
|
LogoutNotifier({required this.ref}) : super(LogoutStateInit());
|
||||||
|
void logout({
|
||||||
|
required String M_UserID,
|
||||||
|
required String M_UserUsername,
|
||||||
|
}) async {
|
||||||
|
try {
|
||||||
|
state = LogoutStateLoading();
|
||||||
|
final resp = await AuthRepository(dio: ref.read(dioProvider))
|
||||||
|
.logout(M_UserID: M_UserID, M_UserUsername: M_UserUsername);
|
||||||
|
|
||||||
|
// print(resp);
|
||||||
|
state = LogoutStateDone(message: resp);
|
||||||
|
} catch (e) {
|
||||||
|
if (e is BaseRepositoryException) {
|
||||||
|
state = LogoutStateError(message: e.message ?? "");
|
||||||
|
} else {
|
||||||
|
state = LogoutStateError(message: e.toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 1. state
|
||||||
|
abstract class LogoutState extends Equatable {
|
||||||
|
final DateTime date;
|
||||||
|
const LogoutState(this.date);
|
||||||
|
@override
|
||||||
|
List<Object?> get props => [date];
|
||||||
|
}
|
||||||
|
|
||||||
|
class LogoutStateInit extends LogoutState {
|
||||||
|
LogoutStateInit() : super(DateTime.now());
|
||||||
|
}
|
||||||
|
|
||||||
|
class LogoutStateLoading extends LogoutState {
|
||||||
|
LogoutStateLoading() : super(DateTime.now());
|
||||||
|
}
|
||||||
|
|
||||||
|
class LogoutStateError extends LogoutState {
|
||||||
|
final String message;
|
||||||
|
LogoutStateError({
|
||||||
|
required this.message,
|
||||||
|
}) : super(DateTime.now());
|
||||||
|
}
|
||||||
|
|
||||||
|
class LogoutStateDone extends LogoutState {
|
||||||
|
final String message;
|
||||||
|
LogoutStateDone({
|
||||||
|
required this.message,
|
||||||
|
}) : super(DateTime.now());
|
||||||
|
}
|
||||||