LCOV - code coverage report
Current view: top level - lib/design/form - list_selector_page.dart (source / functions) Hit Total Coverage
Test: lcov.info Lines: 0 83 0.0 %
Date: 2024-10-04 11:09:33 Functions: 0 0 -

          Line data    Source code
       1             : // Copyright 2023 The terCAD team. All rights reserved.
       2             : // Use of this source code is governed by a CC BY-NC-ND 4.0 license that can be found in the LICENSE file.
       3             : 
       4             : import 'package:app_finance/_classes/herald/app_design.dart';
       5             : import 'package:app_finance/_classes/herald/app_locale.dart';
       6             : import 'package:app_finance/_configs/design_type.dart';
       7             : import 'package:app_finance/design/form/list_selector_item.dart';
       8             : import 'package:app_finance/_configs/theme_helper.dart';
       9             : import 'package:app_finance/_ext/build_context_ext.dart';
      10             : import 'package:app_finance/_ext/color_ext.dart';
      11             : import 'package:app_finance/design/form/simple_input.dart';
      12             : import 'package:flutter/material.dart';
      13             : import 'package:flutter_grid_layout/flutter_grid_layout.dart';
      14             : import 'package:provider/provider.dart';
      15             : 
      16             : typedef FntSelectorCallback = Widget Function(
      17             :   List<ListSelectorItem> options,
      18             :   NavigatorState nav,
      19             : );
      20             : 
      21             : class ListSelectorPage<T extends Object?> extends StatefulWidget {
      22             :   final T? result;
      23             :   final List<ListSelectorItem> options;
      24             :   final String tooltip;
      25             :   final FntSelectorCallback? itemBuilder;
      26             : 
      27           0 :   const ListSelectorPage({
      28             :     super.key,
      29             :     required this.options,
      30             :     required this.tooltip,
      31             :     this.result,
      32             :     this.itemBuilder,
      33             :   });
      34             : 
      35           0 :   @override
      36           0 :   State<StatefulWidget> createState() => ListSelectorPageState<T>();
      37             : }
      38             : 
      39             : class ListSelectorPageState<T extends Object?> extends State<ListSelectorPage> {
      40             :   final controller = TextEditingController();
      41             :   late NavigatorState nav;
      42             :   dynamic result;
      43             :   List<ListSelectorItem> options = [];
      44             :   String value = '';
      45             : 
      46           0 :   @override
      47             :   void initState() {
      48           0 :     result = widget.result;
      49           0 :     options = widget.options;
      50           0 :     controller.addListener(() => controller.text.isEmpty && value.isEmpty ? () {} : setState(filter));
      51           0 :     super.initState();
      52             :   }
      53             : 
      54           0 :   @override
      55             :   void dispose() {
      56           0 :     controller.dispose();
      57           0 :     super.dispose();
      58             :   }
      59             : 
      60           0 :   void filter() {
      61           0 :     value = controller.text;
      62           0 :     options = widget.options.where((e) => e.match(value)).toList();
      63             :   }
      64             : 
      65           0 :   Widget itemBuilder(List<ListSelectorItem> options) =>
      66           0 :       widget.itemBuilder?.call(options, nav) ??
      67           0 :       ListView.builder(
      68           0 :         itemCount: options.length,
      69           0 :         itemBuilder: (BuildContext context, int index) {
      70           0 :           return ListTile(
      71           0 :             tileColor: index % 2 == 0 ? context.colorScheme.primary.withOpacity(0.05) : null,
      72           0 :             hoverColor: context.colorScheme.primary.withOpacity(0.15),
      73           0 :             title: options[index].suggest(context),
      74           0 :             onTap: () => nav.pop<T>(options[index] as T),
      75             :           );
      76             :         },
      77             :       );
      78             : 
      79           0 :   @override
      80             :   Widget build(BuildContext context) {
      81           0 :     final design = Provider.of<AppDesign>(context, listen: false);
      82           0 :     if (design.value == AppDesignType.germany) {
      83           0 :       options.sort((a, b) => a.name.compareTo(b.name));
      84             :     }
      85           0 :     final indent = ThemeHelper.getIndent();
      86           0 :     nav = Navigator.of(context);
      87           0 :     return Directionality(
      88             :       textDirection: TextDirection.ltr,
      89           0 :       child: Scaffold(
      90           0 :         appBar: AppBar(backgroundColor: context.colorScheme.primary, toolbarHeight: 0),
      91           0 :         body: Column(
      92           0 :           crossAxisAlignment: AppDesign.getAlignment(),
      93           0 :           mainAxisAlignment: AppDesign.getAlignment<MainAxisAlignment>(),
      94           0 :           children: [
      95           0 :             Container(
      96           0 :               padding: EdgeInsets.all(ThemeHelper.getIndent()),
      97             :               width: double.infinity,
      98           0 :               decoration: BoxDecoration(
      99           0 :                 color: context.colorScheme.surface,
     100           0 :                 boxShadow: [
     101           0 :                   BoxShadow(
     102           0 :                     color: context.colorScheme.onSurface.withOpacity(0.1),
     103             :                     offset: const Offset(0, 1),
     104             :                     blurRadius: 3,
     105             :                     spreadRadius: 1,
     106             :                   ),
     107           0 :                   BoxShadow(
     108           0 :                     color: context.colorScheme.surface,
     109             :                     offset: const Offset(0, 3),
     110             :                     blurRadius: 0,
     111             :                     spreadRadius: 0,
     112             :                   ),
     113             :                 ],
     114           0 :                 border: Border(bottom: BorderSide(width: 4, color: context.colorScheme.surface.withOpacity(0.2))),
     115             :               ),
     116           0 :               child: Container(
     117           0 :                 decoration: BoxDecoration(
     118           0 :                   color: context.colorScheme.surface,
     119           0 :                   border: Border.all(color: context.colorScheme.onSurface.withOpacity(0.1)),
     120           0 :                   borderRadius: BorderRadius.all(Radius.circular(indent / 2)),
     121             :                 ),
     122           0 :                 height: ThemeHelper.barHeight + indent,
     123             :                 width: double.infinity,
     124           0 :                 padding: EdgeInsets.all(indent / 2),
     125           0 :                 child: GridContainer(
     126           0 :                   alignment: AppDesign.getAlignment<MainAxisAlignment>(),
     127           0 :                   rows: [null, ThemeHelper.barHeight / 2, ThemeHelper.barHeight / 2, ThemeHelper.barHeight, indent],
     128             :                   // ignore: prefer_const_literals_to_create_immutables
     129           0 :                   columns: [ThemeHelper.barHeight],
     130           0 :                   children: [
     131           0 :                     GridItem(
     132             :                       start: const Size(0, 0),
     133             :                       end: const Size(2, 1),
     134           0 :                       child: SimpleInput(
     135           0 :                         controller: controller,
     136           0 :                         tooltip: widget.tooltip,
     137             :                         withLabel: true,
     138             :                         forceFocus: true,
     139           0 :                         onFieldSubmitted: (String value) =>
     140           0 :                             nav.pop<T>(widget.options.where((e) => e.match(value)).firstOrNull as T?),
     141             :                       ),
     142             :                     ),
     143           0 :                     GridItem(
     144             :                       start: const Size(1, 0),
     145             :                       end: const Size(3, 1),
     146           0 :                       child: IconButton(
     147           0 :                         tooltip: AppLocale.labels.clear,
     148           0 :                         style: ButtonStyle(
     149           0 :                           backgroundColor: WidgetStateProperty.all<Color>(
     150           0 :                             context.colorScheme.surface.mesh(context.colorScheme.primary.withOpacity(1), 0.1),
     151             :                           ),
     152             :                         ),
     153             :                         icon: const Icon(Icons.clear),
     154           0 :                         onPressed: () => nav.pop<T?>(null),
     155             :                       ),
     156             :                     ),
     157           0 :                     GridItem(
     158             :                       start: const Size(3, 0),
     159             :                       end: const Size(4, 1),
     160           0 :                       child: IconButton(
     161           0 :                         tooltip: AppLocale.labels.returnBack,
     162             :                         icon: const Icon(Icons.rotate_left_rounded),
     163           0 :                         onPressed: () => nav.pop<T?>(result as T?),
     164             :                       ),
     165             :                     ),
     166             :                   ],
     167             :                 ),
     168             :               ),
     169             :             ),
     170           0 :             if (result != null)
     171           0 :               ListTile(
     172           0 :                 tileColor: context.colorScheme.primary.withOpacity(0.15),
     173           0 :                 hoverColor: context.colorScheme.primary.withOpacity(0.20),
     174           0 :                 title: widget.options.where((e) => e.equal(result)).firstOrNull?.build(context) ?? ThemeHelper.emptyBox,
     175           0 :                 onTap: () => nav.pop<T>(result as T),
     176             :               ),
     177           0 :             Expanded(child: Padding(padding: EdgeInsets.all(indent), child: itemBuilder(options))),
     178             :           ],
     179             :         ),
     180             :       ),
     181             :     );
     182             :   }
     183             : }

Generated by: LCOV version 1.14