|
|
|
@ -4,7 +4,6 @@ part of 'vehicles_on_the_property.dart';
|
|
|
|
|
|
|
|
|
|
// ignore: must_be_immutable
|
|
|
|
|
class VehicleHistoryScreen extends StatefulWidget {
|
|
|
|
|
|
|
|
|
|
VehicleHistoryScreen(this.model, {super.key});
|
|
|
|
|
late VehicleModel model;
|
|
|
|
|
final scaffoldKey = GlobalKey<ScaffoldState>();
|
|
|
|
@ -12,23 +11,21 @@ class VehicleHistoryScreen extends StatefulWidget {
|
|
|
|
|
|
|
|
|
|
@override
|
|
|
|
|
State<VehicleHistoryScreen> createState() => _VehicleHistoryScreenState();
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
class _VehicleHistoryScreenState extends State<VehicleHistoryScreen>
|
|
|
|
|
with Remotable {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@override
|
|
|
|
|
void dispose() {
|
|
|
|
|
super.dispose();
|
|
|
|
|
_scrollController.dispose();
|
|
|
|
|
_pagingController.dispose();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@override
|
|
|
|
|
void initState() {
|
|
|
|
|
super.initState();
|
|
|
|
|
_initializeScrollController();
|
|
|
|
|
_pagingController.addPageRequestListener(_fetch);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@override
|
|
|
|
@ -38,22 +35,19 @@ class _VehicleHistoryScreenState extends State<VehicleHistoryScreen>
|
|
|
|
|
late final double limitedBodyTextSize =
|
|
|
|
|
LimitedFontSizeUtil.getBodyFontSize(context);
|
|
|
|
|
|
|
|
|
|
return Scaffold(
|
|
|
|
|
key: widget.scaffoldKey,
|
|
|
|
|
body: Column(
|
|
|
|
|
mainAxisSize: MainAxisSize.max,
|
|
|
|
|
mainAxisAlignment: MainAxisAlignment.start,
|
|
|
|
|
children: [
|
|
|
|
|
if (_hasData == false &&
|
|
|
|
|
_pageNumber <= 1 &&
|
|
|
|
|
_loading == false)
|
|
|
|
|
_buildNoDataFound(context, limitedHeaderTextSize)
|
|
|
|
|
else if (_hasData == true || _pageNumber >= 1)
|
|
|
|
|
_buildHistoryList(context, limitedBodyTextSize),
|
|
|
|
|
if (_hasData == true && _loading == true)
|
|
|
|
|
_buildLoadingIndicator(context),
|
|
|
|
|
].addToStart(const SizedBox(height: 0)),
|
|
|
|
|
),
|
|
|
|
|
return Column(
|
|
|
|
|
mainAxisSize: MainAxisSize.max,
|
|
|
|
|
mainAxisAlignment: MainAxisAlignment.start,
|
|
|
|
|
children: [
|
|
|
|
|
// if (_hasData == false &&
|
|
|
|
|
// _pageNumber <= 1 &&
|
|
|
|
|
// _loading == false)
|
|
|
|
|
// _buildNoDataFound(context, limitedHeaderTextSize)
|
|
|
|
|
// else if (_hasData == true || _pageNumber >= 1)
|
|
|
|
|
_buildHistoryList(context, limitedBodyTextSize),
|
|
|
|
|
// if (_hasData == true && _loading == true)
|
|
|
|
|
// _buildLoadingIndicator(context),
|
|
|
|
|
].addToStart(const SizedBox(height: 0)),
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -82,30 +76,34 @@ class _VehicleHistoryScreenState extends State<VehicleHistoryScreen>
|
|
|
|
|
|
|
|
|
|
Widget _buildHistoryList(BuildContext context, double limitedBodyTextSize) {
|
|
|
|
|
return Expanded(
|
|
|
|
|
child: FutureBuilder<void>(
|
|
|
|
|
future: _fetch(),
|
|
|
|
|
builder: (context, snapshot) {
|
|
|
|
|
if (snapshot.connectionState == ConnectionState.waiting) {
|
|
|
|
|
return Center(child: CircularProgressIndicator());
|
|
|
|
|
} else if (snapshot.hasError) {
|
|
|
|
|
return Center(child: Text('Error: ${snapshot.error}'));
|
|
|
|
|
} else {
|
|
|
|
|
return ListView.builder(
|
|
|
|
|
shrinkWrap: true,
|
|
|
|
|
addAutomaticKeepAlives: true,
|
|
|
|
|
restorationId: '',
|
|
|
|
|
physics: const BouncingScrollPhysics(),
|
|
|
|
|
controller: _scrollController,
|
|
|
|
|
itemCount: _wrap.length,
|
|
|
|
|
itemBuilder: (context, index) => _generateItems(context, _wrap[index], index),
|
|
|
|
|
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
child: RefreshIndicator(
|
|
|
|
|
onRefresh: () async => _pagingController.refresh(),
|
|
|
|
|
child: PagedListView<int, dynamic>(
|
|
|
|
|
// separatorBuilder: (context, index) => const Divider(),
|
|
|
|
|
pagingController: _pagingController,
|
|
|
|
|
builderDelegate: PagedChildBuilderDelegate(
|
|
|
|
|
animateTransitions: true,
|
|
|
|
|
itemBuilder: (context, item, index) =>
|
|
|
|
|
_generateItems(context, index, item),
|
|
|
|
|
firstPageErrorIndicatorBuilder: (context) => Placeholder(),
|
|
|
|
|
newPageErrorIndicatorBuilder: (context) => Placeholder(),
|
|
|
|
|
),
|
|
|
|
|
),
|
|
|
|
|
),
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// ListView.builder(
|
|
|
|
|
// shrinkWrap: true,
|
|
|
|
|
// addAutomaticKeepAlives: true,
|
|
|
|
|
// restorationId: '',
|
|
|
|
|
// physics: const BouncingScrollPhysics(),
|
|
|
|
|
// controller: _scrollController,
|
|
|
|
|
// itemCount: _wrap.length,
|
|
|
|
|
// itemBuilder: (context, index) => _generateItems(context, _wrap[index], index),
|
|
|
|
|
|
|
|
|
|
// ),
|
|
|
|
|
|
|
|
|
|
Widget _buildLoadingIndicator(BuildContext context) {
|
|
|
|
|
return Container(
|
|
|
|
|
padding: const EdgeInsets.only(top: 15, bottom: 15),
|
|
|
|
@ -118,15 +116,13 @@ class _VehicleHistoryScreenState extends State<VehicleHistoryScreen>
|
|
|
|
|
),
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
mixin Remotable on State<VehicleHistoryScreen> {
|
|
|
|
|
final PagingController<int, dynamic> _pagingController =
|
|
|
|
|
PagingController<int, dynamic>(firstPageKey: 1);
|
|
|
|
|
|
|
|
|
|
late ScrollController _scrollController;
|
|
|
|
|
// late ScrollController _scrollController;
|
|
|
|
|
double offset = 0.0;
|
|
|
|
|
List<dynamic> _wrap = [];
|
|
|
|
|
int _pageNumber = 1;
|
|
|
|
@ -134,37 +130,46 @@ mixin Remotable on State<VehicleHistoryScreen> {
|
|
|
|
|
bool _loading = true;
|
|
|
|
|
int count = 0;
|
|
|
|
|
|
|
|
|
|
Future<void> _fetch() async {
|
|
|
|
|
Future<void> _fetch(dynamic pageKey) async {
|
|
|
|
|
if (!_hasData || !_loading) return;
|
|
|
|
|
print('hasHasData');
|
|
|
|
|
setState(() => _loading = true);
|
|
|
|
|
// setState(() => _loading = true);
|
|
|
|
|
try {
|
|
|
|
|
var newItems =
|
|
|
|
|
await PhpGroup.getVehiclesByProperty.call(pageKey.toString());
|
|
|
|
|
final bool isLastPage = newItems.jsonBody == null ||
|
|
|
|
|
newItems.jsonBody == [] ||
|
|
|
|
|
newItems.jsonBody == '';
|
|
|
|
|
|
|
|
|
|
var response = await PhpGroup.getVehiclesByProperty.call(_pageNumber.toString());
|
|
|
|
|
final List<dynamic> vehicles = response.jsonBody['vehicles'] as List<dynamic>? ?? [];
|
|
|
|
|
safeSetState(() => count = response.jsonBody['total_rows'] ?? 0);
|
|
|
|
|
if (vehicles.isNotEmpty) {
|
|
|
|
|
if (newItems.jsonBody == null) {
|
|
|
|
|
} else {
|
|
|
|
|
final List<dynamic> vehicles =
|
|
|
|
|
newItems.jsonBody['vehicles'] as List<dynamic>? ?? [];
|
|
|
|
|
_pagingController.nextPageKey = pageKey + 1;
|
|
|
|
|
|
|
|
|
|
safeSetState(() => count = newItems.jsonBody['total_rows'] ?? 0);
|
|
|
|
|
if (vehicles.isNotEmpty) {
|
|
|
|
|
// setState(() {
|
|
|
|
|
// _hasData = true;
|
|
|
|
|
// _loading = false;
|
|
|
|
|
// _wrap.addAll(vehicles);
|
|
|
|
|
// });
|
|
|
|
|
_pagingController.appendLastPage(vehicles);
|
|
|
|
|
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
_showNoMoreDataSnackBar(context);
|
|
|
|
|
setState(() {
|
|
|
|
|
_hasData = true;
|
|
|
|
|
_hasData = false;
|
|
|
|
|
_loading = false;
|
|
|
|
|
_wrap.addAll(vehicles);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
print('hasEmpty: ${_wrap.length}');
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
_showNoMoreDataSnackBar(context);
|
|
|
|
|
|
|
|
|
|
setState(() {
|
|
|
|
|
_hasData = false;
|
|
|
|
|
_loading = false;
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
print('hasEmpty: ${_wrap.length}');
|
|
|
|
|
return;
|
|
|
|
|
} catch (e, s) {
|
|
|
|
|
DialogUtil.errorDefault(context);
|
|
|
|
|
LogUtil.requestAPIFailed("proccessRequest.php", "", "Consulta de Veículo", e, s);
|
|
|
|
|
LogUtil.requestAPIFailed(
|
|
|
|
|
"proccessRequest.php", "", "Consulta de Veículo", e, s);
|
|
|
|
|
setState(() {
|
|
|
|
|
_hasData = false;
|
|
|
|
|
_loading = false;
|
|
|
|
@ -202,37 +207,48 @@ mixin Remotable on State<VehicleHistoryScreen> {
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Widget? _generateItems(BuildContext context, dynamic snapshot, int index) {
|
|
|
|
|
if (index == 0) return _buildHeader(context);
|
|
|
|
|
|
|
|
|
|
final bool? isOwner = snapshot['isOwnerVehicle'];
|
|
|
|
|
final IconData? iconData = isOwner == true ? Symbols.garage : Symbols.directions_car;
|
|
|
|
|
final FreCardIcon? cardIcon = isOwner != null
|
|
|
|
|
? FreCardIcon(height: 50, width: 100, icon: Icon(iconData, size: 80, opticalSize: 10))
|
|
|
|
|
: null;
|
|
|
|
|
Widget _generateItems(BuildContext context, int index, dynamic item) {
|
|
|
|
|
log('item: $item');
|
|
|
|
|
|
|
|
|
|
final String? tag = snapshot['tag'];
|
|
|
|
|
final bool containTag = tag.isNotNullAndEmpty;
|
|
|
|
|
final Map<String, String> labelsHashMap = _generateLabelsHashMap(context, snapshot, tag, containTag);
|
|
|
|
|
// return Placeholder();
|
|
|
|
|
|
|
|
|
|
final List<Map<String, Color>> statusHashMapList = _generateStatusHashMapList(snapshot);
|
|
|
|
|
// if (index == 0) return _buildHeader(context);
|
|
|
|
|
|
|
|
|
|
Future<void> onTapCardItemAction() async {
|
|
|
|
|
_handleCardItemTap(context, cardIcon, snapshot);
|
|
|
|
|
}
|
|
|
|
|
final bool? isOwner = item['isOwnerVehicle'];
|
|
|
|
|
final IconData? iconData =
|
|
|
|
|
isOwner == true ? Symbols.garage : Symbols.directions_car;
|
|
|
|
|
final FreCardIcon? cardIcon = isOwner != null
|
|
|
|
|
? FreCardIcon(
|
|
|
|
|
height: 50,
|
|
|
|
|
width: 100,
|
|
|
|
|
icon: Icon(iconData, size: 80, opticalSize: 10))
|
|
|
|
|
: null;
|
|
|
|
|
|
|
|
|
|
final statusLinkedHashMap = statusHashMapList.map((map) => LinkedHashMap<String, Color>.from(map)).toList();
|
|
|
|
|
final length = statusLinkedHashMap.expand((e) => [e.length]);
|
|
|
|
|
final String? tag = item['tag'];
|
|
|
|
|
final bool containTag = tag.isNotNullAndEmpty;
|
|
|
|
|
final Map<String, String> labelsHashMap =
|
|
|
|
|
_generateLabelsHashMap(context, item, tag, containTag);
|
|
|
|
|
|
|
|
|
|
return CardItemTemplateComponentWidget(
|
|
|
|
|
icon: cardIcon,
|
|
|
|
|
labelsHashMap: labelsHashMap,
|
|
|
|
|
statusHashMap: statusHashMapList,
|
|
|
|
|
onTapCardItemAction: onTapCardItemAction,
|
|
|
|
|
itemWidthFactor: length == 1 ? 0.25 : 0.50,
|
|
|
|
|
);
|
|
|
|
|
final List<Map<String, Color>> statusHashMapList =
|
|
|
|
|
_generateStatusHashMapList(item);
|
|
|
|
|
|
|
|
|
|
Future<void> onTapCardItemAction() async {
|
|
|
|
|
_handleCardItemTap(context, cardIcon, item);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
final statusLinkedHashMap = statusHashMapList
|
|
|
|
|
.map((map) => LinkedHashMap<String, Color>.from(map))
|
|
|
|
|
.toList();
|
|
|
|
|
final length = statusLinkedHashMap.expand((e) => [e.length]);
|
|
|
|
|
|
|
|
|
|
return CardItemTemplateComponentWidget(
|
|
|
|
|
icon: cardIcon,
|
|
|
|
|
labelsHashMap: labelsHashMap,
|
|
|
|
|
statusHashMap: statusHashMapList,
|
|
|
|
|
onTapCardItemAction: onTapCardItemAction,
|
|
|
|
|
itemWidthFactor: length == 1 ? 0.25 : 0.50,
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Map<String, String> _generateLabelsHashMap(BuildContext context,
|
|
|
|
|
Map<String, dynamic> uItem, String? tag, bool containTag) {
|
|
|
|
@ -249,17 +265,16 @@ mixin Remotable on State<VehicleHistoryScreen> {
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
List<Map<String, Color>> _generateStatusHashMapList(
|
|
|
|
|
Map<String, dynamic> uItem) {
|
|
|
|
|
final statusHashMap =
|
|
|
|
|
widget.model.generateStatusColorMap(uItem, false);
|
|
|
|
|
List<Map<String, Color>> _generateStatusHashMapList(
|
|
|
|
|
Map<String, dynamic> uItem) {
|
|
|
|
|
final statusHashMap = widget.model.generateStatusColorMap(uItem, false);
|
|
|
|
|
return statusHashMap != null ? [statusHashMap] : [];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Future<void> _handleCardItemTap(BuildContext context, FreCardIcon? cardIcon,
|
|
|
|
|
Map<String, dynamic> uItem) async {
|
|
|
|
|
try {
|
|
|
|
|
final dialogContent = widget.model.buildVehicleDetails(
|
|
|
|
|
final dialogContent = widget.model.buildVehicleDetails(
|
|
|
|
|
icon: cardIcon,
|
|
|
|
|
item: uItem,
|
|
|
|
|
context: context,
|
|
|
|
@ -274,7 +289,7 @@ mixin Remotable on State<VehicleHistoryScreen> {
|
|
|
|
|
).whenComplete(() {
|
|
|
|
|
safeSetState(() {
|
|
|
|
|
_pageNumber = 1;
|
|
|
|
|
_fetch();
|
|
|
|
|
_fetch(1);
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
} catch (e, s) {
|
|
|
|
@ -289,27 +304,26 @@ mixin Remotable on State<VehicleHistoryScreen> {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void _initializeScrollController() {
|
|
|
|
|
_scrollController = ScrollController(keepScrollOffset: true, initialScrollOffset: offset)
|
|
|
|
|
..addListener(() {
|
|
|
|
|
print('ScrollController');
|
|
|
|
|
if(!_hasData) return;
|
|
|
|
|
if
|
|
|
|
|
// (_scrollController.position.pixels >= _scrollController.position.maxScrollExtent)
|
|
|
|
|
(_scrollController.position.atEdge && _scrollController.position.pixels != 0)
|
|
|
|
|
{
|
|
|
|
|
print('ScrollController -> loadMore');
|
|
|
|
|
offset = _scrollController.offset;
|
|
|
|
|
_loadMore();
|
|
|
|
|
}
|
|
|
|
|
},);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void _loadMore() {
|
|
|
|
|
if (_hasData) {
|
|
|
|
|
_pageNumber+=1;
|
|
|
|
|
_loading = true;
|
|
|
|
|
_fetch();
|
|
|
|
|
}
|
|
|
|
|
// _scrollController = ScrollController(keepScrollOffset: true, initialScrollOffset: offset)
|
|
|
|
|
// ..addListener(() {
|
|
|
|
|
// print('ScrollController');
|
|
|
|
|
// if(!_hasData) return;
|
|
|
|
|
// if
|
|
|
|
|
// // (_scrollController.position.pixels >= _scrollController.position.maxScrollExtent)
|
|
|
|
|
// (_scrollController.position.atEdge && _scrollController.position.pixels != 0)
|
|
|
|
|
// {
|
|
|
|
|
// print('ScrollController -> loadMore');
|
|
|
|
|
// offset = _scrollController.offset;
|
|
|
|
|
// _loadMore();
|
|
|
|
|
// }
|
|
|
|
|
// },);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// void _loadMore() {
|
|
|
|
|
// if (_hasData) {
|
|
|
|
|
// _pageNumber+=1;
|
|
|
|
|
// _loading = true;
|
|
|
|
|
// _fetch(_pageNumber);
|
|
|
|
|
// }
|
|
|
|
|
// }
|
|
|
|
|
}
|
|
|
|
|