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 {
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({
required String query,
CancelToken? cancelToken,

13
lib/widget/fx_company_lookup.dart

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

2
lib/widget/fx_data_mitra.dart

@ -63,7 +63,7 @@ class FxDataMitra extends HookConsumerWidget {
await showDialog(
context: 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 'fx_data_mitra.dart';
import 'fx_error_text.dart';
import 'provider/doctor_address_lookup_provider.dart';
import 'provider/doctor_lookup_provider.dart';
import 'provider/selectedDoctorProvider.dart';
class FxDoctorAddress extends HookConsumerWidget {
final double? width;
final String? errorValidation;
const FxDoctorAddress({
Key? key,
this.width,
this.errorValidation,
}) : super(key: key);
@override
@ -35,7 +38,11 @@ class FxDoctorAddress extends HookConsumerWidget {
width: double.infinity,
decoration: BoxDecoration(
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),
),
child: ConstrainedBox(
@ -46,10 +53,13 @@ class FxDoctorAddress extends HookConsumerWidget {
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
FxNormalBlueText(
title: "Alamat dari $doctorName",
isBold: true,
),
errorValidation == null
? FxNormalBlueText(
title: "Address of $doctorName",
isBold: true,
)
: FxErrorText(
title: "Address of $doctorName *) $errorValidation"),
const SizedBox(height: 10),
if (listAddress.value.isNotEmpty)
ConstrainedBox(
@ -61,21 +71,25 @@ class FxDoctorAddress extends HookConsumerWidget {
itemBuilder: (context, idx) {
final model = listAddress.value[idx];
return Row(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Checkbox(
value: model.isCheck,
Radio<AcDoctorAddressResponseModel>(
groupValue:
ref.watch(selectedAcDoctorAddressProvider),
value: model,
onChanged: ((val) {
final List<AcDoctorAddressResponseModel> list =
List.empty(growable: true);
list.addAll(listAddress.value);
list[idx].isCheck = val ?? false;
listAddress.value = list;
ref
.read(selectedAcDoctorAddressProvider
.notifier)
.state = val;
}),
),
const SizedBox(width: 10),
Expanded(
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
class FxAcDoctor extends HookConsumerWidget {
FxAcDoctor({Key? key}) : super(key: key);
final String? errorValidation;
FxAcDoctor({Key? key, this.errorValidation}) : super(key: key);
CancelToken? cancelToken;
@override
@ -29,7 +30,6 @@ class FxAcDoctor extends HookConsumerWidget {
}
ref.listen<AcDoctorResponseModel?>(selectedAcDoctorProvider, ((prev, next) {
if (next != null) {
print("Calling for " + next.fullName);
ref
.read(doctorAddressLookupProvider.notifier)
.lookup(doctorID: next.mDoctorID);
@ -46,6 +46,7 @@ class FxAcDoctor extends HookConsumerWidget {
hint: "Doctor",
fc: fc,
ctrl: ctrl,
errorMessage: errorValidation,
);
},
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_hooks/flutter_hooks.dart';
import 'package:hooks_riverpod/hooks_riverpod.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_mitra_mou.dart';
import 'fx_text_field.dart';
import 'provider/mitra_add_provider.dart';
import 'provider/selectedCompanyProvider.dart';
import 'provider/selectedDoctorProvider.dart';
class FxMitraAddDialog extends HookConsumerWidget {
const FxMitraAddDialog({Key? key}) : super(key: key);
@override
Widget build(BuildContext context, WidgetRef ref) {
final ctrlLogin = useTextEditingController(text: "");
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(
shape: RoundedRectangleBorder(
side: const BorderSide(),
@ -29,28 +78,75 @@ class FxMitraAddDialog extends HookConsumerWidget {
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
FxAcCompany(),
FxAcCompany(
errorValidation: errorCompany.value,
),
const SizedBox(height: 10),
const FxMitraMou(),
FxMitraMou(
errorValidation: errorMou.value,
),
const SizedBox(height: 10),
FxAcDoctor(),
FxAcDoctor(
errorValidation: errorDoctor.value,
),
const SizedBox(height: 10),
FxDoctorAddress(),
FxDoctorAddress(
errorValidation: errorDoctorAddress.value,
),
const SizedBox(height: 10),
FxTextField(
ctrl: ctrlLogin,
fc: fcLogin,
hint: "Login",
label: "Login",
errorMessage: errorLogin.value,
),
const SizedBox(height: 10),
FxTextField(
const FxTextField(
hint: "ID",
label: "ID",
isReadOnly: true,
isEnabled: false,
suffixText: "Auto Generated"),
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 '../screen/md_lab_mitra/mitra_lookup_mou_provider.dart';
import 'fx_data_mitra.dart';
import 'fx_error_text.dart';
import 'provider/selectedCompanyProvider.dart';
class FxMitraMou extends HookConsumerWidget {
final double? width;
final String? errorValidation;
const FxMitraMou({
Key? key,
this.width,
this.errorValidation,
}) : super(key: key);
@override
Widget build(BuildContext context, WidgetRef ref) {
final listMou = useState<List<AcMouResponseModel>>(List.empty());
final companyModel = ref.watch(selectdAcCompanyProvider);
final companyModel = ref.watch(selectedAcCompanyProvider);
String companyName = companyModel?.mCompanyName ?? "";
ref.listen(mitraLookupMouProvider, (prev, next) {
if (next is MitraLookupMouStateDone) {
@ -28,12 +31,15 @@ class FxMitraMou extends HookConsumerWidget {
listMou.value = next.list;
}
});
return Container(
width: double.infinity,
decoration: BoxDecoration(
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),
),
child: ConstrainedBox(
@ -44,10 +50,13 @@ class FxMitraMou extends HookConsumerWidget {
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
FxNormalBlueText(
title: "Agreement $companyName",
isBold: true,
),
errorValidation == null
? FxNormalBlueText(
title: "Agreement $companyName",
isBold: true,
)
: FxErrorText(
title: "Agreement $companyName *) $errorValidation"),
const SizedBox(height: 10),
if (listMou.value.isNotEmpty)
ConstrainedBox(
@ -68,6 +77,8 @@ class FxMitraMou extends HookConsumerWidget {
list.addAll(listMou.value);
list[idx].isCheck = val ?? false;
listMou.value = list;
ref.read(selectedMouProvider.notifier).state =
list.where((el) => el.isCheck).toList();
}),
),
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 '../../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 =
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()
{
$param = $this->sys_input;
$sql = "insert into ";
print_r($param);
}
@ -150,6 +151,8 @@ create table mitra(
MitraM_CompanyID int,
MitraIsActive varchar(1) default 'Y',
MitraCommitment text,
MitraM_DoctorID int,
MitraM_DoctorAddressID int,
MitraCreated datetime default current_timestamp(),
MitraLastUpdated datetime default current_timestamp() on update current_timestamp(),
MitraM_UserID int,

Loading…
Cancel
Save