Untitled

mail@pastecode.io avatar
unknown
plain_text
20 days ago
3.7 kB
3
Indexable
Never
import 'package:flutter/material.dart';

import '../../../../utils/logger.dart';

class ModalBottomSheetWidget extends StatefulWidget {
  final String title;
  final List<BottomSheetModel> items;
  final bool isEnableSearch;

  const ModalBottomSheetWidget({
    super.key,
    required this.title,
    required this.items,
    this.isEnableSearch = false,
  });

  @override
  State<ModalBottomSheetWidget> createState() => _ModalBottomSheetWidgetState();
}

class _ModalBottomSheetWidgetState extends State<ModalBottomSheetWidget> {
  final TextEditingController _searchController = TextEditingController();
  List<BottomSheetModel> _filteredItems = [];

  @override
  void initState() {
    super.initState();
    _filteredItems = widget.items;
    _searchController.addListener(_filterItems);
  }

  @override
  void dispose() {
    _searchController.removeListener(_filterItems);
    _searchController.dispose();
    super.dispose();
  }

  void _filterItems() {
    final query = _searchController.text.toLowerCase();
    setState(() {
      _filteredItems = widget.items.where((item) {
        return item.valueForDisplay.toLowerCase().contains(query);
      }).toList();
    });
  }

  @override
  Widget build(BuildContext context) {
    return LayoutBuilder(
      builder: (context, constraints) {
        logger.i("Constr Height ===> ${constraints.maxHeight}");

        return Container(
          constraints: widget.isEnableSearch == true
              ? BoxConstraints(maxHeight: constraints.maxHeight * 0.95, minHeight: constraints.maxHeight * 0.95)
              : BoxConstraints(maxHeight: constraints.maxHeight * 0.95),
          padding: const EdgeInsets.all(16.0),
          decoration: const BoxDecoration(
            color: Colors.white,
            borderRadius: BorderRadius.vertical(top: Radius.circular(16.0)),
          ),
          child: Column(
            mainAxisSize: MainAxisSize.min,
            children: [
              _buildHeaderSticky(widget.title),
              if (widget.isEnableSearch) _buildSearchBar(),
              const Divider(),
              // Wrap the ListView in Flexible
              Flexible(
                child: ListView.builder(
                  shrinkWrap: true,
                  itemCount: _filteredItems.length,
                  itemBuilder: (context, index) {
                    return ListTile(
                      title: Text(_filteredItems[index].valueForDisplay),
                      onTap: () {
                        Navigator.pop(context);
                      },
                    );
                  },
                ),
              ),
            ],
          ),
        );
      },
    );
  }

  Widget _buildHeaderSticky(String title) {
    return Container(
      padding: const EdgeInsets.symmetric(vertical: 16.0),
      width: double.infinity,
      child: Text(
        title,
        style: const TextStyle(
          fontSize: 20,
          fontWeight: FontWeight.bold,
        ),
        textAlign: TextAlign.center,
      ),
    );
  }

  Widget _buildSearchBar() {
    return Padding(
      padding: const EdgeInsets.symmetric(vertical: 8.0),
      child: TextField(
        controller: _searchController,
        decoration: const InputDecoration(
          hintText: 'Search...',
          border: OutlineInputBorder(),
          prefixIcon: Icon(Icons.search),
        ),
        onChanged: (value) => _filterItems(),
      ),
    );
  }
}

class BottomSheetModel {
  final String valueEn;
  final String valueTh;
  String get valueForDisplay => valueEn;

  BottomSheetModel({
    required this.valueEn,
    required this.valueTh,
  });
}
Leave a Comment