bangladesh_geo_postcode 1.0.0 copy "bangladesh_geo_postcode: ^1.0.0" to clipboard
bangladesh_geo_postcode: ^1.0.0 copied to clipboard

Offline Bangladesh geographic postcode lookup with Division, District, Thana and Postcode search. Supports Bangla and English. Uses Protocol Buffers for fast loading.

example/lib/main.dart

import 'package:flutter/material.dart';
import 'package:bangladesh_geo_postcode/bangladesh_geo_postcode.dart';

void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  await LocationCache.instance.load();
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'BD Geo Postcode',
      debugShowCheckedModeBanner: false,
      theme: ThemeData(
        colorSchemeSeed: Colors.green,
        useMaterial3: true,
      ),
      home: const HomePage(),
    );
  }
}

class HomePage extends StatefulWidget {
  const HomePage({super.key});

  @override
  State<HomePage> createState() => _HomePageState();
}

class _HomePageState extends State<HomePage>
    with SingleTickerProviderStateMixin {
  static const _service = LocationService();

  late final TabController _tabController;

  // ── Browse tab state ────────────────────────────────────────────────
  Language _lang = Language.en;

  String? _selectedDivision;
  String? _selectedDistrict;
  String? _selectedThana;

  List<String> _divisions = [];
  List<String> _districts = [];
  List<String> _thanas = [];
  List<Location> _results = [];

  // ── Search tab state ────────────────────────────────────────────────
  final _searchController = TextEditingController();
  List<Location> _searchResults = [];
  String? _searchMessage;

  @override
  void initState() {
    super.initState();
    _tabController = TabController(length: 2, vsync: this);
    _loadDivisions();
  }

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

  // ── Data loading ────────────────────────────────────────────────────

  void _loadDivisions() {
    setState(() {
      _divisions = _service.getDivisions(_lang);
      _selectedDivision = null;
      _selectedDistrict = null;
      _selectedThana = null;
      _districts = [];
      _thanas = [];
      _results = [];
    });
  }

  void _onDivisionChanged(String? value) {
    if (value == null) {
      return;
    }
    setState(() {
      _selectedDivision = value;
      _selectedDistrict = null;
      _selectedThana = null;
      _districts = _service.getDistricts(value, _lang);
      _thanas = [];
      _results = _service.getPostcodesByDivision(value, lang: _lang);
    });
  }

  void _onDistrictChanged(String? value) {
    if (value == null || _selectedDivision == null) {
      return;
    }
    setState(() {
      _selectedDistrict = value;
      _selectedThana = null;
      _thanas = _service.getThanas(_selectedDivision!, value, _lang);
      _results = _service.getPostcodesByDistrict(
        _selectedDivision!,
        value,
        lang: _lang,
      );
    });
  }

  void _onThanaChanged(String? value) {
    if (value == null ||
        _selectedDivision == null ||
        _selectedDistrict == null) return;
    setState(() {
      _selectedThana = value;
      _results = _service.getPostcodesByThana(
        _selectedDivision!,
        _selectedDistrict!,
        value,
        lang: _lang,
      );
    });
  }

  void _toggleLanguage() {
    setState(() {
      _lang = _lang == Language.en ? Language.bn : Language.en;
    });
    _loadDivisions();
  }

  void _onSearch() {
    final query = _searchController.text.trim();
    if (query.isEmpty) {
      return;
    }

    final all = LocationCache.instance.searchAllByPostcode(query);
    setState(() {
      _searchResults = all;
      _searchMessage =
          all.isEmpty ? 'No results found for "$query"' : null;
    });
  }

  // ── Build ───────────────────────────────────────────────────────────

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('BD Geo Postcode'),
        actions: [
          TextButton.icon(
            onPressed: _toggleLanguage,
            icon: const Icon(Icons.language),
            label: Text(_lang == Language.en ? 'BN' : 'EN'),
          ),
        ],
        bottom: TabBar(
          controller: _tabController,
          tabs: const [
            Tab(text: 'Browse', icon: Icon(Icons.location_on)),
            Tab(text: 'Search', icon: Icon(Icons.search)),
          ],
        ),
      ),
      body: TabBarView(
        controller: _tabController,
        children: [
          _buildBrowseTab(),
          _buildSearchTab(),
        ],
      ),
    );
  }

  // ── Browse tab ──────────────────────────────────────────────────────

  Widget _buildBrowseTab() {
    return Column(
      children: [
        Padding(
          padding: const EdgeInsets.all(12),
          child: Column(
            children: [
              _buildDropdown(
                label: _lang == Language.en ? 'Division' : 'বিভাগ',
                value: _selectedDivision,
                items: _divisions,
                onChanged: _onDivisionChanged,
              ),
              const SizedBox(height: 8),
              _buildDropdown(
                label: _lang == Language.en ? 'District' : 'জেলা',
                value: _selectedDistrict,
                items: _districts,
                onChanged: _onDistrictChanged,
              ),
              const SizedBox(height: 8),
              _buildDropdown(
                label: _lang == Language.en ? 'Thana' : 'থানা',
                value: _selectedThana,
                items: _thanas,
                onChanged: _onThanaChanged,
              ),
            ],
          ),
        ),
        Padding(
          padding: const EdgeInsets.symmetric(horizontal: 12),
          child: Row(
            children: [
              Text(
                '${_results.length} results',
                style: Theme.of(context).textTheme.bodySmall,
              ),
            ],
          ),
        ),
        const Divider(),
        Expanded(child: _buildResultsList(_results)),
      ],
    );
  }

  Widget _buildDropdown({
    required String label,
    required String? value,
    required List<String> items,
    required ValueChanged<String?> onChanged,
  }) {
    return DropdownButtonFormField<String>(
      decoration: InputDecoration(
        labelText: label,
        border: const OutlineInputBorder(),
        contentPadding:
            const EdgeInsets.symmetric(horizontal: 12, vertical: 10),
      ),
      initialValue: value,
      isExpanded: true,
      items: items
          .map((e) => DropdownMenuItem(value: e, child: Text(e)))
          .toList(),
      onChanged: onChanged,
    );
  }

  // ── Search tab ──────────────────────────────────────────────────────

  Widget _buildSearchTab() {
    return Column(
      children: [
        Padding(
          padding: const EdgeInsets.all(12),
          child: Row(
            children: [
              Expanded(
                child: TextField(
                  controller: _searchController,
                  keyboardType: TextInputType.number,
                  decoration: InputDecoration(
                    labelText:
                        _lang == Language.en ? 'Postcode' : 'পোস্টকোড',
                    hintText: _lang == Language.en ? '1206' : '১২০৬',
                    border: const OutlineInputBorder(),
                    contentPadding: const EdgeInsets.symmetric(
                        horizontal: 12, vertical: 10),
                  ),
                  onSubmitted: (_) => _onSearch(),
                ),
              ),
              const SizedBox(width: 8),
              FilledButton(
                onPressed: _onSearch,
                child: const Text('Search'),
              ),
            ],
          ),
        ),
        if (_searchMessage != null)
          Padding(
            padding: const EdgeInsets.all(16),
            child: Text(
              _searchMessage!,
              style: Theme.of(context)
                  .textTheme
                  .bodyMedium
                  ?.copyWith(color: Colors.grey),
            ),
          ),
        Expanded(child: _buildResultsList(_searchResults)),
      ],
    );
  }

  // ── Shared result list ──────────────────────────────────────────────

  Widget _buildResultsList(List<Location> locations) {
    if (locations.isEmpty) {
      return const Center(
        child: Text('Select a filter or search a postcode'),
      );
    }
    return ListView.separated(
      itemCount: locations.length,
      separatorBuilder: (_, __) => const Divider(height: 1),
      itemBuilder: (_, i) {
        final loc = locations[i];
        final isEn = _lang == Language.en;
        return ListTile(
          leading: CircleAvatar(
            child: Text(
              isEn ? loc.postcodeEn : loc.postcodeBn,
              style: const TextStyle(fontSize: 12),
            ),
          ),
          title: Text(
            isEn ? loc.subofficeEn : loc.subofficeBn,
          ),
          subtitle: Text(
            isEn
                ? '${loc.thanaEn}, ${loc.districtEn}, ${loc.divisionEn}'
                : '${loc.thanaBn}, ${loc.districtBn}, ${loc.divisionBn}',
          ),
        );
      },
    );
  }
}
0
likes
160
points
77
downloads

Documentation

API reference

Publisher

verified publisherpritom.me

Weekly Downloads

Offline Bangladesh geographic postcode lookup with Division, District, Thana and Postcode search. Supports Bangla and English. Uses Protocol Buffers for fast loading.

Repository (GitHub)
View/report issues

Topics

#bangladesh #postcode #bangla #localization #protobuf

License

MIT (license)

Dependencies

flutter, protobuf

More

Packages that depend on bangladesh_geo_postcode