From b4257dd5aba498c576569767dcec9b1ad442c379 Mon Sep 17 00:00:00 2001 From: R1K4S Date: Wed, 4 Dec 2024 12:29:21 -0300 Subject: [PATCH 1/8] =?UTF-8?q?feat(#59):=20Cria=C3=A7=C3=A3o=20da=20tela?= =?UTF-8?q?=20EditProfile=20e=20algumas=20classes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/main.dart | 3 +- lib/ui/edit_profile/view/EditProfile.dart | 200 ++++++++++++++++++++++ lib/ui/profile/view/Profile.dart | 0 lib/ui/shared/CustomTextField.dart | 50 ++++++ 4 files changed, 252 insertions(+), 1 deletion(-) create mode 100644 lib/ui/edit_profile/view/EditProfile.dart create mode 100644 lib/ui/profile/view/Profile.dart create mode 100644 lib/ui/shared/CustomTextField.dart diff --git a/lib/main.dart b/lib/main.dart index b053769..a504e6e 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -1,6 +1,7 @@ import 'package:aranduapp/config/ThemeApp.dart'; import 'package:flutter/material.dart'; import 'package:aranduapp/ui/login/view/LoginView.dart'; +import 'package:aranduapp/ui/edit_profile/view/EditProfile.dart'; void main() { runApp(const MyApp()); @@ -15,7 +16,7 @@ class MyApp extends StatelessWidget { theme: ThemeApp.themeData(), darkTheme: ThemeApp.darkThemeData(), debugShowCheckedModeBanner: false, - home: Login(), + home: EditProfile(), ); } } diff --git a/lib/ui/edit_profile/view/EditProfile.dart b/lib/ui/edit_profile/view/EditProfile.dart new file mode 100644 index 0000000..de7161d --- /dev/null +++ b/lib/ui/edit_profile/view/EditProfile.dart @@ -0,0 +1,200 @@ +import 'package:flutter/material.dart'; + +import 'package:aranduapp/ui/shared/TextEmail.dart'; +import 'package:aranduapp/ui/shared/CustomTextField.dart'; +import 'package:aranduapp/ui/shared/TextPassword.dart'; + +class EditProfile extends StatelessWidget { + final TextEditingController firstNameController = TextEditingController(); + final TextEditingController lastNameController = TextEditingController(); + final TextEditingController emailController = TextEditingController(); + final TextEditingController passwordController = TextEditingController(); + + + EditProfile({Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: PreferredSize( + preferredSize: const Size.fromHeight(100), // Altura da AppBar + child: AppBar( + elevation: 0, + backgroundColor: Colors.transparent, + flexibleSpace: Container( + decoration: BoxDecoration( + color: Colors.white, + borderRadius: const BorderRadius.only( + bottomLeft: Radius.circular(25), + bottomRight: Radius.circular(25), + ), + ), + child: Padding( + padding: const EdgeInsets.only(top: 40.0, left: 16.0, right: 16.0), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + // Botão de voltar + IconButton( + onPressed: () { + Navigator.of(context).pop(); + }, + icon: const Icon(Icons.arrow_back, color: Colors.black), + iconSize: 24, + padding: const EdgeInsets.all(8), + color: Colors.grey[300], + ), + + // Título + const Text( + 'Editar Perfil', + style: TextStyle( + fontSize: 20, + fontWeight: FontWeight.w900, + color: Colors.black, + ), + ), + + // Ícone de notificação + IconButton( + onPressed: () { + // Ação para notificações + }, + icon: const Icon(Icons.notifications_outlined, + color: Colors.black), + iconSize: 24, + padding: const EdgeInsets.all(8), + color: Colors.grey[300], + ), + ], + ), + ), + ), + ), + ), + body: Padding( + padding: const EdgeInsets.all(16.0), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + // Campo Nome usando CustomTextField + CustomTextField( + label: 'Primeiro Nome', + placeholder: 'Stefani', + controller: firstNameController, + ), + const SizedBox(height: 16), + + // Campo Último Nome usando CustomTextField + CustomTextField( + label: 'Último Nome', + placeholder: 'Silva', + controller: lastNameController, + ), + const SizedBox(height: 16), + + // Campo E-mail usando TextEmail + TextEmail( + padding: const EdgeInsets.symmetric(horizontal: 0), + controller: emailController, + ), + const SizedBox(height: 32), + + // Campo Password usando TextPassword + TextPassWord( + padding: const EdgeInsets.symmetric(horizontal: 0), + controller: emailController, + ), + const SizedBox(height: 32), + + // Botões lado a lado + Row( + children: [ + + // Botão Deletar Conta + Expanded( + child: ElevatedButton( + onPressed: () { + // Chamar função de deletar conta + _showDeleteConfirmationDialog(context); + }, + style: ElevatedButton.styleFrom( + backgroundColor: const Color.fromARGB(255, 234, 36,31), // Cor do botão + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(20), + ), + padding: const EdgeInsets.symmetric(vertical: 16), + ), + child: const Text( + 'Deletar Conta', + style: TextStyle( + fontSize: 16, + color: Colors.white, // Cor do texto + ), + ), + ), + ), + const SizedBox(width: 64), // Espaçamento entre os botões + // Botão Salvar + Expanded( + child: ElevatedButton( + onPressed: () { + // Lógica ao salvar perfil + print('Primeiro Nome: ${firstNameController.text}'); + print('Último Nome: ${lastNameController.text}'); + print('E-mail: ${emailController.text}'); + }, + style: ElevatedButton.styleFrom( + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(20), + ), + padding: const EdgeInsets.symmetric(vertical: 16), + ), + child: const Text( + 'Salvar', + style: TextStyle(fontSize: 16) + + + ), + ), + ), + ], + ), + ], + ), + ), + ); + } + + void _showDeleteConfirmationDialog(BuildContext context) { + showDialog( + context: context, + builder: (BuildContext context) { + return AlertDialog( + title: const Text('Confirmar Deleção'), + content: const Text( + 'Tem certeza de que deseja deletar sua conta? Essa ação não pode ser desfeita.'), + actions: [ + TextButton( + onPressed: () { + Navigator.of(context).pop(); // Fechar o diálogo + }, + child: const Text('Cancelar'), + ), + ElevatedButton( + onPressed: () { + // Lógica para deletar a conta + print('Conta deletada'); + Navigator.of(context).pop(); // Fechar o diálogo + }, + style: ElevatedButton.styleFrom( + backgroundColor: Colors.red, // Cor do botão + ), + child: const Text('Deletar'), + ), + ], + ); + }, + ); + } +} diff --git a/lib/ui/profile/view/Profile.dart b/lib/ui/profile/view/Profile.dart new file mode 100644 index 0000000..e69de29 diff --git a/lib/ui/shared/CustomTextField.dart b/lib/ui/shared/CustomTextField.dart new file mode 100644 index 0000000..07f734a --- /dev/null +++ b/lib/ui/shared/CustomTextField.dart @@ -0,0 +1,50 @@ +import 'package:flutter/material.dart'; + +class CustomTextField extends StatelessWidget { + final String label; + final String? placeholder; + final TextEditingController? controller; + final bool obscureText; + + const CustomTextField({ + Key? key, + required this.label, + this.placeholder, + this.controller, + this.obscureText = false, + }) : super(key: key); + + @override + Widget build(BuildContext context) { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + label, + style: const TextStyle( + fontSize: 16, + fontWeight: FontWeight.bold, + ), + ), + const SizedBox(height: 8), + TextField( + controller: controller, + obscureText: obscureText, + decoration: InputDecoration( + hintText: placeholder, + filled: true, + fillColor: const Color(0xFFF5F5F5), + contentPadding: const EdgeInsets.symmetric( + horizontal: 16, + vertical: 12, + ), + border: OutlineInputBorder( + borderRadius: BorderRadius.circular(20), + borderSide: BorderSide.none, + ), + ), + ), + ], + ); + } +} \ No newline at end of file From 6b9bdb00667c4aa96b71d722196f181a2125c843 Mon Sep 17 00:00:00 2001 From: R1K4S Date: Wed, 4 Dec 2024 20:24:59 -0300 Subject: [PATCH 2/8] =?UTF-8?q?(#59):=20Modifica=C3=A7=C3=A3o=20da=20?= =?UTF-8?q?tela=20EditProfile?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- devtools_options.yaml | 3 + lib/ui/edit_profile/view/EditProfile.dart | 233 +++++++++++++--------- lib/ui/shared/ProfileCard.Dart | 51 +++++ 3 files changed, 190 insertions(+), 97 deletions(-) create mode 100644 devtools_options.yaml create mode 100644 lib/ui/shared/ProfileCard.Dart diff --git a/devtools_options.yaml b/devtools_options.yaml new file mode 100644 index 0000000..fa0b357 --- /dev/null +++ b/devtools_options.yaml @@ -0,0 +1,3 @@ +description: This file stores settings for Dart & Flutter DevTools. +documentation: https://docs.flutter.dev/tools/devtools/extensions#configure-extension-enablement-states +extensions: diff --git a/lib/ui/edit_profile/view/EditProfile.dart b/lib/ui/edit_profile/view/EditProfile.dart index de7161d..4886c40 100644 --- a/lib/ui/edit_profile/view/EditProfile.dart +++ b/lib/ui/edit_profile/view/EditProfile.dart @@ -1,5 +1,5 @@ import 'package:flutter/material.dart'; - +import 'package:aranduapp/ui/shared/ProfileCard.dart'; import 'package:aranduapp/ui/shared/TextEmail.dart'; import 'package:aranduapp/ui/shared/CustomTextField.dart'; import 'package:aranduapp/ui/shared/TextPassword.dart'; @@ -10,14 +10,13 @@ class EditProfile extends StatelessWidget { final TextEditingController emailController = TextEditingController(); final TextEditingController passwordController = TextEditingController(); - EditProfile({Key? key}) : super(key: key); @override Widget build(BuildContext context) { return Scaffold( appBar: PreferredSize( - preferredSize: const Size.fromHeight(100), // Altura da AppBar + preferredSize: const Size.fromHeight(80), // Altura reduzida da AppBar child: AppBar( elevation: 0, backgroundColor: Colors.transparent, @@ -30,7 +29,8 @@ class EditProfile extends StatelessWidget { ), ), child: Padding( - padding: const EdgeInsets.only(top: 40.0, left: 16.0, right: 16.0), + padding: + const EdgeInsets.only(top: 40.0, left: 16.0, right: 16.0), child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ @@ -40,31 +40,25 @@ class EditProfile extends StatelessWidget { Navigator.of(context).pop(); }, icon: const Icon(Icons.arrow_back, color: Colors.black), - iconSize: 24, - padding: const EdgeInsets.all(8), - color: Colors.grey[300], ), - // Título const Text( 'Editar Perfil', style: TextStyle( fontSize: 20, - fontWeight: FontWeight.w900, + fontWeight: FontWeight.bold, color: Colors.black, ), ), - // Ícone de notificação IconButton( onPressed: () { // Ação para notificações }, - icon: const Icon(Icons.notifications_outlined, - color: Colors.black), - iconSize: 24, - padding: const EdgeInsets.all(8), - color: Colors.grey[300], + icon: const Icon( + Icons.notifications_outlined, + color: Colors.black, + ), ), ], ), @@ -72,95 +66,141 @@ class EditProfile extends StatelessWidget { ), ), ), - body: Padding( - padding: const EdgeInsets.all(16.0), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - // Campo Nome usando CustomTextField - CustomTextField( - label: 'Primeiro Nome', - placeholder: 'Stefani', - controller: firstNameController, - ), - const SizedBox(height: 16), + body: SingleChildScrollView( + child: Padding( + padding: const EdgeInsets.all(16.0), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + // Ícone abaixo da AppBar + const SizedBox(height: 16), + // Card com informações do perfil + ProfileCard( + name: 'Stefani', + role: 'Estudante', + avatarUrl: 'https://via.placeholder.com/150', // URL do avatar + ), + const SizedBox(height: 32), - // Campo Último Nome usando CustomTextField - CustomTextField( - label: 'Último Nome', - placeholder: 'Silva', - controller: lastNameController, - ), - const SizedBox(height: 16), + // Campo Nome usando CustomTextField + CustomTextField( + label: 'Primeiro Nome', + placeholder: 'Stefani', + controller: firstNameController, + ), + const SizedBox(height: 16), - // Campo E-mail usando TextEmail - TextEmail( - padding: const EdgeInsets.symmetric(horizontal: 0), - controller: emailController, - ), - const SizedBox(height: 32), + // Campo Último Nome usando CustomTextField + CustomTextField( + label: 'Último Nome', + placeholder: 'Silva', + controller: lastNameController, + ), + const SizedBox(height: 16), - // Campo Password usando TextPassword - TextPassWord( - padding: const EdgeInsets.symmetric(horizontal: 0), - controller: emailController, - ), - const SizedBox(height: 32), + // Campo E-mail usando TextEmail + TextEmail( + padding: const EdgeInsets.symmetric(horizontal: 0), + controller: emailController, + ), + const SizedBox(height: 32), - // Botões lado a lado - Row( - children: [ - - // Botão Deletar Conta - Expanded( - child: ElevatedButton( - onPressed: () { - // Chamar função de deletar conta - _showDeleteConfirmationDialog(context); - }, - style: ElevatedButton.styleFrom( - backgroundColor: const Color.fromARGB(255, 234, 36,31), // Cor do botão - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(20), + // Campo Password usando TextPassword + TextPassWord( + padding: const EdgeInsets.symmetric(horizontal: 0), + controller: passwordController, + ), + const SizedBox(height: 32), + + // Botões lado a lado + Row( + children: [ + // Botão Deletar Conta + Expanded( + child: ElevatedButton( + onPressed: () { + _showDeleteConfirmationDialog(context); + }, + style: ElevatedButton.styleFrom( + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(20), + ), + padding: const EdgeInsets.symmetric(vertical: 0), + backgroundColor: Colors.transparent, + shadowColor: Colors.transparent, ), - padding: const EdgeInsets.symmetric(vertical: 16), - ), - child: const Text( - 'Deletar Conta', - style: TextStyle( - fontSize: 16, - color: Colors.white, // Cor do texto + child: Ink( + decoration: BoxDecoration( + gradient: LinearGradient( + colors: [ + Color.fromRGBO(144, 11, 9, 1), + Color.fromRGBO(236, 34, 31, 1) + ], + begin: Alignment.bottomLeft, + end: Alignment.topLeft, + ), + borderRadius: BorderRadius.circular(20), + ), + child: Container( + alignment: Alignment.center, + padding: const EdgeInsets.symmetric(vertical: 16), + child: const Text( + 'Deletar Conta', + style: TextStyle( + fontSize: 16, + color: Colors.white, + ), + ), + ), ), ), ), - ), - const SizedBox(width: 64), // Espaçamento entre os botões - // Botão Salvar - Expanded( - child: ElevatedButton( - onPressed: () { - // Lógica ao salvar perfil - print('Primeiro Nome: ${firstNameController.text}'); - print('Último Nome: ${lastNameController.text}'); - print('E-mail: ${emailController.text}'); - }, - style: ElevatedButton.styleFrom( - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(20), + const SizedBox(width: 64), + Expanded( + child: ElevatedButton( + onPressed: () { + print('Primeiro Nome: ${firstNameController.text}'); + print('Último Nome: ${lastNameController.text}'); + print('E-mail: ${emailController.text}'); + }, + style: ElevatedButton.styleFrom( + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(20), + ), + padding: const EdgeInsets.symmetric(vertical: 0), + backgroundColor: Colors.transparent, + shadowColor: Colors.transparent, + ), + child: Ink( + decoration: BoxDecoration( + gradient: LinearGradient( + colors: [ + Color.fromRGBO(8, 145, 178, 1), + Color.fromRGBO(127, 219, 229, 1) + ], + begin: Alignment.topLeft, + end: Alignment.bottomRight, + ), + borderRadius: BorderRadius.circular(20), + ), + child: Container( + alignment: Alignment.center, + padding: const EdgeInsets.symmetric(vertical: 16), + child: const Text( + 'Salvar', + style: TextStyle( + fontSize: 16, + color: Colors.white, + ), + ), + ), ), - padding: const EdgeInsets.symmetric(vertical: 16), - ), - child: const Text( - 'Salvar', - style: TextStyle(fontSize: 16) - - ), ), - ), - ], - ), - ], + ], + ), + ], + ), ), ), ); @@ -177,18 +217,17 @@ class EditProfile extends StatelessWidget { actions: [ TextButton( onPressed: () { - Navigator.of(context).pop(); // Fechar o diálogo + Navigator.of(context).pop(); }, child: const Text('Cancelar'), ), ElevatedButton( onPressed: () { - // Lógica para deletar a conta print('Conta deletada'); - Navigator.of(context).pop(); // Fechar o diálogo + Navigator.of(context).pop(); }, style: ElevatedButton.styleFrom( - backgroundColor: Colors.red, // Cor do botão + backgroundColor: Colors.red, ), child: const Text('Deletar'), ), diff --git a/lib/ui/shared/ProfileCard.Dart b/lib/ui/shared/ProfileCard.Dart new file mode 100644 index 0000000..79cd103 --- /dev/null +++ b/lib/ui/shared/ProfileCard.Dart @@ -0,0 +1,51 @@ +import 'package:flutter/material.dart'; + +class ProfileCard extends StatelessWidget { + final String name; + final String role; + final String avatarUrl; + + const ProfileCard({ + Key? key, + required this.name, + required this.role, + required this.avatarUrl, + }) : super(key: key); + + @override + Widget build(BuildContext context) { + return Row( + children: [ + // Avatar + CircleAvatar( + radius: 30, // Tamanho do avatar + backgroundImage: NetworkImage(avatarUrl), + backgroundColor: Colors.transparent, + ), + const SizedBox(width: 12), // Espaçamento entre avatar e texto + // Nome e função + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + name, + style: const TextStyle( + fontSize: 18, + fontWeight: FontWeight.bold, + color: Colors.black, + ), + ), + const SizedBox(height: 4), // Espaçamento entre nome e função + Text( + role, + style: const TextStyle( + fontSize: 14, + color: Colors.grey, + ), + ), + ], + ), + ], + ); + } +} From 856029d655528bd2b217df432a5c8c1c2e93dac4 Mon Sep 17 00:00:00 2001 From: R1K4S Date: Sat, 7 Dec 2024 00:33:26 -0300 Subject: [PATCH 3/8] =?UTF-8?q?(#59):Adpata=C3=A7=C3=A3o=20para=20o?= =?UTF-8?q?=20Modelo=20MVVM?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../model/EditProfileRequest.dart | 0 .../model/EditProfileResponse.dart | 0 .../service/EditProfileService.dart | 0 lib/ui/edit_profile/view/EditProfile.dart | 356 +++++++++--------- .../viewModel/EditProfileView.dart | 0 5 files changed, 180 insertions(+), 176 deletions(-) create mode 100644 lib/ui/edit_profile/model/EditProfileRequest.dart create mode 100644 lib/ui/edit_profile/model/EditProfileResponse.dart create mode 100644 lib/ui/edit_profile/service/EditProfileService.dart create mode 100644 lib/ui/edit_profile/viewModel/EditProfileView.dart diff --git a/lib/ui/edit_profile/model/EditProfileRequest.dart b/lib/ui/edit_profile/model/EditProfileRequest.dart new file mode 100644 index 0000000..e69de29 diff --git a/lib/ui/edit_profile/model/EditProfileResponse.dart b/lib/ui/edit_profile/model/EditProfileResponse.dart new file mode 100644 index 0000000..e69de29 diff --git a/lib/ui/edit_profile/service/EditProfileService.dart b/lib/ui/edit_profile/service/EditProfileService.dart new file mode 100644 index 0000000..e69de29 diff --git a/lib/ui/edit_profile/view/EditProfile.dart b/lib/ui/edit_profile/view/EditProfile.dart index 4886c40..fe3e043 100644 --- a/lib/ui/edit_profile/view/EditProfile.dart +++ b/lib/ui/edit_profile/view/EditProfile.dart @@ -1,5 +1,5 @@ import 'package:flutter/material.dart'; -import 'package:aranduapp/ui/shared/ProfileCard.dart'; +//import 'package:aranduapp/ui/shared/ProfileCard.dart'; import 'package:aranduapp/ui/shared/TextEmail.dart'; import 'package:aranduapp/ui/shared/CustomTextField.dart'; import 'package:aranduapp/ui/shared/TextPassword.dart'; @@ -15,193 +15,200 @@ class EditProfile extends StatelessWidget { @override Widget build(BuildContext context) { return Scaffold( - appBar: PreferredSize( - preferredSize: const Size.fromHeight(80), // Altura reduzida da AppBar - child: AppBar( - elevation: 0, - backgroundColor: Colors.transparent, - flexibleSpace: Container( - decoration: BoxDecoration( - color: Colors.white, - borderRadius: const BorderRadius.only( - bottomLeft: Radius.circular(25), - bottomRight: Radius.circular(25), - ), + appBar: AppBar( + backgroundColor: const Color.fromARGB( + 255, 255, 255, 255), // Define o fundo transparente + elevation: 0, // Remove a sombra da AppBar + title: Center( + child: Text( + 'Editar perfil', ), - child: Padding( - padding: - const EdgeInsets.only(top: 40.0, left: 16.0, right: 16.0), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - // Botão de voltar - IconButton( - onPressed: () { - Navigator.of(context).pop(); - }, - icon: const Icon(Icons.arrow_back, color: Colors.black), - ), - // Título - const Text( - 'Editar Perfil', - style: TextStyle( - fontSize: 20, - fontWeight: FontWeight.bold, - color: Colors.black, - ), - ), - // Ícone de notificação - IconButton( - onPressed: () { - // Ação para notificações - }, - icon: const Icon( - Icons.notifications_outlined, - color: Colors.black, - ), - ), - ], - ), + ), + actions: [ + IconButton( + icon: Icon(Icons.notifications), // Ícone de notificação + onPressed: () { + // Ação quando o ícone de notificação for pressionado + }, ), + ], + leading: IconButton( + icon: Icon(Icons.arrow_back), + onPressed: () {}, ), ), + body: Column( + mainAxisAlignment: MainAxisAlignment.spaceAround, + children: [ + _icon(context), + _nameAndLast(context), + _emailAndPassword(context), + Row(mainAxisAlignment: MainAxisAlignment.spaceAround, children: [ + _deleteButton(context), + _saveButton(context), + ]) + ], + )); + } + + Widget _nameAndLast(BuildContext context) { + return SingleChildScrollView( + child: Column( + children: [ + CustomTextField( + label: ' Primeiro Nome', + placeholder: 'Stefani', + controller: firstNameController, + ), + + // Campo Último Nome usando CustomTextFieldq + CustomTextField( + label: ' Último Nome', + placeholder: 'Silva', + controller: lastNameController, + ), + ], ), - body: SingleChildScrollView( - child: Padding( - padding: const EdgeInsets.all(16.0), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - // Ícone abaixo da AppBar - const SizedBox(height: 16), - // Card com informações do perfil - ProfileCard( - name: 'Stefani', - role: 'Estudante', - avatarUrl: 'https://via.placeholder.com/150', // URL do avatar - ), - const SizedBox(height: 32), + ); + } - // Campo Nome usando CustomTextField - CustomTextField( - label: 'Primeiro Nome', - placeholder: 'Stefani', - controller: firstNameController, - ), - const SizedBox(height: 16), + Widget _emailAndPassword(BuildContext context) { + return SingleChildScrollView( + child: Column( + children: [ + TextEmail( + padding: const EdgeInsets.symmetric(horizontal: 0), + controller: emailController, + ), + TextPassWord( + padding: const EdgeInsets.symmetric(horizontal: 0), + controller: passwordController, + ), + ], + ), + ); + } - // Campo Último Nome usando CustomTextField - CustomTextField( - label: 'Último Nome', - placeholder: 'Silva', - controller: lastNameController, + Widget _saveButton(BuildContext context) { + return SingleChildScrollView( + child: ElevatedButton( + onPressed: () { + print('Primeiro Nome: ${firstNameController.text}'); + print('Último Nome: ${lastNameController.text}'); + print('E-mail: ${emailController.text}'); + }, + style: ElevatedButton.styleFrom( + fixedSize: Size(200, 50), + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(20), + ), + padding: const EdgeInsets.symmetric(vertical: 0), + backgroundColor: Colors.transparent, + shadowColor: Colors.transparent, + ), + child: Ink( + decoration: BoxDecoration( + gradient: LinearGradient( + colors: [ + Color.fromRGBO(8, 145, 178, 1), + Color.fromRGBO(127, 219, 229, 1) + ], + begin: Alignment.topLeft, + end: Alignment.bottomRight, + ), + borderRadius: BorderRadius.circular(20), + ), + child: Container( + alignment: Alignment.center, + padding: const EdgeInsets.symmetric(vertical: 8), + child: const Text( + 'Salvar', + style: TextStyle( + fontSize: 16, + color: Colors.white, ), - const SizedBox(height: 16), + ), + ), + ), + ), + ); + } - // Campo E-mail usando TextEmail - TextEmail( - padding: const EdgeInsets.symmetric(horizontal: 0), - controller: emailController, + Widget _deleteButton(BuildContext context) { + return SingleChildScrollView( + child: ElevatedButton( + onPressed: () { + _showDeleteConfirmationDialog(context); + }, + style: ElevatedButton.styleFrom( + fixedSize: Size(200, 50), + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(20), + ), + padding: const EdgeInsets.symmetric(vertical: 0), + backgroundColor: Colors.transparent, + shadowColor: Colors.transparent, + ), + child: Ink( + decoration: BoxDecoration( + gradient: LinearGradient( + colors: [ + Color.fromRGBO(144, 11, 9, 1), + Color.fromRGBO(236, 34, 31, 1) + ], + begin: Alignment.bottomLeft, + end: Alignment.topLeft, + ), + borderRadius: BorderRadius.circular(20), + ), + child: Container( + alignment: Alignment.center, + padding: const EdgeInsets.symmetric(vertical: 8), + child: const Text( + 'Deletar Conta', + style: TextStyle( + fontSize: 16, + color: Colors.white, ), - const SizedBox(height: 32), + ), + ), + ), + ), + ); + } - // Campo Password usando TextPassword - TextPassWord( - padding: const EdgeInsets.symmetric(horizontal: 0), - controller: passwordController, + Widget _icon(BuildContext context) { + return Padding( + padding: const EdgeInsets.only( + left: 16.0), // Adiciona espaço da borda esquerda + child: Row( + children: [ + // Ícone circular + CircleAvatar( + radius: 30, // Tamanho do círculo + ), + SizedBox(width: 16), // Espaço entre a imagem e o texto + // Texto com o nome e o cargo + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + "Stefani", + style: TextStyle( + fontSize: 18, + fontWeight: FontWeight.bold, + ), ), - const SizedBox(height: 32), - - // Botões lado a lado - Row( - children: [ - // Botão Deletar Conta - Expanded( - child: ElevatedButton( - onPressed: () { - _showDeleteConfirmationDialog(context); - }, - style: ElevatedButton.styleFrom( - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(20), - ), - padding: const EdgeInsets.symmetric(vertical: 0), - backgroundColor: Colors.transparent, - shadowColor: Colors.transparent, - ), - child: Ink( - decoration: BoxDecoration( - gradient: LinearGradient( - colors: [ - Color.fromRGBO(144, 11, 9, 1), - Color.fromRGBO(236, 34, 31, 1) - ], - begin: Alignment.bottomLeft, - end: Alignment.topLeft, - ), - borderRadius: BorderRadius.circular(20), - ), - child: Container( - alignment: Alignment.center, - padding: const EdgeInsets.symmetric(vertical: 16), - child: const Text( - 'Deletar Conta', - style: TextStyle( - fontSize: 16, - color: Colors.white, - ), - ), - ), - ), - ), - ), - const SizedBox(width: 64), - Expanded( - child: ElevatedButton( - onPressed: () { - print('Primeiro Nome: ${firstNameController.text}'); - print('Último Nome: ${lastNameController.text}'); - print('E-mail: ${emailController.text}'); - }, - style: ElevatedButton.styleFrom( - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(20), - ), - padding: const EdgeInsets.symmetric(vertical: 0), - backgroundColor: Colors.transparent, - shadowColor: Colors.transparent, - ), - child: Ink( - decoration: BoxDecoration( - gradient: LinearGradient( - colors: [ - Color.fromRGBO(8, 145, 178, 1), - Color.fromRGBO(127, 219, 229, 1) - ], - begin: Alignment.topLeft, - end: Alignment.bottomRight, - ), - borderRadius: BorderRadius.circular(20), - ), - child: Container( - alignment: Alignment.center, - padding: const EdgeInsets.symmetric(vertical: 16), - child: const Text( - 'Salvar', - style: TextStyle( - fontSize: 16, - color: Colors.white, - ), - ), - ), - ), - ), - ), - ], + Text( + "Estudante", + style: TextStyle( + fontSize: 14, + color: Colors.grey, + ), ), ], ), - ), + ], ), ); } @@ -226,9 +233,6 @@ class EditProfile extends StatelessWidget { print('Conta deletada'); Navigator.of(context).pop(); }, - style: ElevatedButton.styleFrom( - backgroundColor: Colors.red, - ), child: const Text('Deletar'), ), ], diff --git a/lib/ui/edit_profile/viewModel/EditProfileView.dart b/lib/ui/edit_profile/viewModel/EditProfileView.dart new file mode 100644 index 0000000..e69de29 From cffbc60ac85cf7b6d7175a461c2651389cef52dd Mon Sep 17 00:00:00 2001 From: R1K4S Date: Sat, 7 Dec 2024 00:55:14 -0300 Subject: [PATCH 4/8] (#59):Modelo base do Codigo de EditProfileView --- lib/ui/edit_profile/view/EditProfile.dart | 4 ++-- .../viewModel/EditProfileView.dart | 22 +++++++++++++++++++ 2 files changed, 24 insertions(+), 2 deletions(-) diff --git a/lib/ui/edit_profile/view/EditProfile.dart b/lib/ui/edit_profile/view/EditProfile.dart index fe3e043..ddeb193 100644 --- a/lib/ui/edit_profile/view/EditProfile.dart +++ b/lib/ui/edit_profile/view/EditProfile.dart @@ -5,13 +5,13 @@ import 'package:aranduapp/ui/shared/CustomTextField.dart'; import 'package:aranduapp/ui/shared/TextPassword.dart'; class EditProfile extends StatelessWidget { + EditProfile({Key? key}) : super(key: key); + final TextEditingController firstNameController = TextEditingController(); final TextEditingController lastNameController = TextEditingController(); final TextEditingController emailController = TextEditingController(); final TextEditingController passwordController = TextEditingController(); - EditProfile({Key? key}) : super(key: key); - @override Widget build(BuildContext context) { return Scaffold( diff --git a/lib/ui/edit_profile/viewModel/EditProfileView.dart b/lib/ui/edit_profile/viewModel/EditProfileView.dart index e69de29..0543e4c 100644 --- a/lib/ui/edit_profile/viewModel/EditProfileView.dart +++ b/lib/ui/edit_profile/viewModel/EditProfileView.dart @@ -0,0 +1,22 @@ +import 'package:flutter/material.dart'; +import 'package:local_auth/local_auth.dart'; +import 'package:aranduapp/ui/edit_profile/service/EditProfileService.dart'; +import 'package:aranduapp/ui/edit_profile/model/EditProfileRequest.dart'; + +import 'package:aranduapp/ui/home/view/HomeView.dart'; + +class EditProfileViewModel extends ChangeNotifier { + final BuildContext context; + + bool isLoading; + + final GlobalKey formKey; + final TextEditingController emailController; + final TextEditingController passwordController; + + EditProfileViewModel(this.context) + : isLoading = false, + formKey = GlobalKey(), + emailController = TextEditingController(), + passwordController = TextEditingController(); +} From 36a934b35b44b6469ec16cb838c89a5198f456fb Mon Sep 17 00:00:00 2001 From: R1K4S Date: Sat, 7 Dec 2024 01:35:10 -0300 Subject: [PATCH 5/8] (#59):Alterando o EditProfileViewModel --- lib/main.dart | 2 +- .../view/{EditProfile.dart => EditProfileView.dart} | 12 ++++++++++++ ...ditProfileView.dart => EditProfileViewModel.dart} | 8 ++++++-- 3 files changed, 19 insertions(+), 3 deletions(-) rename lib/ui/edit_profile/view/{EditProfile.dart => EditProfileView.dart} (96%) rename lib/ui/edit_profile/viewModel/{EditProfileView.dart => EditProfileViewModel.dart} (74%) diff --git a/lib/main.dart b/lib/main.dart index a504e6e..6819571 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -1,7 +1,7 @@ import 'package:aranduapp/config/ThemeApp.dart'; import 'package:flutter/material.dart'; import 'package:aranduapp/ui/login/view/LoginView.dart'; -import 'package:aranduapp/ui/edit_profile/view/EditProfile.dart'; +import 'package:aranduapp/ui/edit_profile/view/EditProfileView.dart'; void main() { runApp(const MyApp()); diff --git a/lib/ui/edit_profile/view/EditProfile.dart b/lib/ui/edit_profile/view/EditProfileView.dart similarity index 96% rename from lib/ui/edit_profile/view/EditProfile.dart rename to lib/ui/edit_profile/view/EditProfileView.dart index ddeb193..e5fc7f6 100644 --- a/lib/ui/edit_profile/view/EditProfile.dart +++ b/lib/ui/edit_profile/view/EditProfileView.dart @@ -4,6 +4,18 @@ import 'package:aranduapp/ui/shared/TextEmail.dart'; import 'package:aranduapp/ui/shared/CustomTextField.dart'; import 'package:aranduapp/ui/shared/TextPassword.dart'; +class EditProfile extends StatelessWidget { + const EditProfile({super.key}); + + @override + Widget build(BuildContext context) { + return ChangeNotifierProvider( + create: (context) => EditProfile(context), + child: const _EditProfile(), + ); + } +} + class EditProfile extends StatelessWidget { EditProfile({Key? key}) : super(key: key); diff --git a/lib/ui/edit_profile/viewModel/EditProfileView.dart b/lib/ui/edit_profile/viewModel/EditProfileViewModel.dart similarity index 74% rename from lib/ui/edit_profile/viewModel/EditProfileView.dart rename to lib/ui/edit_profile/viewModel/EditProfileViewModel.dart index 0543e4c..6c6022a 100644 --- a/lib/ui/edit_profile/viewModel/EditProfileView.dart +++ b/lib/ui/edit_profile/viewModel/EditProfileViewModel.dart @@ -1,22 +1,26 @@ import 'package:flutter/material.dart'; import 'package:local_auth/local_auth.dart'; + import 'package:aranduapp/ui/edit_profile/service/EditProfileService.dart'; import 'package:aranduapp/ui/edit_profile/model/EditProfileRequest.dart'; - import 'package:aranduapp/ui/home/view/HomeView.dart'; class EditProfileViewModel extends ChangeNotifier { final BuildContext context; bool isLoading; - final GlobalKey formKey; + final TextEditingController firstNameController; + final TextEditingController lastNameController; final TextEditingController emailController; final TextEditingController passwordController; + // Inicialização dos campos no construtor EditProfileViewModel(this.context) : isLoading = false, formKey = GlobalKey(), + firstNameController = TextEditingController(), + lastNameController = TextEditingController(), emailController = TextEditingController(), passwordController = TextEditingController(); } From 85d426cbc0e1ffb9cc1dc497b083dab96c000d0d Mon Sep 17 00:00:00 2001 From: R1K4S Date: Sat, 7 Dec 2024 08:23:48 -0300 Subject: [PATCH 6/8] =?UTF-8?q?(#59):Aplica=C3=A7=C3=A3o=20do=20Model?= =?UTF-8?q?o=20MVVM?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../model/EditProfileRequest.dart | 16 + .../service/EditProfileService.dart | 14 + lib/ui/edit_profile/view/EditProfileView.dart | 279 ++++++------------ .../viewModel/EditProfileViewModel.dart | 32 +- 4 files changed, 151 insertions(+), 190 deletions(-) diff --git a/lib/ui/edit_profile/model/EditProfileRequest.dart b/lib/ui/edit_profile/model/EditProfileRequest.dart index e69de29..b417b5f 100644 --- a/lib/ui/edit_profile/model/EditProfileRequest.dart +++ b/lib/ui/edit_profile/model/EditProfileRequest.dart @@ -0,0 +1,16 @@ +import 'dart:convert'; + +class EditProfileRequest { + final String? email; + final String? password; + + EditProfileRequest(this.email, this.password); + + factory EditProfileRequest.fromJsonString(String jsonString) { + Map json = jsonDecode(jsonString); + return EditProfileRequest( + json['email'] as String?, + json['password'] as String?, + ); + } +} diff --git a/lib/ui/edit_profile/service/EditProfileService.dart b/lib/ui/edit_profile/service/EditProfileService.dart index e69de29..3b621f8 100644 --- a/lib/ui/edit_profile/service/EditProfileService.dart +++ b/lib/ui/edit_profile/service/EditProfileService.dart @@ -0,0 +1,14 @@ +import 'package:aranduapp/ui/edit_profile/model/EditProfileRequest.dart'; +import 'package:dio/dio.dart'; + +class EditProfileService { + static Future edit(EditProfileRequest editProfileRequest) async { + // TODO: implement build + throw UnimplementedError(); + } + + static Future refreshToken() async { + // TODO: implement build + throw UnimplementedError(); + } +} diff --git a/lib/ui/edit_profile/view/EditProfileView.dart b/lib/ui/edit_profile/view/EditProfileView.dart index e5fc7f6..c060ecb 100644 --- a/lib/ui/edit_profile/view/EditProfileView.dart +++ b/lib/ui/edit_profile/view/EditProfileView.dart @@ -1,5 +1,7 @@ import 'package:flutter/material.dart'; -//import 'package:aranduapp/ui/shared/ProfileCard.dart'; +import 'package:provider/provider.dart'; + +import 'package:aranduapp/ui/edit_profile/viewModel/EditProfileViewModel.dart'; import 'package:aranduapp/ui/shared/TextEmail.dart'; import 'package:aranduapp/ui/shared/CustomTextField.dart'; import 'package:aranduapp/ui/shared/TextPassword.dart'; @@ -10,218 +12,114 @@ class EditProfile extends StatelessWidget { @override Widget build(BuildContext context) { return ChangeNotifierProvider( - create: (context) => EditProfile(context), - child: const _EditProfile(), + create: (context) => EditProfileViewModel(context), + child: const EditProfileScreen(), ); } } -class EditProfile extends StatelessWidget { - EditProfile({Key? key}) : super(key: key); +class EditProfileScreen extends StatefulWidget { + const EditProfileScreen({Key? key}) : super(key: key); + + @override + State createState() => _EditProfileScreenState(); +} - final TextEditingController firstNameController = TextEditingController(); - final TextEditingController lastNameController = TextEditingController(); - final TextEditingController emailController = TextEditingController(); - final TextEditingController passwordController = TextEditingController(); +class _EditProfileScreenState extends State { + Future? _future; @override Widget build(BuildContext context) { + final viewModel = Provider.of(context); + return Scaffold( - appBar: AppBar( - backgroundColor: const Color.fromARGB( - 255, 255, 255, 255), // Define o fundo transparente - elevation: 0, // Remove a sombra da AppBar - title: Center( - child: Text( - 'Editar perfil', - ), - ), - actions: [ - IconButton( - icon: Icon(Icons.notifications), // Ícone de notificação - onPressed: () { - // Ação quando o ícone de notificação for pressionado + appBar: AppBar( + title: const Text('Editar Perfil'), + ), + body: _future == null + ? const Center(child: CircularProgressIndicator()) + : FutureBuilder( + future: _future, + builder: (context, snapshot) { + if (snapshot.connectionState == ConnectionState.waiting) { + return const Center(child: CircularProgressIndicator()); + } else if (snapshot.hasError) { + return Center( + child: Text('Erro: ${snapshot.error}'), + ); + } else { + return _buildForm(viewModel); + } }, ), - ], - leading: IconButton( - icon: Icon(Icons.arrow_back), - onPressed: () {}, - ), - ), - body: Column( - mainAxisAlignment: MainAxisAlignment.spaceAround, - children: [ - _icon(context), - _nameAndLast(context), - _emailAndPassword(context), - Row(mainAxisAlignment: MainAxisAlignment.spaceAround, children: [ - _deleteButton(context), - _saveButton(context), - ]) - ], - )); - } - - Widget _nameAndLast(BuildContext context) { - return SingleChildScrollView( - child: Column( - children: [ - CustomTextField( - label: ' Primeiro Nome', - placeholder: 'Stefani', - controller: firstNameController, - ), - - // Campo Último Nome usando CustomTextFieldq - CustomTextField( - label: ' Último Nome', - placeholder: 'Silva', - controller: lastNameController, - ), - ], - ), ); } - Widget _emailAndPassword(BuildContext context) { + Widget _buildForm(EditProfileViewModel viewModel) { return SingleChildScrollView( - child: Column( - children: [ - TextEmail( - padding: const EdgeInsets.symmetric(horizontal: 0), - controller: emailController, - ), - TextPassWord( - padding: const EdgeInsets.symmetric(horizontal: 0), - controller: passwordController, - ), - ], - ), - ); - } - - Widget _saveButton(BuildContext context) { - return SingleChildScrollView( - child: ElevatedButton( - onPressed: () { - print('Primeiro Nome: ${firstNameController.text}'); - print('Último Nome: ${lastNameController.text}'); - print('E-mail: ${emailController.text}'); - }, - style: ElevatedButton.styleFrom( - fixedSize: Size(200, 50), - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(20), - ), - padding: const EdgeInsets.symmetric(vertical: 0), - backgroundColor: Colors.transparent, - shadowColor: Colors.transparent, - ), - child: Ink( - decoration: BoxDecoration( - gradient: LinearGradient( - colors: [ - Color.fromRGBO(8, 145, 178, 1), - Color.fromRGBO(127, 219, 229, 1) - ], - begin: Alignment.topLeft, - end: Alignment.bottomRight, + padding: const EdgeInsets.all(16.0), + child: Form( + key: viewModel.formKey, + child: Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + CustomTextField( + label: 'Primeiro Nome', + placeholder: 'Stefani', + controller: viewModel.firstNameController, ), - borderRadius: BorderRadius.circular(20), - ), - child: Container( - alignment: Alignment.center, - padding: const EdgeInsets.symmetric(vertical: 8), - child: const Text( - 'Salvar', - style: TextStyle( - fontSize: 16, - color: Colors.white, - ), + const SizedBox(height: 16), + CustomTextField( + label: 'Último Nome', + placeholder: 'Silva', + controller: viewModel.lastNameController, + ), + const SizedBox(height: 16), + TextEmail( + padding: const EdgeInsets.symmetric(horizontal: 0), + controller: viewModel.emailController, ), - ), + const SizedBox(height: 16), + TextPassWord( + padding: const EdgeInsets.symmetric(horizontal: 0), + controller: viewModel.passwordController, + ), + const SizedBox(height: 32), + _saveButton(viewModel), + const SizedBox(height: 16), + _deleteButton(context), + ], ), ), ); } - Widget _deleteButton(BuildContext context) { - return SingleChildScrollView( - child: ElevatedButton( - onPressed: () { - _showDeleteConfirmationDialog(context); - }, - style: ElevatedButton.styleFrom( - fixedSize: Size(200, 50), - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(20), - ), - padding: const EdgeInsets.symmetric(vertical: 0), - backgroundColor: Colors.transparent, - shadowColor: Colors.transparent, - ), - child: Ink( - decoration: BoxDecoration( - gradient: LinearGradient( - colors: [ - Color.fromRGBO(144, 11, 9, 1), - Color.fromRGBO(236, 34, 31, 1) - ], - begin: Alignment.bottomLeft, - end: Alignment.topLeft, - ), - borderRadius: BorderRadius.circular(20), - ), - child: Container( - alignment: Alignment.center, - padding: const EdgeInsets.symmetric(vertical: 8), - child: const Text( - 'Deletar Conta', - style: TextStyle( - fontSize: 16, - color: Colors.white, - ), - ), - ), - ), - ), + Widget _saveButton(EditProfileViewModel viewModel) { + return ElevatedButton( + onPressed: () async { + if (viewModel.isLoading) return; + try { + await viewModel.editprofileWithEmailAndPassword(); + ScaffoldMessenger.of(context).showSnackBar( + const SnackBar(content: Text('Perfil atualizado com sucesso!')), + ); + } catch (e) { + ScaffoldMessenger.of(context).showSnackBar( + SnackBar(content: Text('Erro: $e')), + ); + } + }, + child: const Text('Salvar'), ); } - Widget _icon(BuildContext context) { - return Padding( - padding: const EdgeInsets.only( - left: 16.0), // Adiciona espaço da borda esquerda - child: Row( - children: [ - // Ícone circular - CircleAvatar( - radius: 30, // Tamanho do círculo - ), - SizedBox(width: 16), // Espaço entre a imagem e o texto - // Texto com o nome e o cargo - Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - "Stefani", - style: TextStyle( - fontSize: 18, - fontWeight: FontWeight.bold, - ), - ), - Text( - "Estudante", - style: TextStyle( - fontSize: 14, - color: Colors.grey, - ), - ), - ], - ), - ], + Widget _deleteButton(BuildContext context) { + return ElevatedButton( + onPressed: () => _showDeleteConfirmationDialog(context), + style: ElevatedButton.styleFrom( + backgroundColor: Colors.red, ), + child: const Text('Deletar Conta'), ); } @@ -242,9 +140,14 @@ class EditProfile extends StatelessWidget { ), ElevatedButton( onPressed: () { - print('Conta deletada'); Navigator.of(context).pop(); + ScaffoldMessenger.of(context).showSnackBar( + const SnackBar(content: Text('Conta deletada com sucesso!')), + ); }, + style: ElevatedButton.styleFrom( + backgroundColor: Colors.red, + ), child: const Text('Deletar'), ), ], diff --git a/lib/ui/edit_profile/viewModel/EditProfileViewModel.dart b/lib/ui/edit_profile/viewModel/EditProfileViewModel.dart index 6c6022a..9debafb 100644 --- a/lib/ui/edit_profile/viewModel/EditProfileViewModel.dart +++ b/lib/ui/edit_profile/viewModel/EditProfileViewModel.dart @@ -1,9 +1,7 @@ import 'package:flutter/material.dart'; -import 'package:local_auth/local_auth.dart'; import 'package:aranduapp/ui/edit_profile/service/EditProfileService.dart'; import 'package:aranduapp/ui/edit_profile/model/EditProfileRequest.dart'; -import 'package:aranduapp/ui/home/view/HomeView.dart'; class EditProfileViewModel extends ChangeNotifier { final BuildContext context; @@ -23,4 +21,34 @@ class EditProfileViewModel extends ChangeNotifier { lastNameController = TextEditingController(), emailController = TextEditingController(), passwordController = TextEditingController(); + + Future editprofileWithEmailAndPassword() async { + // TODO use mutex to make this + if (isLoading) { + return; + } + + try { + isLoading = true; + super.notifyListeners(); + + if (!formKey.currentState!.validate()) { + throw Exception('Valores inválidos'); + } + + await EditProfileService.edit( + EditProfileRequest(emailController.text, passwordController.text)); + } catch (e) { + rethrow; + } finally { + isLoading = false; + notifyListeners(); + } + + Future getRefreshTokenFuture() async { + // TODO + //return await LoginService.refreshToken(); + throw UnimplementedError(); + } + } } From 1d7a066e1b4796f5ebaa71fb285c9ab369badcee Mon Sep 17 00:00:00 2001 From: R1K4S Date: Sat, 7 Dec 2024 08:42:07 -0300 Subject: [PATCH 7/8] (#59):Rodando a tela no Modelo MVVM --- lib/ui/edit_profile/view/EditProfileView.dart | 18 +++++++++++------- .../viewModel/EditProfileViewModel.dart | 15 ++++++++++----- 2 files changed, 21 insertions(+), 12 deletions(-) diff --git a/lib/ui/edit_profile/view/EditProfileView.dart b/lib/ui/edit_profile/view/EditProfileView.dart index c060ecb..5cc11ba 100644 --- a/lib/ui/edit_profile/view/EditProfileView.dart +++ b/lib/ui/edit_profile/view/EditProfileView.dart @@ -28,10 +28,20 @@ class EditProfileScreen extends StatefulWidget { class _EditProfileScreenState extends State { Future? _future; + @override + void initState() { + super.initState(); + WidgetsBinding.instance.addPostFrameCallback((_) { + setState(() { + _future = Provider.of(context, listen: false) + .getRefreshTokenFuture(); + }); + }); + } + @override Widget build(BuildContext context) { final viewModel = Provider.of(context); - return Scaffold( appBar: AppBar( title: const Text('Editar Perfil'), @@ -116,9 +126,6 @@ class _EditProfileScreenState extends State { Widget _deleteButton(BuildContext context) { return ElevatedButton( onPressed: () => _showDeleteConfirmationDialog(context), - style: ElevatedButton.styleFrom( - backgroundColor: Colors.red, - ), child: const Text('Deletar Conta'), ); } @@ -145,9 +152,6 @@ class _EditProfileScreenState extends State { const SnackBar(content: Text('Conta deletada com sucesso!')), ); }, - style: ElevatedButton.styleFrom( - backgroundColor: Colors.red, - ), child: const Text('Deletar'), ), ], diff --git a/lib/ui/edit_profile/viewModel/EditProfileViewModel.dart b/lib/ui/edit_profile/viewModel/EditProfileViewModel.dart index 9debafb..9494744 100644 --- a/lib/ui/edit_profile/viewModel/EditProfileViewModel.dart +++ b/lib/ui/edit_profile/viewModel/EditProfileViewModel.dart @@ -23,7 +23,6 @@ class EditProfileViewModel extends ChangeNotifier { passwordController = TextEditingController(); Future editprofileWithEmailAndPassword() async { - // TODO use mutex to make this if (isLoading) { return; } @@ -44,11 +43,17 @@ class EditProfileViewModel extends ChangeNotifier { isLoading = false; notifyListeners(); } + } - Future getRefreshTokenFuture() async { - // TODO - //return await LoginService.refreshToken(); - throw UnimplementedError(); + Future getRefreshTokenFuture() async { + try { + // Exemplo de simulação de uma operação assíncrona: + await Future.delayed(const Duration(seconds: 2)); + // Aqui você deve chamar o serviço real que renova o token de autenticação. + // Exemplo: + // await LoginService.refreshToken(); + } catch (e) { + throw Exception('Erro ao renovar o token: $e'); } } } From b8a0d8423577c0b6b9e8e4ad876d51dc3cbd3222 Mon Sep 17 00:00:00 2001 From: Gabriel Costa de Oliveira Date: Sat, 7 Dec 2024 11:02:37 -0300 Subject: [PATCH 8/8] =?UTF-8?q?Fix(#59):=20corre=C3=A7=C3=A3o=20de=20tela?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/ui/edit_profile/view/EditProfileView.dart | 60 ++++++------------- .../viewModel/EditProfileViewModel.dart | 12 +++- lib/ui/shared/CustomTextField.dart | 50 ---------------- lib/ui/shared/ProfileCard.Dart | 51 ---------------- lib/ui/shared/TextName.dart | 33 ++++++++++ 5 files changed, 59 insertions(+), 147 deletions(-) delete mode 100644 lib/ui/shared/CustomTextField.dart delete mode 100644 lib/ui/shared/ProfileCard.Dart create mode 100644 lib/ui/shared/TextName.dart diff --git a/lib/ui/edit_profile/view/EditProfileView.dart b/lib/ui/edit_profile/view/EditProfileView.dart index 5cc11ba..ec55fcb 100644 --- a/lib/ui/edit_profile/view/EditProfileView.dart +++ b/lib/ui/edit_profile/view/EditProfileView.dart @@ -1,9 +1,9 @@ +import 'package:aranduapp/ui/shared/TextName.dart'; import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; import 'package:aranduapp/ui/edit_profile/viewModel/EditProfileViewModel.dart'; import 'package:aranduapp/ui/shared/TextEmail.dart'; -import 'package:aranduapp/ui/shared/CustomTextField.dart'; import 'package:aranduapp/ui/shared/TextPassword.dart'; class EditProfile extends StatelessWidget { @@ -26,18 +26,6 @@ class EditProfileScreen extends StatefulWidget { } class _EditProfileScreenState extends State { - Future? _future; - - @override - void initState() { - super.initState(); - WidgetsBinding.instance.addPostFrameCallback((_) { - setState(() { - _future = Provider.of(context, listen: false) - .getRefreshTokenFuture(); - }); - }); - } @override Widget build(BuildContext context) { @@ -46,22 +34,7 @@ class _EditProfileScreenState extends State { appBar: AppBar( title: const Text('Editar Perfil'), ), - body: _future == null - ? const Center(child: CircularProgressIndicator()) - : FutureBuilder( - future: _future, - builder: (context, snapshot) { - if (snapshot.connectionState == ConnectionState.waiting) { - return const Center(child: CircularProgressIndicator()); - } else if (snapshot.hasError) { - return Center( - child: Text('Erro: ${snapshot.error}'), - ); - } else { - return _buildForm(viewModel); - } - }, - ), + body: _buildForm(viewModel) ); } @@ -73,27 +46,22 @@ class _EditProfileScreenState extends State { child: Column( crossAxisAlignment: CrossAxisAlignment.stretch, children: [ - CustomTextField( - label: 'Primeiro Nome', - placeholder: 'Stefani', + + TextName( controller: viewModel.firstNameController, + padding: const EdgeInsets.symmetric(vertical: 16) ), - const SizedBox(height: 16), - CustomTextField( - label: 'Último Nome', - placeholder: 'Silva', - controller: viewModel.lastNameController, - ), - const SizedBox(height: 16), + TextEmail( - padding: const EdgeInsets.symmetric(horizontal: 0), + padding: const EdgeInsets.symmetric(vertical: 16), controller: viewModel.emailController, ), - const SizedBox(height: 16), + TextPassWord( - padding: const EdgeInsets.symmetric(horizontal: 0), + padding: const EdgeInsets.symmetric(vertical: 16), controller: viewModel.passwordController, ), + const SizedBox(height: 32), _saveButton(viewModel), const SizedBox(height: 16), @@ -119,7 +87,13 @@ class _EditProfileScreenState extends State { ); } }, - child: const Text('Salvar'), + + child: Consumer( + builder: (context, value, child) => value.isLoading + ? const CircularProgressIndicator(value: null) + : const Text('Salvar'), + ), + ); } diff --git a/lib/ui/edit_profile/viewModel/EditProfileViewModel.dart b/lib/ui/edit_profile/viewModel/EditProfileViewModel.dart index 9494744..9b811c9 100644 --- a/lib/ui/edit_profile/viewModel/EditProfileViewModel.dart +++ b/lib/ui/edit_profile/viewModel/EditProfileViewModel.dart @@ -1,3 +1,4 @@ +import 'package:aranduapp/core/log/Log.dart'; import 'package:flutter/material.dart'; import 'package:aranduapp/ui/edit_profile/service/EditProfileService.dart'; @@ -29,14 +30,19 @@ class EditProfileViewModel extends ChangeNotifier { try { isLoading = true; - super.notifyListeners(); + notifyListeners(); if (!formKey.currentState!.validate()) { throw Exception('Valores inválidos'); } - await EditProfileService.edit( - EditProfileRequest(emailController.text, passwordController.text)); + + await Future.delayed(const Duration(seconds: 10)); + + + // await EditProfileService.edit( + // EditProfileRequest(emailController.text, passwordController.text)); + } catch (e) { rethrow; } finally { diff --git a/lib/ui/shared/CustomTextField.dart b/lib/ui/shared/CustomTextField.dart deleted file mode 100644 index 07f734a..0000000 --- a/lib/ui/shared/CustomTextField.dart +++ /dev/null @@ -1,50 +0,0 @@ -import 'package:flutter/material.dart'; - -class CustomTextField extends StatelessWidget { - final String label; - final String? placeholder; - final TextEditingController? controller; - final bool obscureText; - - const CustomTextField({ - Key? key, - required this.label, - this.placeholder, - this.controller, - this.obscureText = false, - }) : super(key: key); - - @override - Widget build(BuildContext context) { - return Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - label, - style: const TextStyle( - fontSize: 16, - fontWeight: FontWeight.bold, - ), - ), - const SizedBox(height: 8), - TextField( - controller: controller, - obscureText: obscureText, - decoration: InputDecoration( - hintText: placeholder, - filled: true, - fillColor: const Color(0xFFF5F5F5), - contentPadding: const EdgeInsets.symmetric( - horizontal: 16, - vertical: 12, - ), - border: OutlineInputBorder( - borderRadius: BorderRadius.circular(20), - borderSide: BorderSide.none, - ), - ), - ), - ], - ); - } -} \ No newline at end of file diff --git a/lib/ui/shared/ProfileCard.Dart b/lib/ui/shared/ProfileCard.Dart deleted file mode 100644 index 79cd103..0000000 --- a/lib/ui/shared/ProfileCard.Dart +++ /dev/null @@ -1,51 +0,0 @@ -import 'package:flutter/material.dart'; - -class ProfileCard extends StatelessWidget { - final String name; - final String role; - final String avatarUrl; - - const ProfileCard({ - Key? key, - required this.name, - required this.role, - required this.avatarUrl, - }) : super(key: key); - - @override - Widget build(BuildContext context) { - return Row( - children: [ - // Avatar - CircleAvatar( - radius: 30, // Tamanho do avatar - backgroundImage: NetworkImage(avatarUrl), - backgroundColor: Colors.transparent, - ), - const SizedBox(width: 12), // Espaçamento entre avatar e texto - // Nome e função - Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - name, - style: const TextStyle( - fontSize: 18, - fontWeight: FontWeight.bold, - color: Colors.black, - ), - ), - const SizedBox(height: 4), // Espaçamento entre nome e função - Text( - role, - style: const TextStyle( - fontSize: 14, - color: Colors.grey, - ), - ), - ], - ), - ], - ); - } -} diff --git a/lib/ui/shared/TextName.dart b/lib/ui/shared/TextName.dart new file mode 100644 index 0000000..cc6a2d7 --- /dev/null +++ b/lib/ui/shared/TextName.dart @@ -0,0 +1,33 @@ +import 'package:flutter/material.dart'; + +class TextName extends StatelessWidget{ + + + final TextEditingController controller; + final EdgeInsetsGeometry padding; + + + const TextName({ + super.key, + required this.controller, + required this.padding, + }); + + + + @override + Widget build(BuildContext context) { + return Padding( + padding: padding, + child: TextFormField( + validator: (value) => value == null || value.trim().length < 3 ? 'Nome inválido' : null , + controller: controller, + decoration: InputDecoration ( + prefixIcon: Icon ( Icons.person_outline, color: Theme.of(context).colorScheme.primary), + labelText: 'Nome' + ), + ), + ); + } + +}