From 906fbcaf24275b74522520f4cee795b1318ed1c4 Mon Sep 17 00:00:00 2001 From: jantunesmessias Date: Fri, 7 Feb 2025 16:50:45 -0300 Subject: [PATCH] WIP --- .../pages/acess_history_page_widget.dart | 1 + .../vehicle_history_screen.dart | 181 +++++++++--------- .../vehicle_model.dart | 37 ++-- scripts/httpie.sh | 30 +++ 4 files changed, 141 insertions(+), 108 deletions(-) create mode 100755 scripts/httpie.sh diff --git a/lib/features/history/presentation/pages/acess_history_page_widget.dart b/lib/features/history/presentation/pages/acess_history_page_widget.dart index 16708425..b855ec30 100644 --- a/lib/features/history/presentation/pages/acess_history_page_widget.dart +++ b/lib/features/history/presentation/pages/acess_history_page_widget.dart @@ -52,6 +52,7 @@ class _AccessHistoryState extends State { _model = createModel(context, () => AcessHistoryPageModel()); _accessFuture = fetchAccessHistoryService(); + _scrollController = ScrollController() ..addListener(() { if (_scrollController.position.atEdge && diff --git a/lib/pages/vehicles_on_the_property/vehicle_history_screen.dart b/lib/pages/vehicles_on_the_property/vehicle_history_screen.dart index e20e6e36..f6878016 100644 --- a/lib/pages/vehicles_on_the_property/vehicle_history_screen.dart +++ b/lib/pages/vehicles_on_the_property/vehicle_history_screen.dart @@ -4,21 +4,24 @@ part of 'vehicles_on_the_property.dart'; // ignore: must_be_immutable class VehicleHistoryScreen extends StatefulWidget { + VehicleHistoryScreen(this.model, {super.key}); late VehicleModel model; - @override State createState() => _VehicleHistoryScreenState(); + } class _VehicleHistoryScreenState extends State with Remotable { + + + @override void initState() { super.initState(); _initializeScrollController(); - _future = _fetch(); } @override @@ -69,8 +72,8 @@ class _VehicleHistoryScreenState extends State Widget _buildHistoryList(BuildContext context, double limitedBodyTextSize) { return Expanded( - child: FutureBuilder>( - future: _future, + child: FutureBuilder>( + future: _fetch(), builder: (context, snapshot) { if (snapshot.connectionState == ConnectionState.waiting) { return Center(child: CircularProgressIndicator()); @@ -79,17 +82,13 @@ class _VehicleHistoryScreenState extends State } else { return ListView.builder( shrinkWrap: true, + addAutomaticKeepAlives: true, + restorationId: '', physics: const BouncingScrollPhysics(), controller: _scrollController, - itemCount: _wrap.length + 1, - itemBuilder: (context, index) { - if (index == 0) { - return _buildHeader(context, limitedBodyTextSize); - } else { - Widget? item = _wrap[index - 1]; - return _wrap[index - 1] ?? SizedBox.shrink(); - } - }, + itemCount: snapshot.data!.length , + itemBuilder: (context, index) => _generateItems(context, snapshot.data![index], index), + ); } }, @@ -97,24 +96,6 @@ class _VehicleHistoryScreenState extends State ); } - Widget _buildHeader(BuildContext context, double limitedBodyTextSize) { - log('amountRegister: ${widget.model.amountRegister}'); - return Padding( - padding: const EdgeInsets.only(right: 30, top: 10), - child: Text( - (widget.model.amountRegister == '0' || - widget.model.amountRegister == null) - ? '' - : "${FFLocalizations.of(context).getVariableText(ptText: "Quantidade de Veículos: ", enText: "Amount of Vehicles: ")}${widget.model.amountRegister}/${widget.count}", - textAlign: TextAlign.right, - style: TextStyle( - fontFamily: 'Nunito', - fontSize: limitedBodyTextSize, - ), - ), - ); - } - Widget _buildLoadingIndicator(BuildContext context) { return Container( padding: const EdgeInsets.only(top: 15, bottom: 15), @@ -127,56 +108,59 @@ class _VehicleHistoryScreenState extends State ), ); } + + + } -// Mixin for Fetch Visits mixin Remotable on State { - late Future> _future; - List _wrap = []; + + late ScrollController _scrollController; + double offset = 0.0; + List _wrap = []; int _pageNumber = 1; bool _hasData = true; bool _loading = true; int count = 0; - - Future> _fetch() async { - if (!widget._hasData || !widget._loading) return []; - - setState(() => widget._loading = true); - + Future> _fetch() async { + if (!_hasData || !_loading) return _wrap; + print('hasHasData'); + setState(() => _loading = true); try { - var response = await PhpGroup.getVehiclesByProperty.call(widget._pageNumber.toString()); - final List vehicles = response.jsonBody['vehicles'] as List? ?? []; - safeSetState(() => widget.count = response.jsonBody['total_rows'] ?? 0); + var response = await PhpGroup.getVehiclesByProperty.call(_pageNumber.toString()); + final List vehicles = response.jsonBody['vehicles'] as List? ?? []; + safeSetState(() => count = response.jsonBody['total_rows'] ?? 0); if (vehicles.isNotEmpty) { setState(() { - - widget._hasData = true; - widget._loading = false; + _hasData = true; + _loading = false; }); - - - return _generateItems(context, vehicles); + print('vehicles.isNotEmpty'); + _wrap.addAll(vehicles); + return _wrap; } _showNoMoreDataSnackBar(context); setState(() { - widget._hasData = false; - widget._loading = false; + _hasData = false; + _loading = false; }); - return []; + print('hasEmpty: ${_wrap.length}'); + return _wrap; } catch (e, s) { DialogUtil.errorDefault(context); LogUtil.requestAPIFailed("proccessRequest.php", "", "Consulta de Veículo", e, s); setState(() { - widget._hasData = false; - widget._loading = false; + _hasData = false; + _loading = false; }); - return []; + print('hasError'); + return _wrap; } } @@ -189,43 +173,56 @@ mixin Remotable on State { showSnackbar(context, message, true); } - Future> _generateItems(BuildContext context, List uItem) async { - if (!widget._hasData) return []; + Widget _buildHeader(BuildContext context) { + double limitedBodyTextSize = LimitedFontSizeUtil.getBodyFontSize(context); + log('amountRegister: ${widget.model.amountRegister}'); + return Padding( + padding: const EdgeInsets.only(right: 30, top: 10), + child: Text( + (widget.model.amountRegister == '0' || + widget.model.amountRegister == null) + ? '' + : "${FFLocalizations.of(context).getVariableText(ptText: "Quantidade de Veículos: ", enText: "Amount of Vehicles: ")}${widget.model.amountRegister}/$count", + textAlign: TextAlign.right, + style: TextStyle( + fontFamily: 'Nunito', + fontSize: limitedBodyTextSize, + ), + ), + ); + } - List items = []; - - for (var uItem in uItem) { - final bool? isOwner = uItem['isOwnerVehicle']; - final IconData? iconData = isOwner == true ? Symbols.no_crash : Symbols.directions_car; + 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; - final String? tag = uItem['tag']; + final String? tag = snapshot['tag']; final bool containTag = tag.isNotNullAndEmpty; - final Map labelsHashMap = _generateLabelsHashMap(context, uItem, tag, containTag); + final Map labelsHashMap = _generateLabelsHashMap(context, snapshot, tag, containTag); - final statusHashMapList = await _generateStatusHashMapList(uItem); + final List> statusHashMapList = _generateStatusHashMapList(snapshot); Future onTapCardItemAction() async { - await _handleCardItemTap(context, cardIcon, uItem); + _handleCardItemTap(context, cardIcon, snapshot); } final statusLinkedHashMap = statusHashMapList.map((map) => LinkedHashMap.from(map)).toList(); final length = statusLinkedHashMap.expand((e) => [e.length]); - items.add(CardItemTemplateComponentWidget( + return CardItemTemplateComponentWidget( icon: cardIcon, labelsHashMap: labelsHashMap, statusHashMap: statusHashMapList, onTapCardItemAction: onTapCardItemAction, itemWidthFactor: length == 1 ? 0.25 : 0.50, - )); + ); } - - widget._wrap.addAll(items); - return items; - } + Map _generateLabelsHashMap(BuildContext context, Map uItem, String? tag, bool containTag) { @@ -242,17 +239,17 @@ mixin Remotable on State { }; } - Future>> _generateStatusHashMapList( - Map uItem) async { + List> _generateStatusHashMapList( + Map uItem) { final statusHashMap = - await widget.model.generateStatusColorMap(uItem, false); + widget.model.generateStatusColorMap(uItem, false); return statusHashMap != null ? [statusHashMap] : []; } Future _handleCardItemTap(BuildContext context, FreCardIcon? cardIcon, Map uItem) async { try { - final dialogContent = await widget.model.buildVehicleDetails( + final dialogContent = widget.model.buildVehicleDetails( icon: cardIcon, item: uItem, context: context, @@ -266,9 +263,8 @@ mixin Remotable on State { Dialog(alignment: Alignment.center, child: dialogContent), ).whenComplete(() { safeSetState(() { - widget._pageNumber = 1; - widget._wrap = []; - widget._future = _fetch(); + _pageNumber = 1; + _fetch(); }); }); } catch (e, s) { @@ -276,31 +272,34 @@ mixin Remotable on State { LogUtil.requestAPIFailed( "proccessRequest.php", "", "Consulta de Veículos", e, s); safeSetState(() { - widget._hasData = false; - widget._loading = false; + _hasData = false; + _loading = false; }); } } - late ScrollController _scrollController; - void _initializeScrollController() { - _scrollController = ScrollController() + _scrollController = ScrollController(keepScrollOffset: true, initialScrollOffset: offset) ..addListener(() { print('ScrollController'); - if(!widget._hasData) return; - if (_scrollController.position.pixels >= _scrollController.position.maxScrollExtent) { + 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 (widget._hasData) { - widget._pageNumber++; - widget._loading = true; - widget._future = _fetch(); + void _loadMore() async { + if (_hasData) { + _pageNumber+=1; + _loading = true; + _fetch(); } } + } diff --git a/lib/pages/vehicles_on_the_property/vehicle_model.dart b/lib/pages/vehicles_on_the_property/vehicle_model.dart index 800b8c4a..5bee0d41 100644 --- a/lib/pages/vehicles_on_the_property/vehicle_model.dart +++ b/lib/pages/vehicles_on_the_property/vehicle_model.dart @@ -71,6 +71,7 @@ class VehicleModel extends FlutterFlowModel Future initAsync() async { amountRegister = await StorageHelper().get(LocalsStorageKey.vehicleAmountRegister.key); + autoApproval= await StorageHelper().get(LocalsStorageKey.vehicleAutoApproval.key); } bool isFormValid(BuildContext context, GlobalKey formKey) { @@ -89,6 +90,8 @@ mixin class _BaseVehiclePage { bool isEditing = false; ApiCallResponse? vehicleResponse; String? amountRegister = '0'; + late final String? autoApproval; + VoidCallback? onUpdateVehicle; VoidCallback? onRegisterVehicle; @@ -237,10 +240,10 @@ mixin _VehicleUpdateScreenModel on _BaseVehiclePage { /// [_VehicleHistoryScreenModel] is a mixin that contains the business logic of the vehicle history page. mixin _VehicleHistoryScreenModel on _BaseVehiclePage { - Future?>? generateStatusColorMap( - dynamic uItem, bool isDetail) async { - final autoApproval = - await StorageHelper().get(LocalsStorageKey.vehicleAutoApproval.key); + + + Map? generateStatusColorMap(dynamic uItem, bool isDetail) { + if (autoApproval.toBoolean == true) return null; final theme = FlutterFlowTheme.of(context); final localization = FFLocalizations.of(context); @@ -296,7 +299,7 @@ mixin _VehicleHistoryScreenModel on _BaseVehiclePage { return {}; } - Future?> generateActionButtons(dynamic item) async { + List generateActionButtons(dynamic item) { final Color iconButtonColor = FlutterFlowTheme.of(context).primaryText; final FFButtonOptions buttonOptions = FFButtonOptions( height: 40, @@ -339,7 +342,7 @@ mixin _VehicleHistoryScreenModel on _BaseVehiclePage { ptText: 'Você tem certeza que deseja cancelar essa solicitação?', enText: 'Are you sure you want to delete this request?', ), - () async => await processCancelRequest(item['status'], item)); + () async => processCancelRequest(item['status'], item)); } final deleteText = FFLocalizations.of(context) @@ -356,7 +359,7 @@ mixin _VehicleHistoryScreenModel on _BaseVehiclePage { ptText: 'Você tem certeza que deseja excluir esse veículo?', enText: 'Are you sure you want to delete this vehicle?', ), - () async => await processDeleteRequest(item), + () async => processDeleteRequest(item), ); } @@ -401,7 +404,7 @@ mixin _VehicleHistoryScreenModel on _BaseVehiclePage { ]; } - Future processDeleteRequest(dynamic item) async { + void processDeleteRequest(dynamic item) async { log('processDeleteRequest -> item[$item]'); return await PhpGroup.deleteVehicle .call( @@ -448,7 +451,7 @@ mixin _VehicleHistoryScreenModel on _BaseVehiclePage { }); } - Future processCancelRequest(String status, dynamic item) async { + void processCancelRequest(String status, dynamic item) async { late final ApiCallResponse value; try { switch (status) { @@ -500,7 +503,7 @@ mixin _VehicleHistoryScreenModel on _BaseVehiclePage { } } - Future processCancelDeleteRequest(dynamic item) async { + Future processCancelDeleteRequest(dynamic item) async{ return await PhpGroup.deleteVehicle.call( vehicleId: item['vehicleId'], licensePlate: item['licensePlate'], @@ -509,7 +512,7 @@ mixin _VehicleHistoryScreenModel on _BaseVehiclePage { ); } - Future processCancelUpdateRequest(dynamic item) async { + Future processCancelUpdateRequest(dynamic item) async { return await PhpGroup.deleteVehicle.call( vehicleId: item['vehicleId'], licensePlate: item['licensePlate'], @@ -527,7 +530,7 @@ mixin _VehicleHistoryScreenModel on _BaseVehiclePage { ); } - Future> generateLabelsHashMap(dynamic item) async { + Map generateLabelsHashMap(dynamic item) { return { if (item['model'] != null && item['model'] != '') '${FFLocalizations.of(context).getVariableText(ptText: "Modelo", enText: "Model")}:': @@ -547,15 +550,15 @@ mixin _VehicleHistoryScreenModel on _BaseVehiclePage { }; } - Future buildVehicleDetails({ + DetailsComponentWidget buildVehicleDetails({ required dynamic item, required BuildContext context, required VehicleModel model, required FreCardIcon? icon, - }) async { - final status = await generateStatusColorMap(item, true); - final buttons = await generateActionButtons(item); - final labels = await generateLabelsHashMap(item); + }) { + final status = generateStatusColorMap(item, true); + final buttons = generateActionButtons(item); + final labels = generateLabelsHashMap(item); return DetailsComponentWidget( icon: icon, buttons: buttons, diff --git a/scripts/httpie.sh b/scripts/httpie.sh new file mode 100755 index 00000000..c9e4e2dc --- /dev/null +++ b/scripts/httpie.sh @@ -0,0 +1,30 @@ +#!/bin/bash + +# Define the base URL for the API endpoint +BASE_URL="https://freaccess.com.br/freaccess/processRequest.php" + +# Define common parameters +DEV_UUID="6b7b81849c115a8a" +USER_UUID="678aa05b0c2154.50583237" +CLI_ID="7" +ACTIVITY="getVehiclesByProperty" +PAGE_SIZE="10" + +# Function to perform the HTTP request +perform_request() { + local page=$1 + http --form POST "$BASE_URL" \ + devUUID="$DEV_UUID" \ + userUUID="$USER_UUID" \ + cliID="$CLI_ID" \ + atividade="$ACTIVITY" \ + page="$page" \ + pageSize="$PAGE_SIZE" \ + --check-status \ + --ignore-stdin \ + --timeout=10 +} + +# Perform requests for pages 1 and 2 +perform_request 1 +perform_request 2