folly_fields 4.0.0
folly_fields: ^4.0.0 copied to clipboard
Basic form fields and utilities.
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter_localizations/flutter_localizations.dart';
import 'package:folly_fields/fields/bool_field.dart';
import 'package:folly_fields/fields/cep_field.dart';
import 'package:folly_fields/fields/cest_field.dart';
import 'package:folly_fields/fields/choice_chip_field.dart';
import 'package:folly_fields/fields/cnae_field.dart';
import 'package:folly_fields/fields/cnpj_field.dart';
import 'package:folly_fields/fields/color_field.dart';
import 'package:folly_fields/fields/cpf_cnpj_field.dart';
import 'package:folly_fields/fields/cpf_field.dart';
import 'package:folly_fields/fields/date_field.dart';
import 'package:folly_fields/fields/date_time_field.dart';
import 'package:folly_fields/fields/decimal_field.dart';
import 'package:folly_fields/fields/dropdown_field.dart';
import 'package:folly_fields/fields/email_field.dart';
import 'package:folly_fields/fields/icon_data_field.dart';
import 'package:folly_fields/fields/integer_field.dart';
import 'package:folly_fields/fields/ipv4_field.dart';
import 'package:folly_fields/fields/licence_plate_field.dart';
import 'package:folly_fields/fields/local_phone_field.dart';
import 'package:folly_fields/fields/mac_address_field.dart';
import 'package:folly_fields/fields/mobile_phone_field.dart';
import 'package:folly_fields/fields/multiline_field.dart';
import 'package:folly_fields/fields/ncm_field.dart';
import 'package:folly_fields/fields/password_field.dart';
import 'package:folly_fields/fields/password_visible_field.dart';
import 'package:folly_fields/fields/phone_field.dart';
import 'package:folly_fields/fields/string_field.dart';
import 'package:folly_fields/fields/time_field.dart';
import 'package:folly_fields/util/decimal.dart';
import 'package:folly_fields/util/folly_validators.dart';
import 'package:folly_fields/util/icon_helper.dart';
import 'package:folly_fields/util/safe_builder.dart';
import 'package:folly_fields/widgets/circular_waiting.dart';
import 'package:folly_fields/widgets/error_message.dart';
import 'package:folly_fields_example/code_link.dart';
import 'package:folly_fields_example/example_enum.dart';
import 'package:folly_fields_example/example_model.dart';
import 'package:folly_fields_example/views/credit_card.dart';
import 'package:folly_fields_example/views/four_images.dart';
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
import 'package:google_fonts/google_fonts.dart' hide Config;
import 'package:http/http.dart';
import 'package:url_launcher/url_launcher_string.dart';
void main() {
WidgetsFlutterBinding.ensureInitialized();
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
title: 'Folly Fields Example',
theme: ThemeData(
colorSchemeSeed: Colors.deepOrange,
useMaterial3: true,
brightness: Brightness.dark,
),
initialRoute: '/',
routes: <String, WidgetBuilder>{
'/': (_) => const MyHomePage(),
'/four_images': (_) => const FourImages(),
'/credit_card': (_) => const CreditCard(),
},
localizationsDelegates: const <LocalizationsDelegate<dynamic>>[
...GlobalMaterialLocalizations.delegates,
GlobalWidgetsLocalizations.delegate,
],
supportedLocales: const <Locale>[Locale('pt', 'BR')],
);
}
}
class MyHomePage extends StatefulWidget {
const MyHomePage({super.key});
@override
MyHomePageState createState() => MyHomePageState();
}
class MyHomePageState extends State<MyHomePage> {
final GlobalKey<FormState> _formKey = GlobalKey<FormState>();
/// Prefixo utilizado no label dos campos.
/// O conteúdo está no arquivo de configurações.
String labelPrefix = '';
/// Habilita ou desabilita os campos.
bool edit = true;
/// Modelo padrão para o exemplo.
ExampleModel model = ExampleModel.generate();
@override
Widget build(BuildContext context) {
List<MyMenuItem> menuItems = <MyMenuItem>[
/// Github
MyMenuItem(
name: 'GitHub',
iconData: FontAwesomeIcons.github,
onPressed: (BuildContext context) {
CircularWaiting wait = CircularWaiting(context)..show();
launchUrlString(
'https://github.com/edufolly/folly_fields/',
mode: LaunchMode.externalApplication,
)
.then((_) {
Future<void>.delayed(const Duration(seconds: 2), wait.close);
})
.catchError((dynamic e, StackTrace s) {
if (kDebugMode) {
print(e);
print(s);
}
});
},
),
/// Circular Waiting
MyMenuItem(
name: 'Circular Waiting',
iconData: FontAwesomeIcons.spinner,
onPressed: (BuildContext context) {
CircularWaiting wait = CircularWaiting(
context,
message: 'This is the main message.',
subtitle: 'Wait 3 seconds...',
)..show();
Future<void>.delayed(const Duration(seconds: 3), wait.close);
},
),
/// Four Images
MyMenuItem(
name: 'Quatro Imagens',
iconData: FontAwesomeIcons.image,
onPressed: (BuildContext context) =>
Navigator.of(context).pushNamed('/four_images'),
),
MyMenuItem(
name: 'Credit Card',
iconData: FontAwesomeIcons.creditCard,
onPressed: (BuildContext context) =>
Navigator.of(context).pushNamed('/credit_card'),
),
];
return Scaffold(
appBar: AppBar(
title: const Text('Folly Fields'),
actions: <PopupMenuButton<MyMenuItem>>[
PopupMenuButton<MyMenuItem>(
tooltip: 'Menu',
icon: const Icon(FontAwesomeIcons.ellipsisVertical),
itemBuilder: (BuildContext context) => menuItems
.map<PopupMenuEntry<MyMenuItem>>(
(MyMenuItem e) => e.popupMenuItem,
)
.toList(),
onSelected: (MyMenuItem item) => item.onPressed(context),
),
],
),
body: SafeArea(
child: SafeFutureBuilder<Response>(
future: get(
Uri.parse(
'https://raw.githubusercontent.com/edufolly'
'/folly_fields/main/example/lib/main.dart',
),
),
builder: (BuildContext context, Response response, _) {
int statusCode = response.statusCode;
if (statusCode < 200 || statusCode > 299) {
return ErrorMessage(error: 'Status code error: $statusCode');
}
String code = response.body;
return SingleChildScrollView(
padding: const EdgeInsets.all(24),
child: Form(
key: _formKey,
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
/// Título
Padding(
padding: const EdgeInsets.all(8),
child: Text(
'Formulário Básico',
textAlign: TextAlign.center,
style: Theme.of(context).textTheme.headlineMedium,
),
),
// [RootCode]
CodeLink(
code: code,
tag: 'StringField',
source:
'https://github.com/edufolly/folly_fields/'
'blob/main/lib/fields/string_field.dart',
child:
// [StringField]
StringField(
labelPrefix: labelPrefix,
label: 'Texto*',
enabled: edit,
initialValue: model.text,
validator: (String? value) =>
value == null || value.isEmpty
? 'O campo texto precisa ser informado.'
: null,
onSaved: (String? value) => model.text = value,
),
// [/StringField]
),
CodeLink(
code: code,
tag: 'EmailField',
source:
'https://github.com/edufolly/folly_fields/'
'blob/main/lib/fields/email_field.dart',
child:
// [EmailField]
EmailField(
labelPrefix: labelPrefix,
label: 'E-mail*',
enabled: edit,
initialValue: model.email,
onSaved: (String? value) =>
model.email = value ?? '',
),
// [/EmailField]
),
CodeLink(
code: code,
tag: 'PasswordField',
source:
'https://github.com/edufolly/folly_fields/'
'blob/main/lib/fields/password_field.dart',
child:
// [PasswordField]
PasswordField(
labelPrefix: labelPrefix,
label: 'Senha*',
enabled: edit,
validator: (String? value) =>
value == null || value.isEmpty
? 'O campo senha precisa ser informado.'
: null,
onSaved: (String? value) => model.password = value,
),
// [/PasswordField]
),
CodeLink(
code: code,
tag: 'PasswordVisibleField',
source:
'https://github.com/edufolly/folly_fields/'
'blob/main/lib/fields/password_visible_field.dart',
child:
// [PasswordVisibleField]
PasswordVisibleField(
labelPrefix: labelPrefix,
label: 'Senha Visível*',
enabled: edit,
validator: (String? value) =>
value == null || value.isEmpty
? 'O campo senha visível precisa ser informado.'
: null,
onSaved: (String? value) => model.password = value,
),
// [/PasswordVisibleField]
),
CodeLink(
code: code,
tag: 'DecimalField',
source:
'https://github.com/edufolly/folly_fields/'
'blob/main/lib/fields/decimal_field.dart',
child:
// [NewDecimalField]
NewDecimalField(
labelPrefix: labelPrefix,
label: 'Decimal*',
enabled: edit,
initialValue: model.decimal,
onSaved: (Decimal? value) => model.decimal = value,
),
// [/NewDecimalField]
),
CodeLink(
code: code,
tag: 'IntegerField',
source:
'https://github.com/edufolly/folly_fields/'
'blob/main/lib/fields/integer_field.dart',
child:
// [IntegerField]
IntegerField(
labelPrefix: labelPrefix,
label: 'Integer*',
enabled: edit,
initialValue: model.integer,
validator: FollyValidators.intGTZero,
onSaved: (int? value) => model.integer = value ?? 0,
),
// [/IntegerField]
),
CodeLink(
code: code,
tag: 'ColorField',
source:
'https://github.com/edufolly/folly_fields/'
'blob/main/lib/fields/color_field.dart',
child:
// [ColorField]
ColorField(
labelPrefix: labelPrefix,
label: 'Cor',
enabled: edit,
initialValue: model.color,
validator: FollyValidators.notNull,
onSaved: (Color? value) => model.color = value,
clearOnCancel: false,
),
// [/ColorField]
),
CodeLink(
code: code,
tag: 'CpfField',
source:
'https://github.com/edufolly/folly_fields/'
'blob/main/lib/fields/cpf_field.dart',
child:
// [CpfField]
CpfField(
labelPrefix: labelPrefix,
label: 'CPF*',
enabled: edit,
initialValue: model.cpf,
onSaved: (String? value) => model.cpf = value,
),
// [/CpfField]
),
CodeLink(
code: code,
tag: 'CnpjField',
source:
'https://github.com/edufolly/folly_fields/'
'blob/main/lib/fields/cnpj_field.dart',
child:
// [CnpjField]
CnpjField(
labelPrefix: labelPrefix,
label: 'CNPJ*',
enabled: edit,
initialValue: model.cnpj,
onSaved: (String? value) => model.cnpj = value,
),
// [/CnpjField]
),
CodeLink(
code: code,
tag: 'CpfCnpjField',
source:
'https://github.com/edufolly/folly_fields/'
'blob/main/lib/fields/cpf_cnpj_field.dart',
child:
// [CpfCnpjField]
CpfCnpjField(
labelPrefix: labelPrefix,
label: 'CPF ou CNPJ*',
enabled: edit,
initialValue: model.document,
onSaved: (String? value) => model.document = value,
),
// [/CpfCnpjField]
),
CodeLink(
code: code,
tag: 'PhoneField',
source:
'https://github.com/edufolly/folly_fields/'
'blob/main/lib/fields/phone_field.dart',
child:
// [PhoneField]
PhoneField(
labelPrefix: labelPrefix,
label: 'Telefone*',
enabled: edit,
initialValue: model.phone,
onSaved: (String? value) =>
model.phone = value ?? '',
),
// [/PhoneField]
),
CodeLink(
code: code,
tag: 'LocalPhoneField',
source:
'https://github.com/edufolly/folly_fields/'
'blob/main/lib/fields/local_phone_field.dart',
child:
// [LocalPhoneField]
LocalPhoneField(
labelPrefix: labelPrefix,
label: 'Telefone sem DDD*',
enabled: edit,
initialValue: model.localPhone,
onSaved: (String? value) =>
model.localPhone = value ?? '',
),
// [/LocalPhoneField]
),
CodeLink(
code: code,
tag: 'MobilePhoneField',
source:
'https://github.com/edufolly/folly_fields/'
'blob/main/lib/fields/mobile_local_phone_field.dart',
child:
// [MobilePhoneField]
MobilePhoneField(
labelPrefix: labelPrefix,
label: 'Celular*',
enabled: edit,
initialValue: model.mobilePhone,
onSaved: (String? value) =>
model.mobilePhone = value ?? '',
),
// [/MobilePhoneField]
),
CodeLink(
code: code,
tag: 'DateTimeField',
source:
'https://github.com/edufolly/folly_fields/'
'blob/main/lib/fields/date_time_field.dart',
child:
// [DateTimeField]
DateTimeField(
labelPrefix: labelPrefix,
label: 'Data e Hora*',
enabled: edit,
initialValue: model.dateTime,
validator: (DateTime? value) =>
value == null ? 'Informe uma data' : null,
onSaved: (DateTime? value) =>
model.dateTime = value,
clearOnCancel: false,
),
// [/DateTimeField]
),
CodeLink(
code: code,
tag: 'DateField',
source:
'https://github.com/edufolly/folly_fields/'
'blob/main/lib/fields/date_field.dart',
child:
// [DateField]
DateField(
labelPrefix: labelPrefix,
label: 'Data*',
enabled: edit,
initialValue: model.date,
onSaved: (DateTime? value) => model.date = value,
),
// [/DateField]
),
CodeLink(
code: code,
tag: 'TimeField',
source:
'https://github.com/edufolly/folly_fields/'
'blob/main/lib/fields/time_field.dart',
child:
// [TimeField]
TimeField(
labelPrefix: labelPrefix,
label: 'Hora*',
enabled: edit,
initialValue: model.time,
validator: FollyValidators.notNull,
onSaved: (TimeOfDay? value) => model.time = value,
clearOnCancel: false,
),
// [/TimeField]
),
CodeLink(
code: code,
tag: 'MacAddressField',
source:
'https://github.com/edufolly/folly_fields/'
'blob/main/lib/fields/mac_address_field.dart',
child:
// [MacAddressField]
MacAddressField(
labelPrefix: labelPrefix,
label: 'Mac Address*',
enabled: edit,
initialValue: model.macAddress,
onSaved: (String? value) =>
model.macAddress = value,
),
// [/MacAddressField]
),
CodeLink(
code: code,
tag: 'NcmField',
source:
'https://github.com/edufolly/folly_fields/'
'blob/main/lib/fields/ncm_field.dart',
child:
// [NcmField]
NcmField(
labelPrefix: labelPrefix,
label: 'NCM*',
enabled: edit,
initialValue: model.ncm,
onSaved: (String? value) => model.ncm = value,
),
// [/NcmField]
),
CodeLink(
code: code,
tag: 'CestField',
source:
'https://github.com/edufolly/folly_fields/'
'blob/main/lib/fields/cest_field.dart',
child:
// [CestField]
CestField(
labelPrefix: labelPrefix,
label: 'CEST*',
enabled: edit,
initialValue: model.cest,
onSaved: (String? value) => model.cest = value,
),
// [/CestField]
),
CodeLink(
code: code,
tag: 'CnaeField',
source:
'https://github.com/edufolly/folly_fields/'
'blob/main/lib/fields/cnae_field.dart',
child:
// [CnaeField]
CnaeField(
labelPrefix: labelPrefix,
label: 'CNAE*',
enabled: edit,
initialValue: model.cnae,
onSaved: (String? value) => model.cnae = value,
),
// [/CnaeField]
),
CodeLink(
code: code,
tag: 'CepField',
source:
'https://github.com/edufolly/folly_fields/'
'blob/main/lib/fields/cep_field.dart',
child:
// [CepField]
CepField(
labelPrefix: labelPrefix,
label: 'CEP*',
enabled: edit,
initialValue: model.cep,
onSaved: (String? value) => model.cep = value,
),
// [/CepField]
),
CodeLink(
code: code,
tag: 'LicencePlateField',
source:
'https://github.com/edufolly/folly_fields/'
'blob/main/lib/fields/licence_plate_field.dart',
child:
// [LicencePlateField]
LicencePlateField(
labelPrefix: labelPrefix,
label: 'Placa de Veiculo*',
enabled: edit,
initialValue: model.licencePlate,
onSaved: (String? value) =>
model.licencePlate = value,
),
// [/LicencePlateField]
),
CodeLink(
code: code,
tag: 'Ipv4Field',
source:
'https://github.com/edufolly/folly_fields/'
'blob/main/lib/fields/ipv4_field.dart',
child:
// [Ipv4Field]
Ipv4Field(
labelPrefix: labelPrefix,
label: 'IPv4*',
enabled: edit,
initialValue: model.ipv4,
onSaved: (String? value) => model.ipv4 = value,
),
// [/Ipv4Field]
),
CodeLink(
code: code,
tag: 'BoolField',
source:
'https://github.com/edufolly/folly_fields/'
'blob/main/lib/fields/bool_field.dart',
child:
// [BoolField]
BoolField(
labelPrefix: labelPrefix,
label: 'Campo Boleano',
enabled: edit,
initialValue: model.active,
validator: (bool value) => !value
? 'Para testes, este campo deve ser sempre '
'verdadeiro.'
: null,
onSaved: (bool value) => model.active = value,
),
// [/BoolField]
),
CodeLink(
code: code,
tag: 'IconDataField',
source:
'https://github.com/edufolly/folly_fields/'
'blob/main/lib/fields/icon_data_field.dart',
child:
// [IconDataField]
IconDataField(
labelPrefix: labelPrefix,
label: 'Ícone*',
enabled: edit,
icons: IconHelper.data,
initialValue: model.icon,
validator: FollyValidators.notNull,
onSaved: (IconData? iconData) =>
model.icon = iconData,
),
// [/IconDataField]
),
CodeLink(
code: code,
tag: 'DropdownField',
source:
'https://github.com/edufolly/folly_fields/'
'blob/main/lib/fields/dropdown_field.dart',
child:
// [DropdownField]
DropdownField<ExampleEnum, Widget>(
labelPrefix: labelPrefix,
label: 'Ordinal',
enabled: edit,
items: ExampleEnum.values.asMap().map((
_,
ExampleEnum value,
) {
return MapEntry<ExampleEnum, Widget>(
value,
Text(value.value),
);
}),
initialValue: model.ordinal,
validator: FollyValidators.notNull,
onSaved: (ExampleEnum? value) =>
model.ordinal = value,
),
// [/DropdownField]
),
CodeLink(
code: code,
tag: 'MultilineField',
source:
'https://github.com/edufolly/folly_fields/'
'blob/main/lib/fields/multiline_field.dart',
child:
// [MultilineField]
MultilineField(
labelPrefix: labelPrefix,
label: 'Multiline*',
counterText: null,
maxLength: 600,
enabled: edit,
initialValue: model.multiline,
validator: FollyValidators.stringNotEmpty,
onSaved: (String? value) =>
model.multiline = value ?? '',
style: GoogleFonts.firaMono(
textStyle: Theme.of(context).textTheme.bodyMedium,
),
),
// [/MultilineField]
),
CodeLink(
code: code,
tag: 'ChoiceChipField',
source:
'https://github.com/edufolly/folly_fields/'
'blob/main/lib/fields/choice_chip_field.dart',
child:
// [ChoiceChipField]
ChoiceChipField<int>(
label: 'Frutas',
enabled: edit,
items: const <int, ChipEntry>{
0: ChipEntry(
'🍎Maça',
color: Colors.red,
selectedColor: Colors.redAccent,
),
1: ChipEntry(
'🍌Banana',
color: Colors.yellow,
selectedColor: Colors.yellowAccent,
),
2: ChipEntry(
'🍊Tangerina',
color: Colors.orange,
selectedColor: Colors.orangeAccent,
),
},
onChanged: (int? value, {required bool selected}) =>
debugPrint(
'ChoiceChipField $value is'
'${selected ? '' : ' NOT'} selected',
),
validator: FollyValidators.notEmpty,
onSaved: (Set<int>? value) =>
model.fruitIndex = value!.first,
),
// [/ChoiceChipField]
),
// [/RootCode]
/// Botão Enviar
Padding(
padding: const EdgeInsets.symmetric(
vertical: 16,
horizontal: 8,
),
child: ElevatedButton.icon(
icon: const Icon(Icons.send),
label: const Text('ENVIAR'),
onPressed: _send,
),
),
],
),
),
);
},
),
),
);
}
void _send() {
// if (_formKey.currentState!.validate()) {
// _formKey.currentState!.save();
//
// if (kDebugMode) {
// print(model.toMap());
// }
//
// FollyDialogs.dialogMessage(
// context: context,
// title: 'Result of toMap().',
// message: model.toMap().toString(),
// );
// }
}
}
class MyMenuItem {
final String name;
final IconData iconData;
final Function(BuildContext context) onPressed;
MyMenuItem({
required this.name,
required this.iconData,
required this.onPressed,
});
PopupMenuItem<MyMenuItem> get popupMenuItem => PopupMenuItem<MyMenuItem>(
value: this,
child: Row(
children: <Widget>[
Padding(
padding: const EdgeInsets.only(right: 16),
child: Icon(iconData),
),
Text(name),
],
),
);
}