id_doc_kit 1.0.0
id_doc_kit: ^1.0.0 copied to clipboard
Indian ID validation helpers for KYC and onboarding (Aadhaar, PAN, GSTIN, DL, Voter ID, Passport + PIN/Phone/Email).
import 'package:flutter/material.dart';
import 'package:id_doc_kit/id_doc_kit.dart';
void main() {
runApp(const IdDocKitExampleApp());
}
class IdDocKitExampleApp extends StatelessWidget {
const IdDocKitExampleApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'id_doc_kit Example',
debugShowCheckedModeBanner: false,
theme: ThemeData(
useMaterial3: true,
colorScheme: ColorScheme.fromSeed(
seedColor: const Color(0xFF0F172A),
brightness: Brightness.light,
),
cardTheme: CardThemeData(
elevation: 0,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(16),
side: BorderSide(color: Colors.grey.shade200),
),
),
),
home: const ExampleHome(),
);
}
}
class ExampleHome extends StatefulWidget {
const ExampleHome({super.key});
@override
State<ExampleHome> createState() => _ExampleHomeState();
}
class _ExampleHomeState extends State<ExampleHome> {
final _formKey = GlobalKey<FormState>();
// Track results to display metadata and validation status
final Map<IdDocumentType, IdDocumentResult?> _results = {};
// For Auto-Detection Demo
IdDocumentResult? _autoDetectResult;
void _handleAutoDetect(String value) {
setState(() {
if (value.trim().isEmpty) {
_autoDetectResult = null;
} else {
_autoDetectResult = IdValidator.instance.validateAuto(value);
}
});
}
void _updateResult(IdDocumentType type, String value) {
setState(() {
if (value.trim().isEmpty) {
_results[type] = null;
} else {
_results[type] = IdValidator.instance.validate(
type: type,
value: value,
);
}
});
}
@override
Widget build(BuildContext context) {
final theme = Theme.of(context);
final colorScheme = theme.colorScheme;
return Scaffold(
appBar: AppBar(
title: const Text(
'KYC Validator Kit',
style: TextStyle(fontWeight: FontWeight.w800),
),
centerTitle: true,
),
body: Form(
key: _formKey,
child: SingleChildScrollView(
padding: const EdgeInsets.all(16),
child: Center(
child: Container(
constraints: const BoxConstraints(maxWidth: 600),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
_buildHeader(theme, colorScheme),
const SizedBox(height: 24),
_buildSectionTitle('Smart Detection'),
_buildAutoDetectField(theme),
const SizedBox(height: 24),
_buildSectionTitle('Standard Identity Documents'),
_buildIdItem(
type: IdDocumentType.aadhaar,
icon: Icons.fingerprint,
hint: '1234 5678 9012',
),
_buildIdItem(
type: IdDocumentType.pan,
icon: Icons.badge,
hint: 'ABCDE1234F',
),
_buildIdItem(
type: IdDocumentType.gstin,
icon: Icons.business,
hint: '27AAAAA0000A1Z5',
),
const SizedBox(height: 24),
_buildSectionTitle('Custom UI Pattern'),
_buildCustomUiExample(theme),
const SizedBox(height: 24),
_buildSectionTitle('Contact Information'),
_buildIdItem(
type: IdDocumentType.phone,
icon: Icons.phone_iphone,
hint: '98765 43210',
),
_buildIdItem(
type: IdDocumentType.email,
icon: Icons.alternate_email,
hint: 'user@example.com',
),
const SizedBox(height: 32),
_buildValidationSummary(colorScheme, theme),
const SizedBox(height: 40),
],
),
),
),
),
),
);
}
Widget _buildHeader(ThemeData theme, ColorScheme colorScheme) {
return Card(
color: colorScheme.primaryContainer.withValues(alpha: 0.3),
child: Padding(
padding: const EdgeInsets.all(16.0),
child: Row(
children: [
Icon(Icons.security, size: 40, color: colorScheme.primary),
const SizedBox(width: 16),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'KYC Onboarding',
style: theme.textTheme.titleMedium?.copyWith(
fontWeight: FontWeight.bold,
),
),
Text(
'Fields are automatically formatted and verified against Indian government standards.',
style: theme.textTheme.bodySmall,
),
],
),
),
],
),
),
);
}
Widget _buildSectionTitle(String title) {
return Padding(
padding: const EdgeInsets.only(left: 4, bottom: 12),
child: Text(
title,
style: const TextStyle(fontWeight: FontWeight.bold, fontSize: 16),
),
);
}
Widget _buildAutoDetectField(ThemeData theme) {
return Card(
child: Padding(
padding: const EdgeInsets.all(16),
child: Column(
children: [
TextField(
onChanged: _handleAutoDetect,
decoration: InputDecoration(
labelText: 'Paste any ID (PAN, Aadhaar, GSTIN)',
hintText: 'Detects type automatically...',
border: const OutlineInputBorder(),
prefixIcon: const Icon(Icons.auto_awesome),
suffixIcon: _autoDetectResult?.isValid == true
? const Icon(Icons.verified, color: Colors.green)
: null,
),
),
if (_autoDetectResult != null) ...[
const SizedBox(height: 12),
Row(
children: [
const Text('Detected as: ', style: TextStyle(fontSize: 12)),
Chip(
label: Text(_autoDetectResult!.type.name.toUpperCase()),
labelStyle: const TextStyle(
fontSize: 10,
fontWeight: FontWeight.bold,
),
visualDensity: VisualDensity.compact,
),
const SizedBox(width: 8),
Text(
_autoDetectResult!.isValid ? '✅ Valid' : '❌ Invalid Format',
style: TextStyle(
fontSize: 12,
color: _autoDetectResult!.isValid
? Colors.green
: Colors.red,
),
),
],
),
],
],
),
),
);
}
Widget _buildIdItem({
required IdDocumentType type,
required IconData icon,
required String hint,
}) {
final result = _results[type];
final isValid = result?.isValid ?? false;
return Padding(
padding: const EdgeInsets.only(bottom: 16),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
IdTextField(
type: type,
autoFormat: true,
decoration: InputDecoration(
labelText: type.name.toUpperCase(),
hintText: hint,
prefixIcon: Icon(icon),
border: const OutlineInputBorder(),
suffixIcon: result != null
? Icon(
isValid ? Icons.check_circle : Icons.error,
color: isValid ? Colors.green : Colors.red,
)
: null,
),
onChanged: (v) => _updateResult(type, v),
),
if (result != null)
Padding(
padding: const EdgeInsets.only(top: 4, left: 4),
child: Text(
isValid
? result.friendlyMessage
: (result.errorMessage ?? 'Invalid'),
style: TextStyle(
fontSize: 11,
color: isValid ? Colors.green : Colors.red,
fontWeight: FontWeight.w500,
),
),
),
if (isValid && result?.metadata != null)
Padding(
padding: const EdgeInsets.only(top: 4, left: 4),
child: Wrap(
spacing: 4,
children: result!.metadata!.entries
.map(
(e) => Container(
padding: const EdgeInsets.symmetric(
horizontal: 6,
vertical: 2,
),
decoration: BoxDecoration(
color: Colors.grey.withValues(alpha: 0.1),
borderRadius: BorderRadius.circular(4),
),
child: Text(
'${e.key}: ${e.value}',
style: const TextStyle(
fontSize: 10,
color: Colors.grey,
),
),
),
)
.toList(),
),
),
],
),
);
}
Widget _buildCustomUiExample(ThemeData theme) {
return IdField(
type: IdDocumentType.pinCode,
builder: (context, controller, result) {
final isValid = result?.isValid ?? false;
return Container(
padding: const EdgeInsets.all(12),
decoration: BoxDecoration(
color: theme.colorScheme.surfaceContainerHighest.withValues(
alpha: 0.3,
),
borderRadius: BorderRadius.circular(12),
border: Border.all(
color: result != null && !isValid
? Colors.red
: Colors.transparent,
),
),
child: Row(
children: [
const Icon(Icons.pin_drop),
const SizedBox(width: 12),
Expanded(
child: TextField(
controller: controller,
keyboardType: TextInputType.number,
decoration: const InputDecoration(
hintText: 'Enter 6-digit PIN',
border: InputBorder.none,
),
),
),
if (isValid) const Icon(Icons.location_on, color: Colors.green),
],
),
);
},
);
}
Widget _buildValidationSummary(ColorScheme colorScheme, ThemeData theme) {
final validCount = _results.values.where((r) => r?.isValid ?? false).length;
final totalCount = _results.length;
return Card(
color: colorScheme.primaryContainer.withValues(alpha: 0.2),
child: Padding(
padding: const EdgeInsets.all(20),
child: Column(
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
const Text(
'Completion Status',
style: TextStyle(fontWeight: FontWeight.bold),
),
Text('$validCount / $totalCount Validated'),
],
),
const SizedBox(height: 12),
LinearProgressIndicator(
value: totalCount == 0 ? 0 : validCount / totalCount,
borderRadius: BorderRadius.circular(8),
minHeight: 8,
),
const SizedBox(height: 20),
SizedBox(
width: double.infinity,
height: 54,
child: FilledButton.icon(
onPressed: () {
if (_formKey.currentState!.validate()) {
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(content: Text('All documents verified!')),
);
}
},
icon: const Icon(Icons.verified),
label: const Text(
'Confirm & Proceed',
style: TextStyle(fontWeight: FontWeight.bold, fontSize: 16),
),
),
),
],
),
),
);
}
}