import 'package:flutter/material.dart'; import 'package:intl/date_symbol_data_local.dart'; import 'package:table_calendar/table_calendar.dart'; // Dias de Citas No Disponibles final Map _holidays = { DateTime(2020, 11, 6): ['No Hay Citas'], DateTime(2020, 11, 3): ['Dia Elecciones'], DateTime(2020,12,25): ['Chrismas'], DateTime(2020,12,31): ['Despedida del anyo nuevo'], }; //Iniciar la Seccion de las Citas void main() { initializeDateFormatting().then((_) => runApp(Calendario())); } //Inicio del Area de las Citas Disponibles class Calendario extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp( title: 'Citas Disponibles', theme: ThemeData( primarySwatch: Colors.blue, ), home: MyHomePage(title: 'Citas Disponibles'), ); } } class MyHomePage extends StatefulWidget { MyHomePage({Key key, this.title}) : super(key: key); final String title; @override _MyHomePageState createState() => _MyHomePageState(); } //Definimos los controladores del Calendario class _MyHomePageState extends State with TickerProviderStateMixin { Map _events; List _selectedEvents; AnimationController _animationController; CalendarController _calendarController; Map> _events2; //Definimos el dia elegido @override void initState() { super.initState(); final _selectedDay = DateTime.now(); _events = { //Ejemplos de Citas Previamente Hechas de Prueba Para los Recordatorios _selectedDay.add(Duration(days: 3)): Set.from([ 'Cita Cardiologo', 'Cita Dentista']).toList(), _selectedDay.add(Duration(days: 22)): ['Cita Cardiologo', 'Cita Dentista'], }; //Dias de Citas Seleccionados como Recordatorio _selectedEvents = _events[_selectedDay] ?? []; _calendarController = CalendarController(); _events2 = {}; _animationController = AnimationController( vsync: this, duration: const Duration(milliseconds: 400), ); _animationController.forward(); } Map encodeMap(Map map) { Map newMap = {}; map.forEach((key,value) { newMap[key.toString()] = map[key]; }); return newMap; } Map decodeMap(Map map) { Map newMap = {}; map.forEach((key,value) { newMap[DateTime.parse(key)] = map[key]; }); return newMap; } @override void dispose() { _animationController.dispose(); _calendarController.dispose(); super.dispose(); } //Acciones definidas cuando se elige un dia en particular para ver si esta disponible o no void _onDaySelected(DateTime day, List events, List holidays) { print('CALLBACK: _onDaySelected'); setState(() { _selectedEvents = events; }); } void _onVisibleDaysChanged(DateTime first, DateTime last, CalendarFormat format) { print('CALLBACK: _onVisibleDaysChanged'); } void _onCalendarCreated(DateTime first, DateTime last, CalendarFormat format) { print('CALLBACK: _onCalendarCreated'); } //Definimos el "look" del area de las citas @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text(widget.title), ), body: Column( mainAxisSize: MainAxisSize.max, children: [ _buildTableCalendar( ), // _buildTableCalendarWithBuilders(), const SizedBox(height: 8.0), _buildButtons(), const SizedBox(height: 8.0), Expanded(child: _buildEventList()), ], ), ); } // Simple configuracion de la Tabla de Calendario usando estilos Widget _buildTableCalendar() { return TableCalendar( calendarController: _calendarController, events: _events, holidays: _holidays, startingDayOfWeek: StartingDayOfWeek.monday, calendarStyle: CalendarStyle( selectedColor: Colors.lightBlueAccent, todayColor: Colors.blueAccent, markersColor: Colors.brown, outsideDaysVisible: false, ), headerStyle: HeaderStyle( formatButtonTextStyle: TextStyle().copyWith(color: Colors.white, fontSize: 15.0), formatButtonDecoration: BoxDecoration( color: Colors.lightBlue, borderRadius: BorderRadius.circular(16.0), ), ), onDaySelected: _onDaySelected, onVisibleDaysChanged: _onVisibleDaysChanged, onCalendarCreated: _onCalendarCreated, ); } // Configuraciones detalladas del area de citas como definir dias, meses, etc. Widget buildTableCalendarWithBuilders() { return TableCalendar( locale: 'pl_PL', calendarController: _calendarController, events: _events, holidays: _holidays, initialCalendarFormat: CalendarFormat.month, formatAnimation: FormatAnimation.slide, startingDayOfWeek: StartingDayOfWeek.sunday, availableGestures: AvailableGestures.all, availableCalendarFormats: const { CalendarFormat.month: '', CalendarFormat.week: '', }, //Colores de los dias seleccionados calendarStyle: CalendarStyle( outsideDaysVisible: false, weekendStyle: TextStyle().copyWith(color: Colors.blue), holidayStyle: TextStyle().copyWith(color: Colors.blue), ), daysOfWeekStyle: DaysOfWeekStyle( weekendStyle: TextStyle().copyWith(color: Colors.blue), ), headerStyle: HeaderStyle( centerHeaderTitle: true, formatButtonVisible: false, ), builders: CalendarBuilders( selectedDayBuilder: (context, date, _) { //Animacion del Calendario al cambiar el mes return FadeTransition( opacity: Tween(begin: 0.0, end: 1.0).animate(_animationController), child: Container( margin: const EdgeInsets.all(4.0), padding: const EdgeInsets.only(top: 5.0, left: 6.0), color: Colors.green, width: 100, height: 100, child: Text( '${date.day}', style: TextStyle().copyWith(fontSize: 16.0), ), ), ); }, todayDayBuilder: (context, date, _) { return Container( margin: const EdgeInsets.all(4.0), padding: const EdgeInsets.only(top: 5.0, left: 6.0), color: Colors.amber, width: 100, height: 100, child: Text( '${date.day}', style: TextStyle().copyWith(fontSize: 16.0), ), ); }, markersBuilder: (context, date, events, holidays) { final children = []; if (events.isNotEmpty) { children.add( Positioned( right: 1, bottom: 1, child: _buildEventsMarker(date, events), ), ); } if (holidays.isNotEmpty) { children.add( Positioned( right: -2, top: -2, child: _buildHolidaysMarker(), ), ); } return children; }, ), onDaySelected: (date, events, holidays) { _onDaySelected(date, events, holidays); _animationController.forward(from: 0.0); }, onVisibleDaysChanged: _onVisibleDaysChanged, onCalendarCreated: _onCalendarCreated, ); } //Marcador de eventos (aparece debajo de los dias) Widget _buildEventsMarker(DateTime date, List events) { return AnimatedContainer( duration: const Duration(milliseconds: 300), decoration: BoxDecoration( shape: BoxShape.rectangle, color: _calendarController.isSelected(date) ? Colors.brown[500] : _calendarController.isToday(date) ? Colors.brown : Colors.blue, ), width: 16.0, height: 16.0, child: Center( child: Text( '${events.length}', style: TextStyle().copyWith( color: Colors.green, fontSize: 12.0, ), ), ), ); } Widget _buildHolidaysMarker() { return Icon( Icons.add_box, size: 20.0, color: Colors.blueGrey, ); } Widget _buildButtons() { final dateTime = _events.keys.elementAt(_events.length - 2); //Definimos formato del calendario (mes, 2 semanas, semana) return Column( children: [ Row( mainAxisSize: MainAxisSize.max, mainAxisAlignment: MainAxisAlignment.spaceEvenly, children: [ RaisedButton( child: Text('Mes'), onPressed: () { setState(() { _calendarController.setCalendarFormat(CalendarFormat.month); }); }, ), RaisedButton( child: Text('2 Semanas'), onPressed: () { setState(() { _calendarController.setCalendarFormat(CalendarFormat.twoWeeks); }); }, ), RaisedButton( child: Text('Semana'), onPressed: () { setState(() { _calendarController.setCalendarFormat(CalendarFormat.week); }); }, ), ], ), const SizedBox(height: 8.0), RaisedButton( child: Text('Recuerde Cita ${dateTime.day}-${dateTime.month}-${dateTime.year}'), onPressed: () { _calendarController.setSelectedDay( DateTime(dateTime.year, dateTime.month, dateTime.day), runCallback: true, ); }, ), ], ); } //Muestra las citas ya creadas Widget _buildEventList() { return ListView( children: _selectedEvents .map((event) => Container( decoration: BoxDecoration( border: Border.all(width: 0.8), borderRadius: BorderRadius.circular(12.0), ), margin: const EdgeInsets.symmetric(horizontal: 8.0, vertical: 4.0), child: ListTile( title: Text(event.toString()), onTap: () => print('$event tapped!'), ), )) .toList(), ); } }