nigerian_network_detector 1.0.0
nigerian_network_detector: ^1.0.0 copied to clipboard
A lightweight, zero-dependency Dart package for detecting the mobile network carrier of Nigerian phone numbers. Supports MTN, Airtel, Glo, and 9mobile with automatic format normalisation.
example/lib/main.dart
import 'package:flutter/material.dart';
import 'package:nigerian_network_detector/nigerian_network_detector.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Nigerian Network Detector',
theme: ThemeData(
colorScheme: ColorScheme.fromSeed(
seedColor: Colors.green,
brightness: Brightness.light,
),
useMaterial3: true,
),
darkTheme: ThemeData(
colorScheme: ColorScheme.fromSeed(
seedColor: Colors.green,
brightness: Brightness.dark,
),
useMaterial3: true,
),
home: const HomeScreen(),
);
}
}
class HomeScreen extends StatefulWidget {
const HomeScreen({super.key});
@override
State<HomeScreen> createState() => _HomeScreenState();
}
class _HomeScreenState extends State<HomeScreen> {
final TextEditingController _controller = TextEditingController();
NigerianNetworkResult? _result;
void _onChanged(String value) {
setState(() {
if (value.isEmpty) {
_result = null;
} else {
_result = NigerianNetworkDetector.detect(value);
}
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Naija Network Detector'),
centerTitle: true,
),
body: SingleChildScrollView(
padding: const EdgeInsets.all(24.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
const Text(
'Enter a Nigerian phone number to detect its network carrier.',
textAlign: TextAlign.center,
style: TextStyle(fontSize: 16, color: Colors.grey),
),
const SizedBox(height: 32),
TextField(
controller: _controller,
onChanged: _onChanged,
keyboardType: TextInputType.phone,
decoration: InputDecoration(
labelText: 'Phone Number',
hintText: 'e.g., 08031234567 or +234...',
prefixIcon: const Icon(Icons.phone),
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(16),
),
filled: true,
),
),
const SizedBox(height: 40),
if (_result != null) _buildResultCard(),
],
),
),
);
}
Widget _buildResultCard() {
final isSuccess = _result!.isValid;
return AnimatedContainer(
duration: const Duration(milliseconds: 300),
padding: const EdgeInsets.all(20),
decoration: BoxDecoration(
color: Theme.of(context).colorScheme.surfaceVariant.withValues(alpha: 0.5),
borderRadius: BorderRadius.circular(24),
border: Border.all(
color: isSuccess
? Colors.green.withValues(alpha: 0.5)
: Colors.red.withValues(alpha: 0.5),
width: 2,
),
),
child: Column(
children: [
Icon(
isSuccess ? Icons.check_circle_outline : Icons.error_outline,
size: 48,
color: isSuccess ? Colors.green : Colors.red,
),
const SizedBox(height: 16),
if (isSuccess) ...[
Text(
_result!.network.toString().split('.').last.toUpperCase(),
style: const TextStyle(
fontSize: 28,
fontWeight: FontWeight.bold,
letterSpacing: 1.2,
),
),
const SizedBox(height: 8),
const Divider(),
_buildInfoRow('Normalized', _result!.normalized ?? '-'),
_buildInfoRow('International', _result!.international ?? '-'),
_buildInfoRow('Prefix', _result!.prefix ?? '-'),
] else ...[
const Text(
'Invalid Number',
style: TextStyle(
fontSize: 20,
fontWeight: FontWeight.bold,
color: Colors.red,
),
),
const SizedBox(height: 8),
Text(
_result!.error ?? 'Unknown error',
textAlign: TextAlign.center,
),
],
],
),
);
}
Widget _buildInfoRow(String label, String value) {
return Padding(
padding: const EdgeInsets.symmetric(vertical: 4.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(label, style: const TextStyle(fontWeight: FontWeight.w500)),
Text(value, style: const TextStyle(fontFamily: 'monospace')),
],
),
);
}
}