WIP - paginacao

This commit is contained in:
jantunesmessias 2025-02-06 18:01:47 -03:00
parent b2df549066
commit 16f43bbab8
1 changed files with 91 additions and 104 deletions

View File

@ -6,24 +6,19 @@ part of 'vehicles_on_the_property.dart';
class VehicleHistoryScreen extends StatefulWidget { class VehicleHistoryScreen extends StatefulWidget {
VehicleHistoryScreen(this.model, {super.key}); VehicleHistoryScreen(this.model, {super.key});
late VehicleModel model; late VehicleModel model;
late Future<void> _future;
List<dynamic> _wrap = [];
int _pageNumber = 1;
bool _hasData = false;
bool _loading = false;
int count = 0;
@override @override
State<VehicleHistoryScreen> createState() => _VehicleHistoryScreenState(); State<VehicleHistoryScreen> createState() => _VehicleHistoryScreenState();
} }
class _VehicleHistoryScreenState extends State<VehicleHistoryScreen> class _VehicleHistoryScreenState extends State<VehicleHistoryScreen>
with _FetchingMixin, _ScrollControllerMixin, _CardItemMixin { with Remotable {
@override @override
void initState() { void initState() {
super.initState(); super.initState();
_initializeScrollController(); _initializeScrollController();
widget._future = _fetch(); _future = _fetch();
} }
@override @override
@ -37,13 +32,13 @@ class _VehicleHistoryScreenState extends State<VehicleHistoryScreen>
mainAxisSize: MainAxisSize.max, mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.start, mainAxisAlignment: MainAxisAlignment.start,
children: [ children: [
if (widget._hasData == false && if (_hasData == false &&
widget._pageNumber <= 1 && _pageNumber <= 1 &&
widget._loading == false) _loading == false)
_buildNoDataFound(context, limitedHeaderTextSize) _buildNoDataFound(context, limitedHeaderTextSize)
else if (widget._hasData == true || widget._pageNumber >= 1) else if (_hasData == true || _pageNumber >= 1)
_buildVehicleList(context, limitedBodyTextSize), _buildHistoryList(context, limitedBodyTextSize),
if (widget._hasData == true && widget._loading == true) if (_hasData == true && _loading == true)
_buildLoadingIndicator(context), _buildLoadingIndicator(context),
].addToStart(const SizedBox(height: 0)), ].addToStart(const SizedBox(height: 0)),
); );
@ -72,10 +67,10 @@ class _VehicleHistoryScreenState extends State<VehicleHistoryScreen>
); );
} }
Widget _buildVehicleList(BuildContext context, double limitedBodyTextSize) { Widget _buildHistoryList(BuildContext context, double limitedBodyTextSize) {
return Expanded( return Expanded(
child: FutureBuilder<void>( child: FutureBuilder<List<Widget?>>(
future: widget._future, future: _future,
builder: (context, snapshot) { builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.waiting) { if (snapshot.connectionState == ConnectionState.waiting) {
return Center(child: CircularProgressIndicator()); return Center(child: CircularProgressIndicator());
@ -86,13 +81,13 @@ class _VehicleHistoryScreenState extends State<VehicleHistoryScreen>
shrinkWrap: true, shrinkWrap: true,
physics: const BouncingScrollPhysics(), physics: const BouncingScrollPhysics(),
controller: _scrollController, controller: _scrollController,
itemCount: widget._wrap.length + 1, itemCount: _wrap.length + 1,
itemBuilder: (context, index) { itemBuilder: (context, index) {
if (index == 0) { if (index == 0) {
return _buildHeader(context, limitedBodyTextSize); return _buildHeader(context, limitedBodyTextSize);
} else { } else {
Map<String, dynamic> item = widget._wrap[index - 1]; Widget? item = _wrap[index - 1];
return _buildVehicleItem(context, item); return _wrap[index - 1] ?? SizedBox.shrink();
} }
}, },
); );
@ -102,19 +97,6 @@ class _VehicleHistoryScreenState extends State<VehicleHistoryScreen>
); );
} }
Widget _buildVehicleItem(BuildContext context, Map<String, dynamic> item) {
return FutureBuilder<Widget>(
future: _item(context, item),
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.done) {
return snapshot.data ?? Container();
} else {
return Center(child: CircularProgressIndicator());
}
},
);
}
Widget _buildHeader(BuildContext context, double limitedBodyTextSize) { Widget _buildHeader(BuildContext context, double limitedBodyTextSize) {
log('amountRegister: ${widget.model.amountRegister}'); log('amountRegister: ${widget.model.amountRegister}');
return Padding( return Padding(
@ -147,48 +129,36 @@ class _VehicleHistoryScreenState extends State<VehicleHistoryScreen>
} }
} }
// Mixin for Scroll Controller
mixin _ScrollControllerMixin on _FetchingMixin {
late ScrollController _scrollController;
void _initializeScrollController() {
_scrollController = ScrollController()
..addListener(() {
if (_scrollController.position.atEdge &&
_scrollController.position.pixels != 0) {
_loadMore();
}
});
}
void _loadMore() {
if (widget._hasData == true) {
widget._pageNumber++;
widget._future = _fetch();
}
}
}
// Mixin for Fetch Visits // Mixin for Fetch Visits
mixin _FetchingMixin on State<VehicleHistoryScreen> { mixin Remotable on State<VehicleHistoryScreen> {
Future<ApiCallResponse?> _fetch() async { late Future<List<Widget?>> _future;
List<Widget?> _wrap = [];
int _pageNumber = 1;
bool _hasData = true;
bool _loading = true;
int count = 0;
Future<List<Widget?>> _fetch() async {
if (!widget._hasData || !widget._loading) return [];
setState(() => widget._loading = true);
try { try {
setState(() => widget._loading = true); var response = await PhpGroup.getVehiclesByProperty.call(widget._pageNumber.toString());
final List<dynamic> vehicles = response.jsonBody['vehicles'] as List<dynamic>? ?? [];
var response = await PhpGroup.getVehiclesByProperty
.call(widget._pageNumber.toString());
final List<dynamic> vehicles = response.jsonBody['vehicles'] ?? [];
safeSetState(() => widget.count = response.jsonBody['total_rows'] ?? 0); safeSetState(() => widget.count = response.jsonBody['total_rows'] ?? 0);
if (vehicles.isNotEmpty) { if (vehicles.isNotEmpty) {
setState(() { setState(() {
widget._wrap.addAll(vehicles);
widget._hasData = true; widget._hasData = true;
widget._loading = false; widget._loading = false;
}); });
return response;
return _generateItems(context, vehicles);
} }
_showNoMoreDataSnackBar(context); _showNoMoreDataSnackBar(context);
@ -198,17 +168,16 @@ mixin _FetchingMixin on State<VehicleHistoryScreen> {
widget._loading = false; widget._loading = false;
}); });
return null; return [];
} catch (e, s) { } catch (e, s) {
DialogUtil.errorDefault(context); DialogUtil.errorDefault(context);
LogUtil.requestAPIFailed( LogUtil.requestAPIFailed("proccessRequest.php", "", "Consulta de Veículo", e, s);
"proccessRequest.php", "", "Consulta de Veículo", e, s);
setState(() { setState(() {
widget._hasData = false; widget._hasData = false;
widget._loading = false; widget._loading = false;
}); });
return [];
} }
return null;
} }
void _showNoMoreDataSnackBar(BuildContext context) { void _showNoMoreDataSnackBar(BuildContext context) {
@ -219,47 +188,43 @@ mixin _FetchingMixin on State<VehicleHistoryScreen> {
showSnackbar(context, message, true); showSnackbar(context, message, true);
} }
}
// Mixin for Card Item Future<List<Widget?>> _generateItems(BuildContext context, List<dynamic> uItem) async {
mixin _CardItemMixin on _FetchingMixin { if (!widget._hasData) return [];
Future<Widget> _item(BuildContext context, Map<String, dynamic> uItem) async {
final bool? isOwner = uItem['isOwnerVehicle'];
final IconData? iconData = isOwner == null
? null
: isOwner == true
? Symbols.no_crash
: Symbols.directions_car;
final FreCardIcon? cardIcon = isOwner != null
? FreCardIcon(
height: 50,
width: 100,
icon: Icon(iconData, size: 80, opticalSize: 10))
: null;
final String? tag = uItem['tag']; List<Widget?> items = [];
final bool containTag = tag.isNotNullAndEmpty;
final Map<String, String> labelsHashMap =
_generateLabelsHashMap(context, uItem, tag, containTag);
final statusHashMapList = await _generateStatusHashMapList(uItem); for (var uItem in uItem) {
final bool? isOwner = uItem['isOwnerVehicle'];
final IconData? iconData = isOwner == true ? Symbols.no_crash : Symbols.directions_car;
final FreCardIcon? cardIcon = isOwner != null
? FreCardIcon(height: 50, width: 100, icon: Icon(iconData, size: 80, opticalSize: 10))
: null;
Future<void> onTapCardItemAction() async { final String? tag = uItem['tag'];
await _handleCardItemTap(context, cardIcon, uItem); final bool containTag = tag.isNotNullAndEmpty;
final Map<String, String> labelsHashMap = _generateLabelsHashMap(context, uItem, tag, containTag);
final statusHashMapList = await _generateStatusHashMapList(uItem);
Future<void> onTapCardItemAction() async {
await _handleCardItemTap(context, cardIcon, uItem);
}
final statusLinkedHashMap = statusHashMapList.map((map) => LinkedHashMap<String, Color>.from(map)).toList();
final length = statusLinkedHashMap.expand((e) => [e.length]);
items.add(CardItemTemplateComponentWidget(
icon: cardIcon,
labelsHashMap: labelsHashMap,
statusHashMap: statusHashMapList,
onTapCardItemAction: onTapCardItemAction,
itemWidthFactor: length == 1 ? 0.25 : 0.50,
));
} }
final statusLinkedHashMap = statusHashMapList widget._wrap.addAll(items);
.map((map) => LinkedHashMap<String, Color>.from(map)) return items;
.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, String> _generateLabelsHashMap(BuildContext context,
@ -316,4 +281,26 @@ mixin _CardItemMixin on _FetchingMixin {
}); });
} }
} }
late ScrollController _scrollController;
void _initializeScrollController() {
_scrollController = ScrollController()
..addListener(() {
print('ScrollController');
if(!widget._hasData) return;
if (_scrollController.position.pixels >= _scrollController.position.maxScrollExtent) {
print('ScrollController -> loadMore');
_loadMore();
}
});
}
void _loadMore() {
if (widget._hasData) {
widget._pageNumber++;
widget._loading = true;
widget._future = _fetch();
}
}
} }