Browse Source

Edit Mitra

main
padmanto 2 years ago
parent
commit
d3f5a757ab
  1. 42
      lib/model/mitra_response_model.dart
  2. 30
      lib/repository/mitra_repository.dart
  3. 9
      lib/widget/fx_company_lookup.dart
  4. 76
      lib/widget/fx_data_mitra.dart
  5. 16
      lib/widget/fx_doctor_address.dart
  6. 202
      lib/widget/fx_mitra_edit_dialog.dart
  7. 11
      lib/widget/fx_mitra_mou.dart
  8. 87
      lib/widget/provider/mitra_edit_provider.dart
  9. 96
      php-api/mitra/Md.php

42
lib/model/mitra_response_model.dart

@ -12,9 +12,13 @@ class MitraResponseModel {
late String mitraLastUpdated;
late String mitraMCompanyID;
late String mitraMUserID;
late String mitraMDoctorID;
late String mitraMDoctorAddressID;
late String mitraPassword;
late String mitraUsername;
late String aggrement;
late String mDoctorName;
late List<String> aggrementID;
MitraResponseModel({
required this.mCompanyAddress,
@ -33,6 +37,10 @@ class MitraResponseModel {
required this.mitraPassword,
required this.mitraUsername,
required this.aggrement,
this.mitraMDoctorID = "0",
this.mitraMDoctorAddressID = "0",
this.mDoctorName = "",
this.aggrementID = const [],
});
MitraResponseModel.fromJson(Map<String, dynamic> json) {
@ -43,6 +51,8 @@ class MitraResponseModel {
mitraHoldDate = json['MitraHoldDate'];
mitraHoldMUserID = json['MitraHoldM_UserID']?.toString() ?? "";
mitraID = json['MitraID'].toString();
mitraMDoctorID = json['MitraM_DoctorID'].toString();
mitraMDoctorAddressID = json['MitraM_DoctorAddressID'].toString();
mitraIDNo = json['MitraIDNo'];
mitraIsActive = json['MitraIsActive'];
mitraIsHold = json['MitraIsHold'];
@ -55,22 +65,22 @@ class MitraResponseModel {
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['M_CompanyAddress'] = this.mCompanyAddress;
data['M_CompanyName'] = this.mCompanyName;
data['MitraCommitment'] = this.mitraCommitment;
data['MitraCreated'] = this.mitraCreated;
data['MitraHoldDate'] = this.mitraHoldDate;
data['MitraHoldM_UserID'] = this.mitraHoldMUserID;
data['MitraID'] = this.mitraID;
data['MitraIDNo'] = this.mitraIDNo;
data['MitraIsActive'] = this.mitraIsActive;
data['MitraIsHold'] = this.mitraIsHold;
data['MitraLastUpdated'] = this.mitraLastUpdated;
data['MitraM_CompanyID'] = this.mitraMCompanyID;
data['MitraM_UserID'] = this.mitraMUserID;
data['MitraPassword'] = this.mitraPassword;
data['MitraUsername'] = this.mitraUsername;
final Map<String, dynamic> data = <String, dynamic>{};
data['M_CompanyAddress'] = mCompanyAddress;
data['M_CompanyName'] = mCompanyName;
data['MitraCommitment'] = mitraCommitment;
data['MitraCreated'] = mitraCreated;
data['MitraHoldDate'] = mitraHoldDate;
data['MitraHoldM_UserID'] = mitraHoldMUserID;
data['MitraID'] = mitraID;
data['MitraIDNo'] = mitraIDNo;
data['MitraIsActive'] = mitraIsActive;
data['MitraIsHold'] = mitraIsHold;
data['MitraLastUpdated'] = mitraLastUpdated;
data['MitraM_CompanyID'] = mitraMCompanyID;
data['MitraM_UserID'] = mitraMUserID;
data['MitraPassword'] = mitraPassword;
data['MitraUsername'] = mitraUsername;
return data;
}
}

30
lib/repository/mitra_repository.dart

@ -35,6 +35,33 @@ class MitraRepository extends BaseRepository {
return true;
}
Future<bool> edit({
required String mitraID,
required String token,
required String companyID,
required List<String> mouID,
required String doctorID,
required String doctorAddressID,
required String login,
required String password,
CancelToken? cancelToken,
}) async {
final param = {
"token": token,
"mitraID": mitraID,
"companyID": companyID,
"mouID": mouID,
"doctorID": doctorID,
"doctorAddressID": doctorAddressID,
"login": login,
"password": password
};
final service = "${Constants.baseUrl}md/edit";
await post(service: service, jsonParam: param, cancelToken: cancelToken);
return true;
}
Future<List<MitraResponseModel>> search({
required String query,
CancelToken? cancelToken,
@ -46,6 +73,9 @@ class MitraRepository extends BaseRepository {
final List<MitraResponseModel> result = List.empty(growable: true);
for (final el in resp["data"]) {
final model = MitraResponseModel.fromJson(el);
List<String> aggrementID = (el["aggrementID"].toString()).split(",");
model.aggrementID = aggrementID;
model.mDoctorName = el["M_DoctorName"];
result.add(model);
}
return result;

9
lib/widget/fx_company_lookup.dart

@ -14,10 +14,9 @@ import 'provider/selectedCompanyProvider.dart';
// ignore: must_be_immutable
class FxAcCompany extends HookConsumerWidget {
final String? errorValidation;
FxAcCompany({
Key? key,
this.errorValidation,
}) : super(key: key);
final bool readOnly;
FxAcCompany({Key? key, this.errorValidation, this.readOnly = false})
: super(key: key);
CancelToken? cancelToken;
@override
@ -45,6 +44,8 @@ class FxAcCompany extends HookConsumerWidget {
focusNode: fc,
fieldViewBuilder: (context, ctrl, fc, onChange) {
return FxTextField(
isReadOnly: readOnly,
isEnabled: !readOnly,
ctrl: ctrl,
fc: fc,
hint: "Company",

76
lib/widget/fx_data_mitra.dart

@ -3,11 +3,21 @@ 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/model/ac_company_response_model.dart';
import 'package:onemd/model/ac_doctor_model.dart';
import '../model/ac_mou_response_model.dart';
import '../model/mitra_response_model.dart';
import '../provider/dio_provider.dart';
import '../repository/mitra_repository.dart';
import '../screen/md_lab_mitra/mitra_lookup_mou_provider.dart';
import '../screen/md_lab_mitra/mitra_search_provider.dart';
import 'fx_error_text.dart';
import 'fx_mitra_add_dialog.dart';
import 'fx_mitra_edit_dialog.dart';
import 'provider/doctor_address_lookup_provider.dart';
import 'provider/selectedCompanyProvider.dart';
import 'provider/selectedDoctorProvider.dart';
class FxDataMitra extends HookConsumerWidget {
final int rowsPerPage;
@ -76,10 +86,61 @@ class FxDataMitra extends HookConsumerWidget {
titleColumn(""),
],
source: _MitraDataSource(
totalRow: list.value.length,
list: list.value,
pageWidth: pageWidth,
),
totalRow: list.value.length,
list: list.value,
pageWidth: pageWidth,
onEdit: (model) async {
ref.read(selectedMouProvider.notifier).state = model.aggrementID
.map((id) => AcMouResponseModel(
mMouID: id,
mMouName: "",
mMouNote: "",
mMouIsMcu: "",
mMouNumber: "",
mMouEndDate: "",
mMouIsActive: "Y",
mMouStartDate: "",
))
.toList();
ref.read(selectedAcCompanyProvider.notifier).state = AcCompanyModel(
mCompanyID: model.mitraMCompanyID,
mCompanyAddress: model.mCompanyAddress,
mCompanyAddressLocation: "",
mCompanyEmail: "",
mCompanyHp: "",
mCompanyName: model.mCompanyName,
mCompanyNumber: "",
mCompanyPhone: "",
);
ref
.read(mitraLookupMouProvider.notifier)
.lookup(companyID: model.mitraMCompanyID);
ref.read(selectedAcDoctorProvider.notifier).state =
AcDoctorResponseModel(
fullName: model.mDoctorName,
mDoctorID: model.mitraMDoctorID,
);
ref
.read(doctorAddressLookupProvider.notifier)
.lookup(doctorID: model.mitraMDoctorID);
ref.read(selectedAcDoctorAddressProvider.notifier).state =
AcDoctorAddressResponseModel(
mDoctorAddressID: model.mitraMDoctorAddressID,
mDoctorAddressDescription: "",
);
await showDialog(
context: context,
builder: (context) {
return FxMitraEditDialog(
login: model.mitraUsername,
idNo: model.mitraIDNo,
mitraID: model.mitraID,
);
},
);
}),
);
}
@ -117,11 +178,12 @@ class _MitraDataSource extends DataTableSource {
final List<MitraResponseModel> list;
final int totalRow;
final double pageWidth;
final void Function(MitraResponseModel)? onEdit;
_MitraDataSource({
required this.list,
required this.totalRow,
required this.pageWidth,
this.onEdit,
});
@override
DataRow? getRow(int index) {
@ -151,7 +213,9 @@ class _MitraDataSource extends DataTableSource {
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
InkWell(
onTap: () {},
onTap: () {
if (onEdit != null) onEdit!(model);
},
child: Icon(
Icons.edit_rounded,
size: 24,

16
lib/widget/fx_doctor_address.dart

@ -11,11 +11,12 @@ import 'provider/selectedDoctorProvider.dart';
class FxDoctorAddress extends HookConsumerWidget {
final double? width;
final String? errorValidation;
const FxDoctorAddress({
bool isInit;
FxDoctorAddress({
Key? key,
this.width,
this.errorValidation,
this.isInit = true,
}) : super(key: key);
@override
@ -25,15 +26,22 @@ class FxDoctorAddress extends HookConsumerWidget {
final doctorModel = ref.watch(selectedAcDoctorProvider);
String doctorName = doctorModel?.fullName ?? "";
final initState = useState(isInit);
ref.listen(doctorAddressLookupProvider, (prev, next) {
if (next is DoctorAddressLookupStateDone) {
for (int idx = 0; idx < next.list.length; idx++) {
next.list[idx].isCheck = false;
if (ref.read(selectedAcDoctorAddressProvider)?.mDoctorAddressID !=
null &&
ref.read(selectedAcDoctorAddressProvider)!.mDoctorAddressID ==
next.list[idx].mDoctorAddressID) {
ref.read(selectedAcDoctorAddressProvider.notifier).state =
next.list[idx];
}
}
listAddress.value = next.list;
}
});
return Container(
width: double.infinity,
decoration: BoxDecoration(

202
lib/widget/fx_mitra_edit_dialog.dart

@ -0,0 +1,202 @@
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';
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/mitra_edit_provider.dart';
import 'provider/selectedCompanyProvider.dart';
import 'provider/selectedDoctorProvider.dart';
class FxMitraEditDialog extends HookConsumerWidget {
final String login;
final String idNo;
final String mitraID;
const FxMitraEditDialog({
Key? key,
required this.login,
required this.idNo,
required this.mitraID,
}) : super(key: key);
@override
Widget build(BuildContext context, WidgetRef ref) {
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 fcPassword = FocusNode();
final fcRePassword = FocusNode();
final errorPassword = useState<String?>(null);
final errorRePassword = useState<String?>(null);
final ctrlLogin = useTextEditingController(text: login);
final ctrlPassword = useTextEditingController(text: "");
final ctrlRePassword = useTextEditingController(text: "");
bool Function() validationError;
validationError = () {
bool haveError = false;
if (ctrlRePassword.text != ctrlPassword.text) {
errorRePassword.value = "Password confirmation error";
haveError = true;
}
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(),
borderRadius: BorderRadius.circular(10),
),
child: SizedBox(
width: 800,
height: 600,
child: SingleChildScrollView(
child: Padding(
padding: const EdgeInsets.all(20.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
FxAcCompany(
readOnly: true,
errorValidation: errorCompany.value,
),
const SizedBox(height: 10),
FxMitraMou(
errorValidation: errorMou.value,
),
const SizedBox(height: 10),
FxAcDoctor(
errorValidation: errorDoctor.value,
),
const SizedBox(height: 10),
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(
ctrl: ctrlPassword,
fc: fcPassword,
hint: "Password",
label: "Password",
obscureText: true,
errorMessage: errorPassword.value,
),
const SizedBox(height: 10),
FxTextField(
ctrl: ctrlRePassword,
fc: fcRePassword,
hint: "Retype Password",
label: "Retype Password",
obscureText: true,
errorMessage: errorRePassword.value,
),
const SizedBox(height: 10),
FxTextField(
ctrl: useTextEditingController(text: idNo),
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(mitraEditProvider.notifier).edit(
mitraID: mitraID,
companyID: company!.mCompanyID,
mouID: mou.map((e) => e.mMouID).toList(),
doctorID: doctor!.mDoctorID,
doctorAddressID:
doctorAddress!.mDoctorAddressID,
login: ctrlLogin.text,
password: ctrlPassword.text,
query: "",
);
Navigator.of(context).pop();
}
},
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"),
),
],
),
],
),
),
)),
);
}
}

11
lib/widget/fx_mitra_mou.dart

@ -26,7 +26,16 @@ class FxMitraMou extends HookConsumerWidget {
ref.listen(mitraLookupMouProvider, (prev, next) {
if (next is MitraLookupMouStateDone) {
for (int idx = 0; idx < next.list.length; idx++) {
next.list[idx].isCheck = false;
final mouID = next.list[idx].mMouID;
if (ref
.read(selectedMouProvider)
.indexWhere((m) => m.mMouID == mouID) ==
-1) {
next.list[idx].isCheck = false;
} else {
next.list[idx].isCheck = true;
}
}
listMou.value = next.list;
}

87
lib/widget/provider/mitra_edit_provider.dart

@ -0,0 +1,87 @@
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';
import '../../screen/md_lab_mitra/mitra_search_provider.dart';
final mitraEditProvider =
StateNotifierProvider<MitraEditNotifier, MitraEditState>(
(ref) => MitraEditNotifier(ref: ref),
);
class MitraEditNotifier extends StateNotifier<MitraEditState> {
final Ref ref;
CancelToken? cancelToken;
MitraEditNotifier({
required this.ref,
}) : super(MitraEditStateInit());
void reset() {
state = MitraEditStateInit();
}
void edit({
required String mitraID,
required String companyID,
required List<String> mouID,
required String doctorID,
required String doctorAddressID,
required String login,
required String password,
required String query,
}) async {
try {
state = MitraEditStateLoading();
final dio = ref.read(dioProvider);
final localAuth = ref.read(localAuthProvider);
if (localAuth?.token == null) {
throw BaseRepositoryException(message: "Invalid Token");
}
await MitraRepository(dio: dio).edit(
mitraID: mitraID,
token: localAuth!.token!,
mouID: mouID,
companyID: companyID,
doctorID: doctorID,
doctorAddressID: doctorAddressID,
login: login,
password: password,
);
state = MitraEditStateDone();
ref.read(mitraSearchProvider.notifier).search(query: query);
} catch (e) {
if (e is BaseRepositoryException) {
state = MitraEditStateError(message: e.message);
} else {
state = MitraEditStateError(message: "Unknown Error ");
}
}
}
}
abstract class MitraEditState extends Equatable {
final DateTime date;
MitraEditState() : date = DateTime.now();
@override
List<Object?> get props => throw [date];
}
class MitraEditStateInit extends MitraEditState {}
class MitraEditStateLoading extends MitraEditState {}
class MitraEditStateError extends MitraEditState {
final String message;
MitraEditStateError({
required this.message,
});
}
class MitraEditStateDone extends MitraEditState {
MitraEditStateDone();
}

96
php-api/mitra/Md.php

@ -12,6 +12,97 @@ class Md extends MY_Controller
{
echo "Mitra:MD:API";
}
function edit()
{
$param = $this->sys_input;
$user = $this->sys_user;
$userID = $user["M_UserID"];
$this->db->trans_begin();
if ($param["password"] == "") {
$sql = "update mitra
set MitraM_CompanyID=?, MitraM_DoctorID=?,
MitraM_DoctorAddressID=?,MitraUsername=?,
MitraM_UserID=?
where MitraID = ?";
$qry = $this->db->query($sql, [
$param["companyID"], $param["doctorID"],
$param["doctorAddressID"], $param["login"],
$userID, $param["mitraID"]
]);
} else {
$sql = "update mitra
set MitraM_CompanyID=?, MitraM_DoctorID=?,
MitraM_DoctorAddressID=?,MitraUsername=?,
MitraM_UserID=?, MitraPassword = md5(?)
where MitraID = ?";
$qry = $this->db->query($sql, [
$param["companyID"], $param["doctorID"],
$param["doctorAddressID"], $param["login"],
$userID, $param["password"], $param["mitraID"]
]);
}
if (!$qry) {
echo json_encode([
"status" => "ERR",
"message" => $this->db->error()["message"],
]);
exit();
}
$mitraID = $param["mitraID"];
$s_mouID = implode(",", $param["mouID"]);
if ($s_mouID == "") {
$s_mouID = "0";
}
$sql = "update mitra_mou set MitraMouIsActive ='N' where
MitraMouMitraID = ? and MitraMouM_MouID not in ($s_mouID)";
$qry = $this->db->query($sql, [$param["mitraID"]]);
if (!$qry) {
echo json_encode([
"status" => "ERR",
"message" => $this->db->error()["message"],
]);
$this->db->trans_rollback();
exit();
}
$sql = "select * from mitra_mou where MitraMouMitraID =? and MitraMouIsActive ='Y'";
$qry = $this->db->query($sql, [$param["mitraID"]]);
if (!$qry) {
echo json_encode([
"status" => "ERR",
"message" => $this->db->error()["message"],
]);
$this->db->trans_rollback();
exit();
}
$rows_mouid = [];
foreach ($qry->result_array() as $r) {
$rows_mouid[] = $r["MitraMouM_MouID"];
}
$sql = "insert into mitra_mou(MitraMouMitraID,MitraMouM_MouID,
MitraMouM_UserID)
values(?,?,?)";
foreach ($param["mouID"] as $mouID) {
if (in_array($mouID, $rows_mouid)) {
continue;
}
$qry = $this->db->query($sql, [$mitraID, $mouID, $userID]);
if (!$qry) {
echo json_encode([
"status" => "ERR",
"message" => $this->db->error()["message"],
]);
$this->db->trans_rollback();
exit();
}
}
$this->db->trans_commit();
echo json_encode(["status" => "OK"]);
}
function add()
{
$param = $this->sys_input;
@ -82,7 +173,9 @@ class Md extends MY_Controller
$this->corss();
$sql = "select mitra.*,
M_CompanyName, M_CompanyAddress,
group_concat(concat(M_MouName,' [', date_format(M_MouEndDate,'%d/%m/%Y'),'] ') separator '^') aggrement
group_concat(concat(M_MouName,' [', date_format(M_MouEndDate,'%d/%m/%Y'),'] ') separator '^') aggrement,
group_concat(M_MouID separator ',') aggrementID,
M_DoctorName
from mitra
join m_company
on MitraM_CompanyID = M_CompanyID
@ -90,6 +183,7 @@ class Md extends MY_Controller
and (
MitraUsername like ?
or M_CompanyName like ?)
join m_doctor on MitraM_DoctorID = M_DoctorID
join mitra_mou
on MitraID = MitraMouMitraID
and MitraMouIsActive ='Y'

Loading…
Cancel
Save