tbdc_flutter_plugin 3.0.0
tbdc_flutter_plugin: ^3.0.0 copied to clipboard
Plugin of TBDC Company with helper classes and UI Components for Flutter
example/lib/main.dart
import 'package:flutter/material.dart';
import 'package:flutter_localizations/flutter_localizations.dart';
import 'package:tbdc_flutter_plugin/components/phone_input/tbdc_phone_input.dart';
import 'package:tbdc_flutter_plugin/components/phone_input/countries.dart';
import 'package:tbdc_flutter_plugin/helpers/compare_lists_of_object.dart';
import 'package:tbdc_flutter_plugin/l10n/translate.dart';
void main() {
runApp(const TBDCPluginExampleApp());
}
class TBDCPluginExampleApp extends StatelessWidget {
const TBDCPluginExampleApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'TBDC Flutter Plugin Example',
theme: ThemeData(
primarySwatch: Colors.blue,
useMaterial3: true,
),
locale: const Locale('pt', 'BR'),
localizationsDelegates: [
GlobalMaterialLocalizations.delegate,
GlobalWidgetsLocalizations.delegate,
GlobalCupertinoLocalizations.delegate,
...TBDCPluginTranslate.localizationsDelegates(),
],
supportedLocales: const [
Locale('pt', 'BR'),
Locale('en', 'US'),
Locale('es', 'ES'),
],
builder: (context, child) {
TBDCPluginTranslate.setInstances(context);
return child!;
},
home: const ExampleHomePage(),
);
}
}
class ExampleHomePage extends StatefulWidget {
const ExampleHomePage({super.key});
@override
State<ExampleHomePage> createState() => _ExampleHomePageState();
}
class _ExampleHomePageState extends State<ExampleHomePage> {
int _currentIndex = 0;
final List<Widget> _pages = [
const PhoneInputExamplePage(),
const CompareListsExamplePage(),
];
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('TBDC Flutter Plugin Example'),
backgroundColor: Theme.of(context).colorScheme.inversePrimary,
),
body: _pages[_currentIndex],
bottomNavigationBar: BottomNavigationBar(
currentIndex: _currentIndex,
onTap: (index) {
setState(() {
_currentIndex = index;
});
},
items: const [
BottomNavigationBarItem(
icon: Icon(Icons.phone),
label: 'Phone Input',
),
BottomNavigationBarItem(
icon: Icon(Icons.compare_arrows),
label: 'Compare Lists',
),
],
),
);
}
}
class PhoneInputExamplePage extends StatefulWidget {
const PhoneInputExamplePage({super.key});
@override
State<PhoneInputExamplePage> createState() => _PhoneInputExamplePageState();
}
class _PhoneInputExamplePageState extends State<PhoneInputExamplePage> {
String? _controlledPhone;
TBDCPhoneInputValue? _controlledSnapshot;
String? _prefilledPhone = '5511912345678';
TBDCPhoneInputValue? _prefilledSnapshot;
final List<String> _phoneHistory = [];
Country get _usCountry =>
countries.firstWhere((country) => country.acronym == 'US');
@override
Widget build(BuildContext context) {
return Scaffold(
body: SingleChildScrollView(
padding: const EdgeInsets.all(16.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const Text(
'TBDCPhoneInput Examples',
style: TextStyle(
fontSize: 24,
fontWeight: FontWeight.bold,
),
),
const SizedBox(height: 20),
const Text(
'1. Basic Phone Input',
style: TextStyle(
fontSize: 18,
fontWeight: FontWeight.w600,
),
),
const SizedBox(height: 8),
TBDCPhoneInput(
title: 'Enter your phone number',
value: _controlledPhone,
onChanged: (snapshot) {
setState(() {
_controlledPhone = snapshot.e164;
_controlledSnapshot = snapshot;
});
},
),
const SizedBox(height: 8),
Text(
'Latest E.164 value: ${_controlledSnapshot?.e164WithPlus ?? 'None'}',
style: const TextStyle(fontSize: 12, color: Colors.grey),
),
const SizedBox(height: 4),
Text(
'Formatted number: ${_controlledSnapshot != null && _controlledSnapshot!.formattedNumber.isNotEmpty ? _controlledSnapshot!.formattedNumber : 'None'}',
style: const TextStyle(fontSize: 12, color: Colors.grey),
),
const SizedBox(height: 4),
Text(
'Is complete: ${_controlledSnapshot?.isComplete == true ? 'Yes' : 'No'}',
style: const TextStyle(fontSize: 12, color: Colors.grey),
),
const SizedBox(height: 16),
const Text(
'2. Phone Input with Initial Value',
style: TextStyle(
fontSize: 18,
fontWeight: FontWeight.w600,
),
),
const SizedBox(height: 8),
TBDCPhoneInput(
title: 'Phone with initial value',
value: _prefilledPhone,
initialCountry: _usCountry,
onChanged: (snapshot) {
setState(() {
_prefilledPhone = snapshot.e164;
_prefilledSnapshot = snapshot;
});
},
),
const SizedBox(height: 8),
Row(
children: [
ElevatedButton(
onPressed: () {
setState(() {
_prefilledPhone = '5511987654321';
});
},
child: const Text('Set BR sample number'),
),
const SizedBox(width: 12),
OutlinedButton(
onPressed: () {
setState(() {
_prefilledPhone = '14155550125';
});
},
child: const Text('Set US sample number'),
),
],
),
const SizedBox(height: 8),
Text(
'Current preset: ${_prefilledSnapshot != null && _prefilledSnapshot!.formattedNumber.isNotEmpty ? _prefilledSnapshot!.formattedNumber : (_prefilledPhone ?? 'None')}',
style: const TextStyle(fontSize: 12, color: Colors.grey),
),
const SizedBox(height: 20),
if (_phoneHistory.isNotEmpty) ...[
const Text(
'Phone History:',
style: TextStyle(
fontSize: 18,
fontWeight: FontWeight.w600,
),
),
const SizedBox(height: 8),
...(_phoneHistory.map((phone) => Padding(
padding: const EdgeInsets.symmetric(vertical: 4),
child: Text('• $phone'),
))),
],
const SizedBox(height: 20),
ElevatedButton(
onPressed: _controlledSnapshot?.isComplete == true
? () {
final formatted =
_controlledSnapshot!.formattedNumber.isNotEmpty
? _controlledSnapshot!.formattedNumber
: _controlledSnapshot!.localDigits;
final e164 =
_controlledSnapshot!.e164WithPlus ?? 'No E.164';
setState(() {
_phoneHistory.add('$formatted • $e164');
});
}
: null,
child: const Text('Add to History'),
),
],
),
),
);
}
}
class CompareListsExamplePage extends StatefulWidget {
const CompareListsExamplePage({super.key});
@override
State<CompareListsExamplePage> createState() =>
_CompareListsExamplePageState();
}
class _CompareListsExamplePageState extends State<CompareListsExamplePage> {
final List<User> _oldList = [
User(id: '1', name: 'João Silva', email: 'joao@email.com'),
User(id: '2', name: 'Maria Santos', email: 'maria@email.com'),
User(id: '3', name: 'Pedro Costa', email: 'pedro@email.com'),
];
final List<User> _newList = [
User(id: '1', name: 'João Silva', email: 'joao.novo@email.com'),
User(id: '2', name: 'Maria Santos', email: 'maria@email.com'),
User(id: '4', name: 'Ana Oliveira', email: 'ana@email.com'),
];
CompareListsOfObjectResult<User>? _syncResult;
CompareListsOfObjectResult<User>? _asyncResult;
bool _isLoading = false;
@override
void initState() {
super.initState();
_compareLists();
}
void _compareLists() {
_syncResult = CompareListsOfObject.compare(
oldList: _oldList,
newList: _newList,
fieldId: 'id',
);
_performAsyncComparison();
}
Future<void> _performAsyncComparison() async {
setState(() {
_isLoading = true;
});
try {
_asyncResult = await CompareListsOfObject.compareAsync(
oldList: _oldList,
newList: _newList,
fieldId: 'id',
);
} catch (e) {
print('Erro na comparação assíncrona: $e');
} finally {
setState(() {
_isLoading = false;
});
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: SingleChildScrollView(
padding: const EdgeInsets.all(16.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const Text(
'CompareListsOfObject Examples',
style: TextStyle(
fontSize: 24,
fontWeight: FontWeight.bold,
),
),
const SizedBox(height: 20),
const Text(
'Old List:',
style: TextStyle(
fontSize: 18,
fontWeight: FontWeight.w600,
),
),
const SizedBox(height: 8),
...(_oldList
.map((user) => _buildUserCard(user, Colors.blue.shade50))),
const SizedBox(height: 16),
const Text(
'New List:',
style: TextStyle(
fontSize: 18,
fontWeight: FontWeight.w600,
),
),
const SizedBox(height: 8),
...(_newList
.map((user) => _buildUserCard(user, Colors.green.shade50))),
const SizedBox(height: 20),
if (_syncResult != null) ...[
const Text(
'Synchronous Comparison Results:',
style: TextStyle(
fontSize: 18,
fontWeight: FontWeight.w600,
),
),
const SizedBox(height: 8),
_buildComparisonResults(_syncResult!),
const SizedBox(height: 20),
],
if (_isLoading) ...[
const Center(
child: CircularProgressIndicator(),
),
const SizedBox(height: 16),
] else if (_asyncResult != null) ...[
const Text(
'Asynchronous Comparison Results:',
style: TextStyle(
fontSize: 18,
fontWeight: FontWeight.w600,
),
),
const SizedBox(height: 8),
_buildComparisonResults(_asyncResult!),
const SizedBox(height: 20),
],
ElevatedButton(
onPressed: _performAsyncComparison,
child: const Text('Reload Comparison'),
),
],
),
),
);
}
Widget _buildUserCard(User user, Color backgroundColor) {
return Container(
margin: const EdgeInsets.symmetric(vertical: 4),
padding: const EdgeInsets.all(12),
decoration: BoxDecoration(
color: backgroundColor,
borderRadius: BorderRadius.circular(8),
border: Border.all(color: Colors.grey.shade300),
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'ID: ${user.id}',
style: const TextStyle(fontWeight: FontWeight.bold),
),
Text('Nome: ${user.name}'),
Text('Email: ${user.email}'),
],
),
);
}
Widget _buildComparisonResults(CompareListsOfObjectResult<User> result) {
return Column(
children: [
if (result.added.isNotEmpty) ...[
Container(
width: double.infinity,
padding: const EdgeInsets.all(12),
decoration: BoxDecoration(
color: Colors.green.shade50,
borderRadius: BorderRadius.circular(8),
border: Border.all(color: Colors.green),
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'Added (${result.added.length}):',
style: const TextStyle(
fontWeight: FontWeight.bold,
color: Colors.green,
),
),
const SizedBox(height: 8),
...(result.added
.map((user) => Text('• ${user.name} (${user.email})'))),
],
),
),
const SizedBox(height: 8),
],
if (result.removed.isNotEmpty) ...[
Container(
width: double.infinity,
padding: const EdgeInsets.all(12),
decoration: BoxDecoration(
color: Colors.red.shade50,
borderRadius: BorderRadius.circular(8),
border: Border.all(color: Colors.red),
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'Removed (${result.removed.length}):',
style: const TextStyle(
fontWeight: FontWeight.bold,
color: Colors.red,
),
),
const SizedBox(height: 8),
...(result.removed
.map((user) => Text('• ${user.name} (${user.email})'))),
],
),
),
const SizedBox(height: 8),
],
if (result.updated.isNotEmpty) ...[
Container(
width: double.infinity,
padding: const EdgeInsets.all(12),
decoration: BoxDecoration(
color: Colors.orange.shade50,
borderRadius: BorderRadius.circular(8),
border: Border.all(color: Colors.orange),
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'Updated (${result.updated.length}):',
style: const TextStyle(
fontWeight: FontWeight.bold,
color: Colors.orange,
),
),
const SizedBox(height: 8),
...(result.updated
.map((user) => Text('• ${user.name} (${user.email})'))),
],
),
),
],
if (result.added.isEmpty &&
result.removed.isEmpty &&
result.updated.isEmpty) ...[
Container(
width: double.infinity,
padding: const EdgeInsets.all(12),
decoration: BoxDecoration(
color: Colors.grey.shade50,
borderRadius: BorderRadius.circular(8),
border: Border.all(color: Colors.grey),
),
child: const Text(
'No changes detected',
style: TextStyle(
fontWeight: FontWeight.bold,
color: Colors.grey,
),
),
),
],
],
);
}
}
class User extends ObjectComparable {
final String id;
final String name;
final String email;
User({
required this.id,
required this.name,
required this.email,
});
@override
Map<String, dynamic> get map => {
'id': id,
'name': name,
'email': email,
};
@override
String toString() {
return 'User(id: $id, name: $name, email: $email)';
}
}