Feat: Criação de um component de Select e de Upload de Media. Tentativa de criar validadores para o formulário.

This commit is contained in:
Lucas 2024-09-05 17:27:38 -03:00
parent feca086aca
commit 0dd0990523
5 changed files with 598 additions and 105 deletions

View File

@ -5,23 +5,27 @@ import 'package:hub/flutter_flow/flutter_flow_util.dart';
class CustomDatePickerUtil extends StatefulWidget { class CustomDatePickerUtil extends StatefulWidget {
final TextEditingController? controller; final TextEditingController? controller;
final FocusNode? focusNode;
final String hintText; final String hintText;
final String dateFormat; final String dateFormat;
final String locale; final String locale;
final DateTime? initialDate; final DateTime? initialDate;
final DateTime firstDate; final DateTime firstDate;
final DateTime lastDate; final DateTime? lastDate;
final bool timePicker;
final FormFieldValidator<String>? validator; final FormFieldValidator<String>? validator;
const CustomDatePickerUtil({ const CustomDatePickerUtil({
Key? key, Key? key,
this.controller, this.controller,
this.focusNode,
required this.hintText, required this.hintText,
required this.dateFormat, required this.dateFormat,
required this.locale, required this.locale,
required this.timePicker,
this.initialDate, this.initialDate,
required this.firstDate, required this.firstDate,
required this.lastDate, this.lastDate,
this.validator, this.validator,
}) : super(key: key); }) : super(key: key);
@ -44,7 +48,7 @@ class _CustomDatePickerState extends State<CustomDatePickerUtil> {
context: context, context: context,
initialDate: _selectedDate ?? DateTime.now(), initialDate: _selectedDate ?? DateTime.now(),
firstDate: widget.firstDate, firstDate: widget.firstDate,
lastDate: widget.lastDate, lastDate: widget.lastDate ?? DateTime(2100),
builder: (context, child) { builder: (context, child) {
return wrapInMaterialDatePickerTheme( return wrapInMaterialDatePickerTheme(
context, context,
@ -70,48 +74,64 @@ class _CustomDatePickerState extends State<CustomDatePickerUtil> {
); );
if (pickedDate != null) { if (pickedDate != null) {
final TimeOfDay? pickedTime = await showTimePicker( if (widget.timePicker == true) {
context: context, final TimeOfDay? pickedTime = await showTimePicker(
initialTime: TimeOfDay.fromDateTime(_selectedDate ?? DateTime.now()), context: context,
builder: (context, child) { initialTime: TimeOfDay.fromDateTime(_selectedDate ?? DateTime.now()),
return wrapInMaterialTimePickerTheme( builder: (context, child) {
context, return wrapInMaterialTimePickerTheme(
child!, context,
headerBackgroundColor: FlutterFlowTheme.of(context).primary, child!,
headerForegroundColor: FlutterFlowTheme.of(context).info, headerBackgroundColor: FlutterFlowTheme.of(context).primary,
headerTextStyle: FlutterFlowTheme.of(context) headerForegroundColor: FlutterFlowTheme.of(context).info,
.headlineLarge headerTextStyle:
.override( FlutterFlowTheme.of(context).headlineLarge.override(
fontFamily: FlutterFlowTheme.of(context).headlineLargeFamily, fontFamily:
fontSize: 32.0, FlutterFlowTheme.of(context).headlineLargeFamily,
letterSpacing: 0.0, fontSize: 32.0,
fontWeight: FontWeight.w600, letterSpacing: 0.0,
useGoogleFonts: GoogleFonts.asMap().containsKey( fontWeight: FontWeight.w600,
FlutterFlowTheme.of(context).headlineLargeFamily), useGoogleFonts: GoogleFonts.asMap().containsKey(
), FlutterFlowTheme.of(context).headlineLargeFamily),
pickerBackgroundColor: ),
FlutterFlowTheme.of(context).primaryBackground, pickerBackgroundColor:
pickerForegroundColor: FlutterFlowTheme.of(context).info, FlutterFlowTheme.of(context).primaryBackground,
selectedDateTimeBackgroundColor: pickerForegroundColor: FlutterFlowTheme.of(context).info,
FlutterFlowTheme.of(context).primary, selectedDateTimeBackgroundColor:
selectedDateTimeForegroundColor: FlutterFlowTheme.of(context).info, FlutterFlowTheme.of(context).primary,
pickerDialForegroundColor: FlutterFlowTheme.of(context).primaryText, selectedDateTimeForegroundColor:
actionButtonForegroundColor: FlutterFlowTheme.of(context).info,
FlutterFlowTheme.of(context).primaryText, pickerDialForegroundColor:
iconSize: 24.0, FlutterFlowTheme.of(context).primaryText,
); actionButtonForegroundColor:
}, FlutterFlowTheme.of(context).primaryText,
); iconSize: 24.0,
);
},
);
if (pickedTime != null) { if (pickedTime != null) {
setState(() {
_selectedDate = DateTime(
pickedDate.year,
pickedDate.month,
pickedDate.day,
pickedTime.hour,
pickedTime.minute,
);
widget.controller?.text = dateTimeFormat(
widget.dateFormat,
_selectedDate,
locale: widget.locale,
);
widget.controller?.selection = TextSelection.collapsed(
offset: widget.controller!.text.length,
);
});
}
} else {
setState(() { setState(() {
_selectedDate = DateTime( _selectedDate = pickedDate;
pickedDate.year,
pickedDate.month,
pickedDate.day,
pickedTime.hour,
pickedTime.minute,
);
widget.controller?.text = dateTimeFormat( widget.controller?.text = dateTimeFormat(
widget.dateFormat, widget.dateFormat,
_selectedDate, _selectedDate,
@ -140,6 +160,7 @@ class _CustomDatePickerState extends State<CustomDatePickerUtil> {
const EdgeInsetsDirectional.fromSTEB(24.0, 0.0, 24.0, 0.0), const EdgeInsetsDirectional.fromSTEB(24.0, 0.0, 24.0, 0.0),
child: TextFormField( child: TextFormField(
controller: widget.controller, controller: widget.controller,
focusNode: widget.focusNode,
readOnly: true, readOnly: true,
autovalidateMode: AutovalidateMode.onUserInteraction, autovalidateMode: AutovalidateMode.onUserInteraction,
autofocus: false, autofocus: false,
@ -170,31 +191,31 @@ class _CustomDatePickerState extends State<CustomDatePickerUtil> {
), ),
enabledBorder: OutlineInputBorder( enabledBorder: OutlineInputBorder(
borderSide: BorderSide( borderSide: BorderSide(
color: FlutterFlowTheme.of(context).accent4, color: FlutterFlowTheme.of(context).customColor6,
width: 0.5, width: 0.5,
), ),
borderRadius: BorderRadius.circular(8.0), borderRadius: BorderRadius.circular(10.0),
), ),
focusedBorder: OutlineInputBorder( focusedBorder: OutlineInputBorder(
borderSide: BorderSide( borderSide: BorderSide(
color: FlutterFlowTheme.of(context).primary, color: FlutterFlowTheme.of(context).primary,
width: 0.5, width: 0.5,
), ),
borderRadius: BorderRadius.circular(8.0), borderRadius: BorderRadius.circular(10.0),
), ),
errorBorder: OutlineInputBorder( errorBorder: OutlineInputBorder(
borderSide: BorderSide( borderSide: BorderSide(
color: FlutterFlowTheme.of(context).error, color: FlutterFlowTheme.of(context).error,
width: 0.5, width: 0.5,
), ),
borderRadius: BorderRadius.circular(8.0), borderRadius: BorderRadius.circular(10.0),
), ),
focusedErrorBorder: OutlineInputBorder( focusedErrorBorder: OutlineInputBorder(
borderSide: BorderSide( borderSide: BorderSide(
color: FlutterFlowTheme.of(context).error, color: FlutterFlowTheme.of(context).error,
width: 0.5, width: 0.5,
), ),
borderRadius: BorderRadius.circular(8.0), borderRadius: BorderRadius.circular(10.0),
), ),
suffixIcon: Icon( suffixIcon: Icon(
Icons.date_range, Icons.date_range,
@ -226,7 +247,7 @@ class _CustomDatePickerState extends State<CustomDatePickerUtil> {
width: double.infinity, width: double.infinity,
height: 80.0, height: 80.0,
decoration: BoxDecoration( decoration: BoxDecoration(
borderRadius: BorderRadius.circular(8.0), borderRadius: BorderRadius.circular(10.0),
), ),
), ),
), ),

View File

@ -0,0 +1,99 @@
import 'package:flutter/material.dart';
import 'package:google_fonts/google_fonts.dart';
import 'package:hub/flutter_flow/flutter_flow_drop_down.dart';
import 'package:hub/flutter_flow/flutter_flow_theme.dart';
import 'package:hub/flutter_flow/flutter_flow_util.dart';
import 'package:hub/flutter_flow/flutter_flow_widgets.dart';
import 'package:hub/flutter_flow/form_field_controller.dart';
class CustomSelect extends StatefulWidget {
final List<String> options;
final List<String> optionsLabel;
final String hintText;
final FormFieldController<String>? controller;
const CustomSelect({
Key? key,
required this.options,
required this.optionsLabel,
required this.hintText,
this.controller,
}) : super(key: key);
@override
_CustomSelectState createState() => _CustomSelectState();
}
class _CustomSelectState extends State<CustomSelect> {
late FormFieldController<String> _controller;
@override
void initState() {
super.initState();
_controller = widget.controller ?? FormFieldController<String>(null);
}
@override
Widget build(BuildContext context) {
return Padding(
padding: const EdgeInsetsDirectional.fromSTEB(0, 0.0, 0, 10.0),
child: Column(
children: [
Row(
mainAxisSize: MainAxisSize.max,
children: [
Expanded(
child: Padding(
padding: const EdgeInsetsDirectional.fromSTEB(
24.0, 0.0, 24.0, 0.0),
child: Container(
width: 100.0,
height: 48.0,
decoration: const BoxDecoration(),
child: FlutterFlowDropDown<String>(
fillColor:
FlutterFlowTheme.of(context).secondaryBackground,
controller: _controller,
options: widget.options,
optionLabels: widget.optionsLabel,
onChanged: (val) {
setState(() => _controller.value = val);
},
width: double.infinity,
height: double.infinity,
textStyle: FlutterFlowTheme.of(context)
.bodyMedium
.override(
fontFamily:
FlutterFlowTheme.of(context).bodyMediumFamily,
letterSpacing: 0.0,
useGoogleFonts: GoogleFonts.asMap().containsKey(
FlutterFlowTheme.of(context).bodyMediumFamily),
),
hintText: widget.hintText,
icon: Icon(
Icons.keyboard_arrow_down_rounded,
color: FlutterFlowTheme.of(context).accent1,
size: 24.0,
),
elevation: 2.0,
borderColor: FlutterFlowTheme.of(context).customColor6,
borderWidth: 0.5,
borderRadius: 10.0,
margin: const EdgeInsetsDirectional.fromSTEB(
12.0, 0.0, 16.0, 0.0),
hidesUnderline: true,
isOverButton: true,
isSearchable: false,
isMultiSelect: false,
),
),
),
),
],
),
],
),
);
}
}

View File

@ -0,0 +1,173 @@
import 'dart:typed_data';
import 'package:flutter/material.dart';
import 'package:google_fonts/google_fonts.dart';
import 'package:hub/flutter_flow/flutter_flow_theme.dart';
import 'package:hub/flutter_flow/flutter_flow_widgets.dart';
import 'package:hub/flutter_flow/internationalization.dart';
import 'package:hub/flutter_flow/upload_data.dart';
import 'package:hub/flutter_flow/uploaded_file.dart';
class MediaUploadButtonUtil extends StatefulWidget {
final FFUploadedFile uploadedFile;
final bool isUploading;
final String labelText;
const MediaUploadButtonUtil(
{Key? key,
required this.uploadedFile,
required this.isUploading,
required this.labelText})
: super(key: key);
@override
State<MediaUploadButtonUtil> createState() => _MediaUploadButtonUtilState();
}
class _MediaUploadButtonUtilState extends State<MediaUploadButtonUtil> {
late FFUploadedFile _uploadedFile;
late bool _isUploading;
@override
void initState() {
super.initState();
_uploadedFile = widget.uploadedFile ?? FFUploadedFile();
_isUploading = widget.isUploading ?? false;
}
@override
Widget build(BuildContext context) {
return Padding(
padding: const EdgeInsetsDirectional.fromSTEB(24.0, 0.0, 24.0, 0.0),
child: Builder(
builder: (context) {
if ((_uploadedFile.bytes?.isNotEmpty ?? false)) {
return InkWell(
splashColor: Colors.transparent,
focusColor: Colors.transparent,
hoverColor: Colors.transparent,
highlightColor: Colors.transparent,
onTap: () async {
setState(() {
_isUploading = false;
_uploadedFile = FFUploadedFile(bytes: Uint8List.fromList([]));
});
},
child: ClipRRect(
borderRadius: BorderRadius.circular(8.0),
child: Image.memory(
_uploadedFile.bytes ?? Uint8List.fromList([]),
width: 300.0,
height: 200.0,
fit: BoxFit.cover,
),
),
);
} else {
return Stack(
children: [
Align(
alignment: const AlignmentDirectional(0.0, 0.0),
child: FFButtonWidget(
onPressed: () async {
final selectedMedia =
await selectMediaWithSourceBottomSheet(
context: context,
imageQuality: 100,
allowPhoto: true,
includeDimensions: true,
);
if (selectedMedia != null) {
setState(() => _isUploading = true);
var selectedUploadedFiles = <FFUploadedFile>[];
try {
showUploadMessage(
context,
'Uploading file...',
showLoading: true,
);
selectedUploadedFiles = selectedMedia
.map((m) => FFUploadedFile(
name: m.storagePath.split('/').last,
bytes: m.bytes,
height: m.dimensions?.height,
width: m.dimensions?.width,
// blurHash: m.blurHash,
))
.toList();
} finally {
ScaffoldMessenger.of(context).hideCurrentSnackBar();
_isUploading = false;
}
if (selectedUploadedFiles.length ==
selectedMedia.length) {
setState(() {
_uploadedFile = selectedUploadedFiles.first;
});
showUploadMessage(context, 'Success!');
} else {
setState(() {});
showUploadMessage(context, 'Failed to upload data');
return;
}
}
},
text: '',
icon: Icon(
Icons.photo_camera,
color: FlutterFlowTheme.of(context).accent1,
size: 30.0,
),
options: FFButtonOptions(
width: double.infinity,
height: 120.0,
padding: const EdgeInsetsDirectional.fromSTEB(
0.0, 0.0, 0.0, 20.0),
iconPadding: const EdgeInsetsDirectional.fromSTEB(
14.0, 0.0, 0.0, 20.0),
color: FlutterFlowTheme.of(context).primaryBackground,
textStyle: FlutterFlowTheme.of(context)
.titleSmall
.override(
fontFamily:
FlutterFlowTheme.of(context).titleSmallFamily,
color: FlutterFlowTheme.of(context).primaryText,
fontSize: 16.0,
letterSpacing: 0.0,
useGoogleFonts: GoogleFonts.asMap().containsKey(
FlutterFlowTheme.of(context).titleSmallFamily),
),
borderSide: BorderSide(
color: FlutterFlowTheme.of(context).accent1,
width: 0.2,
),
borderRadius: BorderRadius.circular(8.0),
),
),
),
Align(
alignment: const AlignmentDirectional(0.0, 0.0),
child: Padding(
padding: const EdgeInsetsDirectional.fromSTEB(
10.0, 65.0, 10.0, 0.0),
child: Text(
widget.labelText,
style: FlutterFlowTheme.of(context).bodyMedium.override(
fontFamily:
FlutterFlowTheme.of(context).bodyMediumFamily,
color: FlutterFlowTheme.of(context).primaryText,
letterSpacing: 0.0,
useGoogleFonts: GoogleFonts.asMap().containsKey(
FlutterFlowTheme.of(context).bodyMediumFamily),
),
),
),
),
],
);
}
},
),
);
}
}

View File

@ -1,31 +1,61 @@
import 'dart:async'; import 'dart:developer';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:hub/flutter_flow/flutter_flow_model.dart';
import 'package:hub/flutter_flow/flutter_flow_util.dart'; import 'package:hub/flutter_flow/flutter_flow_util.dart';
import 'package:hub/flutter_flow/uploaded_file.dart'; import 'package:hub/flutter_flow/form_field_controller.dart';
import 'package:hub/pages/pets_page/pets_page_widget.dart'; import 'package:hub/pages/pets_page/pets_page_widget.dart';
class PetsPageModel extends FlutterFlowModel<PetsPageWidget> { class PetsPageModel extends FlutterFlowModel<PetsPageWidget> {
late final TabController tabBarController; late final TabController tabBarController;
Timer? _debounceTimer;
final unfocusNode = FocusNode(); final unfocusNode = FocusNode();
// Controller para o Upload de Arquivos
bool isDataUploading = false; bool isDataUploading = false;
FFUploadedFile uploadedLocalFile = FFUploadedFile uploadedLocalFile =
FFUploadedFile(bytes: Uint8List.fromList([])); FFUploadedFile(bytes: Uint8List.fromList([]));
void debounce(Function() fn, Duration time) { // Controller para o DropDown
if (_debounceTimer != null) { String? dropDownValue1;
_debounceTimer!.cancel(); FormFieldController<String>? dropDownValueController1;
String? dropDownValue2;
FormFieldController<String>? dropDownValueController2;
// Controller para o TextField
FocusNode? textFieldFocusName;
TextEditingController? textControllerName;
String? Function(BuildContext, String?)? textControllerNameValidator;
String? _textControllerNameValidator(BuildContext context, String? val) {
log('Chamou esta merda');
if (val == null || val.isEmpty) {
return FFLocalizations.of(context).getVariableText(
enText: 'This field is required',
ptText: 'Este campo é obrigatório',
);
} }
_debounceTimer = Timer(time, fn);
return null;
} }
@override FocusNode? textFieldFocusSpecies;
void dispose() { TextEditingController? textControllerSpecies;
tabBarController.dispose(); String? Function(BuildContext, String?)? textControllerSpeciesValidator;
}
FocusNode? textFieldFocusRace;
TextEditingController? textControllerRace;
String? Function(BuildContext, String?)? textControllerRaceValidator;
FocusNode? textFieldFocusColor;
TextEditingController? textControllerColor;
String? Function(BuildContext, String?)? textControllerColorValidator;
FocusNode? textFieldFocusData;
TextEditingController? textControllerData;
String? Function(BuildContext, String?)? textControllerDataValidator;
FocusNode? textFieldFocusObservation;
TextEditingController? textControllerObservation;
String? Function(BuildContext, String?)? textControllerObservationValidator;
@override @override
void initState(BuildContext context) { void initState(BuildContext context) {
@ -34,5 +64,17 @@ class PetsPageModel extends FlutterFlowModel<PetsPageWidget> {
vsync: Navigator.of(context), vsync: Navigator.of(context),
length: 2, length: 2,
); );
textFieldFocusName = FocusNode();
textControllerName = TextEditingController();
textControllerNameValidator =
(context, value) => _textControllerNameValidator(context, value);
}
@override
void dispose() {
tabBarController.dispose();
textFieldFocusName?.dispose();
textControllerName?.dispose();
} }
} }

View File

@ -1,21 +1,25 @@
import 'package:easy_debounce/easy_debounce.dart'; import 'dart:developer';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/scheduler.dart';
import 'package:flutter/services.dart'; import 'package:flutter/services.dart';
import 'package:google_fonts/google_fonts.dart'; import 'package:google_fonts/google_fonts.dart';
import 'package:hub/components/atomic_components/shared_components_atoms/appbar.dart'; import 'package:hub/components/atomic_components/shared_components_atoms/appbar.dart';
import 'package:hub/components/atomic_components/shared_components_atoms/custom_datepicker.dart'; import 'package:hub/components/atomic_components/shared_components_atoms/custom_datepicker.dart';
import 'package:hub/components/atomic_components/shared_components_atoms/custom_input.dart'; import 'package:hub/components/atomic_components/shared_components_atoms/custom_input.dart';
import 'package:hub/components/atomic_components/shared_components_atoms/custom_select.dart';
import 'package:hub/components/atomic_components/shared_components_atoms/media_upload_button.dart';
import 'package:hub/components/atomic_components/shared_components_atoms/tabview.dart'; import 'package:hub/components/atomic_components/shared_components_atoms/tabview.dart';
import 'package:hub/flutter_flow/flutter_flow_icon_button.dart';
import 'package:hub/flutter_flow/flutter_flow_model.dart';
import 'package:hub/flutter_flow/flutter_flow_theme.dart'; import 'package:hub/flutter_flow/flutter_flow_theme.dart';
import 'package:hub/flutter_flow/flutter_flow_util.dart'; import 'package:hub/flutter_flow/flutter_flow_util.dart';
import 'package:hub/flutter_flow/flutter_flow_widgets.dart'; import 'package:hub/flutter_flow/flutter_flow_widgets.dart';
import 'package:hub/flutter_flow/internationalization.dart'; import 'package:hub/flutter_flow/internationalization.dart';
import 'package:hub/flutter_flow/nav/nav.dart'; import 'package:hub/flutter_flow/nav/nav.dart';
import 'package:hub/flutter_flow/upload_data.dart'; import 'package:hub/flutter_flow/upload_data.dart';
import 'package:hub/pages/pets_page/pets_page_model.dart'; import 'package:hub/pages/pets_page/pets_page_model.dart';
class PetsPageWidget extends StatefulWidget { class PetsPageWidget extends StatefulWidget {
@ -34,6 +38,11 @@ class _PetsPageWidgetState extends State<PetsPageWidget>
super.initState(); super.initState();
_model = PetsPageModel(); _model = PetsPageModel();
_model.tabBarController = TabController(length: 2, vsync: this); _model.tabBarController = TabController(length: 2, vsync: this);
_model.textControllerName ??= TextEditingController();
_model.textFieldFocusName ??= FocusNode();
_model.textControllerSpecies ??= TextEditingController();
} }
@override @override
@ -42,11 +51,17 @@ class _PetsPageWidgetState extends State<PetsPageWidget>
super.dispose(); super.dispose();
} }
void _onTextChanged() {
setState(() {});
}
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Scaffold( return Scaffold(
appBar: appBarPets(context), appBar: appBarPets(context),
body: tabViewPets(context, _model, _model.tabBarController)); backgroundColor: FlutterFlowTheme.of(context).primaryBackground,
body: tabViewPets(
context, _model, _model.tabBarController, safeSetState, setState));
} }
} }
@ -54,19 +69,33 @@ PreferredSizeWidget appBarPets(BuildContext context) {
return AppBarUtil(title: 'Pets', onBackButtonPressed: () => context.pop()); return AppBarUtil(title: 'Pets', onBackButtonPressed: () => context.pop());
} }
Widget tabViewPets(BuildContext context, PetsPageModel _model, controller) { Widget tabViewPets(BuildContext context, PetsPageModel _model, controller,
Function safeSetState, Function setState) {
return TabViewUtil( return TabViewUtil(
context: context, context: context,
model: _model, model: _model,
labelTab1: 'Cadastrar', labelTab1: 'Cadastrar',
labelTab2: 'Consultar', labelTab2: 'Consultar',
controller: controller, controller: controller,
widget1: formAddPets(context), widget1: formAddPets(context, _model, safeSetState, setState),
widget2: Center(child: Text('Consultar')), widget2: Center(child: Text('Consultar')),
); );
} }
Widget formAddPets(BuildContext context) { Widget formAddPets(BuildContext context, PetsPageModel _model,
Function safeSetState, Function setState) {
bool _isFormValid(BuildContext context) {
log('Validando Formulário');
if (_model.uploadedLocalFile.bytes?.isEmpty ?? true) {
return false;
}
if (_model.textControllerName.text.isEmpty) {
return false;
}
return true;
}
final _formKey = GlobalKey<FormState>();
return SingleChildScrollView( return SingleChildScrollView(
child: Column( child: Column(
mainAxisSize: MainAxisSize.max, mainAxisSize: MainAxisSize.max,
@ -91,12 +120,26 @@ Widget formAddPets(BuildContext context) {
), ),
), ),
Form( Form(
key: _formKey,
autovalidateMode: AutovalidateMode.onUserInteraction, autovalidateMode: AutovalidateMode.onUserInteraction,
child: Column( child: Column(
mainAxisSize: MainAxisSize.max, mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.spaceEvenly, mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [ children: [
Padding(
padding: const EdgeInsets.fromLTRB(0, 10, 0, 20),
child: MediaUploadButtonUtil(
uploadedFile: _model.uploadedLocalFile,
isUploading: _model.isDataUploading,
labelText: FFLocalizations.of(context).getVariableText(
ptText: 'Clique para adicionar a foto de seu Pet',
enText: 'Click to add your Pet\'s photo'),
),
),
CustomInputUtil( CustomInputUtil(
controller: _model.textControllerName,
validator:
_model.textControllerNameValidator.asValidator(context),
labelText: FFLocalizations.of(context) labelText: FFLocalizations.of(context)
.getVariableText(ptText: 'Nome', enText: 'Name'), .getVariableText(ptText: 'Nome', enText: 'Name'),
hintText: FFLocalizations.of(context) hintText: FFLocalizations.of(context)
@ -105,45 +148,160 @@ Widget formAddPets(BuildContext context) {
haveMaxLength: true, haveMaxLength: true,
maxLength: 80, maxLength: 80,
), ),
CustomInputUtil( Padding(
labelText: FFLocalizations.of(context) padding: const EdgeInsets.fromLTRB(0, 0, 0, 15),
.getVariableText(ptText: 'Espécie', enText: 'Species'), child: CustomInputUtil(
hintText: FFLocalizations.of(context) controller: _model.textControllerSpecies,
.getVariableText(ptText: 'Espécie', enText: 'Species'), labelText: FFLocalizations.of(context).getVariableText(
suffixIcon: Icons.pest_control, ptText: 'Espécie', enText: 'Species'),
haveMaxLength: false, hintText: FFLocalizations.of(context).getVariableText(
ptText: 'Espécie', enText: 'Species'),
suffixIcon: Icons.pest_control,
haveMaxLength: false,
),
),
Padding(
padding: const EdgeInsets.fromLTRB(0, 0, 0, 15),
child: CustomInputUtil(
controller: _model.textControllerRace,
labelText: FFLocalizations.of(context)
.getVariableText(ptText: 'Raça', enText: 'Race'),
hintText: FFLocalizations.of(context)
.getVariableText(ptText: 'Raça', enText: 'Race'),
suffixIcon: Icons.pets,
haveMaxLength: false,
),
),
Padding(
padding: const EdgeInsets.fromLTRB(0, 0, 0, 15),
child: CustomInputUtil(
controller: _model.textControllerColor,
labelText: FFLocalizations.of(context)
.getVariableText(ptText: 'Cor', enText: 'Color'),
hintText: FFLocalizations.of(context)
.getVariableText(ptText: 'Cor', enText: 'Color'),
suffixIcon: Icons.invert_colors,
haveMaxLength: false,
),
),
Padding(
padding: const EdgeInsets.fromLTRB(0, 0, 0, 15),
child: CustomDatePickerUtil(
controller: _model.textControllerData,
focusNode: _model.textFieldFocusData,
hintText: FFLocalizations.of(context).getVariableText(
ptText: 'Data de Nascimento', enText: 'Birth Date'),
dateFormat: 'dd/MM/yyyy HH:mm:ss',
locale: FFLocalizations.of(context).languageCode,
firstDate: DateTime(2000),
lastDate: DateTime.now(),
timePicker: false,
validator: (value) {
if (value == null || value.isEmpty) {
return 'Por favor, selecione uma data';
}
return null;
},
),
),
Align(
alignment: const AlignmentDirectional(-1.0, 0.0),
child: Padding(
padding: const EdgeInsetsDirectional.fromSTEB(
24.0, 0, 0.0, 15),
child: Text(
FFLocalizations.of(context).getVariableText(
ptText: 'Selecione as opções disponíveis',
enText: 'Select the available options',
),
textAlign: TextAlign.start,
style: FlutterFlowTheme.of(context).bodySmall.override(
fontFamily:
FlutterFlowTheme.of(context).bodySmallFamily,
letterSpacing: 0.0,
fontWeight: FontWeight.w600,
useGoogleFonts: GoogleFonts.asMap().containsKey(
FlutterFlowTheme.of(context)
.bodyMediumFamily),
),
),
),
),
Padding(
padding: const EdgeInsets.fromLTRB(0, 0, 0, 15),
child: CustomSelect(
options: const ['MAC', 'FEM'],
controller: _model.dropDownValueController1,
optionsLabel: [
FFLocalizations.of(context)
.getVariableText(ptText: 'Macho', enText: 'Male'),
FFLocalizations.of(context).getVariableText(
ptText: 'Fêmea', enText: 'Female')
],
hintText: FFLocalizations.of(context).getVariableText(
ptText: 'Selecione o gênero do Pet',
enText: 'Select the gender of the Pet')),
),
Padding(
padding: const EdgeInsets.fromLTRB(0, 0, 0, 15),
child: CustomSelect(
options: const ['MIN', 'PEQ', 'MED', 'GRA', 'GIG'],
controller: _model.dropDownValueController1,
optionsLabel: [
FFLocalizations.of(context)
.getVariableText(ptText: 'Mini', enText: 'Mini'),
FFLocalizations.of(context).getVariableText(
ptText: 'Pequeno', enText: 'Small'),
FFLocalizations.of(context).getVariableText(
ptText: 'Médio', enText: 'Medium'),
FFLocalizations.of(context)
.getVariableText(ptText: 'Grande', enText: 'Big'),
FFLocalizations.of(context).getVariableText(
ptText: 'Gigante', enText: 'Giant'),
],
hintText: FFLocalizations.of(context).getVariableText(
ptText: 'Selecione o porte do Pet',
enText: 'Select the size of the Pet')),
),
Align(
alignment: const AlignmentDirectional(-1.0, 0.0),
child: Padding(
padding: const EdgeInsetsDirectional.fromSTEB(
24.0, 0, 0.0, 15),
child: Text(
FFLocalizations.of(context).getVariableText(
ptText: 'Você tem alguma observação sobre o seu Pet?',
enText:
'Do you have any observations about your Pet?',
),
textAlign: TextAlign.start,
style: FlutterFlowTheme.of(context).bodySmall.override(
fontFamily:
FlutterFlowTheme.of(context).bodySmallFamily,
letterSpacing: 0.0,
fontWeight: FontWeight.w600,
useGoogleFonts: GoogleFonts.asMap().containsKey(
FlutterFlowTheme.of(context)
.bodyMediumFamily),
),
),
),
), ),
CustomInputUtil( CustomInputUtil(
labelText: FFLocalizations.of(context) controller: _model.textControllerObservation,
.getVariableText(ptText: 'Raça', enText: 'Race'), labelText: FFLocalizations.of(context).getVariableText(
hintText: FFLocalizations.of(context) ptText: 'Escreva as suas observações aqui...',
.getVariableText(ptText: 'Raça', enText: 'Race'), enText: 'Write your observations here...'),
suffixIcon: Icons.pets,
haveMaxLength: false,
),
CustomInputUtil(
labelText: FFLocalizations.of(context)
.getVariableText(ptText: 'Cor', enText: 'Color'),
hintText: FFLocalizations.of(context)
.getVariableText(ptText: 'Cor', enText: 'Color'),
suffixIcon: Icons.invert_colors,
haveMaxLength: false,
),
CustomDatePickerUtil(
// controller: ,
hintText: FFLocalizations.of(context).getVariableText( hintText: FFLocalizations.of(context).getVariableText(
ptText: 'Data de Nascimento', enText: 'Birth Date'), ptText: 'Escreva as suas observações aqui...',
dateFormat: 'dd/MM/yyyy HH:mm:ss', enText: 'Write your observations here...'),
locale: FFLocalizations.of(context).languageCode, suffixIcon: Icons.text_fields,
firstDate: DateTime(2000), haveMaxLength: true,
lastDate: DateTime(2050), maxLength: 80,
validator: (value) {
if (value == null || value.isEmpty) {
return 'Por favor, selecione uma data';
}
return null;
},
), ),
ElevatedButton(
onPressed: _isFormValid(context) ? () {} : () {},
child: Text('Cadastrar')),
])), ])),
], ],
), ),