|
|
|
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 'package:onemd/widget/provider/mitra_delete_provider.dart';
|
|
|
|
|
|
|
|
import '../model/ac_mou_response_model.dart';
|
|
|
|
import '../model/mitra_response_model.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;
|
|
|
|
const FxDataMitra({
|
|
|
|
Key? key,
|
|
|
|
this.rowsPerPage = 10,
|
|
|
|
}) : super(key: key);
|
|
|
|
|
|
|
|
@override
|
|
|
|
Widget build(BuildContext context, WidgetRef ref) {
|
|
|
|
final list = useState<List<MitraResponseModel>>(List.empty());
|
|
|
|
final isLoading = useState(false);
|
|
|
|
final errorMessage = useState("");
|
|
|
|
|
|
|
|
ref.listen(mitraSearchProvider, (prev, next) {
|
|
|
|
if (next is MitraSearchStateLoading) {
|
|
|
|
isLoading.value = true;
|
|
|
|
} else if (next is MitraSearchStateError) {
|
|
|
|
isLoading.value = false;
|
|
|
|
errorMessage.value = next.message;
|
|
|
|
Timer(const Duration(seconds: 3), () {
|
|
|
|
errorMessage.value = "";
|
|
|
|
});
|
|
|
|
} else if (next is MitraSearchStateDone) {
|
|
|
|
isLoading.value = false;
|
|
|
|
list.value = next.list;
|
|
|
|
}
|
|
|
|
});
|
|
|
|
final pageWidth = MediaQuery.of(context).size.width - 200;
|
|
|
|
return PaginatedDataTable(
|
|
|
|
arrowHeadColor: Colors.red,
|
|
|
|
columnSpacing: 10,
|
|
|
|
header: Column(
|
|
|
|
children: [
|
|
|
|
const FxNormalBlueText(title: "Daftar Lab Mitra"),
|
|
|
|
if (isLoading.value) const LinearProgressIndicator(),
|
|
|
|
if (errorMessage.value != "") FxErrorText(title: errorMessage.value)
|
|
|
|
],
|
|
|
|
),
|
|
|
|
rowsPerPage: rowsPerPage,
|
|
|
|
actions: [
|
|
|
|
SizedBox(
|
|
|
|
width: 150,
|
|
|
|
child: TextButton(
|
|
|
|
child: Row(
|
|
|
|
mainAxisSize: MainAxisSize.max,
|
|
|
|
children: const [
|
|
|
|
Text("New Lab Mitra"),
|
|
|
|
Icon(Icons.add_rounded, size: 24),
|
|
|
|
],
|
|
|
|
),
|
|
|
|
onPressed: () async {
|
|
|
|
await showDialog(
|
|
|
|
context: context,
|
|
|
|
builder: (context) {
|
|
|
|
return const FxMitraAddDialog();
|
|
|
|
});
|
|
|
|
}),
|
|
|
|
),
|
|
|
|
],
|
|
|
|
columns: [
|
|
|
|
titleColumn("Company"),
|
|
|
|
titleColumn("Login"),
|
|
|
|
titleColumn("ID"),
|
|
|
|
titleColumn("Aggreement"),
|
|
|
|
titleColumn(""),
|
|
|
|
],
|
|
|
|
source: _MitraDataSource(
|
|
|
|
totalRow: list.value.length,
|
|
|
|
list: list.value,
|
|
|
|
pageWidth: pageWidth,
|
|
|
|
onDelete: (model) async {
|
|
|
|
await showDialog(
|
|
|
|
context: context,
|
|
|
|
builder: (context) {
|
|
|
|
return AlertDialog(
|
|
|
|
title: const Text("Delete Mitra"),
|
|
|
|
content: Text(
|
|
|
|
"Confirm delete ${model.mitraUsername} , ${model.mCompanyName} ?"),
|
|
|
|
actions: [
|
|
|
|
TextButton(
|
|
|
|
onPressed: () {
|
|
|
|
ref
|
|
|
|
.read(mitraDeleteProvider.notifier)
|
|
|
|
.delete(mitraID: model.mitraID, query: "");
|
|
|
|
Navigator.of(context).pop();
|
|
|
|
},
|
|
|
|
style: ButtonStyle(
|
|
|
|
backgroundColor: MaterialStateColor.resolveWith(
|
|
|
|
(state) => Colors.red),
|
|
|
|
),
|
|
|
|
child: const Text("Delete",
|
|
|
|
style: TextStyle(color: Colors.white)),
|
|
|
|
),
|
|
|
|
TextButton(
|
|
|
|
style: ButtonStyle(
|
|
|
|
backgroundColor: MaterialStateColor.resolveWith(
|
|
|
|
(state) => Colors.green),
|
|
|
|
),
|
|
|
|
onPressed: () {
|
|
|
|
Navigator.of(context).pop();
|
|
|
|
},
|
|
|
|
child: const Text("Cancel",
|
|
|
|
style: TextStyle(color: Colors.white)),
|
|
|
|
)
|
|
|
|
],
|
|
|
|
);
|
|
|
|
});
|
|
|
|
},
|
|
|
|
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,
|
|
|
|
);
|
|
|
|
},
|
|
|
|
);
|
|
|
|
}),
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
DataColumn titleColumn(String title) {
|
|
|
|
return DataColumn(
|
|
|
|
label: FxNormalBlueText(title: title),
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
class FxNormalBlueText extends StatelessWidget {
|
|
|
|
final String title;
|
|
|
|
final bool isBold;
|
|
|
|
const FxNormalBlueText({
|
|
|
|
Key? key,
|
|
|
|
required this.title,
|
|
|
|
this.isBold = false,
|
|
|
|
}) : super(key: key);
|
|
|
|
|
|
|
|
@override
|
|
|
|
Widget build(BuildContext context) {
|
|
|
|
return Text(
|
|
|
|
title,
|
|
|
|
overflow: TextOverflow.ellipsis,
|
|
|
|
style: TextStyle(
|
|
|
|
fontSize: 16,
|
|
|
|
fontWeight: isBold ? FontWeight.w700 : FontWeight.normal,
|
|
|
|
color: Colors.blue.shade500,
|
|
|
|
),
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
class _MitraDataSource extends DataTableSource {
|
|
|
|
final List<MitraResponseModel> list;
|
|
|
|
final int totalRow;
|
|
|
|
final double pageWidth;
|
|
|
|
final void Function(MitraResponseModel)? onEdit;
|
|
|
|
final void Function(MitraResponseModel)? onDelete;
|
|
|
|
_MitraDataSource({
|
|
|
|
required this.list,
|
|
|
|
required this.totalRow,
|
|
|
|
required this.pageWidth,
|
|
|
|
this.onEdit,
|
|
|
|
this.onDelete,
|
|
|
|
});
|
|
|
|
@override
|
|
|
|
DataRow? getRow(int index) {
|
|
|
|
final model = list[index];
|
|
|
|
final List<double> width = [
|
|
|
|
pageWidth * 1.5 / 7,
|
|
|
|
pageWidth * 0.8 / 7,
|
|
|
|
pageWidth * 0.8 / 7,
|
|
|
|
pageWidth * 3.9 / 7
|
|
|
|
];
|
|
|
|
final agreement = model.aggrement.replaceAll('^', ', ');
|
|
|
|
return DataRow(
|
|
|
|
color: (index % 2 == 0)
|
|
|
|
? MaterialStateColor.resolveWith(
|
|
|
|
(state) => Colors.blue.shade50.withOpacity(0.2))
|
|
|
|
: null,
|
|
|
|
cells: [
|
|
|
|
dataCell(model.mCompanyName, width[0]),
|
|
|
|
dataCell(model.mitraUsername, width[1]),
|
|
|
|
dataCell(model.mitraIDNo, width[2]),
|
|
|
|
dataCell(agreement, width[3]),
|
|
|
|
DataCell(
|
|
|
|
SizedBox(
|
|
|
|
width: 60,
|
|
|
|
child: Row(
|
|
|
|
mainAxisSize: MainAxisSize.max,
|
|
|
|
mainAxisAlignment: MainAxisAlignment.spaceAround,
|
|
|
|
children: [
|
|
|
|
InkWell(
|
|
|
|
onTap: () {
|
|
|
|
if (onEdit != null) onEdit!(model);
|
|
|
|
},
|
|
|
|
child: Icon(
|
|
|
|
Icons.edit_rounded,
|
|
|
|
size: 24,
|
|
|
|
color: Colors.green.shade700,
|
|
|
|
),
|
|
|
|
),
|
|
|
|
InkWell(
|
|
|
|
onTap: () async {
|
|
|
|
if (onDelete != null) {
|
|
|
|
onDelete!(model);
|
|
|
|
}
|
|
|
|
},
|
|
|
|
child: Icon(
|
|
|
|
Icons.delete_rounded,
|
|
|
|
size: 24,
|
|
|
|
color: Colors.red.shade700,
|
|
|
|
),
|
|
|
|
),
|
|
|
|
],
|
|
|
|
),
|
|
|
|
),
|
|
|
|
),
|
|
|
|
],
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
DataCell dataCell(
|
|
|
|
String value,
|
|
|
|
double width,
|
|
|
|
) {
|
|
|
|
return DataCell(
|
|
|
|
SizedBox(
|
|
|
|
width: width,
|
|
|
|
child: Padding(
|
|
|
|
padding: const EdgeInsets.all(5.0),
|
|
|
|
child: Text(
|
|
|
|
value,
|
|
|
|
style: TextStyle(
|
|
|
|
fontSize: 16,
|
|
|
|
color: Colors.blue.shade500,
|
|
|
|
),
|
|
|
|
),
|
|
|
|
),
|
|
|
|
),
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
@override
|
|
|
|
bool get isRowCountApproximate => false;
|
|
|
|
|
|
|
|
@override
|
|
|
|
int get rowCount => list.length;
|
|
|
|
|
|
|
|
@override
|
|
|
|
int get selectedRowCount => 0;
|
|
|
|
}
|