From 5088160013a664f933f9607dcc120c1bca5b78b3 Mon Sep 17 00:00:00 2001 From: Luis Guilherme de Souza Munhoz Date: Tue, 24 Oct 2023 17:58:13 -0300 Subject: [PATCH] =?UTF-8?q?Removendo=20calend[end=C3=A1rio=20e=20adicionan?= =?UTF-8?q?do=20melhorias=20no=20crud=20de=20compromisso?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- mobile/lib/appointments.dart | 463 ++++++++++++++++++++--------------- mobile/lib/calendar.dart | 181 -------------- mobile/lib/navbar.dart | 11 +- 3 files changed, 270 insertions(+), 385 deletions(-) delete mode 100644 mobile/lib/calendar.dart diff --git a/mobile/lib/appointments.dart b/mobile/lib/appointments.dart index 99835f7..b233cf8 100644 --- a/mobile/lib/appointments.dart +++ b/mobile/lib/appointments.dart @@ -1,7 +1,6 @@ import 'package:flutter/material.dart'; import 'package:flutter_secure_storage/flutter_secure_storage.dart'; import 'package:http/http.dart' as http; -import 'package:mauagendar/calendar.dart'; import 'dart:convert'; class Appointment { @@ -62,6 +61,11 @@ class Compromissos extends StatefulWidget { } class _CompromissosState extends State { + final _formKey = GlobalKey(); + final _titleController = TextEditingController(); + final _descriptionController = TextEditingController(); + final _startTimeController = TextEditingController(); + final _endTimeController = TextEditingController(); late List _appointments; late Appointment _newAppointment; @@ -207,6 +211,15 @@ class _CompromissosState extends State { } } + @override + void dispose() { + _titleController.dispose(); + _descriptionController.dispose(); + _startTimeController.dispose(); + _endTimeController.dispose(); + super.dispose(); + } + @override Widget build(BuildContext context) { return Scaffold( @@ -216,218 +229,280 @@ class _CompromissosState extends State { onPressed: () => Navigator.pop(context), ), title: const Text('Compromissos'), - actions: [ - IconButton( - icon: const Icon(Icons.calendar_today), - onPressed: () => Navigator.push( - context, - MaterialPageRoute( - builder: (context) => CalendarPage(userId: widget.userId)), - ), - ), - ], ), body: SingleChildScrollView( - child: Column( - children: [ - const SizedBox(height: 16), - Column( - children: _appointments.map((appointment) { - return Container( - padding: const EdgeInsets.all(16), - margin: - const EdgeInsets.symmetric(vertical: 8, horizontal: 16), - decoration: BoxDecoration( - border: Border.all(color: Colors.purple[300]!), - borderRadius: BorderRadius.circular(8), - ), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - appointment.title, - style: const TextStyle( - fontSize: 20, - fontWeight: FontWeight.bold, - color: Colors.white, + child: Form( + key: _formKey, + child: Column( + children: [ + const SizedBox(height: 16), + Column( + children: _appointments.map((appointment) { + return Container( + padding: const EdgeInsets.all(16), + margin: + const EdgeInsets.symmetric(vertical: 8, horizontal: 16), + decoration: BoxDecoration( + border: Border.all(color: Colors.purple[300]!), + borderRadius: BorderRadius.circular(8), + ), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + appointment.title, + style: const TextStyle( + fontSize: 20, + fontWeight: FontWeight.bold, + color: Colors.white, + ), ), - ), - const SizedBox(height: 8), - Text( - appointment.description, - style: const TextStyle( - color: Colors.white, + const SizedBox(height: 8), + Text( + appointment.description, + style: const TextStyle( + color: Colors.white, + ), ), - ), - const SizedBox(height: 8), - Text( - 'Tempo de Início: ${appointment.startTime}', - style: const TextStyle( - color: Colors.white, + const SizedBox(height: 8), + Text( + 'Tempo de Início: ${appointment.startTime}', + style: const TextStyle( + color: Colors.white, + ), ), - ), - const SizedBox(height: 8), - Text( - 'Prazo: ${appointment.endTime}', - style: const TextStyle( - color: Colors.white, + const SizedBox(height: 8), + Text( + 'Prazo: ${appointment.endTime}', + style: const TextStyle( + color: Colors.white, + ), ), - ), - const SizedBox(height: 16), - Row( - mainAxisAlignment: MainAxisAlignment.end, - children: [ - TextButton( - onPressed: () => _deleteAppointment(appointment.id), - child: Text( - 'Deletar', - style: TextStyle( - color: Colors.red[500], + const SizedBox(height: 16), + Row( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + TextButton( + onPressed: () => + _deleteAppointment(appointment.id), + child: Text( + 'Deletar', + style: TextStyle( + color: Colors.red[500], + ), ), ), - ), - TextButton( - onPressed: () => setState(() { - _newAppointment = appointment; - }), - child: Text( - 'Editar', - style: TextStyle( - color: Colors.blue[500], + TextButton( + onPressed: () => setState(() { + _newAppointment = appointment.copyWith(); + _titleController.text = appointment.title; + _descriptionController.text = + appointment.description; + _startTimeController.text = + appointment.startTime; + _endTimeController.text = appointment.endTime; + }), + child: Text( + 'Editar', + style: TextStyle( + color: Colors.blue[500], + ), ), ), - ), - ], - ), - ], - ), - ); - }).toList(), - ), - const SizedBox(height: 16), - const Text( - 'Criar Compromisso', - style: TextStyle( - fontSize: 20, - fontWeight: FontWeight.bold, - color: Colors.white, - ), - ), - const SizedBox(height: 16), - Padding( - padding: const EdgeInsets.symmetric(horizontal: 16), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - TextField( - decoration: const InputDecoration( - labelText: 'Título', - ), - style: const TextStyle( - color: Colors.white, - ), - onChanged: (value) { - setState(() { - _newAppointment = - _newAppointment.copyWith(title: value); - }); - }, - ), - const SizedBox(height: 16), - TextField( - decoration: const InputDecoration( - labelText: 'Descrição', - ), - style: const TextStyle( - color: Colors.white, - ), - onChanged: (value) { - setState(() { - _newAppointment = - _newAppointment.copyWith(description: value); - }); - }, - ), - const SizedBox(height: 16), - TextField( - decoration: const InputDecoration( - labelText: 'Tempo de Início', - ), - style: const TextStyle( - color: Colors.white, - ), - onChanged: (value) { - setState(() { - _newAppointment = - _newAppointment.copyWith(startTime: value); - }); - }, - ), - const SizedBox(height: 16), - TextField( - decoration: const InputDecoration( - labelText: 'Prazo', + ], + ), + ], ), - style: const TextStyle( - color: Colors.white, + ); + }).toList(), + ), + const SizedBox(height: 16), + const Text( + 'Criar ou Atualizar Compromisso', + style: TextStyle( + fontSize: 20, + fontWeight: FontWeight.bold, + color: Colors.white, + ), + ), + const SizedBox(height: 16), + Padding( + padding: const EdgeInsets.symmetric(horizontal: 16), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + TextFormField( + controller: _titleController, + decoration: const InputDecoration( + labelText: 'Título', + ), + style: const TextStyle( + color: Colors.white, + ), + validator: (value) { + if (value == null || value.isEmpty) { + return 'Por favor, insira um título'; + } + return null; + }, + onChanged: (value) { + setState(() { + _newAppointment = + _newAppointment.copyWith(title: value); + }); + }, ), - onChanged: (value) { - setState(() { - _newAppointment = - _newAppointment.copyWith(endTime: value); - }); - }, - ), - const SizedBox(height: 16), - ElevatedButton( - onPressed: () { - if (_newAppointment.id == 0) { - _createAppointment().catchError((error) { - showDialog( - context: context, - builder: (context) => AlertDialog( - title: const Text('Error'), - content: Text(error.toString()), - actions: [ - TextButton( - onPressed: () => Navigator.pop(context), - child: const Text('OK'), - ), - ], - ), - ); + const SizedBox(height: 16), + TextFormField( + controller: _descriptionController, + decoration: const InputDecoration( + labelText: 'Descrição', + ), + style: const TextStyle( + color: Colors.white, + ), + validator: (value) { + if (value == null || value.isEmpty) { + return 'Por favor, insira uma descrição'; + } + return null; + }, + onChanged: (value) { + setState(() { + _newAppointment = + _newAppointment.copyWith(description: value); }); - } else { - _updateAppointment(_newAppointment.id) - .catchError((error) { - showDialog( - context: context, - builder: (context) => AlertDialog( - title: const Text('Error'), - content: Text(error.toString()), - actions: [ - TextButton( - onPressed: () => Navigator.pop(context), - child: const Text('OK'), - ), - ], - ), - ); + }, + ), + const SizedBox(height: 16), + TextFormField( + controller: _startTimeController, + decoration: const InputDecoration( + labelText: 'Tempo de Início', + ), + style: const TextStyle( + color: Colors.white, + ), + validator: (value) { + if (value == null || value.isEmpty) { + return 'Por favor, insira um tempo de início'; + } + return null; + }, + onChanged: (value) { + setState(() { + _newAppointment = + _newAppointment.copyWith(startTime: value); }); - } - }, - child: Text( - _newAppointment.id == 0 ? 'Criar' : 'Atualizar', + }, + ), + const SizedBox(height: 16), + TextFormField( + controller: _endTimeController, + decoration: const InputDecoration( + labelText: 'Prazo', + ), style: const TextStyle( color: Colors.white, ), + validator: (value) { + if (value == null || value.isEmpty) { + return 'Por favor, insira um prazo'; + } + return null; + }, + onChanged: (value) { + setState(() { + _newAppointment = + _newAppointment.copyWith(endTime: value); + }); + }, + ), + const SizedBox(height: 16), + Row( + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + children: [ + ElevatedButton( + onPressed: () { + if (_formKey.currentState!.validate()) { + _createAppointment().catchError((error) { + showDialog( + context: context, + builder: (context) => AlertDialog( + title: const Text('Error'), + content: Text(error.toString()), + actions: [ + TextButton( + onPressed: () => Navigator.pop(context), + child: const Text('OK'), + ), + ], + ), + ); + }); + } + }, + child: const Text( + 'Criar', + style: TextStyle( + color: Colors.white, + ), + ), + ), + ElevatedButton( + onPressed: () { + if (_formKey.currentState!.validate()) { + if (_newAppointment.id == 0) { + showDialog( + context: context, + builder: (context) => AlertDialog( + title: const Text('Error'), + content: const Text( + 'Por favor, selecione um compromisso para atualizar'), + actions: [ + TextButton( + onPressed: () => Navigator.pop(context), + child: const Text('OK'), + ), + ], + ), + ); + } else { + _updateAppointment(_newAppointment.id) + .catchError((error) { + showDialog( + context: context, + builder: (context) => AlertDialog( + title: const Text('Error'), + content: Text(error.toString()), + actions: [ + TextButton( + onPressed: () => + Navigator.pop(context), + child: const Text('OK'), + ), + ], + ), + ); + }); + } + } + }, + child: const Text( + 'Atualizar', + style: TextStyle( + color: Colors.white, + ), + ), + ), + ], ), - ), - ], + ], + ), ), - ), - const SizedBox(height: 16), - ], + const SizedBox(height: 16), + ], + ), ), ), ); diff --git a/mobile/lib/calendar.dart b/mobile/lib/calendar.dart deleted file mode 100644 index bf13d67..0000000 --- a/mobile/lib/calendar.dart +++ /dev/null @@ -1,181 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:flutter_secure_storage/flutter_secure_storage.dart'; -import 'package:http/http.dart' as http; -import 'dart:convert'; -import 'package:table_calendar/table_calendar.dart'; - -class Appointment { - final int id; - final String title; - final DateTime startTime; - final DateTime endTime; - final String description; - - Appointment({ - required this.id, - required this.title, - required this.startTime, - required this.endTime, - required this.description, - }); - - factory Appointment.fromJson(Map json) { - return Appointment( - id: json['id'], - title: json['title'], - startTime: DateTime.parse(json['start_time']), - endTime: DateTime.parse(json['end_time']), - description: json['description'], - ); - } -} - -class CalendarPage extends StatefulWidget { - final String userId; - - const CalendarPage({super.key, required this.userId}); - - @override - _CalendarPageState createState() => _CalendarPageState(); -} - -class _CalendarPageState extends State { - late Map> _events; - late List _appointments; - - @override - void initState() { - super.initState(); - _events = {}; - _appointments = []; - _fetchAppointments(); - } - - Future _fetchAppointments() async { - const storage = FlutterSecureStorage(); - final token = await storage.read(key: 'jwt'); - final url = - Uri.parse('http://localhost:5000/user/${widget.userId}/appointments'); - final response = await http.get( - url, - headers: { - 'Content-Type': 'application/json', - 'Authorization': 'Bearer $token', - }, - ); - - if (response.statusCode < 400) { - final data = jsonDecode(response.body); - final appointments = List.from( - data.map((appointment) => Appointment.fromJson(appointment))); - setState(() { - _appointments = appointments; - _events = _groupAppointmentsByDate(appointments); - }); - } else { - throw Exception('Failed to fetch appointments'); - } - } - - Map> _groupAppointmentsByDate( - List appointments) { - final Map> events = {}; - for (final appointment in appointments) { - final date = DateTime(appointment.startTime.year, - appointment.startTime.month, appointment.startTime.day); - if (events[date] == null) { - events[date] = []; - } - events[date]!.add(appointment); - } - return events; - } - - List _getAppointmentsForDay(DateTime day) { - return _events[day] ?? []; - } - - @override - Widget build(BuildContext context) { - return Scaffold( - appBar: AppBar( - title: const Text('Meus Compromissos'), - ), - body: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - TableCalendar( - calendarBuilders: CalendarBuilders( - selectedBuilder: (context, date, _) { - return Container( - margin: const EdgeInsets.all(4.0), - alignment: Alignment.center, - decoration: BoxDecoration( - color: Colors.deepPurple[800], - shape: BoxShape.circle, - ), - child: Text( - date.day.toString(), - style: const TextStyle(color: Colors.white), - ), - ); - }, - todayBuilder: (context, date, _) { - return Container( - margin: const EdgeInsets.all(4.0), - alignment: Alignment.center, - decoration: BoxDecoration( - color: Colors.deepPurple[800], - shape: BoxShape.circle, - ), - child: Text( - date.day.toString(), - style: const TextStyle(color: Colors.white), - ), - ); - }, - ), - headerStyle: const HeaderStyle( - formatButtonVisible: false, - ), - eventLoader: _getAppointmentsForDay, - calendarStyle: CalendarStyle( - todayDecoration: BoxDecoration( - color: Colors.deepPurple[800], - shape: BoxShape.circle, - ), - selectedDecoration: BoxDecoration( - color: Colors.deepPurple[800], - shape: BoxShape.circle, - ), - selectedTextStyle: const TextStyle(color: Colors.white), - todayTextStyle: const TextStyle(color: Colors.white), - ), - focusedDay: DateTime.now(), - firstDay: DateTime.utc(2022, 1, 1), - lastDay: DateTime.utc(2025, 12, 31), - onDaySelected: (DateTime selectedDay, DateTime focusedDay) { - setState(() { - _appointments = _getAppointmentsForDay(selectedDay); - }); - }, - ), - Expanded( - child: ListView.builder( - itemCount: _appointments.length, - itemBuilder: (context, index) { - final appointment = _appointments[index]; - return ListTile( - title: Text(appointment.title), - subtitle: Text(appointment.description), - trailing: Text( - '${appointment.startTime.hour}:${appointment.startTime.minute} - ${appointment.endTime.hour}:${appointment.endTime.minute}'), - ); - }, - ), - ), - ], - ), - ); - } -} diff --git a/mobile/lib/navbar.dart b/mobile/lib/navbar.dart index 52e8c6e..a593061 100644 --- a/mobile/lib/navbar.dart +++ b/mobile/lib/navbar.dart @@ -1,5 +1,4 @@ import 'package:flutter/material.dart'; -import 'package:mauagendar/calendar.dart'; import 'package:mauagendar/appointments.dart'; class Navbar extends StatefulWidget { @@ -31,8 +30,6 @@ class _NavbarState extends State { ), Row( children: [ - _buildNavLink( - context, 'Calendario', '/calendar', widget.userId), _buildNavLink( context, 'Compromissos', '/appointments', widget.userId), ], @@ -50,13 +47,7 @@ Widget _buildNavLink( padding: const EdgeInsets.symmetric(horizontal: 16.0), child: TextButton( onPressed: () { - if (route == '/calendar') { - Navigator.push( - context, - MaterialPageRoute( - builder: (context) => CalendarPage(userId: userId)), - ); - } else if (route == '/appointments') { + if (route == '/appointments') { Navigator.push( context, MaterialPageRoute(