|
|
|
import 'dart:async';
|
|
|
|
|
|
|
|
import 'package:flutter/material.dart';
|
|
|
|
import 'package:flutter_hooks/flutter_hooks.dart';
|
|
|
|
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
|
|
|
|
|
|
|
import '../model/mitra_response_model.dart';
|
|
|
|
import '../screen/md_lab_mitra/mitra_search_provider.dart';
|
|
|
|
import 'fx_error_text.dart';
|
|
|
|
import 'fx_mitra_add_dialog.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,
|
|
|
|
),
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
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;
|
|
|
|
|
|
|
|
_MitraDataSource({
|
|
|
|
required this.list,
|
|
|
|
required this.totalRow,
|
|
|
|
required this.pageWidth,
|
|
|
|
});
|
|
|
|
@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: () {},
|
|
|
|
child: Icon(
|
|
|
|
Icons.edit_rounded,
|
|
|
|
size: 24,
|
|
|
|
color: Colors.green.shade700,
|
|
|
|
),
|
|
|
|
),
|
|
|
|
InkWell(
|
|
|
|
onTap: () {},
|
|
|
|
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;
|
|
|
|
}
|