diff --git a/assets/images/logoEduca.png b/assets/images/logoEduca.png new file mode 100644 index 0000000..3720ff0 Binary files /dev/null and b/assets/images/logoEduca.png differ diff --git a/assets/images/logo.PNG b/assets/images/logoRKM.PNG similarity index 100% rename from assets/images/logo.PNG rename to assets/images/logoRKM.PNG diff --git a/lib/main.dart b/lib/main.dart index a697a51..eae6cd0 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -14,7 +14,7 @@ class MyApp extends StatelessWidget { return MaterialApp( debugShowCheckedModeBanner: false, title: 'Controle de Acesso', - home: HomeScreen(), + home: LoginScreen(), ); } } diff --git a/lib/models/responsavel_model.dart b/lib/models/responsavel_model.dart new file mode 100644 index 0000000..cee2d5e --- /dev/null +++ b/lib/models/responsavel_model.dart @@ -0,0 +1,25 @@ +class ResponsavelModel{ + String nomeAluno; + String raAluno; + String escola; + String serie; + String turma; + String nomeResponsavel; + String parentesco; + String cpf; + String senha; + String dataCadastro; + + ResponsavelModel({ + required this.nomeAluno, + required this.raAluno, + required this.escola, + required this.serie, + required this.turma, + required this.nomeResponsavel, + required this.parentesco, + required this.cpf, + required this.senha, + required this.dataCadastro, + }); +} \ No newline at end of file diff --git a/lib/screens/home_screen.dart b/lib/screens/home_screen.dart index 8e9b4ae..55a1f30 100644 --- a/lib/screens/home_screen.dart +++ b/lib/screens/home_screen.dart @@ -27,7 +27,6 @@ class _HomeScreenState extends State { pesquisa(){ pesquisarAluno(); - } pesquisarAluno()async{ @@ -35,7 +34,13 @@ class _HomeScreenState extends State { if(controllerPesquisa.text.isNotEmpty){ for (int i =0;alunos.length>i;i++) { String nome = alunos[i].nome.toUpperCase(); - if(nome.contains(controllerPesquisa.text.toUpperCase())){ + String data = alunos[i].data_nasc.toUpperCase(); + String ra = alunos[i].ra.toUpperCase(); + + if(nome.contains(controllerPesquisa.text.toUpperCase()) || + data.contains(controllerPesquisa.text.toUpperCase()) || + ra.contains(controllerPesquisa.text.toUpperCase()) + ){ if(resultadoPesquisa.length<10){ resultadoPesquisa.add(alunos[i]); } @@ -63,7 +68,17 @@ class _HomeScreenState extends State { double height = MediaQuery.of(context).size.height; return Scaffold( - appBar: AppBar(title: TextCustom(text: 'Cadastrar responsável',color: Colors.white,),backgroundColor: PaletteColors.grey), + appBar: AppBar( + title: Row( + children: [ + Container( + child: Image.asset("assets/images/logoEduca.png",width:width * 0.08,height: height * 0.12) + ), + TextCustom(text: '- Pesquisar aluno',color: Colors.white,), + ], + ), + backgroundColor: PaletteColors.grey, + ), body: Padding( padding: const EdgeInsets.all(8.0), child: ListView( @@ -71,7 +86,7 @@ class _HomeScreenState extends State { SizedBox(height: height*0.05), Padding( padding: EdgeInsets.symmetric(horizontal: width>900?width*0.3:width*0.05), - child: InputText(controller: controllerPesquisa, width: width*0.2,title: 'Pesquisar Aluno(a)',) + child: InputText(controller: controllerPesquisa, width: width*0.2,title: 'Pesquisar Aluno(a)',inputFormatters: [],) ), Container( padding: EdgeInsets.symmetric(horizontal: width>900?width*0.3:width*0.05), diff --git a/lib/screens/login_screen.dart b/lib/screens/login_screen.dart index ba2658c..944980f 100644 --- a/lib/screens/login_screen.dart +++ b/lib/screens/login_screen.dart @@ -4,7 +4,6 @@ import 'package:flutter/material.dart'; import '../utils/colors.dart'; import '../widgets/buttom_custom.dart'; import '../widgets/snackBars.dart'; -import '../widgets/text_custom.dart'; class LoginScreen extends StatefulWidget { const LoginScreen({Key? key}) : super(key: key); @@ -54,11 +53,12 @@ class _LoginScreenState extends State { mainAxisSize: MainAxisSize.min, children: [ Container( - child: Image.asset("assets/image/logo.PNG",width:width * 0.2 ,height: height * 0.12) + child: Image.asset("assets/images/logoEduca.png",width:width * 0.15,height: height * 0.12) ), Container( width: width>900? width * 0.18:width*0.5, child: InputText( + inputFormatters: [], controller: inputEmail, title: 'E-mail', width: width>900? width * 0.18:width*0.5, @@ -69,6 +69,7 @@ class _LoginScreenState extends State { Container( width: width>900? width * 0.18:width*0.5, child: InputText( + inputFormatters: [], controller: inputSenha, title: 'Senha', obscure: true, @@ -86,7 +87,6 @@ class _LoginScreenState extends State { colorButton: PaletteColors.primaryColor, colorBorder: PaletteColors.primaryColor, onPressed: ()=>verificacao(), - font: 'Nunito', ), ], ), diff --git a/lib/screens/responsible_register_screen.dart b/lib/screens/responsible_register_screen.dart new file mode 100644 index 0000000..c812577 --- /dev/null +++ b/lib/screens/responsible_register_screen.dart @@ -0,0 +1,288 @@ +import 'package:brasil_fields/brasil_fields.dart'; +import 'package:educa_controle_acesso/models/aluno_model.dart'; +import 'package:educa_controle_acesso/models/responsavel_model.dart'; +import 'package:educa_controle_acesso/widgets/dados_responsaveis_container.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; +import 'package:get/get.dart'; +import 'package:intl/intl.dart'; +import '../utils/colors.dart'; +import '../widgets/buttom_custom.dart'; +import '../widgets/input_text.dart'; +import '../widgets/snackBars.dart'; +import '../widgets/text_custom.dart'; + +class ResponsibleRegisterScreen extends StatefulWidget { + AlunoModel alunoModel; + + ResponsibleRegisterScreen({required this.alunoModel}); + + @override + State createState() => _ResponsibleRegisterScreenState(); +} + +class _ResponsibleRegisterScreenState extends State { + + List responsaveis = []; + bool showRegister = false; + bool editando = false; + int? indice; + var inputNome = TextEditingController(); + var inputParentesco = TextEditingController(); + var inputCpf = TextEditingController(); + var inputSenha = TextEditingController(); + var inputData = TextEditingController(); + + salvarResponsavel() { + if(inputNome.text.isNotEmpty && inputNome.text.contains(' ')){ + if(inputParentesco.text.isNotEmpty){ + if(inputCpf.text.isNotEmpty && GetUtils.isCpf(inputCpf.text)){ + if(inputSenha.text.isNotEmpty && inputSenha.text.length > 5){ + if(editando && indice!=null){ + responsaveis[indice!] = ResponsavelModel( + nomeAluno: widget.alunoModel.nome, + raAluno: widget.alunoModel.ra, + escola: widget.alunoModel.escola, + serie: widget.alunoModel.serie, + turma: widget.alunoModel.turma, + nomeResponsavel: inputNome.text, + parentesco: inputParentesco.text, + cpf: inputCpf.text, + senha: inputSenha.text, + dataCadastro: DateFormat('dd/MM/yyyy HH:mm').format(DateTime.now()) + ); + }else{ + responsaveis.add( + ResponsavelModel( + nomeAluno: widget.alunoModel.nome.toUpperCase(), + raAluno: widget.alunoModel.ra.toUpperCase(), + escola: widget.alunoModel.escola.toUpperCase(), + serie: widget.alunoModel.serie.toUpperCase(), + turma: widget.alunoModel.turma.toUpperCase(), + nomeResponsavel: inputNome.text.toUpperCase(), + parentesco: inputParentesco.text.toUpperCase(), + cpf: inputCpf.text, + senha: inputSenha.text.toUpperCase(), + dataCadastro: DateFormat('dd/MM/yyyy HH:mm').format(DateTime.now()) + ) + ); + } + editando? + showSnackBar(context, 'Responsável alterado!', Colors.green): + showSnackBar(context, 'Responsável adicionado!', Colors.green); + inputNome.clear(); + inputParentesco.clear(); + inputCpf.clear(); + inputSenha.clear(); + showRegister = false; + editando = false; + indice = null; + inputData.clear(); + setState((){}); + }else{ + showSnackBar(context, 'Insira o uma senha com o mínimo de 6 caracteres', Colors.red); + } + }else{ + showSnackBar(context, 'CPF inválido', Colors.red); + } + }else{ + showSnackBar(context, 'Insira o parentesco do responsável', Colors.red); + } + }else{ + showSnackBar(context, 'Insira o nome completo do responsável', Colors.red); + } + } + + @override + Widget build(BuildContext context) { + + double width = MediaQuery.of(context).size.width; + double height = MediaQuery.of(context).size.height; + + return Scaffold( + appBar: AppBar( + title: Row( + children: [ + Container( + child: Image.asset("assets/images/logoEduca.png",width:width * 0.08,height: height * 0.12) + ), + TextCustom(text: '- Cadastrar Responsável',color: Colors.white,), + ], + ), + backgroundColor: PaletteColors.grey, + ), + body: Padding( + padding: const EdgeInsets.all(30.0), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + TextCustom(text: 'Aluno(a): ${widget.alunoModel.nome}'), + TextCustom(text: 'Turma: ${widget.alunoModel.serie}° ANO ${widget.alunoModel.turma}'), + TextCustom(text: 'RA: ${widget.alunoModel.ra}'), + TextCustom(text: 'Escola: ${widget.alunoModel.escola}'), + SizedBox(height: 50,), + Row( + children: [ + TextCustom(text: 'Responsáveis Cadastrados:'), + IconButton( + icon: Icon(Icons.add_circle,color: PaletteColors.primaryColor), + onPressed: ()=>setState(()=>showRegister = true), + ) + ], + ), + showRegister?Container( + alignment: Alignment.center, + padding: EdgeInsets.symmetric(horizontal: width*0.35), + width: width, + child: Card( + elevation: 10, + child: Padding( + padding: EdgeInsets.only(bottom: 20), + child: Column( + children: [ + Container( + width: width*0.30, + padding: EdgeInsets.all(10), + color: Colors.black54, + child: TextCustom( + text: 'Novo responsável', + color: Colors.white, + textAlign: TextAlign.center, + ), + ), + Padding( + padding: const EdgeInsets.symmetric(vertical: 15.0), + child: TextCustom(text: 'Prencha os campos todos os campos para adicionar.'), + ), + Container( + width: width>900? width * 0.18:width*0.4, + child: InputText( + inputFormatters: [], + controller: inputNome, + title: 'Nome Completo', + width: width * 0.18, + colorBorder: PaletteColors.white, + ), + ), + Container( + width: width>900? width * 0.18:width*0.4, + child: InputText( + inputFormatters: [], + controller: inputParentesco, + title: 'Parentesco', + width: width * 0.18, + colorBorder: PaletteColors.white, + ), + ), + Container( + width: width>900? width * 0.18:width*0.4, + child: InputText( + controller: inputCpf, + title: 'CPF', + width: width * 0.18, + colorBorder: PaletteColors.white, + inputFormatters: [ + FilteringTextInputFormatter.digitsOnly, + CpfInputFormatter(), + ], + ), + ), + Container( + width: width>900? width * 0.18:width*0.4, + child: InputText( + inputFormatters: [], + controller: inputSenha, + title: 'Senha', + width: width * 0.18, + colorBorder: PaletteColors.white, + ), + ), + editando?Container( + width: width>900? width * 0.18:width*0.4, + child: InputText( + inputFormatters: [], + controller: inputData, + title: 'Data de Cadastro', + width: width * 0.18, + colorBorder: PaletteColors.white, + enable: false, + ), + ):Container(), + SizedBox(height: 50,), + Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + ButtonCustom( + onPressed:()=>setState((){ + showRegister = false; + editando = false; + indice = null; + inputData.clear(); + inputNome.clear(); + inputParentesco.clear(); + inputSenha.clear(); + inputCpf.clear(); + }), + text: 'Cancelar', + widthCustom: 0.1, + heightCustom: 0.05, + colorText: Colors.white, + colorBorder: PaletteColors.primaryColor, + colorButton: PaletteColors.primaryColor, + size: 15, + ), + SizedBox(width: 50,), + ButtonCustom( + onPressed:()=>salvarResponsavel(), + text: 'Salvar', + widthCustom: 0.1, + heightCustom: 0.05, + colorText: Colors.white, + colorBorder: PaletteColors.green, + colorButton: PaletteColors.green, + size: 15, + ) + ], + ) + ], + ), + ), + ), + ):Container(), + showRegister?Container():Container( + width: width*0.3, + height: height*0.3, + child: ListView.separated( + itemCount: responsaveis.length, + separatorBuilder: (context,index){ + return Divider(); + }, + itemBuilder: (context,index){ + return DadosResponsaveisContainer( + responsavelModel: responsaveis[index], + onTapEdit: (){ + showRegister = true; + editando = true; + indice = index; + inputNome.text = responsaveis[index].nomeResponsavel; + inputParentesco.text = responsaveis[index].parentesco; + inputCpf.text = responsaveis[index].cpf; + inputSenha.text = responsaveis[index].senha; + inputData.text = responsaveis[index].dataCadastro; + setState(() {}); + }, + onTapDelete: (){ + responsaveis.removeAt(index); + setState(() {}); + showSnackBar(context, 'Responsável deletado!', Colors.green); + }, + ); + } + ), + ), + ], + ), + ) + ); + } +} diff --git a/lib/utils/colors.dart b/lib/utils/colors.dart index 9b717e8..e8936d4 100644 --- a/lib/utils/colors.dart +++ b/lib/utils/colors.dart @@ -10,5 +10,5 @@ class PaletteColors{ static const Color lightGrey = Color(0xffD0D0D0); static const Color midGrey = Color(0xffC4C4C4); static const Color backGrey = Color(0xffE9E9E9); - static const Color greenAcent = Color(0xff1DBF24); + static const Color green = Color(0xff06790c); } \ No newline at end of file diff --git a/lib/widgets/buttom_custom.dart b/lib/widgets/buttom_custom.dart index 76f0938..6bc22a6 100644 --- a/lib/widgets/buttom_custom.dart +++ b/lib/widgets/buttom_custom.dart @@ -9,11 +9,8 @@ class ButtonCustom extends StatelessWidget{ final Color colorBorder; final widthCustom; final heightCustom; - final font; - const ButtonCustom( - {Key? key, - required this.font, +ButtonCustom({ required this.onPressed, required this.text, required this.size, @@ -22,7 +19,7 @@ class ButtonCustom extends StatelessWidget{ required this.colorBorder, this.widthCustom = 1.0, this.heightCustom = 1.0 -}) : super(key: key); +}); @override Widget build (BuildContext context) { double width =MediaQuery.of(context).size.width; @@ -33,16 +30,14 @@ class ButtonCustom extends StatelessWidget{ primary: colorButton, minimumSize: Size(width*widthCustom! , height*heightCustom!), side: BorderSide(width: 2,color : colorBorder,), - - ), onPressed: onPressed, child: Text(text, - style: TextStyle(fontFamily: font, color: colorText, - fontSize: size,fontWeight: FontWeight.bold + style: TextStyle( + color: colorText, + fontSize: size, + fontWeight: FontWeight.bold ), - - ) , ); } diff --git a/lib/widgets/dados_alunos_container.dart b/lib/widgets/dados_alunos_container.dart index 2309ba3..ec2a6fa 100644 --- a/lib/widgets/dados_alunos_container.dart +++ b/lib/widgets/dados_alunos_container.dart @@ -1,4 +1,5 @@ import 'package:educa_controle_acesso/models/aluno_model.dart'; +import 'package:educa_controle_acesso/screens/responsible_register_screen.dart'; import 'package:educa_controle_acesso/widgets/text_custom.dart'; import 'package:flutter/material.dart'; import '../utils/colors.dart'; @@ -13,37 +14,45 @@ class DadosAlunosContainer extends StatelessWidget { @override Widget build(BuildContext context) { - return Container( - padding: EdgeInsets.symmetric(vertical: 10,horizontal: 5), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - TextCustom( - text: 'Nome: '+alunoModel.nome, - color: PaletteColors.grey, - size: 20, - ), - TextCustom( - text: 'Data de Nascimento: '+alunoModel.data_nasc, + return InkWell( + onTap: (){ + Navigator.push( + context, + MaterialPageRoute(builder: (context) => ResponsibleRegisterScreen(alunoModel: alunoModel)), + ); + }, + child: Container( + padding: EdgeInsets.symmetric(vertical: 10,horizontal: 5), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + TextCustom( + text: 'Nome: '+alunoModel.nome, + color: PaletteColors.grey, + size: 20, + ), + TextCustom( + text: 'Data de Nascimento: '+alunoModel.data_nasc, + color: PaletteColors.grey, + size: 15, + ), + TextCustom( + text: 'RA: '+alunoModel.ra, color: PaletteColors.grey, size: 15, - ), - TextCustom( - text: 'RA: '+alunoModel.ra, - color: PaletteColors.grey, - size: 15, - ), - TextCustom( - text: 'Turma: '+alunoModel.serie+'° ANO '+alunoModel.turma, - color: PaletteColors.grey, - size: 15, - ), - TextCustom( - text: 'Escola: '+alunoModel.escola, - color: PaletteColors.grey, - size: 15, - ), - ], + ), + TextCustom( + text: 'Turma: '+alunoModel.serie+'° ANO '+alunoModel.turma, + color: PaletteColors.grey, + size: 15, + ), + TextCustom( + text: 'Escola: '+alunoModel.escola, + color: PaletteColors.grey, + size: 15, + ), + ], + ), ), ); } diff --git a/lib/widgets/dados_responsaveis_container.dart b/lib/widgets/dados_responsaveis_container.dart new file mode 100644 index 0000000..e98a309 --- /dev/null +++ b/lib/widgets/dados_responsaveis_container.dart @@ -0,0 +1,46 @@ +import 'package:educa_controle_acesso/models/aluno_model.dart'; +import 'package:educa_controle_acesso/models/responsavel_model.dart'; +import 'package:educa_controle_acesso/screens/responsible_register_screen.dart'; +import 'package:educa_controle_acesso/widgets/text_custom.dart'; +import 'package:flutter/material.dart'; +import '../utils/colors.dart'; + +class DadosResponsaveisContainer extends StatelessWidget { + + ResponsavelModel responsavelModel; + var onTapEdit; + var onTapDelete; + + DadosResponsaveisContainer({ + required this.responsavelModel, + required this.onTapEdit, + required this.onTapDelete +}); + + @override + Widget build(BuildContext context) { + + double width = MediaQuery.of(context).size.width; + + return InkWell( + onTap: onTapEdit, + child: Row( + children: [ + IconButton( + onPressed:onTapDelete, + icon: Icon(Icons.delete,color: PaletteColors.grey,), + ), + Container( + width: width*0.15, + padding: EdgeInsets.symmetric(vertical: 10,horizontal: 5), + child: TextCustom( + text: '${responsavelModel.nomeResponsavel}, ${responsavelModel.parentesco}', + color: PaletteColors.grey, + size: 15, + ), + ), + ], + ), + ); + } +} diff --git a/lib/widgets/input_text.dart b/lib/widgets/input_text.dart index 2550ce1..afd6114 100644 --- a/lib/widgets/input_text.dart +++ b/lib/widgets/input_text.dart @@ -12,6 +12,8 @@ class InputText extends StatelessWidget { int maxLines; Color colorBorder; var onChanged; + bool enable; + List inputFormatters; InputText({ required this.controller, @@ -23,6 +25,8 @@ class InputText extends StatelessWidget { this.maxLines = 1, this.colorBorder = PaletteColors.grey, this.onChanged = null, + this.enable = true, + required this.inputFormatters }); @override @@ -32,11 +36,13 @@ class InputText extends StatelessWidget { width: width, margin: EdgeInsets.only(bottom: 5), child: TextFormField( + inputFormatters: inputFormatters, keyboardType: textInputType, maxLines: maxLines, onChanged: onChanged, obscureText: this.obscure, controller: this.controller, + enabled: enable, style: TextStyle( color: Colors.black, fontSize: this.fontSize, diff --git a/lib/widgets/text_custom.dart b/lib/widgets/text_custom.dart index 4383cfd..176b2ec 100644 --- a/lib/widgets/text_custom.dart +++ b/lib/widgets/text_custom.dart @@ -14,7 +14,7 @@ class TextCustom extends StatelessWidget { TextCustom({ required this.text, this.size = 16.0, - this.color = PaletteColors.primaryColor, + this.color = PaletteColors.grey, this.fontWeight = FontWeight.normal, this.textAlign = TextAlign.start, this.maxLines = 1, diff --git a/pubspec.lock b/pubspec.lock index 0f3a736..956287c 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -15,6 +15,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "2.1.0" + brasil_fields: + dependency: "direct main" + description: + name: brasil_fields + url: "https://pub.dartlang.org" + source: hosted + version: "1.12.0" characters: dependency: transitive description: @@ -67,6 +74,20 @@ packages: description: flutter source: sdk version: "0.0.0" + get: + dependency: "direct main" + description: + name: get + url: "https://pub.dartlang.org" + source: hosted + version: "4.6.5" + intl: + dependency: "direct main" + description: + name: intl + url: "https://pub.dartlang.org" + source: hosted + version: "0.18.1" lints: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index 0c1567c..d182689 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -11,6 +11,9 @@ dependencies: sdk: flutter cupertino_icons: ^1.0.2 + brasil_fields: + get: + intl: dev_dependencies: flutter_test: