step 3 : hapus ai_barcode_scanner, ai barcode, update permission_handler, flutter_map,latlong2
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_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() {
|
||||
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 {
|
||||
@@ -11,112 +22,34 @@ class MyApp extends StatelessWidget {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return MaterialApp(
|
||||
title: 'Flutter Demo',
|
||||
title: 'Aplikasi Kurir Kedungdoro',
|
||||
theme: ThemeData(
|
||||
// This is the theme of your application.
|
||||
//
|
||||
// TRY THIS: Try running your application with "flutter run". You'll see
|
||||
// the application has a purple toolbar. Then, without quitting the app,
|
||||
// try changing the seedColor in the colorScheme below to Colors.green
|
||||
// and then invoke "hot reload" (save your changes or press the "hot
|
||||
// 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'),
|
||||
primarySwatch: createMaterialColor(const Color(0xFF005AA9)),
|
||||
fontFamily: 'OpenSans'),
|
||||
debugShowCheckedModeBanner: false,
|
||||
// initialRoute: loginRoute,
|
||||
initialRoute: splashRoute,
|
||||
onGenerateRoute: AppRoute.generateRoute,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class MyHomePage extends StatefulWidget {
|
||||
const MyHomePage({super.key, required this.title});
|
||||
MaterialColor createMaterialColor(Color color) {
|
||||
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
|
||||
// that it has a State object (defined below) that contains fields that affect
|
||||
// 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 (int i = 1; i < 10; i++) {
|
||||
strengths.add(0.1 * i);
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
// This method is rerun every time setState is called, for instance as done
|
||||
// by the _incrementCounter method above.
|
||||
//
|
||||
// The Flutter framework has been optimized to make rerunning build methods
|
||||
// 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.
|
||||
for (var strength in strengths) {
|
||||
final double ds = 0.5 - strength;
|
||||
swatch[(strength * 1000).round()] = Color.fromRGBO(
|
||||
r + ((ds < 0 ? r : (255 - r)) * ds).round(),
|
||||
g + ((ds < 0 ? g : (255 - g)) * ds).round(),
|
||||
b + ((ds < 0 ? b : (255 - b)) * ds).round(),
|
||||
1,
|
||||
);
|
||||
}
|
||||
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());
|
||||
}
|
||||
95
lib/screen/menu_screen/menu_screen.dart
Normal file
@@ -0,0 +1,95 @@
|
||||
import 'package:fancy_bottom_navigation_2/fancy_bottom_navigation.dart';
|
||||
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 '/screen/history_screen/history_screen.dart';
|
||||
import '/screen/profile_screen/profile_screen.dart';
|
||||
import '/screen/work_list_screen/work_list_screen.dart';
|
||||
import 'package:loader_overlay/loader_overlay.dart';
|
||||
import 'package:loading_animation_widget/loading_animation_widget.dart';
|
||||
|
||||
import '../../app/constant.dart';
|
||||
import '../../provider/current_user_provider.dart';
|
||||
import '../home_screen/home_screen.dart';
|
||||
import '../home_screen/pending_work_provider.dart';
|
||||
import '../home_screen/total_work_provider.dart';
|
||||
import '../work_list_screen/work_status_provider.dart';
|
||||
import '../work_list_screen/work_supervisor_moder.dart';
|
||||
import '../work_list_screen/work_type_provider.dart';
|
||||
|
||||
class MenuScreen extends HookConsumerWidget {
|
||||
const MenuScreen({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context, WidgetRef ref) {
|
||||
final current_page = useState(0);
|
||||
final mUsername =
|
||||
ref.watch(currentUserProvider)?.model.user?.mStaffName ?? "0";
|
||||
|
||||
final mCourirID =
|
||||
ref.watch(currentUserProvider)?.model.user?.mCourierID ?? "0";
|
||||
|
||||
changeMenu() {
|
||||
switch (current_page.value) {
|
||||
case 0:
|
||||
return HomeScreen();
|
||||
break;
|
||||
case 1:
|
||||
return WorkListScreen();
|
||||
break;
|
||||
case 2:
|
||||
return HistoryScreen();
|
||||
break;
|
||||
case 3:
|
||||
return ProfilScreen();
|
||||
break;
|
||||
default:
|
||||
return HomeScreen();
|
||||
}
|
||||
}
|
||||
|
||||
return LoaderOverlay(
|
||||
useDefaultLoading: false,
|
||||
overlayColor: Colors.black,
|
||||
overlayWidget: Center(
|
||||
child: LoadingAnimationWidget.inkDrop(
|
||||
color: Constant.primaryBlue, size: 50),
|
||||
),
|
||||
child: Scaffold(
|
||||
resizeToAvoidBottomInset: false,
|
||||
backgroundColor:
|
||||
current_page.value == 1 ? const Color(0XFFF4F6F8) : Colors.white,
|
||||
bottomNavigationBar: Container(
|
||||
height: Constant.getActualY(context: context, y: 67),
|
||||
child: SizedBox(
|
||||
height: Constant.getActualY(context: context, y: 67),
|
||||
child: FancyBottomNavigation(
|
||||
tabs: [
|
||||
TabData(iconData: Icons.home_outlined, title: "Beranda"),
|
||||
TabData(
|
||||
iconData: Icons.work_history_outlined,
|
||||
title: "List Pekerjaan"),
|
||||
TabData(iconData: Icons.map_outlined, title: "Riwayat"),
|
||||
TabData(iconData: Icons.person_outlined, title: "Profil")
|
||||
],
|
||||
onTabChangedListener: (position) {
|
||||
current_page.value = position;
|
||||
|
||||
// if (position == 0) {
|
||||
// ref.read(TotalWorkProvider.notifier).getData(id: mCourirID);
|
||||
// ref.read(PendingWorkProvider.notifier).getData(id: mCourirID);
|
||||
// ref.read(WorkTypeProvider.notifier).getData();
|
||||
// ref.read(WorkStatusProvider.notifier).getData();
|
||||
// ref.read(WorkSupervisorProvider.notifier).getData();
|
||||
// }
|
||||
},
|
||||
),
|
||||
),
|
||||
),
|
||||
body: changeMenu(),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
import 'package:equatable/equatable.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import '/models/personal_information_model.dart';
|
||||
import '../../repository/personal_information_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 PersonalInformationState extends Equatable {
|
||||
final DateTime date;
|
||||
const PersonalInformationState(this.date);
|
||||
@override
|
||||
List<Object?> get props => [date];
|
||||
}
|
||||
|
||||
class PersonalInformationStateInit extends PersonalInformationState {
|
||||
PersonalInformationStateInit() : super(DateTime.now());
|
||||
}
|
||||
|
||||
class PersonalInformationStateLoading extends PersonalInformationState {
|
||||
PersonalInformationStateLoading() : super(DateTime.now());
|
||||
}
|
||||
|
||||
class PersonalInformationStateError extends PersonalInformationState {
|
||||
final String message;
|
||||
PersonalInformationStateError({
|
||||
required this.message,
|
||||
}) : super(DateTime.now());
|
||||
}
|
||||
|
||||
class PersonalInformationStateDone extends PersonalInformationState {
|
||||
final List<PersonalInformationModel> model;
|
||||
PersonalInformationStateDone({
|
||||
required this.model,
|
||||
}) : super(DateTime.now());
|
||||
}
|
||||
|
||||
//notifier
|
||||
class PersonalInformationNotifier extends StateNotifier<PersonalInformationState> {
|
||||
final Ref ref;
|
||||
PersonalInformationNotifier({
|
||||
required this.ref,
|
||||
}) : super(PersonalInformationStateInit());
|
||||
|
||||
void getData(
|
||||
{required String mCourierID}) async {
|
||||
try {
|
||||
state = PersonalInformationStateLoading();
|
||||
final dio = ref.read(dioProvider);
|
||||
final resp = await PersonalInformationRepository(dio: dio).getPersonalInformation(mCourierID: mCourierID);
|
||||
state = PersonalInformationStateDone(model: resp);
|
||||
} catch (e) {
|
||||
if (e is BaseRepositoryException) {
|
||||
state = PersonalInformationStateError(message: e.message.toString());
|
||||
} else {
|
||||
state = PersonalInformationStateError(message: e.toString());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//provider
|
||||
final PersonalInformationProvider = StateNotifierProvider<PersonalInformationNotifier, PersonalInformationState>(
|
||||
(ref) => PersonalInformationNotifier(ref: ref));
|
||||