From 23e94252177b5c4116055b2d7ce92c5fd57872cc Mon Sep 17 00:00:00 2001 From: gitadmin Date: Fri, 17 Oct 2025 11:44:18 +0530 Subject: [PATCH] financial changes --- lib/financials/add_transactions.dart | 53 +++--- lib/financials/financial_main_screen.dart | 207 ++++++++-------------- lib/resources/resources_drivers.dart | 63 +++++-- lib/resources/resources_fleet.dart | 70 +++++++- lib/resources/resources_sources.dart | 120 +++++++++++-- 5 files changed, 324 insertions(+), 189 deletions(-) diff --git a/lib/financials/add_transactions.dart b/lib/financials/add_transactions.dart index 63b0fc6..d01d4fe 100644 --- a/lib/financials/add_transactions.dart +++ b/lib/financials/add_transactions.dart @@ -114,8 +114,7 @@ class _AddTransactionScreenState extends State { value: transactionType, onChanged: (val) => setState(() => transactionType = val), - hintStyle: fontTextStyle( - 14, const Color(0xFF939495), FontWeight.w400), + hintStyle: fontTextStyle(14, const Color(0xFF939495), FontWeight.w400), ), const SizedBox(height: 16), fieldLabel("Account Name", requiredMark: true), @@ -124,8 +123,7 @@ class _AddTransactionScreenState extends State { items: const ["Name1", "Name2"], value: accountName, onChanged: (val) => setState(() => accountName = val), - hintStyle: fontTextStyle( - 14, const Color(0xFF939495), FontWeight.w400), + hintStyle: fontTextStyle(14, const Color(0xFF939495), FontWeight.w400), ), const SizedBox(height: 16), fieldLabel("Amount (in ₹)", requiredMark: true), @@ -140,8 +138,7 @@ class _AddTransactionScreenState extends State { .isEmpty) ? "Amount is required" : null, - hintStyle: fontTextStyle( - 14, const Color(0xFF939495), FontWeight.w400), + hintStyle: fontTextStyle(14, const Color(0xFF939495), FontWeight.w400), ), const SizedBox(height: 16), Row( @@ -162,10 +159,7 @@ class _AddTransactionScreenState extends State { value: paymentStatus, onChanged: (val) => setState(() => paymentStatus = val), - hintStyle: fontTextStyle( - 14, - const Color(0xFF939495), - FontWeight.w400), // ← styled + hintStyle: fontTextStyle(14, Color(0xFF939495), FontWeight.w400), // ← styled ), ], ), @@ -218,8 +212,8 @@ class _AddTransactionScreenState extends State { // TODO: Save handler } }, - child: const Text("Save", - style: TextStyle(fontSize: 16)), + child: Text("Save", + style:fontTextStyle(14, Color(0xFFFFFFFF), FontWeight.w600),), ), ), ], @@ -244,11 +238,14 @@ class _AddTransactionScreenState extends State { }) { return DropdownButtonFormField( value: value, - // must be null to show the hint isExpanded: true, isDense: true, + + // 👇 your custom down-arrow image + icon: Image.asset('images/downarrow.png', width: 16, height: 16), + iconSize: 16, // optional, keeps layout tight + decoration: InputDecoration( - // don't set hintText here; use the `hint:` widget below contentPadding: contentPadding ?? const EdgeInsets.symmetric(horizontal: 12, vertical: 12), ), @@ -258,15 +255,12 @@ class _AddTransactionScreenState extends State { hint, textAlign: centerHint ? TextAlign.center : TextAlign.start, style: hintStyle ?? - fontTextStyle( - 14, - const Color(0xFF939495), - FontWeight.w400), + fontTextStyle(14, const Color(0xFF939495), FontWeight.w400), ), ), - - items: - items.map((e) => DropdownMenuItem(value: e, child: Text(e))).toList(), + items: items + .map((e) => DropdownMenuItem(value: e, child: Text(e))) + .toList(), onChanged: onChanged, dropdownColor: Colors.white, validator: (v) => (v == null || v.isEmpty) ? "Required" : null, @@ -285,8 +279,7 @@ class _AddTransactionScreenState extends State { if (requiredMark) ...[ const SizedBox(width: 2), Text("*", - style: fontTextStyle( - 12, const Color(0xFFD32F2F), FontWeight.w800)), + style: fontTextStyle(12, const Color(0xFFD32F2F), FontWeight.w800)), ], ], ), @@ -301,16 +294,24 @@ class _AddTransactionScreenState extends State { }) { return DropdownButtonFormField( value: value, - decoration: InputDecoration(labelText: label), isExpanded: true, - items: - items.map((e) => DropdownMenuItem(value: e, child: Text(e))).toList(), + isDense: true, + + // 👇 same custom icon here + icon: Image.asset('images/downarrow.png', width: 16, height: 16), + iconSize: 16, + + decoration: InputDecoration(labelText: label), + items: items + .map((e) => DropdownMenuItem(value: e, child: Text(e))) + .toList(), onChanged: onChanged, dropdownColor: Colors.white, validator: (v) => (v == null || v.isEmpty) ? "Required" : null, ); } + Widget buildTextField({ required String hint, required TextEditingController controller, diff --git a/lib/financials/financial_main_screen.dart b/lib/financials/financial_main_screen.dart index 0e1743e..36418f9 100644 --- a/lib/financials/financial_main_screen.dart +++ b/lib/financials/financial_main_screen.dart @@ -244,126 +244,102 @@ class _FinancialMainScreenState extends State SizedBox(width: 4), Text( "Create Account", - style: fontTextStyle( - 14, const Color(0xFFFFFFFF), FontWeight.w400), + style: fontTextStyle(12, const Color(0xFFFFFFFF), FontWeight.w400), ), ], ), ), ), + // Account Summary (ONLY header + count) Container( padding: const EdgeInsets.all(16), decoration: BoxDecoration( color: Colors.white, borderRadius: BorderRadius.circular(16), ), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, + child: Row( + crossAxisAlignment: CrossAxisAlignment.center, children: [ - Row( + Expanded( + child: Text( + "Account Summary", + style: fontTextStyle(12, const Color(0xFF2D2E30), FontWeight.w500), + ), + ), + Column( + crossAxisAlignment: CrossAxisAlignment.end, children: [ - const Expanded( - child: Text( - "Account Summary", - style: TextStyle( - fontSize: 16, fontWeight: FontWeight.w600), - ), + Text( + "05", + style: fontTextStyle(24, const Color(0xFF0D3771), FontWeight.w500), ), - Column( - children: const [ - Text( - "05", - style: TextStyle( - fontSize: 28, - fontWeight: FontWeight.bold, - color: Colors.blue), - ), - SizedBox(height: 2), - Text( - "4 active, 1 overdue", - style: TextStyle( - fontSize: 12, - color: Colors.grey, - ), - ), - ], + const SizedBox(height: 2), + Text( + "4 active, 1 overdue", + style: fontTextStyle(10, const Color(0xFF646566), FontWeight.w400), ), ], ), - const SizedBox(height: 16), - Row( - children: [ - Expanded( - child: Container( - padding: const EdgeInsets.all(12), - decoration: BoxDecoration( - borderRadius: BorderRadius.circular(12), - color: const Color(0xfffafafa), - ), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: const [ - Text( - "Receivable Balance", - style: TextStyle( - fontSize: 12, color: Colors.black54), - ), - SizedBox(height: 4), - Text( - "₹24,000", - style: TextStyle( - fontSize: 16, - fontWeight: FontWeight.bold, - color: Colors.red), - ), - Text( - "40.6% of total credit", - style: TextStyle( - fontSize: 11, color: Colors.grey), - ), - ], - ), - ), + ], + ), + ), + + const SizedBox(height: 12), + +// NEW: Balances in a separate container/card + Container( + padding: const EdgeInsets.all(16), + + child: Row( + children: [ + Expanded( + child: Container( + padding: const EdgeInsets.all(12), + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(12), + color: const Color(0xffFFFFFF), ), - const SizedBox(width: 12), - Expanded( - child: Container( - padding: const EdgeInsets.all(12), - decoration: BoxDecoration( - borderRadius: BorderRadius.circular(12), - color: const Color(0xfffafafa), - ), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: const [ - Text( - "Advance Balance", - style: TextStyle( - fontSize: 12, color: Colors.black54), - ), - SizedBox(height: 4), - Text( - "₹24,000", - style: TextStyle( - fontSize: 16, - fontWeight: FontWeight.bold, - color: Colors.green), - ), - Text( - "60.4% of total credit", - style: TextStyle( - fontSize: 11, color: Colors.grey), - ), - ], - ), - ), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text("Receivable Balance", + style: fontTextStyle(12, Color(0xFF2D2E30), FontWeight.w500)), + const SizedBox(height: 4), + Text("₹24,000", + style: fontTextStyle(16, Color(0xFFE2483D), FontWeight.w500)), + Text("40.6% of total credit", + style: fontTextStyle(10, Color(0xFF646566), FontWeight.w400)), + ], ), - ], + ), + ), + const SizedBox(width: 12), + Expanded( + child: Container( + padding: const EdgeInsets.all(12), + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(12), + color: const Color(0xffFFFFFF), + ), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text("Advance Balance", + style: fontTextStyle(12, Color(0xFF2D2E30), FontWeight.w500)), + const SizedBox(height: 4), + Text("₹24,000", + style: fontTextStyle(16, Color(0xFFE2483D), FontWeight.w500)), + Text("60.4% of total credit", + style: fontTextStyle(10, Color(0xFF646566), FontWeight.w400)), + ], + ), + ), ), ], ), ), + const SizedBox(height: 20), // Search Bar @@ -386,13 +362,13 @@ class _FinancialMainScreenState extends State ), ), ), - IconButton( - onPressed: () {}, - icon: const Icon(Icons.sort, color: Colors.grey), - ), + Image.asset("images/icon_tune.png", width: 24, height: 24), + const SizedBox(width: 16), + Image.asset("images/up_down arrow.png", width: 24, height: 24), ], ), ), + const SizedBox(height: 20), // Accounts List @@ -462,36 +438,7 @@ class _FinancialMainScreenState extends State crossAxisAlignment: CrossAxisAlignment.start, children: [ // Name + Status - Row( - children: [ - Expanded( - child: Text( - name, - style: const TextStyle( - fontSize: 16, fontWeight: FontWeight.bold), - ), - ), - Container( - padding: - const EdgeInsets.symmetric(horizontal: 8, vertical: 4), - decoration: BoxDecoration( - color: status == "active" - ? Colors.green.withOpacity(0.1) - : Colors.red.withOpacity(0.1), - borderRadius: BorderRadius.circular(12), - ), - child: Text( - status, - style: TextStyle( - color: - status == "active" ? Colors.green : Colors.redAccent, - fontSize: 12, - fontWeight: FontWeight.w500, - ), - ), - ) - ], - ), + Row( children: [ Expanded( child: Text( name, style: fontTextStyle(14, Color(0xFF2D2E30), FontWeight.w500)), ), Container( padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 4), decoration: BoxDecoration( color: status == "active" ? Colors.green.withOpacity(0.1) : Colors.red.withOpacity(0.1), borderRadius: BorderRadius.circular(12), ), child: Text( status, style: TextStyle( color: status == "active" ? Colors.green : Colors.redAccent, fontSize: 12, fontWeight: FontWeight.w500, ), ), ) ], ), const SizedBox(height: 4), Text( orders, diff --git a/lib/resources/resources_drivers.dart b/lib/resources/resources_drivers.dart index 5961e88..50815d7 100644 --- a/lib/resources/resources_drivers.dart +++ b/lib/resources/resources_drivers.dart @@ -4,6 +4,35 @@ import 'package:flutter/services.dart'; import 'package:supplier_new/common/settings.dart'; import 'package:supplier_new/resources/drivers_model.dart'; +class FirstCharUppercaseFormatter extends TextInputFormatter { + const FirstCharUppercaseFormatter(); + + @override + TextEditingValue formatEditUpdate( + TextEditingValue oldValue, + TextEditingValue newValue, + ) { + final text = newValue.text; + if (text.isEmpty) return newValue; + + // Find first non-space char + final i = text.indexOf(RegExp(r'\S')); + if (i == -1) return newValue; + + final first = text[i]; + final upper = first.toUpperCase(); + if (first == upper) return newValue; + + final newText = text.replaceRange(i, i + 1, upper); + + return newValue.copyWith( + text: newText, + selection: newValue.selection, + composing: TextRange.empty, + ); + } +} + class ResourcesDriverScreen extends StatefulWidget { const ResourcesDriverScreen({super.key}); @@ -145,11 +174,11 @@ class _ResourcesDriverScreenState extends State { } // ---------- bottom sheet ---------- - void _openDriverFormSheet(BuildContext context) { - _resetForm(); // fresh form every time - showModalBottomSheet( + Future _openDriverFormSheet(BuildContext context)async { + + await showModalBottomSheet( context: context, - isScrollControlled: true, // allow content to move for keyboard + isScrollControlled: true, backgroundColor: Colors.transparent, // style inner container builder: (context) { final bottomInset = MediaQuery.of(context).viewInsets.bottom; @@ -175,7 +204,7 @@ class _ResourcesDriverScreenState extends State { Expanded( child: Center( child: Container( - width: 36, + width: 86, height: 4, margin: const EdgeInsets.only(bottom: 12), decoration: BoxDecoration( @@ -185,10 +214,6 @@ class _ResourcesDriverScreenState extends State { ), ), ), - IconButton( - onPressed: () => Navigator.pop(context), - icon: const Icon(Icons.close), - ), ], ), @@ -197,6 +222,10 @@ class _ResourcesDriverScreenState extends State { child: TextFormField( controller: _nameCtrl, validator: (v) => _required(v, field: "Driver Name"), + textCapitalization: TextCapitalization.none, + inputFormatters: const [ + FirstCharUppercaseFormatter(), // << live first-letter caps + ], decoration: InputDecoration( hintText: "Full Name", hintStyle: fontTextStyle(14, const Color(0xFF939495), FontWeight.w400), @@ -303,6 +332,10 @@ class _ResourcesDriverScreenState extends State { child: TextFormField( controller: _locationCtrl, validator: (v) => _required(v, field: "Location"), + textCapitalization: TextCapitalization.none, + inputFormatters: const [ + FirstCharUppercaseFormatter(), // << live first-letter caps + ], decoration: InputDecoration( hintText: "Area / locality", hintStyle: fontTextStyle(14, const Color(0xFF939495), FontWeight.w400), @@ -679,7 +712,12 @@ class _LabeledField extends StatelessWidget { final String label; final Widget child; const _LabeledField({required this.label, required this.child}); - + String _capFirstWord(String input) { + if (input.isEmpty) return input; + final i = input.indexOf(RegExp(r'\S')); + if (i == -1) return input; + return input.replaceRange(i, i + 1, input[i].toUpperCase()); + } @override Widget build(BuildContext context) { return Padding( @@ -687,7 +725,10 @@ class _LabeledField extends StatelessWidget { child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - Text(label, style: fontTextStyle(12, const Color(0xFF515253), FontWeight.w600)), + Text( + _capFirstWord(label), + style: fontTextStyle(12, const Color(0xFF515253), FontWeight.w600), + ), const SizedBox(height: 6), child, ], diff --git a/lib/resources/resources_fleet.dart b/lib/resources/resources_fleet.dart index ea1d4dc..a32e38b 100644 --- a/lib/resources/resources_fleet.dart +++ b/lib/resources/resources_fleet.dart @@ -3,12 +3,38 @@ import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:supplier_new/common/settings.dart'; import 'package:supplier_new/resources/tankers_model.dart'; - -// Screens (single import each) – keep if you actually navigate to these import 'fleet.dart'; import 'resources_drivers.dart'; import 'resources_sources.dart'; +class FirstCharUppercaseFormatter extends TextInputFormatter { + const FirstCharUppercaseFormatter(); + + @override + TextEditingValue formatEditUpdate( + TextEditingValue oldValue, + TextEditingValue newValue, + ) { + final text = newValue.text; + if (text.isEmpty) return newValue; + + // Find first non-space char + final i = text.indexOf(RegExp(r'\S')); + if (i == -1) return newValue; + + final first = text[i]; + final upper = first.toUpperCase(); + if (first == upper) return newValue; + + final newText = text.replaceRange(i, i + 1, upper); + + return newValue.copyWith( + text: newText, + selection: newValue.selection, + composing: TextRange.empty, + ); + } +} void main() => runApp(const MaterialApp(home: ResourcesFleetScreen())); class ResourcesFleetScreen extends StatefulWidget { @@ -169,10 +195,8 @@ class _ResourcesFleetScreenState extends State { } } - void openTankerSimpleSheet(BuildContext context) { - _resetForm(); // open fresh - - showModalBottomSheet( + Future openTankerSimpleSheet(BuildContext context) async { + await showModalBottomSheet( context: context, isScrollControlled: true, backgroundColor: Colors.transparent, @@ -194,11 +218,33 @@ class _ResourcesFleetScreenState extends State { child: Column( crossAxisAlignment: CrossAxisAlignment.stretch, children: [ + Row( + children: [ + Expanded( + child: Center( + child: Container( + width: 86, + height: 4, + margin: const EdgeInsets.only(bottom: 12), + decoration: BoxDecoration( + color: const Color(0xFFE0E0E0), + borderRadius: BorderRadius.circular(2), + ), + ), + ), + ), + ], + ), + _LabeledField( label: "Tanker Name *", child: TextFormField( controller: _nameCtrl, validator: (v) => _required(v, field: "Tanker Name"), + textCapitalization: TextCapitalization.none, + inputFormatters: const [ + FirstCharUppercaseFormatter(), // << live first-letter caps + ], decoration: InputDecoration( hintText: "Enter Tanker Name", hintStyle: fontTextStyle(14, const Color(0xFF939495), FontWeight.w400), @@ -722,6 +768,13 @@ class _LabeledField extends StatelessWidget { const _LabeledField({required this.label, required this.child}); + String _capFirstWord(String input) { + if (input.isEmpty) return input; + final i = input.indexOf(RegExp(r'\S')); + if (i == -1) return input; + return input.replaceRange(i, i + 1, input[i].toUpperCase()); + } + @override Widget build(BuildContext context) { return Padding( @@ -729,7 +782,10 @@ class _LabeledField extends StatelessWidget { child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - Text(label, style: fontTextStyle(12, const Color(0xFF515253), FontWeight.w600)), + Text( + _capFirstWord(label), + style: fontTextStyle(12, const Color(0xFF515253), FontWeight.w600), + ), const SizedBox(height: 6), child, ], diff --git a/lib/resources/resources_sources.dart b/lib/resources/resources_sources.dart index 58f749a..ff815a7 100644 --- a/lib/resources/resources_sources.dart +++ b/lib/resources/resources_sources.dart @@ -4,12 +4,42 @@ import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:supplier_new/common/settings.dart'; import 'package:supplier_new/resources/source_loctaions_model.dart'; +import '../google_maps_place_picker_mb/src/models/pick_result.dart'; +import '../google_maps_place_picker_mb/src/place_picker.dart'; +import 'package:supplier_new/google_maps_place_picker_mb/google_maps_place_picker.dart'; +import 'dart:io' show File, Platform; +import 'package:google_maps_flutter_android/google_maps_flutter_android.dart'; +import 'package:google_maps_flutter_platform_interface/google_maps_flutter_platform_interface.dart'; +import 'package:location/location.dart' as locationmap; -// If you use the PlacePicker flow in the button below, make sure you have -// the needed imports in your project (google_maps_flutter, place_picker, etc). -// import 'package:google_maps_flutter/google_maps_flutter.dart'; -// import 'package:place_picker/place_picker.dart'; -// import 'package:location/location.dart'; +class FirstCharUppercaseFormatter extends TextInputFormatter { + const FirstCharUppercaseFormatter(); + + @override + TextEditingValue formatEditUpdate( + TextEditingValue oldValue, + TextEditingValue newValue, + ) { + final text = newValue.text; + if (text.isEmpty) return newValue; + + // Find first non-space char + final i = text.indexOf(RegExp(r'\S')); + if (i == -1) return newValue; + + final first = text[i]; + final upper = first.toUpperCase(); + if (first == upper) return newValue; + + final newText = text.replaceRange(i, i + 1, upper); + + return newValue.copyWith( + text: newText, + selection: newValue.selection, + composing: TextRange.empty, + ); + } +} void main() => runApp(const MaterialApp(home: ResourcesSourceScreen())); @@ -20,6 +50,38 @@ class ResourcesSourceScreen extends StatefulWidget { State createState() => _ResourcesSourceScreenState(); } +PickResult? selectedPlace; + +bool _mapsInitialized = false; +final String _mapsRenderer = "latest"; + +var kInitialPosition = const LatLng(15.462477, 78.717401); + +locationmap.Location location = locationmap.Location(); + +final GoogleMapsFlutterPlatform mapsImplementation = + GoogleMapsFlutterPlatform.instance; + +void initRenderer() { + if (_mapsInitialized) return; + if (mapsImplementation is GoogleMapsFlutterAndroid) { + switch (_mapsRenderer) { + case "legacy": + (mapsImplementation as GoogleMapsFlutterAndroid) + .initializeWithRenderer(AndroidMapRenderer.legacy); + break; + case "latest": + (mapsImplementation as GoogleMapsFlutterAndroid) + .initializeWithRenderer(AndroidMapRenderer.latest); + break; + } + } + // setState(() { + // _mapsInitialized = true; + // }); +} + + class _ResourcesSourceScreenState extends State { int selectedTab = 2; String search = ''; @@ -35,9 +97,6 @@ class _ResourcesSourceScreenState extends State { String? selectedWaterType; final List waterTypes = const ['Drinking water', 'Bore water', 'Both']; - // Optional: values used by your map flow - // final location = Location(); // from 'location' package - // PickResult? selectedPlace; double? lat; double? lng; String? address; @@ -146,12 +205,11 @@ class _ResourcesSourceScreenState extends State { } } - void _openSourceFormSheet(BuildContext context) { - _resetForm(); // fresh form each time you open - showModalBottomSheet( - context: context, - isScrollControlled: true, - backgroundColor: Colors.transparent, + Future _openSourceFormSheet(BuildContext context)async { + await showModalBottomSheet( + context: context, + isScrollControlled: true, + backgroundColor: Colors.transparent, builder: (context) { final kbInset = MediaQuery.of(context).viewInsets.bottom; return FractionallySizedBox( @@ -169,11 +227,33 @@ class _ResourcesSourceScreenState extends State { child: Column( crossAxisAlignment: CrossAxisAlignment.stretch, children: [ + Row( + children: [ + Expanded( + child: Center( + child: Container( + width: 86, + height: 4, + margin: const EdgeInsets.only(bottom: 12), + decoration: BoxDecoration( + color: const Color(0xFFE0E0E0), + borderRadius: BorderRadius.circular(2), + ), + ), + ), + ), + ], + ), + _LabeledField( label: "Location Name *", child: TextFormField( controller: _locationNameController, validator: (v) => _required(v, field: "Location Name"), + textCapitalization: TextCapitalization.none, + inputFormatters: const [ + FirstCharUppercaseFormatter(), // << live first-letter caps + ], decoration: InputDecoration( hintText: "Location Name", hintStyle: fontTextStyle(14, const Color(0xFF939495), FontWeight.w400), @@ -634,6 +714,13 @@ class _LabeledField extends StatelessWidget { const _LabeledField({required this.label, required this.child}); + String _capFirstWord(String input) { + if (input.isEmpty) return input; + final i = input.indexOf(RegExp(r'\S')); + if (i == -1) return input; + return input.replaceRange(i, i + 1, input[i].toUpperCase()); + } + @override Widget build(BuildContext context) { return Padding( @@ -641,7 +728,10 @@ class _LabeledField extends StatelessWidget { child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - Text(label, style: fontTextStyle(12, const Color(0xFF515253), FontWeight.w600)), + Text( + _capFirstWord(label), + style: fontTextStyle(12, const Color(0xFF515253), FontWeight.w600), + ), const SizedBox(height: 6), child, ],