LCOV - code coverage report
Current view: top level - lib/design/form - date_time_input.dart Coverage Total Hit
Test: lcov.info Lines: 29.8 % 84 25
Test Date: 2026-11-14 15:04:37 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_locale.dart';
       5              : import 'package:app_finance/_configs/custom_color_scheme.dart';
       6              : import 'package:app_finance/_configs/custom_text_theme.dart';
       7              : import 'package:app_finance/_configs/theme_helper.dart';
       8              : import 'package:app_finance/_ext/build_context_ext.dart';
       9              : import 'package:app_finance/design/form/abstract_selector.dart';
      10              : import 'package:app_finance/design/form/date_input.dart';
      11              : import 'package:app_finance/design/wrapper/row_widget.dart';
      12              : import 'package:material_ui/material_ui.dart';
      13              : import 'package:intl/intl.dart';
      14              : 
      15              : class DateTimeInput extends AbstractSelector {
      16              :   final Function setState;
      17              :   @override
      18              :   // ignore: overridden_fields
      19              :   final DateTime value;
      20              :   final double? width;
      21              : 
      22            2 :   const DateTimeInput({
      23              :     super.key,
      24              :     required this.setState,
      25              :     required this.value,
      26              :     this.width,
      27            2 :   }) : super(value: value);
      28              : 
      29            2 :   @override
      30            2 :   DateTimeInputState createState() => DateTimeInputState();
      31              : }
      32              : 
      33              : class DateTimeInputState extends AbstractSelectorState<DateTimeInput> {
      34            0 :   Future<TimeOfDay?> _showCompactTimePicker(BuildContext context) {
      35            0 :     final initial = TimeOfDay.fromDateTime(widget.value);
      36            0 :     final indent = ThemeHelper.getIndent(2);
      37            0 :     return showModalBottomSheet<TimeOfDay>(
      38              :       context: context,
      39              :       isScrollControlled: true,
      40              :       useSafeArea: true,
      41              :       shape: const RoundedRectangleBorder(borderRadius: BorderRadius.zero),
      42            0 :       builder: (sheetContext) {
      43            0 :         int hour = initial.hour;
      44            0 :         int minute = initial.minute;
      45            0 :         return StatefulBuilder(
      46            0 :           builder: (context, setModalState) {
      47            0 :             return Padding(
      48            0 :               padding: EdgeInsets.fromLTRB(
      49              :                 indent,
      50              :                 indent,
      51              :                 indent,
      52            0 :                 MediaQuery.of(context).viewInsets.bottom + indent,
      53              :               ),
      54            0 :               child: ConstrainedBox(
      55              :                 constraints: const BoxConstraints(maxWidth: 420),
      56            0 :                 child: Column(
      57              :                   mainAxisSize: MainAxisSize.min,
      58              :                   crossAxisAlignment: CrossAxisAlignment.stretch,
      59            0 :                   children: [
      60            0 :                     Text(
      61            0 :                       AppLocale.labels.balanceDate,
      62            0 :                       style: sheetContext.textTheme.titleMedium,
      63              :                     ),
      64            0 :                     SizedBox(height: indent),
      65            0 :                     Row(
      66            0 :                       children: [
      67            0 :                         Expanded(
      68            0 :                           child: DropdownButtonFormField<int>(
      69              :                             initialValue: hour,
      70            0 :                             decoration: InputDecoration(
      71            0 :                               labelText: AppLocale.labels.hour,
      72              :                               filled: true,
      73              :                               border: InputBorder.none,
      74            0 :                               fillColor: context.colorScheme.fieldBackground,
      75              :                             ),
      76            0 :                             items: List<DropdownMenuItem<int>>.generate(
      77              :                               24,
      78            0 :                               (index) => DropdownMenuItem<int>(
      79              :                                 value: index,
      80            0 :                                 child: Text(index.toString().padLeft(2, '0')),
      81              :                               ),
      82              :                             ),
      83            0 :                             onChanged: (value) {
      84              :                               if (value != null) {
      85            0 :                                 setModalState(() => hour = value);
      86              :                               }
      87              :                             },
      88              :                           ),
      89              :                         ),
      90            0 :                         SizedBox(width: indent),
      91            0 :                         Expanded(
      92            0 :                           child: DropdownButtonFormField<int>(
      93              :                             initialValue: minute,
      94            0 :                             decoration: InputDecoration(
      95            0 :                               labelText: AppLocale.labels.minute,
      96              :                               filled: true,
      97              :                               border: InputBorder.none,
      98            0 :                               fillColor: context.colorScheme.fieldBackground,
      99              :                             ),
     100            0 :                             items: List<DropdownMenuItem<int>>.generate(
     101              :                               60,
     102            0 :                               (index) => DropdownMenuItem<int>(
     103              :                                 value: index,
     104            0 :                                 child: Text(index.toString().padLeft(2, '0')),
     105              :                               ),
     106              :                             ),
     107            0 :                             onChanged: (value) {
     108              :                               if (value != null) {
     109            0 :                                 setModalState(() => minute = value);
     110              :                               }
     111              :                             },
     112              :                           ),
     113              :                         ),
     114              :                       ],
     115              :                     ),
     116            0 :                     SizedBox(height: indent),
     117            0 :                     Row(
     118              :                       mainAxisAlignment: MainAxisAlignment.end,
     119            0 :                       children: [
     120            0 :                         TextButton(
     121            0 :                           onPressed: () => Navigator.of(sheetContext).pop(),
     122            0 :                           child: Text(AppLocale.labels.btnCancel),
     123              :                         ),
     124            0 :                         SizedBox(width: indent),
     125            0 :                         FilledButton(
     126            0 :                           style: FilledButton.styleFrom(foregroundColor: sheetContext.colorScheme.surface),
     127            0 :                           onPressed: () => Navigator.of(sheetContext).pop(TimeOfDay(hour: hour, minute: minute)),
     128            0 :                           child: Text(AppLocale.labels.btnConfirm),
     129              :                         ),
     130              :                       ],
     131              :                     ),
     132              :                   ],
     133              :                 ),
     134              :               ),
     135              :             );
     136              :           },
     137              :         );
     138              :       },
     139              :     );
     140              :   }
     141              : 
     142            0 :   @override
     143              :   Future<void> onTap(BuildContext context) async {
     144            0 :     FocusManager.instance.primaryFocus?.unfocus();
     145            0 :     final time = await _showCompactTimePicker(context);
     146              :     if (time != null) {
     147            0 :       widget.setState(DateTime(widget.value.year, widget.value.month, widget.value.day, time.hour, time.minute));
     148            0 :       focusController.onEditingComplete(this);
     149              :     }
     150              :   }
     151              : 
     152            2 :   @override
     153              :   Widget buildContent(BuildContext context) {
     154            2 :     double indent = ThemeHelper.getIndent(2);
     155            4 :     double width = widget.width ?? ThemeHelper.getWidth(context, 4);
     156            2 :     final DateFormat formatterTime = DateFormat.Hms(AppLocale.code);
     157            2 :     final textTheme = context.textTheme;
     158              : 
     159            2 :     return RowWidget(
     160              :       indent: indent,
     161            2 :       maxWidth: width + indent,
     162              :       chunk: const [0.6, 0.4],
     163            2 :       children: [
     164            2 :         [
     165            2 :           DateInput(
     166            4 :             value: widget.value,
     167            4 :             setState: widget.setState,
     168              :           ),
     169              :         ],
     170            2 :         [
     171            2 :           Material(
     172            4 :             color: context.colorScheme.fieldBackground,
     173            2 :             child: ListTile(
     174            2 :               focusNode: focus,
     175            4 :               autofocus: focusController.isFocused(this),
     176            2 :               title: Text(
     177            6 :                 formatterTime.format(widget.value),
     178              :                 overflow: TextOverflow.ellipsis,
     179            2 :                 style: textTheme.numberMedium,
     180              :               ),
     181            0 :               onTap: () => onTap(context),
     182              :             ),
     183              :           ),
     184              :         ],
     185              :       ],
     186              :     );
     187              :   }
     188              : }
        

Generated by: LCOV version 2.0-1