Browse Source

Validation Send to Backend

main
padmanto 2 years ago
parent
commit
e143037aa4
  1. 24
      lib/repository/mitra_repository.dart
  2. 13
      lib/widget/fx_company_lookup.dart
  3. 2
      lib/widget/fx_data_mitra.dart
  4. 42
      lib/widget/fx_doctor_address.dart
  5. 5
      lib/widget/fx_doctor_lookup.dart
  6. 110
      lib/widget/fx_mitra_add_dialog.dart
  7. 25
      lib/widget/fx_mitra_mou.dart
  8. 79
      lib/widget/provider/mitra_add_provider.dart
  9. 5
      lib/widget/provider/selectedCompanyProvider.dart
  10. 3
      lib/widget/provider/selectedDoctorProvider.dart
  11. 3
      php-api/mitra/Md.php

24
lib/repository/mitra_repository.dart

@ -9,6 +9,30 @@ import 'base_repository.dart';
class MitraRepository extends BaseRepository { class MitraRepository extends BaseRepository {
MitraRepository({required super.dio}); MitraRepository({required super.dio});
Future<bool> add({
required String token,
required String companyID,
required List<String> mouID,
required String doctorID,
required String doctorAddressID,
required String login,
CancelToken? cancelToken,
}) async {
final param = {
"token": token,
"companyID": companyID,
"mouID": mouID,
"doctorID": doctorID,
"doctorAddressID": doctorAddressID,
"login": login
};
final service = "${Constants.baseUrl}md/add";
await post(service: service, jsonParam: param, cancelToken: cancelToken);
return true;
}
Future<List<MitraResponseModel>> search({ Future<List<MitraResponseModel>> search({
required String query, required String query,
CancelToken? cancelToken, CancelToken? cancelToken,

13
lib/widget/fx_company_lookup.dart

@ -13,7 +13,11 @@ import 'provider/selectedCompanyProvider.dart';
// ignore: must_be_immutable // ignore: must_be_immutable
class FxAcCompany extends HookConsumerWidget { class FxAcCompany extends HookConsumerWidget {
FxAcCompany({Key? key}) : super(key: key); final String? errorValidation;
FxAcCompany({
Key? key,
this.errorValidation,
}) : super(key: key);
CancelToken? cancelToken; CancelToken? cancelToken;
@override @override
@ -23,11 +27,11 @@ class FxAcCompany extends HookConsumerWidget {
cancelToken = CancelToken(); cancelToken = CancelToken();
final fc = FocusNode(); final fc = FocusNode();
final selectedCompany = ref.read(selectdAcCompanyProvider); final selectedCompany = ref.read(selectedAcCompanyProvider);
if (selectedCompany != null) { if (selectedCompany != null) {
ctrl.text = selectedCompany.mCompanyName; ctrl.text = selectedCompany.mCompanyName;
} }
ref.listen<AcCompanyModel?>(selectdAcCompanyProvider, ((prev, next) { ref.listen<AcCompanyModel?>(selectedAcCompanyProvider, ((prev, next) {
if (next != null) { if (next != null) {
ref ref
.read(mitraLookupMouProvider.notifier) .read(mitraLookupMouProvider.notifier)
@ -45,6 +49,7 @@ class FxAcCompany extends HookConsumerWidget {
fc: fc, fc: fc,
hint: "Company", hint: "Company",
label: "Company", label: "Company",
errorMessage: errorValidation,
); );
}, },
optionsBuilder: (tv) async { optionsBuilder: (tv) async {
@ -71,7 +76,7 @@ class FxAcCompany extends HookConsumerWidget {
final model = listModel.elementAt(idx); final model = listModel.elementAt(idx);
return InkWell( return InkWell(
onTap: () { onTap: () {
ref.read(selectdAcCompanyProvider.notifier).state = ref.read(selectedAcCompanyProvider.notifier).state =
model; model;
onSelect(model); onSelect(model);
}, },

2
lib/widget/fx_data_mitra.dart

@ -63,7 +63,7 @@ class FxDataMitra extends HookConsumerWidget {
await showDialog( await showDialog(
context: context, context: context,
builder: (context) { builder: (context) {
return const FxMitraAddDialog(); return FxMitraAddDialog();
}); });
}), }),
), ),

42
lib/widget/fx_doctor_address.dart

@ -4,15 +4,18 @@ import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:onemd/model/ac_doctor_model.dart'; import 'package:onemd/model/ac_doctor_model.dart';
import 'fx_data_mitra.dart'; import 'fx_data_mitra.dart';
import 'fx_error_text.dart';
import 'provider/doctor_address_lookup_provider.dart'; import 'provider/doctor_address_lookup_provider.dart';
import 'provider/doctor_lookup_provider.dart';
import 'provider/selectedDoctorProvider.dart'; import 'provider/selectedDoctorProvider.dart';
class FxDoctorAddress extends HookConsumerWidget { class FxDoctorAddress extends HookConsumerWidget {
final double? width; final double? width;
final String? errorValidation;
const FxDoctorAddress({ const FxDoctorAddress({
Key? key, Key? key,
this.width, this.width,
this.errorValidation,
}) : super(key: key); }) : super(key: key);
@override @override
@ -35,7 +38,11 @@ class FxDoctorAddress extends HookConsumerWidget {
width: double.infinity, width: double.infinity,
decoration: BoxDecoration( decoration: BoxDecoration(
borderRadius: BorderRadius.circular(10), borderRadius: BorderRadius.circular(10),
border: Border.all(color: Colors.blue.shade700), border: Border.all(
color: errorValidation == null
? Colors.blue.shade700
: Colors.red.shade700,
),
color: Colors.blue.shade100.withOpacity(0.3), color: Colors.blue.shade100.withOpacity(0.3),
), ),
child: ConstrainedBox( child: ConstrainedBox(
@ -46,10 +53,13 @@ class FxDoctorAddress extends HookConsumerWidget {
mainAxisSize: MainAxisSize.min, mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
FxNormalBlueText( errorValidation == null
title: "Alamat dari $doctorName", ? FxNormalBlueText(
isBold: true, title: "Address of $doctorName",
), isBold: true,
)
: FxErrorText(
title: "Address of $doctorName *) $errorValidation"),
const SizedBox(height: 10), const SizedBox(height: 10),
if (listAddress.value.isNotEmpty) if (listAddress.value.isNotEmpty)
ConstrainedBox( ConstrainedBox(
@ -61,21 +71,25 @@ class FxDoctorAddress extends HookConsumerWidget {
itemBuilder: (context, idx) { itemBuilder: (context, idx) {
final model = listAddress.value[idx]; final model = listAddress.value[idx];
return Row( return Row(
crossAxisAlignment: CrossAxisAlignment.center,
children: [ children: [
Checkbox( Radio<AcDoctorAddressResponseModel>(
value: model.isCheck, groupValue:
ref.watch(selectedAcDoctorAddressProvider),
value: model,
onChanged: ((val) { onChanged: ((val) {
final List<AcDoctorAddressResponseModel> list = ref
List.empty(growable: true); .read(selectedAcDoctorAddressProvider
list.addAll(listAddress.value); .notifier)
list[idx].isCheck = val ?? false; .state = val;
listAddress.value = list;
}), }),
), ),
const SizedBox(width: 10), const SizedBox(width: 10),
Expanded( Expanded(
child: FxNormalBlueText( child: FxNormalBlueText(
title: model.mDoctorAddressDescription), title: model.mDoctorAddressDescription
.replaceAll("\n", ""),
),
), ),
], ],
); );

5
lib/widget/fx_doctor_lookup.dart

@ -13,7 +13,8 @@ import 'provider/doctor_address_lookup_provider.dart';
// ignore: must_be_immutable // ignore: must_be_immutable
class FxAcDoctor extends HookConsumerWidget { class FxAcDoctor extends HookConsumerWidget {
FxAcDoctor({Key? key}) : super(key: key); final String? errorValidation;
FxAcDoctor({Key? key, this.errorValidation}) : super(key: key);
CancelToken? cancelToken; CancelToken? cancelToken;
@override @override
@ -29,7 +30,6 @@ class FxAcDoctor extends HookConsumerWidget {
} }
ref.listen<AcDoctorResponseModel?>(selectedAcDoctorProvider, ((prev, next) { ref.listen<AcDoctorResponseModel?>(selectedAcDoctorProvider, ((prev, next) {
if (next != null) { if (next != null) {
print("Calling for " + next.fullName);
ref ref
.read(doctorAddressLookupProvider.notifier) .read(doctorAddressLookupProvider.notifier)
.lookup(doctorID: next.mDoctorID); .lookup(doctorID: next.mDoctorID);
@ -46,6 +46,7 @@ class FxAcDoctor extends HookConsumerWidget {
hint: "Doctor", hint: "Doctor",
fc: fc, fc: fc,
ctrl: ctrl, ctrl: ctrl,
errorMessage: errorValidation,
); );
}, },
optionsBuilder: (tv) async { optionsBuilder: (tv) async {

110
lib/widget/fx_mitra_add_dialog.dart

@ -1,4 +1,7 @@
import 'dart:async';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_hooks/flutter_hooks.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:onemd/widget/fx_doctor_address.dart'; import 'package:onemd/widget/fx_doctor_address.dart';
@ -6,15 +9,61 @@ import 'fx_company_lookup.dart';
import 'fx_doctor_lookup.dart'; import 'fx_doctor_lookup.dart';
import 'fx_mitra_mou.dart'; import 'fx_mitra_mou.dart';
import 'fx_text_field.dart'; import 'fx_text_field.dart';
import 'provider/mitra_add_provider.dart';
import 'provider/selectedCompanyProvider.dart';
import 'provider/selectedDoctorProvider.dart';
class FxMitraAddDialog extends HookConsumerWidget { class FxMitraAddDialog extends HookConsumerWidget {
const FxMitraAddDialog({Key? key}) : super(key: key); const FxMitraAddDialog({Key? key}) : super(key: key);
@override @override
Widget build(BuildContext context, WidgetRef ref) { Widget build(BuildContext context, WidgetRef ref) {
final ctrlLogin = useTextEditingController(text: "");
final fcLogin = FocusNode(); final fcLogin = FocusNode();
final company = ref.watch(selectedAcCompanyProvider);
final doctor = ref.watch(selectedAcDoctorProvider);
final doctorAddress = ref.watch(selectedAcDoctorAddressProvider);
final mou = ref.watch(selectedMouProvider);
final errorCompany = useState<String?>(null);
final errorDoctor = useState<String?>(null);
final errorDoctorAddress = useState<String?>(null);
final errorMou = useState<String?>(null);
final errorLogin = useState<String?>(null);
final ctrlLogin = useTextEditingController(text: "");
bool Function() validationError;
validationError = () {
bool haveError = false;
if (company == null) {
errorCompany.value = "Company is mandatory";
haveError = true;
}
if (mou.isEmpty) {
errorMou.value = "Mou is mandatory";
haveError = true;
}
if (doctor == null) {
errorDoctor.value = "Doctor is mandatory";
haveError = true;
}
if (doctorAddress == null) {
errorDoctorAddress.value = "Doctor Address is mandatory";
haveError = true;
}
if (ctrlLogin.text == "") {
errorLogin.value = "Login is mandatory";
haveError = true;
}
Timer(const Duration(seconds: 3), () {
errorCompany.value = null;
errorMou.value = null;
errorDoctor.value = null;
errorDoctorAddress.value = null;
errorLogin.value = null;
});
return haveError;
};
return Dialog( return Dialog(
shape: RoundedRectangleBorder( shape: RoundedRectangleBorder(
side: const BorderSide(), side: const BorderSide(),
@ -29,28 +78,75 @@ class FxMitraAddDialog extends HookConsumerWidget {
child: Column( child: Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
FxAcCompany(), FxAcCompany(
errorValidation: errorCompany.value,
),
const SizedBox(height: 10), const SizedBox(height: 10),
const FxMitraMou(), FxMitraMou(
errorValidation: errorMou.value,
),
const SizedBox(height: 10), const SizedBox(height: 10),
FxAcDoctor(), FxAcDoctor(
errorValidation: errorDoctor.value,
),
const SizedBox(height: 10), const SizedBox(height: 10),
FxDoctorAddress(), FxDoctorAddress(
errorValidation: errorDoctorAddress.value,
),
const SizedBox(height: 10), const SizedBox(height: 10),
FxTextField( FxTextField(
ctrl: ctrlLogin, ctrl: ctrlLogin,
fc: fcLogin, fc: fcLogin,
hint: "Login", hint: "Login",
label: "Login", label: "Login",
errorMessage: errorLogin.value,
), ),
const SizedBox(height: 10), const SizedBox(height: 10),
FxTextField( const FxTextField(
hint: "ID", hint: "ID",
label: "ID", label: "ID",
isReadOnly: true, isReadOnly: true,
isEnabled: false, isEnabled: false,
suffixText: "Auto Generated"), suffixText: "Auto Generated"),
const SizedBox(height: 10), const SizedBox(height: 10),
Row(
mainAxisAlignment: MainAxisAlignment.end,
mainAxisSize: MainAxisSize.max,
children: [
ElevatedButton(
style: ButtonStyle(
backgroundColor: MaterialStateColor.resolveWith(
(st) => Colors.green,
),
),
onPressed: () {
if (!validationError()) {
ref.read(mitraAddProvider.notifier).add(
companyID: company!.mCompanyID,
mouID: mou.map((e) => e.mMouID).toList(),
doctorID: doctor!.mDoctorID,
doctorAddressID:
doctorAddress!.mDoctorAddressID,
login: ctrlLogin.text,
);
}
},
child: const Text("Save"),
),
const SizedBox(width: 20),
ElevatedButton(
style: ButtonStyle(
backgroundColor: MaterialStateColor.resolveWith(
(st) => Colors.red,
),
),
onPressed: () {
Navigator.of(context).pop();
},
child: const Text("Cancel"),
),
],
),
], ],
), ),
), ),
@ -58,5 +154,3 @@ class FxMitraAddDialog extends HookConsumerWidget {
); );
} }
} }
useTextEditingController({required String text}) {}

25
lib/widget/fx_mitra_mou.dart

@ -5,20 +5,23 @@ import 'package:hooks_riverpod/hooks_riverpod.dart';
import '../model/ac_mou_response_model.dart'; import '../model/ac_mou_response_model.dart';
import '../screen/md_lab_mitra/mitra_lookup_mou_provider.dart'; import '../screen/md_lab_mitra/mitra_lookup_mou_provider.dart';
import 'fx_data_mitra.dart'; import 'fx_data_mitra.dart';
import 'fx_error_text.dart';
import 'provider/selectedCompanyProvider.dart'; import 'provider/selectedCompanyProvider.dart';
class FxMitraMou extends HookConsumerWidget { class FxMitraMou extends HookConsumerWidget {
final double? width; final double? width;
final String? errorValidation;
const FxMitraMou({ const FxMitraMou({
Key? key, Key? key,
this.width, this.width,
this.errorValidation,
}) : super(key: key); }) : super(key: key);
@override @override
Widget build(BuildContext context, WidgetRef ref) { Widget build(BuildContext context, WidgetRef ref) {
final listMou = useState<List<AcMouResponseModel>>(List.empty()); final listMou = useState<List<AcMouResponseModel>>(List.empty());
final companyModel = ref.watch(selectdAcCompanyProvider); final companyModel = ref.watch(selectedAcCompanyProvider);
String companyName = companyModel?.mCompanyName ?? ""; String companyName = companyModel?.mCompanyName ?? "";
ref.listen(mitraLookupMouProvider, (prev, next) { ref.listen(mitraLookupMouProvider, (prev, next) {
if (next is MitraLookupMouStateDone) { if (next is MitraLookupMouStateDone) {
@ -28,12 +31,15 @@ class FxMitraMou extends HookConsumerWidget {
listMou.value = next.list; listMou.value = next.list;
} }
}); });
return Container( return Container(
width: double.infinity, width: double.infinity,
decoration: BoxDecoration( decoration: BoxDecoration(
borderRadius: BorderRadius.circular(10), borderRadius: BorderRadius.circular(10),
border: Border.all(color: Colors.blue.shade700), border: Border.all(
color: errorValidation == null
? Colors.blue.shade700
: Colors.red.shade700,
),
color: Colors.blue.shade100.withOpacity(0.3), color: Colors.blue.shade100.withOpacity(0.3),
), ),
child: ConstrainedBox( child: ConstrainedBox(
@ -44,10 +50,13 @@ class FxMitraMou extends HookConsumerWidget {
mainAxisSize: MainAxisSize.min, mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
FxNormalBlueText( errorValidation == null
title: "Agreement $companyName", ? FxNormalBlueText(
isBold: true, title: "Agreement $companyName",
), isBold: true,
)
: FxErrorText(
title: "Agreement $companyName *) $errorValidation"),
const SizedBox(height: 10), const SizedBox(height: 10),
if (listMou.value.isNotEmpty) if (listMou.value.isNotEmpty)
ConstrainedBox( ConstrainedBox(
@ -68,6 +77,8 @@ class FxMitraMou extends HookConsumerWidget {
list.addAll(listMou.value); list.addAll(listMou.value);
list[idx].isCheck = val ?? false; list[idx].isCheck = val ?? false;
listMou.value = list; listMou.value = list;
ref.read(selectedMouProvider.notifier).state =
list.where((el) => el.isCheck).toList();
}), }),
), ),
const SizedBox(width: 10), const SizedBox(width: 10),

79
lib/widget/provider/mitra_add_provider.dart

@ -0,0 +1,79 @@
import 'package:dio/dio.dart';
import 'package:equatable/equatable.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import '../../provider/dio_provider.dart';
import '../../provider/local_auth_provider.dart';
import '../../repository/base_repository.dart';
import '../../repository/mitra_repository.dart';
final mitraAddProvider = StateNotifierProvider<MitraAddNotifier, MitraAddState>(
(ref) => MitraAddNotifier(ref: ref),
);
class MitraAddNotifier extends StateNotifier<MitraAddState> {
final Ref ref;
CancelToken? cancelToken;
MitraAddNotifier({
required this.ref,
}) : super(MitraAddStateInit());
void reset() {
state = MitraAddStateInit();
}
void add({
required String companyID,
required List<String> mouID,
required String doctorID,
required String doctorAddressID,
required String login,
}) async {
try {
state = MitraAddStateLoading();
final dio = ref.read(dioProvider);
final localAuth = ref.read(localAuthProvider);
if (localAuth?.token == null) {
throw BaseRepositoryException(message: "Invalid Token");
}
await MitraRepository(dio: dio).add(
token: localAuth!.token!,
mouID: mouID,
companyID: companyID,
doctorID: doctorID,
doctorAddressID: doctorAddressID,
login: login,
);
state = MitraAddStateDone();
} catch (e) {
if (e is BaseRepositoryException) {
state = MitraAddStateError(message: e.message);
} else {
state = MitraAddStateError(message: "Unknown Error ");
}
}
}
}
abstract class MitraAddState extends Equatable {
final DateTime date;
MitraAddState() : date = DateTime.now();
@override
List<Object?> get props => throw [date];
}
class MitraAddStateInit extends MitraAddState {}
class MitraAddStateLoading extends MitraAddState {}
class MitraAddStateError extends MitraAddState {
final String message;
MitraAddStateError({
required this.message,
});
}
class MitraAddStateDone extends MitraAddState {
MitraAddStateDone();
}

5
lib/widget/provider/selectedCompanyProvider.dart

@ -1,5 +1,8 @@
import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart';
import '../../model/ac_company_response_model.dart'; import '../../model/ac_company_response_model.dart';
import '../../model/ac_mou_response_model.dart';
final selectdAcCompanyProvider = StateProvider<AcCompanyModel?>((ref) => null); final selectedAcCompanyProvider = StateProvider<AcCompanyModel?>((ref) => null);
final selectedMouProvider =
StateProvider<List<AcMouResponseModel>>((ref) => List.empty());

3
lib/widget/provider/selectedDoctorProvider.dart

@ -3,3 +3,6 @@ import 'package:onemd/model/ac_doctor_model.dart';
final selectedAcDoctorProvider = final selectedAcDoctorProvider =
StateProvider<AcDoctorResponseModel?>((ref) => null); StateProvider<AcDoctorResponseModel?>((ref) => null);
final selectedAcDoctorAddressProvider =
StateProvider<AcDoctorAddressResponseModel?>((ref) => null);

3
php-api/mitra/Md.php

@ -15,6 +15,7 @@ class Md extends MY_Controller
function add() function add()
{ {
$param = $this->sys_input; $param = $this->sys_input;
$sql = "insert into ";
print_r($param); print_r($param);
} }
@ -150,6 +151,8 @@ create table mitra(
MitraM_CompanyID int, MitraM_CompanyID int,
MitraIsActive varchar(1) default 'Y', MitraIsActive varchar(1) default 'Y',
MitraCommitment text, MitraCommitment text,
MitraM_DoctorID int,
MitraM_DoctorAddressID int,
MitraCreated datetime default current_timestamp(), MitraCreated datetime default current_timestamp(),
MitraLastUpdated datetime default current_timestamp() on update current_timestamp(), MitraLastUpdated datetime default current_timestamp() on update current_timestamp(),
MitraM_UserID int, MitraM_UserID int,

Loading…
Cancel
Save